1/* BEGIN_HEADER */
2
3#include <stdlib.h>
4
5#include "mps_reader.h"
6
7/*
8 * Compile-time configuration for test suite.
9 */
10
11/* Comment/Uncomment this to disable/enable the
12 * testing of the various MPS layers.
13 * This can be useful for time-consuming instrumentation
14 * tasks such as the conversion of E-ACSL annotations
15 * into runtime assertions. */
16#define TEST_SUITE_MPS_READER
17
18/* End of compile-time configuration. */
19
20/* END_HEADER */
21
22/* BEGIN_DEPENDENCIES
23 * depends_on:MBEDTLS_SSL_PROTO_TLS1_3
24 * END_DEPENDENCIES
25 */
26
27/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER */
28void mbedtls_mps_reader_no_pausing_single_step_single_round(int with_acc)
29{
30    /* This test exercises the most basic use of the MPS reader:
31     * - The 'producing' layer provides a buffer
32     * - The 'consuming' layer fetches it in a single go.
33     * - After processing, the consuming layer commits the data
34     *   and the reader is moved back to producing mode.
35     *
36     * Parameters:
37     * - with_acc: 0 if the reader should be initialized without accumulator.
38     *             1 if the reader should be initialized with accumulator.
39     *
40     *             Whether the accumulator is present or not should not matter,
41     *             since the consumer's request can be fulfilled from the data
42     *             that the producer has provided.
43     */
44    unsigned char bufA[100];
45    unsigned char acc[10];
46    unsigned char *tmp;
47    int paused;
48    mbedtls_mps_reader rd;
49    for (size_t i = 0; (unsigned) i < sizeof(bufA); i++) {
50        bufA[i] = (unsigned char) i;
51    }
52
53    /* Preparation (lower layer) */
54    if (with_acc == 0) {
55        mbedtls_mps_reader_init(&rd, NULL, 0);
56    } else {
57        mbedtls_mps_reader_init(&rd, acc, sizeof(acc));
58    }
59    TEST_ASSERT(mbedtls_mps_reader_feed(&rd, bufA, sizeof(bufA)) == 0);
60    /* Consumption (upper layer) */
61    /* Consume exactly what's available */
62    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 100, &tmp, NULL) == 0);
63    TEST_MEMORY_COMPARE(tmp, 100, bufA, 100);
64    TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
65    /* Wrapup (lower layer) */
66    TEST_ASSERT(mbedtls_mps_reader_reclaim(&rd, &paused) == 0);
67    TEST_ASSERT(paused == 0);
68
69exit:
70    mbedtls_mps_reader_free(&rd);
71}
72/* END_CASE */
73
74/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER */
75void mbedtls_mps_reader_no_pausing_single_step_multiple_rounds(int with_acc)
76{
77    /* This test exercises multiple rounds of the basic use of the MPS reader:
78     * - The 'producing' layer provides a buffer
79     * - The 'consuming' layer fetches it in a single go.
80     * - After processing, the consuming layer commits the data
81     *   and the reader is moved back to producing mode.
82     *
83     * Parameters:
84     * - with_acc: 0 if the reader should be initialized without accumulator.
85     *             1 if the reader should be initialized with accumulator.
86     *
87     *             Whether the accumulator is present or not should not matter,
88     *             since the consumer's request can be fulfilled from the data
89     *             that the producer has provided.
90     */
91
92    unsigned char bufA[100], bufB[100];
93    unsigned char acc[10];
94    unsigned char *tmp;
95    mbedtls_mps_reader rd;
96    for (size_t i = 0; (unsigned) i < sizeof(bufA); i++) {
97        bufA[i] = (unsigned char) i;
98    }
99    for (size_t i = 0; (unsigned) i < sizeof(bufB); i++) {
100        bufB[i] = ~((unsigned char) i);
101    }
102
103    /* Preparation (lower layer) */
104    if (with_acc == 0) {
105        mbedtls_mps_reader_init(&rd, NULL, 0);
106    } else {
107        mbedtls_mps_reader_init(&rd, acc, sizeof(acc));
108    }
109    TEST_ASSERT(mbedtls_mps_reader_feed(&rd, bufA, sizeof(bufA)) == 0);
110    /* Consumption (upper layer) */
111    /* Consume exactly what's available */
112    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 100, &tmp, NULL) == 0);
113    TEST_MEMORY_COMPARE(tmp, 100, bufA, 100);
114    TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
115    /* Preparation */
116    TEST_ASSERT(mbedtls_mps_reader_reclaim(&rd, NULL) == 0);
117    TEST_ASSERT(mbedtls_mps_reader_feed(&rd, bufB, sizeof(bufB)) == 0);
118    /* Consumption */
119    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 100, &tmp, NULL) == 0);
120    TEST_MEMORY_COMPARE(tmp, 100, bufB, 100);
121    TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
122    /* Wrapup (lower layer) */
123    TEST_ASSERT(mbedtls_mps_reader_reclaim(&rd, NULL) == 0);
124
125exit:
126    mbedtls_mps_reader_free(&rd);
127}
128/* END_CASE */
129
130/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER */
131void mbedtls_mps_reader_no_pausing_multiple_steps_single_round(int with_acc)
132{
133    /* This test exercises one round of the following:
134     * - The 'producing' layer provides a buffer
135     * - The 'consuming' layer fetches it in multiple calls
136     *   to `mbedtls_mps_reader_get()`, without committing in between.
137     * - After processing, the consuming layer commits the data
138     *   and the reader is moved back to producing mode.
139     *
140     * Parameters:
141     * - with_acc: 0 if the reader should be initialized without accumulator.
142     *             1 if the reader should be initialized with accumulator.
143     *
144     *             Whether the accumulator is present or not should not matter,
145     *             since the consumer's requests can be fulfilled from the data
146     *             that the producer has provided.
147     */
148
149    /* Lower layer provides data that the upper layer fully consumes
150     * through multiple `get` calls. */
151    unsigned char buf[100];
152    unsigned char acc[10];
153    unsigned char *tmp;
154    mbedtls_mps_size_t tmp_len;
155    mbedtls_mps_reader rd;
156    for (size_t i = 0; (unsigned) i < sizeof(buf); i++) {
157        buf[i] = (unsigned char) i;
158    }
159
160    /* Preparation (lower layer) */
161    if (with_acc == 0) {
162        mbedtls_mps_reader_init(&rd, NULL, 0);
163    } else {
164        mbedtls_mps_reader_init(&rd, acc, sizeof(acc));
165    }
166    TEST_ASSERT(mbedtls_mps_reader_feed(&rd, buf, sizeof(buf)) == 0);
167    /* Consumption (upper layer) */
168    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 10, &tmp, NULL) == 0);
169    TEST_MEMORY_COMPARE(tmp, 10, buf, 10);
170    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 70, &tmp, NULL) == 0);
171    TEST_MEMORY_COMPARE(tmp, 70, buf + 10, 70);
172    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 30, &tmp, &tmp_len) == 0);
173    TEST_MEMORY_COMPARE(tmp, tmp_len, buf + 80, 20);
174    TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
175    /* Wrapup (lower layer) */
176    TEST_ASSERT(mbedtls_mps_reader_reclaim(&rd, NULL) == 0);
177
178exit:
179    mbedtls_mps_reader_free(&rd);
180}
181/* END_CASE */
182
183/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER */
184void mbedtls_mps_reader_no_pausing_multiple_steps_multiple_rounds(int with_acc)
185{
186    /* This test exercises one round of fetching a buffer in multiple chunks
187     * and passing it back to the producer afterwards, followed by another
188     * single-step sequence of feed-fetch-commit-reclaim.
189     */
190    unsigned char bufA[100], bufB[100];
191    unsigned char acc[10];
192    unsigned char *tmp;
193    mbedtls_mps_size_t tmp_len;
194    mbedtls_mps_reader rd;
195    for (size_t i = 0; (unsigned) i < sizeof(bufA); i++) {
196        bufA[i] = (unsigned char) i;
197    }
198    for (size_t i = 0; (unsigned) i < sizeof(bufB); i++) {
199        bufB[i] = ~((unsigned char) i);
200    }
201
202    /* Preparation (lower layer) */
203    if (with_acc == 0) {
204        mbedtls_mps_reader_init(&rd, NULL, 0);
205    } else {
206        mbedtls_mps_reader_init(&rd, acc, sizeof(acc));
207    }
208    TEST_ASSERT(mbedtls_mps_reader_feed(&rd, bufA, sizeof(bufA)) == 0);
209    /* Consumption (upper layer) */
210    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 10, &tmp, NULL) == 0);
211    TEST_MEMORY_COMPARE(tmp, 10, bufA, 10);
212    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 70, &tmp, NULL) == 0);
213    TEST_MEMORY_COMPARE(tmp, 70, bufA + 10, 70);
214    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 30, &tmp, &tmp_len) == 0);
215    TEST_MEMORY_COMPARE(tmp, tmp_len, bufA + 80, 20);
216    TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
217    /* Preparation */
218    TEST_ASSERT(mbedtls_mps_reader_reclaim(&rd, NULL) == 0);
219    TEST_ASSERT(mbedtls_mps_reader_feed(&rd, bufB, sizeof(bufB)) == 0);
220    /* Consumption */
221    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 100, &tmp, NULL) == 0);
222    TEST_MEMORY_COMPARE(tmp, 100, bufB, 100);
223    TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
224    /* Wrapup */
225    TEST_ASSERT(mbedtls_mps_reader_reclaim(&rd, NULL) == 0);
226
227exit:
228    mbedtls_mps_reader_free(&rd);
229}
230/* END_CASE */
231
232/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER */
233void mbedtls_mps_reader_pausing_needed_disabled()
234{
235    /* This test exercises the behaviour of the MPS reader when a read request
236     * of the consumer exceeds what has been provided by the producer, and when
237     * no accumulator is available in the reader.
238     *
239     * In this case, we expect the reader to fail.
240     */
241
242    unsigned char buf[100];
243    unsigned char *tmp;
244    mbedtls_mps_reader rd;
245    for (size_t i = 0; (unsigned) i < sizeof(buf); i++) {
246        buf[i] = (unsigned char) i;
247    }
248
249    /* Preparation (lower layer) */
250    mbedtls_mps_reader_init(&rd, NULL, 0);
251    TEST_ASSERT(mbedtls_mps_reader_feed(&rd, buf, sizeof(buf)) == 0);
252    /* Consumption (upper layer) */
253    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 50, &tmp, NULL) == 0);
254    TEST_MEMORY_COMPARE(tmp, 50, buf, 50);
255    TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
256    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 100, &tmp, NULL) ==
257                MBEDTLS_ERR_MPS_READER_OUT_OF_DATA);
258    /* Wrapup (lower layer) */
259    TEST_ASSERT(mbedtls_mps_reader_reclaim(&rd, NULL) ==
260                MBEDTLS_ERR_MPS_READER_NEED_ACCUMULATOR);
261
262exit:
263    mbedtls_mps_reader_free(&rd);
264}
265/* END_CASE */
266
267/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER */
268void mbedtls_mps_reader_pausing_needed_buffer_too_small()
269{
270    /* This test exercises the behaviour of the MPS reader with accumulator
271     * in the situation where a read request goes beyond the bounds of the
272     * current read buffer, _and_ the reader's accumulator is too small to
273     * hold the requested amount of data.
274     *
275     * In this case, we expect mbedtls_mps_reader_reclaim() to fail,
276     * but it should be possible to continue fetching data as if
277     * there had been no excess request via mbedtls_mps_reader_get()
278     * and the call to mbedtls_mps_reader_reclaim() had been rejected
279     * because of data remaining.
280     */
281
282    unsigned char buf[100];
283    unsigned char acc[10];
284    unsigned char *tmp;
285    mbedtls_mps_reader rd;
286    mbedtls_mps_size_t tmp_len;
287
288    for (size_t i = 0; (unsigned) i < sizeof(buf); i++) {
289        buf[i] = (unsigned char) i;
290    }
291
292    /* Preparation (lower layer) */
293    mbedtls_mps_reader_init(&rd, acc, sizeof(acc));
294    TEST_ASSERT(mbedtls_mps_reader_feed(&rd, buf, sizeof(buf)) == 0);
295    /* Consumption (upper layer) */
296    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 50, &tmp, NULL) == 0);
297    TEST_MEMORY_COMPARE(tmp, 50, buf, 50);
298    TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
299    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 10, &tmp, NULL) == 0);
300    TEST_MEMORY_COMPARE(tmp, 10, buf + 50, 10);
301    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 100, &tmp, NULL) ==
302                MBEDTLS_ERR_MPS_READER_OUT_OF_DATA);
303    /* Wrapup (lower layer) */
304    TEST_ASSERT(mbedtls_mps_reader_reclaim(&rd, NULL) ==
305                MBEDTLS_ERR_MPS_READER_ACCUMULATOR_TOO_SMALL);
306
307    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 50, &tmp, &tmp_len) == 0);
308    TEST_MEMORY_COMPARE(tmp, tmp_len, buf + 50, 50);
309
310exit:
311    mbedtls_mps_reader_free(&rd);
312}
313/* END_CASE */
314
315/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER */
316void mbedtls_mps_reader_reclaim_overflow()
317{
318    /* This test exercises the behaviour of the MPS reader with accumulator
319     * in the situation where upon calling mbedtls_mps_reader_reclaim(), the
320     * uncommitted data together with the excess data missing in the last
321     * call to mbedtls_mps_reader_get() exceeds the bounds of the type
322     * holding the buffer length.
323     */
324
325    unsigned char buf[100];
326    unsigned char acc[50];
327    unsigned char *tmp;
328    mbedtls_mps_reader rd;
329
330    for (size_t i = 0; (unsigned) i < sizeof(buf); i++) {
331        buf[i] = (unsigned char) i;
332    }
333
334    /* Preparation (lower layer) */
335    mbedtls_mps_reader_init(&rd, acc, sizeof(acc));
336    TEST_ASSERT(mbedtls_mps_reader_feed(&rd, buf, sizeof(buf)) == 0);
337    /* Consumption (upper layer) */
338    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 50, &tmp, NULL) == 0);
339    TEST_MEMORY_COMPARE(tmp, 50, buf, 50);
340    /* Excess request */
341    TEST_ASSERT(mbedtls_mps_reader_get(&rd, (mbedtls_mps_size_t) -1, &tmp, NULL) ==
342                MBEDTLS_ERR_MPS_READER_OUT_OF_DATA);
343    /* Wrapup (lower layer) */
344    TEST_ASSERT(mbedtls_mps_reader_reclaim(&rd, NULL) ==
345                MBEDTLS_ERR_MPS_READER_ACCUMULATOR_TOO_SMALL);
346
347exit:
348    mbedtls_mps_reader_free(&rd);
349}
350/* END_CASE */
351
352/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER */
353void mbedtls_mps_reader_pausing(int option)
354{
355    /* This test exercises the behaviour of the reader when the
356     * accumulator is used to fulfill a consumer's request.
357     *
358     * More detailed:
359     * - The producer feeds some data.
360     * - The consumer asks for more data than what's available.
361     * - The reader remembers the request and goes back to
362     *   producing mode, waiting for more data from the producer.
363     * - The producer provides another chunk of data which is
364     *   sufficient to fulfill the original read request.
365     * - The consumer retries the original read request, which
366     *   should now succeed.
367     *
368     * This test comes in multiple variants controlled by the
369     * `option` parameter and documented below.
370     */
371
372    unsigned char bufA[100], bufB[100];
373    unsigned char *tmp;
374    unsigned char acc[40];
375    int paused;
376    mbedtls_mps_reader rd;
377    for (size_t i = 0; (unsigned) i < sizeof(bufA); i++) {
378        bufA[i] = (unsigned char) i;
379    }
380    for (size_t i = 0; (unsigned) i < sizeof(bufB); i++) {
381        bufB[i] = ~((unsigned char) i);
382    }
383
384    /* Preparation (lower layer) */
385    mbedtls_mps_reader_init(&rd, acc, sizeof(acc));
386    TEST_ASSERT(mbedtls_mps_reader_feed(&rd, bufA, sizeof(bufA)) == 0);
387
388    /* Consumption (upper layer) */
389    /* Ask for more than what's available. */
390    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 80, &tmp, NULL) == 0);
391    TEST_MEMORY_COMPARE(tmp, 80, bufA, 80);
392    TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
393    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 10, &tmp, NULL) == 0);
394    TEST_MEMORY_COMPARE(tmp, 10, bufA + 80, 10);
395    switch (option) {
396        case 0:  /* Single uncommitted fetch at pausing */
397        case 1:
398            TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
399            break;
400        default: /* Multiple uncommitted fetches at pausing */
401            break;
402    }
403    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 20, &tmp, NULL) ==
404                MBEDTLS_ERR_MPS_READER_OUT_OF_DATA);
405
406    /* Preparation */
407    TEST_ASSERT(mbedtls_mps_reader_reclaim(&rd, &paused) == 0);
408    TEST_ASSERT(paused == 1);
409    TEST_ASSERT(mbedtls_mps_reader_feed(&rd, bufB, sizeof(bufB)) == 0);
410
411    /* Consumption */
412    switch (option) {
413        case 0: /* Single fetch at pausing, re-fetch with commit. */
414            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 20, &tmp, NULL) == 0);
415            TEST_MEMORY_COMPARE(tmp, 10, bufA + 90, 10);
416            TEST_MEMORY_COMPARE(tmp + 10, 10, bufB, 10);
417            TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
418            break;
419
420        case 1: /* Single fetch at pausing, re-fetch without commit. */
421            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 20, &tmp, NULL) == 0);
422            TEST_MEMORY_COMPARE(tmp, 10, bufA + 90, 10);
423            TEST_MEMORY_COMPARE(tmp + 10, 10, bufB, 10);
424            break;
425
426        case 2: /* Multiple fetches at pausing, repeat without commit. */
427            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 10, &tmp, NULL) == 0);
428            TEST_MEMORY_COMPARE(tmp, 10, bufA + 80, 10);
429            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 20, &tmp, NULL) == 0);
430            TEST_MEMORY_COMPARE(tmp, 10, bufA + 90, 10);
431            TEST_MEMORY_COMPARE(tmp + 10, 10, bufB, 10);
432            break;
433
434        case 3: /* Multiple fetches at pausing, repeat with commit 1. */
435            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 10, &tmp, NULL) == 0);
436            TEST_MEMORY_COMPARE(tmp, 10, bufA + 80, 10);
437            TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
438            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 20, &tmp, NULL) == 0);
439            TEST_MEMORY_COMPARE(tmp, 10, bufA + 90, 10);
440            TEST_MEMORY_COMPARE(tmp + 10, 10, bufB, 10);
441            break;
442
443        case 4: /* Multiple fetches at pausing, repeat with commit 2. */
444            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 10, &tmp, NULL) == 0);
445            TEST_MEMORY_COMPARE(tmp, 10, bufA + 80, 10);
446            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 20, &tmp, NULL) == 0);
447            TEST_MEMORY_COMPARE(tmp, 10, bufA + 90, 10);
448            TEST_MEMORY_COMPARE(tmp + 10, 10, bufB, 10);
449            TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
450            break;
451
452        case 5: /* Multiple fetches at pausing, repeat with commit 3. */
453            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 10, &tmp, NULL) == 0);
454            TEST_MEMORY_COMPARE(tmp, 10, bufA + 80, 10);
455            TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
456            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 20, &tmp, NULL) == 0);
457            TEST_MEMORY_COMPARE(tmp, 10, bufA + 90, 10);
458            TEST_MEMORY_COMPARE(tmp + 10, 10, bufB, 10);
459            TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
460            break;
461
462        default:
463            TEST_ASSERT(0);
464    }
465
466    /* In all cases, fetch the rest of the second buffer. */
467    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 90, &tmp, NULL) == 0);
468    TEST_MEMORY_COMPARE(tmp, 90, bufB + 10, 90);
469    TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
470
471    /* Wrapup */
472    TEST_ASSERT(mbedtls_mps_reader_reclaim(&rd, NULL) == 0);
473
474exit:
475    mbedtls_mps_reader_free(&rd);
476}
477/* END_CASE */
478
479/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER */
480void mbedtls_mps_reader_pausing_multiple_feeds(int option)
481{
482    /* This test exercises the behaviour of the MPS reader
483     * in the following situation:
484     * - The consumer has asked for more than what's available, so the
485     *   reader pauses and waits for further input data via
486     *   `mbedtls_mps_reader_feed()`
487     * - Multiple such calls to `mbedtls_mps_reader_feed()` are necessary
488     *   to fulfill the original request, and the reader needs to do
489     *   the necessary bookkeeping under the hood.
490     *
491     * This test comes in a few variants differing in the number and
492     * size of feed calls that the producer issues while the reader is
493     * accumulating the necessary data - see the comments below.
494     */
495
496    unsigned char bufA[100], bufB[100];
497    unsigned char *tmp;
498    unsigned char acc[70];
499    mbedtls_mps_reader rd;
500    mbedtls_mps_size_t fetch_len;
501    for (size_t i = 0; (unsigned) i < sizeof(bufA); i++) {
502        bufA[i] = (unsigned char) i;
503    }
504    for (size_t i = 0; (unsigned) i < sizeof(bufB); i++) {
505        bufB[i] = ~((unsigned char) i);
506    }
507
508    /* Preparation (lower layer) */
509    mbedtls_mps_reader_init(&rd, acc, sizeof(acc));
510    TEST_ASSERT(mbedtls_mps_reader_feed(&rd, bufA, sizeof(bufA)) == 0);
511
512    /* Consumption (upper layer) */
513    /* Ask for more than what's available. */
514    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 80, &tmp, NULL) == 0);
515    TEST_MEMORY_COMPARE(tmp, 80, bufA, 80);
516    TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
517    /* 20 left, ask for 70 -> 50 overhead */
518    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 70, &tmp, NULL) ==
519                MBEDTLS_ERR_MPS_READER_OUT_OF_DATA);
520
521    /* Preparation */
522    TEST_ASSERT(mbedtls_mps_reader_reclaim(&rd, NULL) == 0);
523    switch (option) {
524        case 0: /* 10 + 10 + 80 byte feed */
525            TEST_ASSERT(mbedtls_mps_reader_feed(&rd, bufB, 10) ==
526                        MBEDTLS_ERR_MPS_READER_NEED_MORE);
527            TEST_ASSERT(mbedtls_mps_reader_feed(&rd, bufB + 10, 10) ==
528                        MBEDTLS_ERR_MPS_READER_NEED_MORE);
529            TEST_ASSERT(mbedtls_mps_reader_feed(&rd, bufB + 20, 80) == 0);
530            break;
531
532        case 1: /* 50 x 1byte */
533            for (size_t num_feed = 0; num_feed < 49; num_feed++) {
534                TEST_ASSERT(mbedtls_mps_reader_feed(&rd, bufB + num_feed, 1) ==
535                            MBEDTLS_ERR_MPS_READER_NEED_MORE);
536            }
537            TEST_ASSERT(mbedtls_mps_reader_feed(&rd, bufB + 49, 1) == 0);
538            break;
539
540        case 2: /* 49 x 1byte + 51bytes */
541            for (size_t num_feed = 0; num_feed < 49; num_feed++) {
542                TEST_ASSERT(mbedtls_mps_reader_feed(&rd, bufB + num_feed, 1) ==
543                            MBEDTLS_ERR_MPS_READER_NEED_MORE);
544            }
545            TEST_ASSERT(mbedtls_mps_reader_feed(&rd, bufB + 49, 51) == 0);
546            break;
547
548        default:
549            TEST_ASSERT(0);
550            break;
551    }
552
553    /* Consumption */
554    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 70, &tmp, NULL) == 0);
555    TEST_MEMORY_COMPARE(tmp, 20, bufA + 80, 20);
556    TEST_MEMORY_COMPARE(tmp + 20, 50, bufB, 50);
557    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 1000, &tmp, &fetch_len) == 0);
558    switch (option) {
559        case 0:
560            TEST_ASSERT(fetch_len == 50);
561            break;
562
563        case 1:
564            TEST_ASSERT(fetch_len == 0);
565            break;
566
567        case 2:
568            TEST_ASSERT(fetch_len == 50);
569            break;
570
571        default:
572            TEST_ASSERT(0);
573            break;
574    }
575    TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
576
577    /* Wrapup */
578    TEST_ASSERT(mbedtls_mps_reader_reclaim(&rd, NULL) == 0);
579
580exit:
581    mbedtls_mps_reader_free(&rd);
582}
583/* END_CASE */
584
585
586/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER */
587void mbedtls_mps_reader_reclaim_data_left(int option)
588{
589    /* This test exercises the behaviour of the MPS reader when a
590     * call to mbedtls_mps_reader_reclaim() is made before all data
591     * provided by the producer has been fetched and committed. */
592
593    unsigned char buf[100];
594    unsigned char *tmp;
595    mbedtls_mps_reader rd;
596    for (size_t i = 0; (unsigned) i < sizeof(buf); i++) {
597        buf[i] = (unsigned char) i;
598    }
599
600    /* Preparation (lower layer) */
601    mbedtls_mps_reader_init(&rd, NULL, 0);
602    TEST_ASSERT(mbedtls_mps_reader_feed(&rd, buf, sizeof(buf)) == 0);
603
604    /* Consumption (upper layer) */
605    switch (option) {
606        case 0:
607            /* Fetch (but not commit) the entire buffer. */
608            TEST_ASSERT(mbedtls_mps_reader_get(&rd, sizeof(buf), &tmp, NULL)
609                        == 0);
610            TEST_MEMORY_COMPARE(tmp, 100, buf, 100);
611            break;
612
613        case 1:
614            /* Fetch (but not commit) parts of the buffer. */
615            TEST_ASSERT(mbedtls_mps_reader_get(&rd, sizeof(buf) / 2,
616                                               &tmp, NULL) == 0);
617            TEST_MEMORY_COMPARE(tmp, sizeof(buf) / 2, buf, sizeof(buf) / 2);
618            break;
619
620        case 2:
621            /* Fetch and commit parts of the buffer, then
622             * fetch but not commit the rest of the buffer. */
623            TEST_ASSERT(mbedtls_mps_reader_get(&rd, sizeof(buf) / 2,
624                                               &tmp, NULL) == 0);
625            TEST_MEMORY_COMPARE(tmp, sizeof(buf) / 2, buf, sizeof(buf) / 2);
626            TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
627            TEST_ASSERT(mbedtls_mps_reader_get(&rd, sizeof(buf) / 2,
628                                               &tmp, NULL) == 0);
629            TEST_MEMORY_COMPARE(tmp, sizeof(buf) / 2,
630                                buf + sizeof(buf) / 2,
631                                sizeof(buf) / 2);
632            break;
633
634        default:
635            TEST_ASSERT(0);
636            break;
637    }
638
639    /* Wrapup */
640    TEST_ASSERT(mbedtls_mps_reader_reclaim(&rd, NULL) ==
641                MBEDTLS_ERR_MPS_READER_DATA_LEFT);
642
643exit:
644    mbedtls_mps_reader_free(&rd);
645}
646/* END_CASE */
647
648/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER */
649void mbedtls_mps_reader_reclaim_data_left_retry()
650{
651    /* This test exercises the behaviour of the MPS reader when an attempt
652     * by the producer to reclaim the reader fails because of more data pending
653     * to be processed, and the consumer subsequently fetches more data. */
654    unsigned char buf[100];
655    unsigned char *tmp;
656    mbedtls_mps_reader rd;
657
658    for (size_t i = 0; (unsigned) i < sizeof(buf); i++) {
659        buf[i] = (unsigned char) i;
660    }
661
662    /* Preparation (lower layer) */
663    mbedtls_mps_reader_init(&rd, NULL, 0);
664    TEST_ASSERT(mbedtls_mps_reader_feed(&rd, buf, sizeof(buf)) == 0);
665    /* Consumption (upper layer) */
666    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 50, &tmp, NULL) == 0);
667    TEST_MEMORY_COMPARE(tmp, 50, buf, 50);
668    TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
669    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 50, &tmp, NULL) == 0);
670    TEST_MEMORY_COMPARE(tmp, 50, buf + 50, 50);
671    /* Preparation */
672    TEST_ASSERT(mbedtls_mps_reader_reclaim(&rd, NULL) ==
673                MBEDTLS_ERR_MPS_READER_DATA_LEFT);
674    /* Consumption */
675    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 50, &tmp, NULL) == 0);
676    TEST_MEMORY_COMPARE(tmp, 50, buf + 50, 50);
677    TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
678    /* Wrapup */
679    TEST_ASSERT(mbedtls_mps_reader_reclaim(&rd, NULL) == 0);
680    mbedtls_mps_reader_free(&rd);
681}
682/* END_CASE */
683
684/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER */
685void mbedtls_mps_reader_multiple_pausing(int option)
686{
687    /* This test exercises the behaviour of the MPS reader
688     * in the following situation:
689     * - A read request via `mbedtls_mps_reader_get()` can't
690     *   be served and the reader is paused to accumulate
691     *   the desired amount of data from the producer.
692     * - Once enough data is available, the consumer successfully
693     *   reads the data from the reader, but afterwards exceeds
694     *   the available data again - pausing is necessary for a
695     *   second time.
696     */
697
698    unsigned char bufA[100], bufB[20], bufC[10];
699    unsigned char *tmp;
700    unsigned char acc[50];
701    mbedtls_mps_size_t tmp_len;
702    mbedtls_mps_reader rd;
703    for (size_t i = 0; (unsigned) i < sizeof(bufA); i++) {
704        bufA[i] = (unsigned char) i;
705    }
706    for (size_t i = 0; (unsigned) i < sizeof(bufB); i++) {
707        bufB[i] = ~((unsigned char) i);
708    }
709    for (size_t i = 0; (unsigned) i < sizeof(bufC); i++) {
710        bufC[i] = ~((unsigned char) i);
711    }
712
713    /* Preparation (lower layer) */
714    mbedtls_mps_reader_init(&rd, acc, sizeof(acc));
715    TEST_ASSERT(mbedtls_mps_reader_feed(&rd, bufA, sizeof(bufA)) == 0);
716
717    /* Consumption (upper layer) */
718    /* Ask for more than what's available. */
719    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 80, &tmp, NULL) == 0);
720    TEST_MEMORY_COMPARE(tmp, 80, bufA, 80);
721    TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
722    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 10, &tmp, NULL) == 0);
723    TEST_MEMORY_COMPARE(tmp, 10, bufA + 80, 10);
724    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 20, &tmp, NULL) ==
725                MBEDTLS_ERR_MPS_READER_OUT_OF_DATA);
726
727    /* Preparation */
728    TEST_ASSERT(mbedtls_mps_reader_reclaim(&rd, NULL) == 0);
729    TEST_ASSERT(mbedtls_mps_reader_feed(&rd, bufB, sizeof(bufB)) == 0);
730
731    switch (option) {
732        case 0: /* Fetch same chunks, commit afterwards, and
733                 * then exceed bounds of new buffer; accumulator
734                 * large enough. */
735
736            /* Consume */
737            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 10, &tmp, &tmp_len) == 0);
738            TEST_MEMORY_COMPARE(tmp, tmp_len, bufA + 80, 10);
739            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 20, &tmp, NULL) == 0);
740            TEST_MEMORY_COMPARE(tmp, 10, bufA + 90, 10);
741            TEST_MEMORY_COMPARE(tmp + 10, 10, bufB, 10);
742            TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
743            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 20, &tmp, NULL) ==
744                        MBEDTLS_ERR_MPS_READER_OUT_OF_DATA);
745
746            /* Prepare */
747            TEST_ASSERT(mbedtls_mps_reader_reclaim(&rd, NULL) == 0);
748            TEST_ASSERT(mbedtls_mps_reader_feed(&rd, bufC, sizeof(bufC)) == 0);;
749
750            /* Consume */
751            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 20, &tmp, NULL) == 0);
752            TEST_MEMORY_COMPARE(tmp, 10, bufB + 10, 10);
753            TEST_MEMORY_COMPARE(tmp + 10, 10, bufC, 10);
754            break;
755
756        case 1: /* Fetch same chunks, commit afterwards, and
757                 * then exceed bounds of new buffer; accumulator
758                 * not large enough. */
759            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 10, &tmp, NULL) == 0);
760            TEST_MEMORY_COMPARE(tmp, 10, bufA + 80, 10);
761            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 20, &tmp, NULL) == 0);
762            TEST_MEMORY_COMPARE(tmp, 10, bufA + 90, 10);
763            TEST_MEMORY_COMPARE(tmp + 10, 10, bufB, 10);
764            TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
765            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 51, &tmp, NULL) ==
766                        MBEDTLS_ERR_MPS_READER_OUT_OF_DATA);
767
768            /* Prepare */
769            TEST_ASSERT(mbedtls_mps_reader_reclaim(&rd, NULL) ==
770                        MBEDTLS_ERR_MPS_READER_ACCUMULATOR_TOO_SMALL);
771            break;
772
773        case 2: /* Fetch same chunks, don't commit afterwards, and
774                 * then exceed bounds of new buffer; accumulator
775                 * large enough. */
776            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 10, &tmp, NULL) == 0);
777            TEST_MEMORY_COMPARE(tmp, 10, bufA + 80, 10);
778            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 20, &tmp, NULL) == 0);
779            TEST_MEMORY_COMPARE(tmp, 10, bufA + 90, 10);
780            TEST_MEMORY_COMPARE(tmp + 10, 10, bufB, 10);
781            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 20, &tmp, NULL) ==
782                        MBEDTLS_ERR_MPS_READER_OUT_OF_DATA);
783
784            /* Prepare */
785            TEST_ASSERT(mbedtls_mps_reader_reclaim(&rd, NULL) == 0);
786            TEST_ASSERT(mbedtls_mps_reader_feed(&rd, bufC, sizeof(bufC)) == 0);;
787
788            /* Consume */
789            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 50, &tmp, NULL) == 0);
790            TEST_MEMORY_COMPARE(tmp, 20, bufA + 80, 20);
791            TEST_MEMORY_COMPARE(tmp + 20, 20, bufB, 20);
792            TEST_MEMORY_COMPARE(tmp + 40, 10, bufC, 10);
793            break;
794
795        case 3: /* Fetch same chunks, don't commit afterwards, and
796                 * then exceed bounds of new buffer; accumulator
797                 * not large enough. */
798            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 10, &tmp, NULL) == 0);
799            TEST_MEMORY_COMPARE(tmp, 10, bufA + 80, 10);
800            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 20, &tmp, NULL) == 0);
801            TEST_MEMORY_COMPARE(tmp, 10, bufA + 90, 10);
802            TEST_MEMORY_COMPARE(tmp + 10, 10, bufB, 10);
803            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 21, &tmp, NULL) ==
804                        MBEDTLS_ERR_MPS_READER_OUT_OF_DATA);
805
806            /* Prepare */
807            TEST_ASSERT(mbedtls_mps_reader_reclaim(&rd, NULL) ==
808                        MBEDTLS_ERR_MPS_READER_ACCUMULATOR_TOO_SMALL);
809            break;
810
811        default:
812            TEST_ASSERT(0);
813            break;
814    }
815
816exit:
817    mbedtls_mps_reader_free(&rd);
818}
819/* END_CASE */
820
821/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER:MBEDTLS_MPS_STATE_VALIDATION */
822void mbedtls_mps_reader_random_usage(int num_out_chunks,
823                                     int max_chunk_size,
824                                     int max_request,
825                                     int acc_size)
826
827{
828    /* Randomly pass a reader object back and forth between lower and
829     * upper layer and let each of them call the respective reader API
830     * functions in a random fashion.
831     *
832     * On the lower layer, we're tracking and concatenating
833     * the data passed to successful feed calls.
834     *
835     * For the upper layer, we track and concatenate buffers
836     * obtained from successful get calls.
837     *
838     * As long as the lower layer calls reclaim at least once, (resetting the
839     * fetched but not-yet-committed data), this should always lead to the same
840     * stream of outgoing/incoming data for the lower/upper layers, even if
841     * most of the random calls fail.
842     *
843     * NOTE: This test uses rand() for random data, which is not optimal.
844     *       Instead, it would be better to get the random data from a
845     *       static buffer. This both eases reproducibility and allows
846     *       simple conversion to a fuzz target.
847     */
848    int ret;
849    unsigned char *acc = NULL;
850    unsigned char *outgoing = NULL, *incoming = NULL;
851    unsigned char *cur_chunk = NULL;
852    size_t cur_out_chunk, out_pos, in_commit, in_fetch;
853    int rand_op;  /* Lower layer:
854                   * - Reclaim (0)
855                   * - Feed (1)
856                   * Upper layer:
857                   * - Get, do tolerate smaller output (0)
858                   * - Get, don't tolerate smaller output (1)
859                   * - Commit (2) */
860    int mode = 0; /* Lower layer (0) or Upper layer (1) */
861    int reclaimed = 1; /* Have to call reclaim at least once before
862                        * returning the reader to the upper layer. */
863    mbedtls_mps_reader rd;
864
865    if (acc_size > 0) {
866        TEST_CALLOC(acc, acc_size);
867    }
868
869    /* This probably needs to be changed because we want
870     * our tests to be deterministic. */
871    //    srand( time( NULL ) );
872
873    TEST_CALLOC(outgoing, num_out_chunks * max_chunk_size);
874    TEST_CALLOC(incoming, num_out_chunks * max_chunk_size);
875
876    mbedtls_mps_reader_init(&rd, acc, acc_size);
877
878    cur_out_chunk = 0;
879    in_commit = 0;
880    in_fetch = 0;
881    out_pos = 0;
882    while (cur_out_chunk < (unsigned) num_out_chunks) {
883        if (mode == 0) {
884            /* Choose randomly between reclaim and feed */
885            rand_op = rand() % 2;
886
887            if (rand_op == 0) {
888                /* Reclaim */
889                ret = mbedtls_mps_reader_reclaim(&rd, NULL);
890
891                if (ret == 0) {
892                    TEST_ASSERT(cur_chunk != NULL);
893                    mbedtls_free(cur_chunk);
894                    cur_chunk = NULL;
895                }
896                reclaimed = 1;
897            } else {
898                /* Feed reader with a random chunk */
899                unsigned char *tmp = NULL;
900                size_t tmp_size;
901                if (cur_out_chunk == (unsigned) num_out_chunks) {
902                    continue;
903                }
904
905                tmp_size = (rand() % max_chunk_size) + 1;
906                TEST_CALLOC(tmp, tmp_size);
907
908                TEST_ASSERT(mbedtls_test_rnd_std_rand(NULL, tmp, tmp_size) == 0);
909                ret = mbedtls_mps_reader_feed(&rd, tmp, tmp_size);
910
911                if (ret == 0 || ret == MBEDTLS_ERR_MPS_READER_NEED_MORE) {
912                    cur_out_chunk++;
913                    memcpy(outgoing + out_pos, tmp, tmp_size);
914                    out_pos += tmp_size;
915                }
916
917                if (ret == 0) {
918                    TEST_ASSERT(cur_chunk == NULL);
919                    cur_chunk = tmp;
920                } else {
921                    mbedtls_free(tmp);
922                }
923
924            }
925
926            /* Randomly switch to consumption mode if reclaim
927             * was called at least once. */
928            if (reclaimed == 1 && rand() % 3 == 0) {
929                in_fetch = 0;
930                mode = 1;
931            }
932        } else {
933            /* Choose randomly between get tolerating fewer data,
934             * get not tolerating fewer data, and commit. */
935            rand_op = rand() % 3;
936            if (rand_op == 0 || rand_op == 1) {
937                mbedtls_mps_size_t get_size, real_size;
938                unsigned char *chunk_get;
939                get_size = (rand() % max_request) + 1;
940                if (rand_op == 0) {
941                    ret = mbedtls_mps_reader_get(&rd, get_size, &chunk_get,
942                                                 &real_size);
943                } else {
944                    real_size = get_size;
945                    ret = mbedtls_mps_reader_get(&rd, get_size, &chunk_get, NULL);
946                }
947
948                /* Check if output is in accordance with what was written */
949                if (ret == 0) {
950                    memcpy(incoming + in_commit + in_fetch,
951                           chunk_get, real_size);
952                    TEST_ASSERT(memcmp(incoming + in_commit + in_fetch,
953                                       outgoing + in_commit + in_fetch,
954                                       real_size) == 0);
955                    in_fetch += real_size;
956                }
957            } else if (rand_op == 2) { /* Commit */
958                ret = mbedtls_mps_reader_commit(&rd);
959                if (ret == 0) {
960                    in_commit += in_fetch;
961                    in_fetch = 0;
962                }
963            }
964
965            /* Randomly switch back to preparation */
966            if (rand() % 3 == 0) {
967                reclaimed = 0;
968                mode = 0;
969            }
970        }
971    }
972
973exit:
974    /* Cleanup */
975    mbedtls_mps_reader_free(&rd);
976    mbedtls_free(incoming);
977    mbedtls_free(outgoing);
978    mbedtls_free(acc);
979    mbedtls_free(cur_chunk);
980}
981/* END_CASE */
982
983/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER */
984void mbedtls_reader_inconsistent_usage(int option)
985{
986    /* This test exercises the behaviour of the MPS reader
987     * in the following situation:
988     * - The consumer asks for more data than what's available
989     * - The reader is paused and receives more data from the
990     *   producer until the original read request can be fulfilled.
991     * - The consumer does not repeat the original request but
992     *   requests data in a different way.
993     *
994     * The reader does not guarantee that inconsistent read requests
995     * after pausing will succeed, and this test triggers some cases
996     * where the request fails.
997     */
998
999    unsigned char bufA[100], bufB[100];
1000    unsigned char *tmp;
1001    unsigned char acc[40];
1002    mbedtls_mps_reader rd;
1003    int success = 0;
1004    for (size_t i = 0; (unsigned) i < sizeof(bufA); i++) {
1005        bufA[i] = (unsigned char) i;
1006    }
1007    for (size_t i = 0; (unsigned) i < sizeof(bufB); i++) {
1008        bufB[i] = ~((unsigned char) i);
1009    }
1010
1011    /* Preparation (lower layer) */
1012    mbedtls_mps_reader_init(&rd, acc, sizeof(acc));
1013    TEST_ASSERT(mbedtls_mps_reader_feed(&rd, bufA, sizeof(bufA)) == 0);
1014    /* Consumption (upper layer) */
1015    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 80, &tmp, NULL) == 0);
1016    TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
1017    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 10, &tmp, NULL) == 0);
1018    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 20, &tmp, NULL) ==
1019                MBEDTLS_ERR_MPS_READER_OUT_OF_DATA);
1020    /* Preparation */
1021    TEST_ASSERT(mbedtls_mps_reader_reclaim(&rd, NULL) == 0);
1022    TEST_ASSERT(mbedtls_mps_reader_feed(&rd, bufB, sizeof(bufB)) == 0);
1023    /* Consumption */
1024    switch (option) {
1025        case 0:
1026            /* Ask for buffered data in a single chunk, no commit */
1027            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 30, &tmp, NULL) == 0);
1028            TEST_MEMORY_COMPARE(tmp, 20, bufA + 80, 20);
1029            TEST_MEMORY_COMPARE(tmp + 20, 10, bufB, 10);
1030            success = 1;
1031            break;
1032
1033        case 1:
1034            /* Ask for buffered data in a single chunk, with commit */
1035            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 30, &tmp, NULL) == 0);
1036            TEST_MEMORY_COMPARE(tmp, 20, bufA + 80, 20);
1037            TEST_MEMORY_COMPARE(tmp + 20, 10, bufB, 10);
1038            TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
1039            success = 1;
1040            break;
1041
1042        case 2:
1043            /* Ask for more than was requested when pausing, #1 */
1044            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 31, &tmp, NULL) ==
1045                        MBEDTLS_ERR_MPS_READER_INCONSISTENT_REQUESTS);
1046            break;
1047
1048        case 3:
1049            /* Ask for more than was requested when pausing #2 */
1050            TEST_ASSERT(mbedtls_mps_reader_get(&rd, (mbedtls_mps_size_t) -1, &tmp, NULL) ==
1051                        MBEDTLS_ERR_MPS_READER_INCONSISTENT_REQUESTS);
1052            break;
1053
1054        case 4:
1055            /* Asking for buffered data in different
1056             * chunks than before CAN fail. */
1057            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 15, &tmp, NULL) == 0);
1058            TEST_MEMORY_COMPARE(tmp, 15, bufA + 80, 15);
1059            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 10, &tmp, NULL) ==
1060                        MBEDTLS_ERR_MPS_READER_INCONSISTENT_REQUESTS);
1061            break;
1062
1063        case 5:
1064            /* Asking for buffered data different chunks
1065             * than before NEED NOT fail - no commits */
1066            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 15, &tmp, NULL) == 0);
1067            TEST_MEMORY_COMPARE(tmp, 15, bufA + 80, 15);
1068            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 15, &tmp, NULL) == 0);
1069            TEST_MEMORY_COMPARE(tmp, 5, bufA + 95, 5);
1070            TEST_MEMORY_COMPARE(tmp + 5, 10, bufB, 10);
1071            success = 1;
1072            break;
1073
1074        case 6:
1075            /* Asking for buffered data different chunks
1076             * than before NEED NOT fail - intermediate commit */
1077            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 15, &tmp, NULL) == 0);
1078            TEST_MEMORY_COMPARE(tmp, 15, bufA + 80, 15);
1079            TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
1080            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 15, &tmp, NULL) == 0);
1081            TEST_MEMORY_COMPARE(tmp, 5, bufA + 95, 5);
1082            TEST_MEMORY_COMPARE(tmp + 5, 10, bufB, 10);
1083            success = 1;
1084            break;
1085
1086        case 7:
1087            /* Asking for buffered data different chunks
1088             * than before NEED NOT fail - end commit */
1089            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 15, &tmp, NULL) == 0);
1090            TEST_MEMORY_COMPARE(tmp, 15, bufA + 80, 15);
1091            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 15, &tmp, NULL) == 0);
1092            TEST_MEMORY_COMPARE(tmp, 5, bufA + 95, 5);
1093            TEST_MEMORY_COMPARE(tmp + 5, 10, bufB, 10);
1094            TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
1095            success = 1;
1096            break;
1097
1098        case 8:
1099            /* Asking for buffered data different chunks
1100             * than before NEED NOT fail - intermediate & end commit */
1101            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 15, &tmp, NULL) == 0);
1102            TEST_MEMORY_COMPARE(tmp, 15, bufA + 80, 15);
1103            TEST_ASSERT(mbedtls_mps_reader_get(&rd, 15, &tmp, NULL) == 0);
1104            TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
1105            TEST_MEMORY_COMPARE(tmp, 5, bufA + 95, 5);
1106            TEST_MEMORY_COMPARE(tmp + 5, 10, bufB, 10);
1107            TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
1108            success = 1;
1109            break;
1110
1111        default:
1112            TEST_ASSERT(0);
1113            break;
1114    }
1115
1116    if (success == 1) {
1117        /* In all succeeding cases, fetch the rest of the second buffer. */
1118        TEST_ASSERT(mbedtls_mps_reader_get(&rd, 90, &tmp, NULL) == 0);
1119        TEST_MEMORY_COMPARE(tmp, 90, bufB + 10, 90);
1120        TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
1121
1122        /* Wrapup */
1123        TEST_ASSERT(mbedtls_mps_reader_reclaim(&rd, NULL) == 0);
1124    }
1125
1126exit:
1127    /* Wrapup */
1128    mbedtls_mps_reader_free(&rd);
1129}
1130/* END_CASE */
1131
1132/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER */
1133void mbedtls_mps_reader_feed_empty()
1134{
1135    /* This test exercises the behaviour of the reader when it is
1136     * fed with a NULL buffer. */
1137    unsigned char buf[100];
1138    unsigned char *tmp;
1139    mbedtls_mps_reader rd;
1140    for (size_t i = 0; (unsigned) i < sizeof(buf); i++) {
1141        buf[i] = (unsigned char) i;
1142    }
1143
1144    /* Preparation (lower layer) */
1145    mbedtls_mps_reader_init(&rd, NULL, 0);
1146
1147    TEST_ASSERT(mbedtls_mps_reader_feed(&rd, NULL, sizeof(buf)) ==
1148                MBEDTLS_ERR_MPS_READER_INVALID_ARG);
1149
1150    /* Subsequent feed-calls should still succeed. */
1151    TEST_ASSERT(mbedtls_mps_reader_feed(&rd, buf, sizeof(buf)) == 0);
1152
1153    /* Consumption (upper layer) */
1154    TEST_ASSERT(mbedtls_mps_reader_get(&rd, 100, &tmp, NULL) == 0);
1155    TEST_MEMORY_COMPARE(tmp, 100, buf, 100);
1156    TEST_ASSERT(mbedtls_mps_reader_commit(&rd) == 0);
1157
1158    /* Wrapup */
1159    TEST_ASSERT(mbedtls_mps_reader_reclaim(&rd, NULL) == 0);
1160
1161exit:
1162    mbedtls_mps_reader_free(&rd);
1163}
1164/* END_CASE */
1165