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