1/* BEGIN_HEADER */
2#include "mbedtls/bignum.h"
3#include "mbedtls/entropy.h"
4#include "bignum_core.h"
5#include "constant_time_internal.h"
6#include "test/constant_flow.h"
7
8/** Verifies mbedtls_mpi_core_add().
9 *
10 * \param[in] A       Little-endian presentation of the left operand.
11 * \param[in] B       Little-endian presentation of the right operand.
12 * \param limbs       Number of limbs in each MPI (\p A, \p B, \p S and \p X).
13 * \param[in] S       Little-endian presentation of the expected sum.
14 * \param carry       Expected carry from the addition.
15 * \param[in,out] X   Temporary storage to be used for results.
16 *
17 * \return  1 if mbedtls_mpi_core_add() passes this test, otherwise 0.
18 */
19static int mpi_core_verify_add(mbedtls_mpi_uint *A,
20                               mbedtls_mpi_uint *B,
21                               size_t limbs,
22                               mbedtls_mpi_uint *S,
23                               int carry,
24                               mbedtls_mpi_uint *X)
25{
26    int ret = 0;
27
28    size_t bytes = limbs * sizeof(*A);
29
30    /* The test cases have A <= B to avoid repetition, so we test A + B then,
31     * if A != B, B + A. If A == B, we can test when A and B are aliased */
32
33    /* A + B */
34
35    /* A + B => correct result and carry */
36    TEST_EQUAL(carry, mbedtls_mpi_core_add(X, A, B, limbs));
37    TEST_MEMORY_COMPARE(X, bytes, S, bytes);
38
39    /* A + B; alias output and first operand => correct result and carry */
40    memcpy(X, A, bytes);
41    TEST_EQUAL(carry, mbedtls_mpi_core_add(X, X, B, limbs));
42    TEST_MEMORY_COMPARE(X, bytes, S, bytes);
43
44    /* A + B; alias output and second operand => correct result and carry */
45    memcpy(X, B, bytes);
46    TEST_EQUAL(carry, mbedtls_mpi_core_add(X, A, X, limbs));
47    TEST_MEMORY_COMPARE(X, bytes, S, bytes);
48
49    if (memcmp(A, B, bytes) == 0) {
50        /* A == B, so test where A and B are aliased */
51
52        /* A + A => correct result and carry */
53        TEST_EQUAL(carry, mbedtls_mpi_core_add(X, A, A, limbs));
54        TEST_MEMORY_COMPARE(X, bytes, S, bytes);
55
56        /* A + A, output aliased to both operands => correct result and carry */
57        memcpy(X, A, bytes);
58        TEST_EQUAL(carry, mbedtls_mpi_core_add(X, X, X, limbs));
59        TEST_MEMORY_COMPARE(X, bytes, S, bytes);
60    } else {
61        /* A != B, so test B + A */
62
63        /* B + A => correct result and carry */
64        TEST_EQUAL(carry, mbedtls_mpi_core_add(X, B, A, limbs));
65        TEST_MEMORY_COMPARE(X, bytes, S, bytes);
66
67        /* B + A; alias output and first operand => correct result and carry */
68        memcpy(X, B, bytes);
69        TEST_EQUAL(carry, mbedtls_mpi_core_add(X, X, A, limbs));
70        TEST_MEMORY_COMPARE(X, bytes, S, bytes);
71
72        /* B + A; alias output and second operand => correct result and carry */
73        memcpy(X, A, bytes);
74        TEST_EQUAL(carry, mbedtls_mpi_core_add(X, B, X, limbs));
75        TEST_MEMORY_COMPARE(X, bytes, S, bytes);
76    }
77
78    ret = 1;
79
80exit:
81    return ret;
82}
83
84/** Verifies mbedtls_mpi_core_add_if().
85 *
86 * \param[in] A       Little-endian presentation of the left operand.
87 * \param[in] B       Little-endian presentation of the right operand.
88 * \param limbs       Number of limbs in each MPI (\p A, \p B, \p S and \p X).
89 * \param[in] S       Little-endian presentation of the expected sum.
90 * \param carry       Expected carry from the addition.
91 * \param[in,out] X   Temporary storage to be used for results.
92 *
93 * \return  1 if mbedtls_mpi_core_add_if() passes this test, otherwise 0.
94 */
95static int mpi_core_verify_add_if(mbedtls_mpi_uint *A,
96                                  mbedtls_mpi_uint *B,
97                                  size_t limbs,
98                                  mbedtls_mpi_uint *S,
99                                  int carry,
100                                  mbedtls_mpi_uint *X)
101{
102    int ret = 0;
103
104    size_t bytes = limbs * sizeof(*A);
105
106    /* The test cases have A <= B to avoid repetition, so we test A + B then,
107     * if A != B, B + A. If A == B, we can test when A and B are aliased */
108
109    /* A + B */
110
111    /* cond = 0 => X unchanged, no carry */
112    memcpy(X, A, bytes);
113    TEST_EQUAL(0, mbedtls_mpi_core_add_if(X, B, limbs, 0));
114    TEST_MEMORY_COMPARE(X, bytes, A, bytes);
115
116    /* cond = 1 => correct result and carry */
117    TEST_EQUAL(carry, mbedtls_mpi_core_add_if(X, B, limbs, 1));
118    TEST_MEMORY_COMPARE(X, bytes, S, bytes);
119
120    if (memcmp(A, B, bytes) == 0) {
121        /* A == B, so test where A and B are aliased */
122
123        /* cond = 0 => X unchanged, no carry */
124        memcpy(X, B, bytes);
125        TEST_EQUAL(0, mbedtls_mpi_core_add_if(X, X, limbs, 0));
126        TEST_MEMORY_COMPARE(X, bytes, B, bytes);
127
128        /* cond = 1 => correct result and carry */
129        TEST_EQUAL(carry, mbedtls_mpi_core_add_if(X, X, limbs, 1));
130        TEST_MEMORY_COMPARE(X, bytes, S, bytes);
131    } else {
132        /* A != B, so test B + A */
133
134        /* cond = 0 => d unchanged, no carry */
135        memcpy(X, B, bytes);
136        TEST_EQUAL(0, mbedtls_mpi_core_add_if(X, A, limbs, 0));
137        TEST_MEMORY_COMPARE(X, bytes, B, bytes);
138
139        /* cond = 1 => correct result and carry */
140        TEST_EQUAL(carry, mbedtls_mpi_core_add_if(X, A, limbs, 1));
141        TEST_MEMORY_COMPARE(X, bytes, S, bytes);
142    }
143
144    ret = 1;
145
146exit:
147    return ret;
148}
149
150/* END_HEADER */
151
152/* BEGIN_DEPENDENCIES
153 * depends_on:MBEDTLS_BIGNUM_C
154 * END_DEPENDENCIES
155 */
156
157/* BEGIN_CASE */
158void mpi_core_io_null()
159{
160    mbedtls_mpi_uint X = 0;
161    int ret;
162
163    ret = mbedtls_mpi_core_read_be(&X, 1, NULL, 0);
164    TEST_EQUAL(ret, 0);
165    ret = mbedtls_mpi_core_write_be(&X, 1, NULL, 0);
166    TEST_EQUAL(ret, 0);
167
168    ret = mbedtls_mpi_core_read_be(NULL, 0, NULL, 0);
169    TEST_EQUAL(ret, 0);
170    ret = mbedtls_mpi_core_write_be(NULL, 0, NULL, 0);
171    TEST_EQUAL(ret, 0);
172
173    ret = mbedtls_mpi_core_read_le(&X, 1, NULL, 0);
174    TEST_EQUAL(ret, 0);
175    ret = mbedtls_mpi_core_write_le(&X, 1, NULL, 0);
176    TEST_EQUAL(ret, 0);
177
178    ret = mbedtls_mpi_core_read_le(NULL, 0, NULL, 0);
179    TEST_EQUAL(ret, 0);
180    ret = mbedtls_mpi_core_write_le(NULL, 0, NULL, 0);
181    TEST_EQUAL(ret, 0);
182
183exit:
184    ;
185}
186/* END_CASE */
187
188/* BEGIN_CASE */
189void mpi_core_io_be(data_t *input, int nb_int, int nx_32_int, int iret,
190                    int oret)
191{
192    if (iret != 0) {
193        TEST_ASSERT(oret == 0);
194    }
195
196    TEST_LE_S(0, nb_int);
197    size_t nb = nb_int;
198
199    unsigned char buf[1024];
200    TEST_LE_U(nb, sizeof(buf));
201
202    /* nx_32_int is the number of 32 bit limbs, if we have 64 bit limbs we need
203     * to halve the number of limbs to have the same size. */
204    size_t nx;
205    TEST_LE_S(0, nx_32_int);
206    if (sizeof(mbedtls_mpi_uint) == 8) {
207        nx = nx_32_int / 2 + nx_32_int % 2;
208    } else {
209        nx = nx_32_int;
210    }
211
212    mbedtls_mpi_uint X[sizeof(buf) / sizeof(mbedtls_mpi_uint)];
213    TEST_LE_U(nx, sizeof(X) / sizeof(X[0]));
214
215    int ret = mbedtls_mpi_core_read_be(X, nx, input->x, input->len);
216    TEST_EQUAL(ret, iret);
217
218    if (iret == 0) {
219        ret =  mbedtls_mpi_core_write_be(X, nx, buf, nb);
220        TEST_EQUAL(ret, oret);
221    }
222
223    if ((iret == 0) && (oret == 0)) {
224        if (nb > input->len) {
225            size_t leading_zeroes = nb - input->len;
226            TEST_ASSERT(memcmp(buf + nb - input->len, input->x, input->len) == 0);
227            for (size_t i = 0; i < leading_zeroes; i++) {
228                TEST_EQUAL(buf[i], 0);
229            }
230        } else {
231            size_t leading_zeroes = input->len - nb;
232            TEST_ASSERT(memcmp(input->x + input->len - nb, buf, nb) == 0);
233            for (size_t i = 0; i < leading_zeroes; i++) {
234                TEST_EQUAL(input->x[i], 0);
235            }
236        }
237    }
238
239exit:
240    ;
241}
242/* END_CASE */
243
244/* BEGIN_CASE */
245void mpi_core_io_le(data_t *input, int nb_int, int nx_32_int, int iret,
246                    int oret)
247{
248    if (iret != 0) {
249        TEST_ASSERT(oret == 0);
250    }
251
252    TEST_LE_S(0, nb_int);
253    size_t nb = nb_int;
254
255    unsigned char buf[1024];
256    TEST_LE_U(nb, sizeof(buf));
257
258    /* nx_32_int is the number of 32 bit limbs, if we have 64 bit limbs we need
259     * to halve the number of limbs to have the same size. */
260    size_t nx;
261    TEST_LE_S(0, nx_32_int);
262    if (sizeof(mbedtls_mpi_uint) == 8) {
263        nx = nx_32_int / 2 + nx_32_int % 2;
264    } else {
265        nx = nx_32_int;
266    }
267
268    mbedtls_mpi_uint X[sizeof(buf) / sizeof(mbedtls_mpi_uint)];
269    TEST_LE_U(nx, sizeof(X) / sizeof(X[0]));
270
271    int ret =  mbedtls_mpi_core_read_le(X, nx, input->x, input->len);
272    TEST_EQUAL(ret, iret);
273
274    if (iret == 0) {
275        ret =  mbedtls_mpi_core_write_le(X, nx, buf, nb);
276        TEST_EQUAL(ret, oret);
277    }
278
279    if ((iret == 0) && (oret == 0)) {
280        if (nb > input->len) {
281            TEST_ASSERT(memcmp(buf, input->x, input->len) == 0);
282            for (size_t i = input->len; i < nb; i++) {
283                TEST_EQUAL(buf[i], 0);
284            }
285        } else {
286            TEST_ASSERT(memcmp(input->x, buf, nb) == 0);
287            for (size_t i = nb; i < input->len; i++) {
288                TEST_EQUAL(input->x[i], 0);
289            }
290        }
291    }
292
293exit:
294    ;
295}
296/* END_CASE */
297
298/* BEGIN_CASE */
299void mpi_core_bitlen(char *input_X, int nr_bits)
300{
301    mbedtls_mpi_uint *X = NULL;
302    size_t limbs;
303
304    TEST_EQUAL(mbedtls_test_read_mpi_core(&X, &limbs, input_X), 0);
305    TEST_EQUAL(mbedtls_mpi_core_bitlen(X, limbs), nr_bits);
306
307exit:
308    mbedtls_free(X);
309}
310/* END_CASE */
311
312
313/* BEGIN_CASE */
314void mpi_core_clz(int leading_zeros, int trailing_zeros)
315{
316    if ((size_t) (leading_zeros + trailing_zeros) >= (sizeof(mbedtls_mpi_uint) * 8)) {
317        // can't fit required number of leading and trailing zeros - skip test
318        goto exit;
319    }
320
321    // Construct a test input value where the count of leading zeros and
322    // trailing zeros is given in the test case, and we add ones to fill
323    // the gap.
324    mbedtls_mpi_uint x;
325    if ((leading_zeros + trailing_zeros) > 0) {
326        // some zero bits
327        uint32_t s = (sizeof(mbedtls_mpi_uint) * 8 - leading_zeros - trailing_zeros);
328        x = ((((mbedtls_mpi_uint) 1) << s) - 1) << trailing_zeros;
329    } else {
330        // all bits set
331        x = ~((mbedtls_mpi_uint) 0);
332    }
333
334    size_t n = mbedtls_mpi_core_clz(x);
335    TEST_EQUAL(n, leading_zeros);
336exit:
337    ;
338}
339/* END_CASE */
340
341
342/* BEGIN_CASE */
343void mpi_core_lt_ct(char *input_X, char *input_Y, int exp_ret)
344{
345    mbedtls_mpi_uint *X = NULL;
346    size_t X_limbs;
347    mbedtls_mpi_uint *Y = NULL;
348    size_t Y_limbs;
349    int ret;
350
351    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&X, &X_limbs, input_X));
352    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&Y, &Y_limbs, input_Y));
353
354    /* We need two same-length limb arrays */
355    TEST_EQUAL(X_limbs, Y_limbs);
356
357    TEST_CF_SECRET(X, X_limbs * sizeof(mbedtls_mpi_uint));
358    TEST_CF_SECRET(Y, X_limbs * sizeof(mbedtls_mpi_uint));
359
360    ret = mbedtls_mpi_core_lt_ct(X, Y, X_limbs);
361    TEST_EQUAL(!!ret, exp_ret);
362
363exit:
364    mbedtls_free(X);
365    mbedtls_free(Y);
366}
367/* END_CASE */
368
369/* BEGIN_CASE */
370void mpi_core_uint_le_mpi(char *input_A)
371{
372    mbedtls_mpi_uint *A = NULL;
373    size_t A_limbs = 0;
374
375    TEST_EQUAL(mbedtls_test_read_mpi_core(&A, &A_limbs, input_A), 0);
376
377    int is_large = 0; /* nonzero limbs beyond the lowest-order one? */
378    for (size_t i = 1; i < A_limbs; i++) {
379        if (A[i] != 0) {
380            is_large = 1;
381            break;
382        }
383    }
384
385    TEST_CF_SECRET(A, A_limbs * sizeof(*A));
386
387    TEST_EQUAL(!!mbedtls_mpi_core_uint_le_mpi(0, A, A_limbs), 1);
388    TEST_EQUAL(!!mbedtls_mpi_core_uint_le_mpi(A[0], A, A_limbs), 1);
389
390    if (is_large) {
391        TEST_EQUAL(!!mbedtls_mpi_core_uint_le_mpi(A[0] + 1,
392                                                  A, A_limbs), 1);
393        TEST_EQUAL(!!mbedtls_mpi_core_uint_le_mpi((mbedtls_mpi_uint) (-1) >> 1,
394                                                  A, A_limbs), 1);
395        TEST_EQUAL(!!mbedtls_mpi_core_uint_le_mpi((mbedtls_mpi_uint) (-1),
396                                                  A, A_limbs), 1);
397    } else {
398        TEST_EQUAL(!!mbedtls_mpi_core_uint_le_mpi(A[0] + 1,
399                                                  A, A_limbs),
400                   A[0] + 1 <= A[0]);
401        TEST_EQUAL(!!mbedtls_mpi_core_uint_le_mpi((mbedtls_mpi_uint) (-1) >> 1,
402                                                  A, A_limbs),
403                   (mbedtls_mpi_uint) (-1) >> 1 <= A[0]);
404        TEST_EQUAL(!!mbedtls_mpi_core_uint_le_mpi((mbedtls_mpi_uint) (-1),
405                                                  A, A_limbs),
406                   (mbedtls_mpi_uint) (-1) <= A[0]);
407    }
408
409exit:
410    mbedtls_free(A);
411}
412/* END_CASE */
413
414/* BEGIN_CASE */
415void mpi_core_cond_assign(char *input_X,
416                          char *input_Y,
417                          int input_bytes)
418{
419    mbedtls_mpi_uint *X = NULL;
420    mbedtls_mpi_uint *Y = NULL;
421    size_t limbs_X;
422    size_t limbs_Y;
423
424    TEST_EQUAL(mbedtls_test_read_mpi_core(&X, &limbs_X, input_X), 0);
425    TEST_EQUAL(mbedtls_test_read_mpi_core(&Y, &limbs_Y, input_Y), 0);
426
427    size_t limbs = limbs_X;
428    size_t copy_limbs = CHARS_TO_LIMBS(input_bytes);
429    size_t bytes = limbs * sizeof(mbedtls_mpi_uint);
430    size_t copy_bytes = copy_limbs * sizeof(mbedtls_mpi_uint);
431
432    TEST_EQUAL(limbs_X, limbs_Y);
433    TEST_ASSERT(copy_limbs <= limbs);
434
435    /* condition is false */
436    TEST_CF_SECRET(X, bytes);
437    TEST_CF_SECRET(Y, bytes);
438
439    mbedtls_mpi_core_cond_assign(X, Y, copy_limbs, 0);
440
441    TEST_CF_PUBLIC(X, bytes);
442    TEST_CF_PUBLIC(Y, bytes);
443
444    TEST_ASSERT(memcmp(X, Y, bytes) != 0);
445
446    /* condition is true */
447    TEST_CF_SECRET(X, bytes);
448    TEST_CF_SECRET(Y, bytes);
449
450    mbedtls_mpi_core_cond_assign(X, Y, copy_limbs, mbedtls_ct_bool(1));
451
452    TEST_CF_PUBLIC(X, bytes);
453    TEST_CF_PUBLIC(Y, bytes);
454
455    /* Check if the given length is copied even it is smaller
456       than the length of the given MPIs. */
457    if (copy_limbs < limbs) {
458        TEST_CF_PUBLIC(X, bytes);
459        TEST_CF_PUBLIC(Y, bytes);
460
461        TEST_MEMORY_COMPARE(X, copy_bytes, Y, copy_bytes);
462        TEST_ASSERT(memcmp(X, Y, bytes) != 0);
463    } else {
464        TEST_MEMORY_COMPARE(X, bytes, Y, bytes);
465    }
466
467exit:
468    mbedtls_free(X);
469    mbedtls_free(Y);
470}
471/* END_CASE */
472
473/* BEGIN_CASE */
474void mpi_core_cond_swap(char *input_X,
475                        char *input_Y,
476                        int input_bytes)
477{
478    mbedtls_mpi_uint *tmp_X = NULL;
479    mbedtls_mpi_uint *tmp_Y = NULL;
480    mbedtls_mpi_uint *X = NULL;
481    mbedtls_mpi_uint *Y = NULL;
482    size_t limbs_X;
483    size_t limbs_Y;
484
485    TEST_EQUAL(mbedtls_test_read_mpi_core(&tmp_X, &limbs_X, input_X), 0);
486    TEST_EQUAL(mbedtls_test_read_mpi_core(&tmp_Y, &limbs_Y, input_Y), 0);
487
488    size_t limbs = limbs_X;
489    size_t copy_limbs = CHARS_TO_LIMBS(input_bytes);
490    size_t bytes = limbs * sizeof(mbedtls_mpi_uint);
491    size_t copy_bytes = copy_limbs * sizeof(mbedtls_mpi_uint);
492
493    TEST_EQUAL(limbs_X, limbs_Y);
494    TEST_ASSERT(copy_limbs <= limbs);
495
496    TEST_CALLOC(X, limbs);
497    memcpy(X, tmp_X, bytes);
498
499    TEST_CALLOC(Y, limbs);
500    memcpy(Y, tmp_Y, bytes);
501
502    /* condition is false */
503    TEST_CF_SECRET(X, bytes);
504    TEST_CF_SECRET(Y, bytes);
505
506    mbedtls_mpi_core_cond_swap(X, Y, copy_limbs, 0);
507
508    TEST_CF_PUBLIC(X, bytes);
509    TEST_CF_PUBLIC(Y, bytes);
510
511    TEST_MEMORY_COMPARE(X, bytes, tmp_X, bytes);
512    TEST_MEMORY_COMPARE(Y, bytes, tmp_Y, bytes);
513
514    /* condition is true */
515    TEST_CF_SECRET(X, bytes);
516    TEST_CF_SECRET(Y, bytes);
517
518    mbedtls_mpi_core_cond_swap(X, Y, copy_limbs, mbedtls_ct_bool(1));
519
520    TEST_CF_PUBLIC(X, bytes);
521    TEST_CF_PUBLIC(Y, bytes);
522
523    /* Check if the given length is copied even it is smaller
524       than the length of the given MPIs. */
525    if (copy_limbs < limbs) {
526        TEST_MEMORY_COMPARE(X, copy_bytes, tmp_Y, copy_bytes);
527        TEST_MEMORY_COMPARE(Y, copy_bytes, tmp_X, copy_bytes);
528        TEST_ASSERT(memcmp(X, tmp_X, bytes) != 0);
529        TEST_ASSERT(memcmp(X, tmp_Y, bytes) != 0);
530        TEST_ASSERT(memcmp(Y, tmp_X, bytes) != 0);
531        TEST_ASSERT(memcmp(Y, tmp_Y, bytes) != 0);
532    } else {
533        TEST_MEMORY_COMPARE(X, bytes, tmp_Y, bytes);
534        TEST_MEMORY_COMPARE(Y, bytes, tmp_X, bytes);
535    }
536
537exit:
538    mbedtls_free(tmp_X);
539    mbedtls_free(tmp_Y);
540    mbedtls_free(X);
541    mbedtls_free(Y);
542}
543/* END_CASE */
544
545/* BEGIN_CASE */
546void mpi_core_shift_r(char *input, int count, char *result)
547{
548    mbedtls_mpi_uint *X = NULL;
549    mbedtls_mpi_uint *Y = NULL;
550    size_t limbs, n;
551
552    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&X, &limbs, input));
553    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&Y, &n, result));
554    TEST_EQUAL(limbs, n);
555
556    mbedtls_mpi_core_shift_r(X, limbs, count);
557    TEST_MEMORY_COMPARE(X, limbs * ciL, Y, limbs * ciL);
558
559exit:
560    mbedtls_free(X);
561    mbedtls_free(Y);
562}
563/* END_CASE */
564
565/* BEGIN_CASE */
566void mpi_core_shift_l(char *input, int count, char *result)
567{
568    mbedtls_mpi_uint *X = NULL;
569    mbedtls_mpi_uint *Y = NULL;
570    size_t limbs, n;
571
572    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&X, &limbs, input));
573    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&Y, &n, result));
574    TEST_EQUAL(limbs, n);
575
576    mbedtls_mpi_core_shift_l(X, limbs, count);
577    TEST_MEMORY_COMPARE(X, limbs * ciL, Y, limbs * ciL);
578
579exit:
580    mbedtls_free(X);
581    mbedtls_free(Y);
582}
583/* END_CASE */
584
585/* BEGIN_CASE */
586void mpi_core_add_and_add_if(char *input_A, char *input_B,
587                             char *input_S, int carry)
588{
589    mbedtls_mpi_uint *A = NULL; /* first value to add */
590    mbedtls_mpi_uint *B = NULL; /* second value to add */
591    mbedtls_mpi_uint *S = NULL; /* expected result */
592    mbedtls_mpi_uint *X = NULL; /* destination - the in/out first operand */
593    size_t A_limbs, B_limbs, S_limbs;
594
595    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&A, &A_limbs, input_A));
596    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&B, &B_limbs, input_B));
597    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&S, &S_limbs, input_S));
598
599    /* add and add_if expect all operands to be the same length */
600    TEST_EQUAL(A_limbs, B_limbs);
601    TEST_EQUAL(A_limbs, S_limbs);
602
603    size_t limbs = A_limbs;
604    TEST_CALLOC(X, limbs);
605
606    TEST_ASSERT(mpi_core_verify_add(A, B, limbs, S, carry, X));
607    TEST_ASSERT(mpi_core_verify_add_if(A, B, limbs, S, carry, X));
608
609exit:
610    mbedtls_free(A);
611    mbedtls_free(B);
612    mbedtls_free(S);
613    mbedtls_free(X);
614}
615/* END_CASE */
616
617/* BEGIN_CASE */
618void mpi_core_sub(char *input_A, char *input_B,
619                  char *input_X, int carry)
620{
621    mbedtls_mpi A, B, X;
622    mbedtls_mpi_uint *a = NULL;
623    mbedtls_mpi_uint *b = NULL;
624    mbedtls_mpi_uint *x = NULL; /* expected */
625    mbedtls_mpi_uint *r = NULL; /* result */
626
627    mbedtls_mpi_init(&A);
628    mbedtls_mpi_init(&B);
629    mbedtls_mpi_init(&X);
630
631    TEST_EQUAL(0, mbedtls_test_read_mpi(&A, input_A));
632    TEST_EQUAL(0, mbedtls_test_read_mpi(&B, input_B));
633    TEST_EQUAL(0, mbedtls_test_read_mpi(&X, input_X));
634
635    /* All of the inputs are +ve (or zero) */
636    TEST_EQUAL(1, A.s);
637    TEST_EQUAL(1, B.s);
638    TEST_EQUAL(1, X.s);
639
640    /* Get the number of limbs we will need */
641    size_t limbs = MAX(A.n, B.n);
642    size_t bytes = limbs * sizeof(mbedtls_mpi_uint);
643
644    /* The result shouldn't have more limbs than the longest input */
645    TEST_LE_U(X.n, limbs);
646
647    /* Now let's get arrays of mbedtls_mpi_uints, rather than MPI structures */
648
649    /* TEST_CALLOC() uses calloc() under the hood, so these do get zeroed */
650    TEST_CALLOC(a, bytes);
651    TEST_CALLOC(b, bytes);
652    TEST_CALLOC(x, bytes);
653    TEST_CALLOC(r, bytes);
654
655    /* Populate the arrays. As the mbedtls_mpi_uint[]s in mbedtls_mpis (and as
656     * processed by mbedtls_mpi_core_sub()) are little endian, we can just
657     * copy what we have as long as MSBs are 0 (which they are from TEST_CALLOC())
658     */
659    memcpy(a, A.p, A.n * sizeof(mbedtls_mpi_uint));
660    memcpy(b, B.p, B.n * sizeof(mbedtls_mpi_uint));
661    memcpy(x, X.p, X.n * sizeof(mbedtls_mpi_uint));
662
663    /* 1a) r = a - b => we should get the correct carry */
664    TEST_EQUAL(carry, mbedtls_mpi_core_sub(r, a, b, limbs));
665
666    /* 1b) r = a - b => we should get the correct result */
667    TEST_MEMORY_COMPARE(r, bytes, x, bytes);
668
669    /* 2 and 3 test "r may be aliased to a or b" */
670    /* 2a) r = a; r -= b => we should get the correct carry (use r to avoid clobbering a) */
671    memcpy(r, a, bytes);
672    TEST_EQUAL(carry, mbedtls_mpi_core_sub(r, r, b, limbs));
673
674    /* 2b) r -= b => we should get the correct result */
675    TEST_MEMORY_COMPARE(r, bytes, x, bytes);
676
677    /* 3a) r = b; r = a - r => we should get the correct carry (use r to avoid clobbering b) */
678    memcpy(r, b, bytes);
679    TEST_EQUAL(carry, mbedtls_mpi_core_sub(r, a, r, limbs));
680
681    /* 3b) r = a - b => we should get the correct result */
682    TEST_MEMORY_COMPARE(r, bytes, x, bytes);
683
684    /* 4 tests "r may be aliased to [...] both" */
685    if (A.n == B.n && memcmp(A.p, B.p, bytes) == 0) {
686        memcpy(r, b, bytes);
687        TEST_EQUAL(carry, mbedtls_mpi_core_sub(r, r, r, limbs));
688        TEST_MEMORY_COMPARE(r, bytes, x, bytes);
689    }
690
691exit:
692    mbedtls_free(a);
693    mbedtls_free(b);
694    mbedtls_free(x);
695    mbedtls_free(r);
696
697    mbedtls_mpi_free(&A);
698    mbedtls_mpi_free(&B);
699    mbedtls_mpi_free(&X);
700}
701/* END_CASE */
702
703/* BEGIN_CASE */
704void mpi_core_mla(char *input_A, char *input_B, char *input_S,
705                  char *input_X4, char *input_cy4,
706                  char *input_X8, char *input_cy8)
707{
708    /* We are testing A += B * s; A, B are MPIs, s is a scalar.
709     *
710     * However, we encode s as an MPI in the .data file as the test framework
711     * currently only supports `int`-typed scalars, and that doesn't cover the
712     * full range of `mbedtls_mpi_uint`.
713     *
714     * We also have the different results for sizeof(mbedtls_mpi_uint) == 4 or 8.
715     */
716    mbedtls_mpi A, B, S, X4, X8, cy4, cy8;
717    mbedtls_mpi_uint *a = NULL;
718    mbedtls_mpi_uint *x = NULL;
719
720    mbedtls_mpi_init(&A);
721    mbedtls_mpi_init(&B);
722    mbedtls_mpi_init(&S);
723    mbedtls_mpi_init(&X4);
724    mbedtls_mpi_init(&X8);
725    mbedtls_mpi_init(&cy4);
726    mbedtls_mpi_init(&cy8);
727
728    TEST_EQUAL(0, mbedtls_test_read_mpi(&A, input_A));
729    TEST_EQUAL(0, mbedtls_test_read_mpi(&B, input_B));
730    TEST_EQUAL(0, mbedtls_test_read_mpi(&S, input_S));
731    TEST_EQUAL(0, mbedtls_test_read_mpi(&X4, input_X4));
732    TEST_EQUAL(0, mbedtls_test_read_mpi(&cy4, input_cy4));
733    TEST_EQUAL(0, mbedtls_test_read_mpi(&X8, input_X8));
734    TEST_EQUAL(0, mbedtls_test_read_mpi(&cy8, input_cy8));
735
736    /* The MPI encoding of scalar s must be only 1 limb */
737    TEST_EQUAL(1, S.n);
738
739    /* We only need to work with X4 or X8, and cy4 or cy8, depending on sizeof(mbedtls_mpi_uint) */
740    mbedtls_mpi *X = (sizeof(mbedtls_mpi_uint) == 4) ? &X4 : &X8;
741    mbedtls_mpi *cy = (sizeof(mbedtls_mpi_uint) == 4) ? &cy4 : &cy8;
742
743    /* The carry should only have one limb */
744    TEST_EQUAL(1, cy->n);
745
746    /* All of the inputs are +ve (or zero) */
747    TEST_EQUAL(1, A.s);
748    TEST_EQUAL(1, B.s);
749    TEST_EQUAL(1, S.s);
750    TEST_EQUAL(1, X->s);
751    TEST_EQUAL(1, cy->s);
752
753    /* Get the (max) number of limbs we will need */
754    size_t limbs = MAX(A.n, B.n);
755    size_t bytes = limbs * sizeof(mbedtls_mpi_uint);
756
757    /* The result shouldn't have more limbs than the longest input */
758    TEST_LE_U(X->n, limbs);
759
760    /* Now let's get arrays of mbedtls_mpi_uints, rather than MPI structures */
761
762    /* TEST_CALLOC() uses calloc() under the hood, so these do get zeroed */
763    TEST_CALLOC(a, bytes);
764    TEST_CALLOC(x, bytes);
765
766    /* Populate the arrays. As the mbedtls_mpi_uint[]s in mbedtls_mpis (and as
767     * processed by mbedtls_mpi_core_mla()) are little endian, we can just
768     * copy what we have as long as MSBs are 0 (which they are from TEST_CALLOC()).
769     */
770    memcpy(a, A.p, A.n * sizeof(mbedtls_mpi_uint));
771    memcpy(x, X->p, X->n * sizeof(mbedtls_mpi_uint));
772
773    /* 1a) A += B * s => we should get the correct carry */
774    TEST_EQUAL(mbedtls_mpi_core_mla(a, limbs, B.p, B.n, *S.p), *cy->p);
775
776    /* 1b) A += B * s => we should get the correct result */
777    TEST_MEMORY_COMPARE(a, bytes, x, bytes);
778
779    if (A.n == B.n && memcmp(A.p, B.p, bytes) == 0) {
780        /* Check when A and B are aliased */
781        memcpy(a, A.p, A.n * sizeof(mbedtls_mpi_uint));
782        TEST_EQUAL(mbedtls_mpi_core_mla(a, limbs, a, limbs, *S.p), *cy->p);
783        TEST_MEMORY_COMPARE(a, bytes, x, bytes);
784    }
785
786exit:
787    mbedtls_free(a);
788    mbedtls_free(x);
789
790    mbedtls_mpi_free(&A);
791    mbedtls_mpi_free(&B);
792    mbedtls_mpi_free(&S);
793    mbedtls_mpi_free(&X4);
794    mbedtls_mpi_free(&X8);
795    mbedtls_mpi_free(&cy4);
796    mbedtls_mpi_free(&cy8);
797}
798/* END_CASE */
799
800
801/* BEGIN_CASE */
802void mpi_montg_init(char *input_N, char *input_mm)
803{
804    mbedtls_mpi N, mm;
805
806    mbedtls_mpi_init(&N);
807    mbedtls_mpi_init(&mm);
808
809    TEST_EQUAL(0, mbedtls_test_read_mpi(&N, input_N));
810    TEST_EQUAL(0, mbedtls_test_read_mpi(&mm, input_mm));
811
812    /* The MPI encoding of mm should be 1 limb (sizeof(mbedtls_mpi_uint) == 8) or
813     * 2 limbs (sizeof(mbedtls_mpi_uint) == 4).
814     *
815     * The data file contains the expected result for sizeof(mbedtls_mpi_uint) == 8;
816     * for sizeof(mbedtls_mpi_uint) == 4 it's just the LSW of this.
817     */
818    TEST_ASSERT(mm.n == 1  || mm.n == 2);
819
820    /* All of the inputs are +ve (or zero) */
821    TEST_EQUAL(1, N.s);
822    TEST_EQUAL(1, mm.s);
823
824    /* mbedtls_mpi_core_montmul_init() only returns a result, no error possible */
825    mbedtls_mpi_uint result = mbedtls_mpi_core_montmul_init(N.p);
826
827    /* Check we got the correct result */
828    TEST_EQUAL(result, mm.p[0]);
829
830exit:
831    mbedtls_mpi_free(&N);
832    mbedtls_mpi_free(&mm);
833}
834/* END_CASE */
835
836/* BEGIN_CASE */
837void mpi_core_montmul(int limbs_AN4, int limbs_B4,
838                      int limbs_AN8, int limbs_B8,
839                      char *input_A,
840                      char *input_B,
841                      char *input_N,
842                      char *input_X4,
843                      char *input_X8)
844{
845    mbedtls_mpi A, B, N, X4, X8, T, R;
846
847    mbedtls_mpi_init(&A);
848    mbedtls_mpi_init(&B);
849    mbedtls_mpi_init(&N);
850    mbedtls_mpi_init(&X4);      /* expected result, sizeof(mbedtls_mpi_uint) == 4 */
851    mbedtls_mpi_init(&X8);      /* expected result, sizeof(mbedtls_mpi_uint) == 8 */
852    mbedtls_mpi_init(&T);
853    mbedtls_mpi_init(&R);       /* for the result */
854
855    TEST_EQUAL(0, mbedtls_test_read_mpi(&A, input_A));
856    TEST_EQUAL(0, mbedtls_test_read_mpi(&B, input_B));
857    TEST_EQUAL(0, mbedtls_test_read_mpi(&N, input_N));
858    TEST_EQUAL(0, mbedtls_test_read_mpi(&X4, input_X4));
859    TEST_EQUAL(0, mbedtls_test_read_mpi(&X8, input_X8));
860
861    mbedtls_mpi *X = (sizeof(mbedtls_mpi_uint) == 4) ? &X4 : &X8;
862
863    int limbs_AN = (sizeof(mbedtls_mpi_uint) == 4) ? limbs_AN4 : limbs_AN8;
864    int limbs_B = (sizeof(mbedtls_mpi_uint) == 4) ? limbs_B4 : limbs_B8;
865
866    TEST_LE_U(A.n, (size_t) limbs_AN);
867    TEST_LE_U(X->n, (size_t) limbs_AN);
868    TEST_LE_U(B.n, (size_t) limbs_B);
869    TEST_LE_U(limbs_B, limbs_AN);
870
871    /* All of the inputs are +ve (or zero) */
872    TEST_EQUAL(1, A.s);
873    TEST_EQUAL(1, B.s);
874    TEST_EQUAL(1, N.s);
875    TEST_EQUAL(1, X->s);
876
877    TEST_EQUAL(0, mbedtls_mpi_grow(&A, limbs_AN));
878    TEST_EQUAL(0, mbedtls_mpi_grow(&N, limbs_AN));
879    TEST_EQUAL(0, mbedtls_mpi_grow(X, limbs_AN));
880    TEST_EQUAL(0, mbedtls_mpi_grow(&B, limbs_B));
881
882    size_t working_limbs = mbedtls_mpi_core_montmul_working_limbs(limbs_AN);
883    TEST_EQUAL(working_limbs, limbs_AN * 2 + 1);
884    TEST_EQUAL(0, mbedtls_mpi_grow(&T, working_limbs));
885
886    /* Calculate the Montgomery constant (this is unit tested separately) */
887    mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N.p);
888
889    TEST_EQUAL(0, mbedtls_mpi_grow(&R, limbs_AN));     /* ensure it's got the right number of limbs */
890
891    mbedtls_mpi_core_montmul(R.p, A.p, B.p, B.n, N.p, N.n, mm, T.p);
892    size_t bytes = N.n * sizeof(mbedtls_mpi_uint);
893    TEST_MEMORY_COMPARE(R.p, bytes, X->p, bytes);
894
895    /* The output (R, above) may be aliased to A - use R to save the value of A */
896
897    memcpy(R.p, A.p, bytes);
898
899    mbedtls_mpi_core_montmul(A.p, A.p, B.p, B.n, N.p, N.n, mm, T.p);
900    TEST_MEMORY_COMPARE(A.p, bytes, X->p, bytes);
901
902    memcpy(A.p, R.p, bytes);    /* restore A */
903
904    /* The output may be aliased to N - use R to save the value of N */
905
906    memcpy(R.p, N.p, bytes);
907
908    mbedtls_mpi_core_montmul(N.p, A.p, B.p, B.n, N.p, N.n, mm, T.p);
909    TEST_MEMORY_COMPARE(N.p, bytes, X->p, bytes);
910
911    memcpy(N.p, R.p, bytes);
912
913    if (limbs_AN == limbs_B) {
914        /* Test when A aliased to B (requires A == B on input values) */
915        if (memcmp(A.p, B.p, bytes) == 0) {
916            /* Test with A aliased to B and output, since this is permitted -
917             * don't bother with yet another test with only A and B aliased */
918
919            mbedtls_mpi_core_montmul(B.p, B.p, B.p, B.n, N.p, N.n, mm, T.p);
920            TEST_MEMORY_COMPARE(B.p, bytes, X->p, bytes);
921
922            memcpy(B.p, A.p, bytes);    /* restore B from equal value A */
923        }
924
925        /* The output may be aliased to B - last test, so we don't save B */
926
927        mbedtls_mpi_core_montmul(B.p, A.p, B.p, B.n, N.p, N.n, mm, T.p);
928        TEST_MEMORY_COMPARE(B.p, bytes, X->p, bytes);
929    }
930
931exit:
932    mbedtls_mpi_free(&A);
933    mbedtls_mpi_free(&B);
934    mbedtls_mpi_free(&N);
935    mbedtls_mpi_free(&X4);
936    mbedtls_mpi_free(&X8);
937    mbedtls_mpi_free(&T);
938    mbedtls_mpi_free(&R);
939}
940/* END_CASE */
941
942/* BEGIN_CASE */
943void mpi_core_get_mont_r2_unsafe_neg()
944{
945    mbedtls_mpi N, RR;
946    mbedtls_mpi_init(&N);
947    mbedtls_mpi_init(&RR);
948    const char *n = "7ffffffffffffff1";
949
950    /* Test for zero divisor */
951    TEST_EQUAL(MBEDTLS_ERR_MPI_DIVISION_BY_ZERO,
952               mbedtls_mpi_core_get_mont_r2_unsafe(&RR, &N));
953
954    /* Test for negative input */
955    TEST_EQUAL(0, mbedtls_test_read_mpi(&N, n));
956    N.s = -1;
957    TEST_EQUAL(MBEDTLS_ERR_MPI_NEGATIVE_VALUE,
958               mbedtls_mpi_core_get_mont_r2_unsafe(&RR, &N));
959    N.s = 1;
960
961exit:
962    mbedtls_mpi_free(&N);
963    mbedtls_mpi_free(&RR);
964}
965/* END_CASE */
966
967/* BEGIN_CASE */
968void mpi_core_get_mont_r2_unsafe(char *input_N,
969                                 char *input_RR_X4,
970                                 char *input_RR_X8)
971{
972    mbedtls_mpi N, RR, RR_REF;
973
974    /* Select the appropriate output */
975    char *input_rr = (sizeof(mbedtls_mpi_uint) == 4) ? input_RR_X4 : input_RR_X8;
976
977    mbedtls_mpi_init(&N);
978    mbedtls_mpi_init(&RR);
979    mbedtls_mpi_init(&RR_REF);
980
981    /* Read inputs */
982    TEST_EQUAL(0, mbedtls_test_read_mpi(&N, input_N));
983    TEST_EQUAL(0, mbedtls_test_read_mpi(&RR_REF, input_rr));
984
985    /* All of the inputs are +ve (or zero) */
986    TEST_EQUAL(1, N.s);
987    TEST_EQUAL(1, RR_REF.s);
988
989    /* Test valid input */
990    TEST_EQUAL(0, mbedtls_mpi_core_get_mont_r2_unsafe(&RR, &N));
991
992    /* Test that the moduli is odd */
993    TEST_EQUAL(N.p[0] ^ 1, N.p[0] - 1);
994
995    /* Output is +ve (or zero) */
996    TEST_EQUAL(1, RR_REF.s);
997
998    /* rr is updated to a valid pointer */
999    TEST_ASSERT(RR.p != NULL);
1000
1001    /* Calculated rr matches expected value */
1002    TEST_ASSERT(mbedtls_mpi_cmp_mpi(&RR, &RR_REF) == 0);
1003
1004exit:
1005    mbedtls_mpi_free(&N);
1006    mbedtls_mpi_free(&RR);
1007    mbedtls_mpi_free(&RR_REF);
1008}
1009/* END_CASE */
1010
1011/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS */
1012void mpi_core_ct_uint_table_lookup(int bitlen, int window_size)
1013{
1014    size_t limbs = BITS_TO_LIMBS(bitlen);
1015    size_t count = ((size_t) 1) << window_size;
1016
1017    mbedtls_mpi_uint *table = NULL;
1018    mbedtls_mpi_uint *dest = NULL;
1019
1020    TEST_CALLOC(table, limbs * count);
1021    TEST_CALLOC(dest, limbs);
1022
1023    /*
1024     * Fill the table with a unique counter so that differences are easily
1025     * detected. (And have their relationship to the index relatively non-trivial just
1026     * to be sure.)
1027     */
1028    for (size_t i = 0; i < count * limbs; i++) {
1029        table[i] = ~i - 1;
1030    }
1031
1032    for (size_t i = 0; i < count; i++) {
1033        mbedtls_mpi_uint *current = table + i * limbs;
1034        memset(dest, 0x00, limbs * sizeof(*dest));
1035
1036        /*
1037         * We shouldn't leak anything through timing.
1038         * We need to set these in every loop as we need to make the loop
1039         * variable public for the loop head and the buffers for comparison.
1040         */
1041        TEST_CF_SECRET(&i, sizeof(i));
1042        TEST_CF_SECRET(dest, limbs * sizeof(*dest));
1043        TEST_CF_SECRET(table, count * limbs * sizeof(*table));
1044
1045        mbedtls_mpi_core_ct_uint_table_lookup(dest, table, limbs, count, i);
1046
1047        TEST_CF_PUBLIC(dest, limbs * sizeof(*dest));
1048        TEST_CF_PUBLIC(table, count * limbs * sizeof(*table));
1049        TEST_MEMORY_COMPARE(dest, limbs * sizeof(*dest),
1050                            current, limbs * sizeof(*current));
1051        TEST_CF_PUBLIC(&i, sizeof(i));
1052    }
1053
1054exit:
1055    mbedtls_free(table);
1056    mbedtls_free(dest);
1057}
1058/* END_CASE */
1059
1060/* BEGIN_CASE */
1061void mpi_core_fill_random(int wanted_bytes_arg, int extra_rng_bytes,
1062                          int extra_limbs, int before, int expected_ret)
1063{
1064    size_t wanted_bytes = wanted_bytes_arg;
1065    mbedtls_mpi_uint *X = NULL;
1066    size_t X_limbs = CHARS_TO_LIMBS(wanted_bytes) + extra_limbs;
1067    size_t rng_bytes = wanted_bytes + extra_rng_bytes;
1068    unsigned char *rnd_data = NULL;
1069    mbedtls_test_rnd_buf_info rnd_info = { NULL, rng_bytes, NULL, NULL };
1070    int ret;
1071
1072    /* Prepare an RNG with known output, limited to rng_bytes. */
1073    TEST_CALLOC(rnd_data, rng_bytes);
1074    TEST_EQUAL(0, mbedtls_test_rnd_std_rand(NULL, rnd_data, rng_bytes));
1075    rnd_info.buf = rnd_data;
1076
1077    /* Allocate an MPI with room for wanted_bytes plus extra_limbs.
1078     * extra_limbs may be negative but the total limb count must be positive.
1079     * Fill the MPI with the byte value in before. */
1080    TEST_LE_U(1, X_limbs);
1081    TEST_CALLOC(X, X_limbs);
1082    memset(X, before, X_limbs * sizeof(*X));
1083
1084    ret = mbedtls_mpi_core_fill_random(X, X_limbs, wanted_bytes,
1085                                       mbedtls_test_rnd_buffer_rand,
1086                                       &rnd_info);
1087    TEST_EQUAL(expected_ret, ret);
1088
1089    if (expected_ret == 0) {
1090        /* mbedtls_mpi_core_fill_random is documented to use bytes from the
1091         * RNG as a big-endian representation of the number. We used an RNG
1092         * with known output, so check that the output contains the
1093         * expected value. Bytes above wanted_bytes must be zero. */
1094        for (size_t i = 0; i < wanted_bytes; i++) {
1095            mbedtls_test_set_step(i);
1096            TEST_EQUAL(GET_BYTE(X, i), rnd_data[wanted_bytes - 1 - i]);
1097        }
1098        for (size_t i = wanted_bytes; i < X_limbs * ciL; i++) {
1099            mbedtls_test_set_step(i);
1100            TEST_EQUAL(GET_BYTE(X, i), 0);
1101        }
1102    }
1103
1104exit:
1105    mbedtls_free(rnd_data);
1106    mbedtls_free(X);
1107}
1108/* END_CASE */
1109
1110/* BEGIN_CASE */
1111void mpi_core_mul(char *input_A,
1112                  char *input_B,
1113                  char *result)
1114{
1115    mbedtls_mpi_uint *A      = NULL;
1116    mbedtls_mpi_uint *A_orig = NULL;
1117    mbedtls_mpi_uint *B      = NULL;
1118    mbedtls_mpi_uint *B_orig = NULL;
1119    mbedtls_mpi_uint *R      = NULL;
1120    mbedtls_mpi_uint *X      = NULL;
1121    size_t A_limbs, B_limbs, R_limbs;
1122
1123    TEST_EQUAL(mbedtls_test_read_mpi_core(&A, &A_limbs, input_A), 0);
1124    TEST_EQUAL(mbedtls_test_read_mpi_core(&B, &B_limbs, input_B), 0);
1125    TEST_EQUAL(mbedtls_test_read_mpi_core(&R, &R_limbs, result), 0);
1126
1127    TEST_EQUAL(R_limbs, A_limbs + B_limbs);
1128
1129    const size_t X_limbs = A_limbs + B_limbs;
1130    const size_t X_bytes = X_limbs * sizeof(mbedtls_mpi_uint);
1131    TEST_CALLOC(X, X_limbs);
1132
1133    const size_t A_bytes = A_limbs * sizeof(mbedtls_mpi_uint);
1134    TEST_CALLOC(A_orig, A_limbs);
1135    memcpy(A_orig, A, A_bytes);
1136
1137    const size_t B_bytes = B_limbs * sizeof(mbedtls_mpi_uint);
1138    TEST_CALLOC(B_orig, B_limbs);
1139    memcpy(B_orig, B, B_bytes);
1140
1141    /* Set result to something that is unlikely to be correct */
1142    memset(X, '!', X_bytes);
1143
1144    /* 1. X = A * B - result should be correct, A and B unchanged */
1145    mbedtls_mpi_core_mul(X, A, A_limbs, B, B_limbs);
1146    TEST_MEMORY_COMPARE(X, X_bytes, R, X_bytes);
1147    TEST_MEMORY_COMPARE(A, A_bytes, A_orig, A_bytes);
1148    TEST_MEMORY_COMPARE(B, B_bytes, B_orig, B_bytes);
1149
1150    /* 2. A == B: alias A and B - result should be correct, A and B unchanged */
1151    if (A_bytes == B_bytes && memcmp(A, B, A_bytes) == 0) {
1152        memset(X, '!', X_bytes);
1153        mbedtls_mpi_core_mul(X, A, A_limbs, A, A_limbs);
1154        TEST_MEMORY_COMPARE(X, X_bytes, R, X_bytes);
1155        TEST_MEMORY_COMPARE(A, A_bytes, A_orig, A_bytes);
1156    }
1157    /* 3. X = B * A - result should be correct, A and B unchanged */
1158    else {
1159        memset(X, '!', X_bytes);
1160        mbedtls_mpi_core_mul(X, B, B_limbs, A, A_limbs);
1161        TEST_MEMORY_COMPARE(X, X_bytes, R, X_bytes);
1162        TEST_MEMORY_COMPARE(A, A_bytes, A_orig, A_bytes);
1163        TEST_MEMORY_COMPARE(B, B_bytes, B_orig, B_bytes);
1164    }
1165
1166exit:
1167    mbedtls_free(A);
1168    mbedtls_free(A_orig);
1169    mbedtls_free(B);
1170    mbedtls_free(B_orig);
1171    mbedtls_free(R);
1172    mbedtls_free(X);
1173}
1174/* END_CASE */
1175
1176/* BEGIN_CASE */
1177void mpi_core_exp_mod(char *input_N, char *input_A,
1178                      char *input_E, char *input_X)
1179{
1180    mbedtls_mpi_uint *A = NULL;
1181    mbedtls_mpi_uint *E = NULL;
1182    mbedtls_mpi_uint *N = NULL;
1183    mbedtls_mpi_uint *X = NULL;
1184    size_t A_limbs, E_limbs, N_limbs, X_limbs;
1185    const mbedtls_mpi_uint *R2 = NULL;
1186    mbedtls_mpi_uint *Y = NULL;
1187    mbedtls_mpi_uint *T = NULL;
1188    /* Legacy MPIs for computing R2 */
1189    mbedtls_mpi N_mpi;
1190    mbedtls_mpi_init(&N_mpi);
1191    mbedtls_mpi R2_mpi;
1192    mbedtls_mpi_init(&R2_mpi);
1193
1194    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&A, &A_limbs, input_A));
1195    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&E, &E_limbs, input_E));
1196    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&N, &N_limbs, input_N));
1197    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&X, &X_limbs, input_X));
1198    TEST_CALLOC(Y, N_limbs);
1199
1200    TEST_EQUAL(A_limbs, N_limbs);
1201    TEST_EQUAL(X_limbs, N_limbs);
1202
1203    TEST_EQUAL(0, mbedtls_mpi_grow(&N_mpi, N_limbs));
1204    memcpy(N_mpi.p, N, N_limbs * sizeof(*N));
1205    N_mpi.n = N_limbs;
1206    TEST_EQUAL(0,
1207               mbedtls_mpi_core_get_mont_r2_unsafe(&R2_mpi, &N_mpi));
1208    TEST_EQUAL(0, mbedtls_mpi_grow(&R2_mpi, N_limbs));
1209    R2 = R2_mpi.p;
1210
1211    size_t working_limbs = mbedtls_mpi_core_exp_mod_working_limbs(N_limbs,
1212                                                                  E_limbs);
1213
1214    /* No point exactly duplicating the code in mbedtls_mpi_core_exp_mod_working_limbs()
1215     * to see if the output is correct, but we can check that it's in a
1216     * reasonable range.  The current calculation works out as
1217     * `1 + N_limbs * (welem + 3)`, where welem is the number of elements in
1218     * the window (1 << 1 up to 1 << 6).
1219     */
1220    size_t min_expected_working_limbs = 1 + N_limbs * 4;
1221    size_t max_expected_working_limbs = 1 + N_limbs * 67;
1222
1223    TEST_LE_U(min_expected_working_limbs, working_limbs);
1224    TEST_LE_U(working_limbs, max_expected_working_limbs);
1225
1226    /* Should also be at least mbedtls_mpi_core_montmul_working_limbs() */
1227    TEST_LE_U(mbedtls_mpi_core_montmul_working_limbs(N_limbs),
1228              working_limbs);
1229
1230    TEST_CALLOC(T, working_limbs);
1231
1232    mbedtls_mpi_core_exp_mod(Y, A, N, N_limbs, E, E_limbs, R2, T);
1233
1234    TEST_EQUAL(0, memcmp(X, Y, N_limbs * sizeof(mbedtls_mpi_uint)));
1235
1236    /* Check when output aliased to input */
1237
1238    mbedtls_mpi_core_exp_mod(A, A, N, N_limbs, E, E_limbs, R2, T);
1239
1240    TEST_EQUAL(0, memcmp(X, A, N_limbs * sizeof(mbedtls_mpi_uint)));
1241
1242exit:
1243    mbedtls_free(T);
1244    mbedtls_free(A);
1245    mbedtls_free(E);
1246    mbedtls_free(N);
1247    mbedtls_free(X);
1248    mbedtls_free(Y);
1249    mbedtls_mpi_free(&N_mpi);
1250    mbedtls_mpi_free(&R2_mpi);
1251    // R2 doesn't need to be freed as it is only aliasing R2_mpi
1252}
1253/* END_CASE */
1254
1255/* BEGIN_CASE */
1256void mpi_core_sub_int(char *input_A, char *input_B,
1257                      char *input_X, int borrow)
1258{
1259    /* We are testing A - b, where A is an MPI and b is a scalar, expecting
1260     * result X with borrow borrow.  However, for ease of handling we encode b
1261     * as a 1-limb MPI (B) in the .data file. */
1262
1263    mbedtls_mpi_uint *A = NULL;
1264    mbedtls_mpi_uint *B = NULL;
1265    mbedtls_mpi_uint *X = NULL;
1266    mbedtls_mpi_uint *R = NULL;
1267    size_t A_limbs, B_limbs, X_limbs;
1268
1269    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&A, &A_limbs, input_A));
1270    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&B, &B_limbs, input_B));
1271    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&X, &X_limbs, input_X));
1272
1273    /* The MPI encoding of scalar b must be only 1 limb */
1274    TEST_EQUAL(B_limbs, 1);
1275
1276    /* The subtraction is fixed-width, so A and X must have the same number of limbs */
1277    TEST_EQUAL(A_limbs, X_limbs);
1278    size_t limbs = A_limbs;
1279
1280    TEST_CALLOC(R, limbs);
1281
1282#define TEST_COMPARE_CORE_MPIS(A, B, limbs) \
1283    TEST_MEMORY_COMPARE(A, (limbs) * sizeof(mbedtls_mpi_uint), \
1284                        B, (limbs) * sizeof(mbedtls_mpi_uint))
1285
1286    /* 1. R = A - b. Result and borrow should be correct */
1287    TEST_EQUAL(mbedtls_mpi_core_sub_int(R, A, B[0], limbs), borrow);
1288    TEST_COMPARE_CORE_MPIS(R, X, limbs);
1289
1290    /* 2. A = A - b. Result and borrow should be correct */
1291    TEST_EQUAL(mbedtls_mpi_core_sub_int(A, A, B[0], limbs), borrow);
1292    TEST_COMPARE_CORE_MPIS(A, X, limbs);
1293
1294exit:
1295    mbedtls_free(A);
1296    mbedtls_free(B);
1297    mbedtls_free(X);
1298    mbedtls_free(R);
1299}
1300/* END_CASE */
1301
1302/* BEGIN_CASE */
1303void mpi_core_check_zero_ct(char *input_X, int expected_is_zero)
1304{
1305    mbedtls_mpi_uint *X = NULL;
1306    size_t X_limbs;
1307
1308    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&X, &X_limbs, input_X));
1309
1310    TEST_CF_SECRET(X, X_limbs * sizeof(mbedtls_mpi_uint));
1311
1312    mbedtls_mpi_uint check = mbedtls_mpi_core_check_zero_ct(X, X_limbs);
1313    int is_zero = (check == 0);
1314    TEST_EQUAL(is_zero, expected_is_zero);
1315
1316exit:
1317    mbedtls_free(X);
1318}
1319/* END_CASE */
1320