blob: 6e25ff720070bb46879d52df65a8d4e1fcddd7d8 [file] [log] [blame]
Werner Lewis0c6ea122022-09-30 13:02:16 +01001/* BEGIN_HEADER */
2#include "mbedtls/bignum.h"
3#include "mbedtls/entropy.h"
4#include "bignum_mod.h"
Gabor Mezeieca74662022-12-13 10:53:50 +01005#include "bignum_mod_raw.h"
Werner Lewis0c6ea122022-09-30 13:02:16 +01006#include "constant_time_internal.h"
7#include "test/constant_flow.h"
Tom Cosgrove62b20482022-12-01 14:27:37 +00008
9#define TEST_COMPARE_MPI_RESIDUES( a, b ) \
10 ASSERT_COMPARE( (a).p, (a).limbs * sizeof(mbedtls_mpi_uint), \
11 (b).p, (b).limbs * sizeof(mbedtls_mpi_uint) )
12
Tom Cosgrovef51f9722022-12-05 15:47:40 +000013static int test_read_modulus( mbedtls_mpi_mod_modulus *m,
14 mbedtls_mpi_mod_rep_selector int_rep,
15 char *input )
Tom Cosgrove62b20482022-12-01 14:27:37 +000016{
17 mbedtls_mpi_uint *p = NULL;
18 size_t limbs;
19
20 int ret = mbedtls_test_read_mpi_core( &p, &limbs, input );
21 if( ret != 0 )
22 return( ret );
23
24 return( mbedtls_mpi_mod_modulus_setup( m, p, limbs, int_rep ) );
25}
26
Tom Cosgrovef51f9722022-12-05 15:47:40 +000027static int test_read_residue( mbedtls_mpi_mod_residue *r,
28 const mbedtls_mpi_mod_modulus *m,
29 char *input,
30 int skip_limbs_and_value_checks )
Tom Cosgrove62b20482022-12-01 14:27:37 +000031{
32 mbedtls_mpi_uint *p = NULL;
33 size_t limbs;
34
35 int ret = mbedtls_test_read_mpi_core( &p, &limbs, input );
36 if( ret != 0 )
37 return( ret );
38
39 if( skip_limbs_and_value_checks )
40 {
41 r->p = p;
42 r->limbs = limbs;
43 return( 0 );
44 }
45
46 /* mbedtls_mpi_mod_residue_setup() checks limbs, and that value < m */
47 return( mbedtls_mpi_mod_residue_setup( r, m, p, limbs ) );
48}
Werner Lewis0c6ea122022-09-30 13:02:16 +010049/* END_HEADER */
50
51/* BEGIN_DEPENDENCIES
52 * depends_on:MBEDTLS_BIGNUM_C
53 * END_DEPENDENCIES
54 */
55
56/* BEGIN_CASE */
Janos Follath91295d22022-11-24 18:20:26 +000057void mpi_mod_setup( int int_rep, int iret )
Werner Lewis0c6ea122022-09-30 13:02:16 +010058{
59 #define MLIMBS 8
60 mbedtls_mpi_uint mp[MLIMBS];
61 mbedtls_mpi_mod_modulus m;
62 int ret;
63
Minos Galanakis4d4c98b2022-10-27 15:58:02 +010064 memset( mp, 0xFF, sizeof(mp) );
Werner Lewis0c6ea122022-09-30 13:02:16 +010065
66 mbedtls_mpi_mod_modulus_init( &m );
Janos Follath91295d22022-11-24 18:20:26 +000067 ret = mbedtls_mpi_mod_modulus_setup( &m, mp, MLIMBS, int_rep );
Werner Lewis0c6ea122022-09-30 13:02:16 +010068 TEST_EQUAL( ret, iret );
69
Minos Galanakisdd365a52022-10-19 01:48:32 +010070 /* Only test if the constants have been set-up */
71 if ( ret == 0 && int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY )
72 {
73 /* Test that the consts have been calculated */
74 TEST_ASSERT( m.rep.mont.rr != NULL );
75 TEST_ASSERT( m.rep.mont.mm != 0 );
76
Minos Galanakisdd365a52022-10-19 01:48:32 +010077 }
78
Werner Lewis0c6ea122022-09-30 13:02:16 +010079 /* Address sanitiser should catch if we try to free mp */
80 mbedtls_mpi_mod_modulus_free( &m );
81
82 /* Make sure that the modulus doesn't have reference to mp anymore */
83 TEST_ASSERT( m.p != mp );
84
Minos Galanakisdd365a52022-10-19 01:48:32 +010085 /* Only test if the constants have been set-up */
86 if ( ret == 0 && int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY )
87 {
Minos Galanakisdd365a52022-10-19 01:48:32 +010088 /* Verify the data and pointers allocated have been properly wiped */
89 TEST_ASSERT( m.rep.mont.rr == NULL );
90 TEST_ASSERT( m.rep.mont.mm == 0 );
Minos Galanakisdd365a52022-10-19 01:48:32 +010091 }
Werner Lewis0c6ea122022-09-30 13:02:16 +010092exit:
93 /* It should be safe to call an mbedtls free several times */
94 mbedtls_mpi_mod_modulus_free( &m );
95
96 #undef MLIMBS
97}
98/* END_CASE */
Janos Follath5933f692022-11-02 14:35:17 +000099
100/* BEGIN MERGE SLOT 1 */
101
102/* END MERGE SLOT 1 */
103
104/* BEGIN MERGE SLOT 2 */
105
Gabor Mezeieca74662022-12-13 10:53:50 +0100106/* BEGIN_CASE */
107void mpi_mod_mul( char * input_A,
108 char * input_B,
109 char * input_N,
110 char * result )
111{
Gabor Mezeieca74662022-12-13 10:53:50 +0100112 mbedtls_mpi_uint *X = NULL;
Gabor Mezeieca74662022-12-13 10:53:50 +0100113
114 mbedtls_mpi_mod_modulus m;
115 mbedtls_mpi_mod_modulus_init( &m );
116
Gabor Mezei809baef2022-12-16 16:31:59 +0100117 TEST_EQUAL( test_read_modulus( &m, MBEDTLS_MPI_MOD_REP_MONTGOMERY, input_N ),
118 0 );
Gabor Mezeieca74662022-12-13 10:53:50 +0100119
120 mbedtls_mpi_mod_residue rA;
Gabor Mezei809baef2022-12-16 16:31:59 +0100121 TEST_EQUAL( test_read_residue( &rA, &m, input_A, 0 ), 0 );
Gabor Mezeieca74662022-12-13 10:53:50 +0100122
123 mbedtls_mpi_mod_residue rB;
Gabor Mezei809baef2022-12-16 16:31:59 +0100124 TEST_EQUAL( test_read_residue( &rB, &m, input_B, 0 ), 0 );
125
126 mbedtls_mpi_mod_residue rR;
127 TEST_EQUAL( test_read_residue( &rR, &m, result, 0 ), 0 );
128
129 const size_t limbs = m.limbs;
130 const size_t bytes = limbs * sizeof( mbedtls_mpi_uint );
131
132 TEST_EQUAL( rA.limbs, limbs );
133 TEST_EQUAL( rB.limbs, limbs );
134 TEST_EQUAL( rR.limbs, limbs );
135
136 ASSERT_ALLOC( X, limbs );
Gabor Mezeieca74662022-12-13 10:53:50 +0100137
138 mbedtls_mpi_mod_residue rX;
139 TEST_EQUAL( mbedtls_mpi_mod_residue_setup( &rX, &m, X, limbs ), 0 );
140
Gabor Mezeieca74662022-12-13 10:53:50 +0100141 TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rA, &rB, &m ), 0 );
Gabor Mezei809baef2022-12-16 16:31:59 +0100142 ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
Gabor Mezeieca74662022-12-13 10:53:50 +0100143
144 /* alias X to A */
145 memcpy( rX.p, rA.p, bytes );
146 TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rX, &rB, &m ), 0 );
Gabor Mezei809baef2022-12-16 16:31:59 +0100147 ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
Gabor Mezeieca74662022-12-13 10:53:50 +0100148
149 /* alias X to B */
150 memcpy( rX.p, rB.p, bytes );
151 TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rA, &rX, &m ), 0);
Gabor Mezei809baef2022-12-16 16:31:59 +0100152 ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
Gabor Mezeieca74662022-12-13 10:53:50 +0100153
154 /* A == B: alias A and B */
155 if( memcmp( rA.p, rB.p, bytes ) == 0 )
156 {
157 TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rA, &rA, &m ), 0 );
Gabor Mezei809baef2022-12-16 16:31:59 +0100158 ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
Gabor Mezeieca74662022-12-13 10:53:50 +0100159
160 /* X, A, B all aliased together */
161 memcpy( rX.p, rA.p, bytes );
162 TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rX, &rX, &m ), 0 );
Gabor Mezei809baef2022-12-16 16:31:59 +0100163 ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
Gabor Mezeieca74662022-12-13 10:53:50 +0100164 }
165
166 /* A != B: test B * A */
167 else
168 {
169 TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rB, &rA, &m ), 0 );
Gabor Mezei809baef2022-12-16 16:31:59 +0100170 ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
Gabor Mezeieca74662022-12-13 10:53:50 +0100171
172 /* B * A: alias X to A */
173 memcpy( rX.p, rA.p, bytes );
174 TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rB, &rX, &m ), 0 );
Gabor Mezei809baef2022-12-16 16:31:59 +0100175 ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
Gabor Mezeieca74662022-12-13 10:53:50 +0100176
177 /* B + A: alias X to B */
178 memcpy( rX.p, rB.p, bytes );
179 TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rX, &rA, &m ), 0 );
Gabor Mezei809baef2022-12-16 16:31:59 +0100180 ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
Gabor Mezeieca74662022-12-13 10:53:50 +0100181 }
182
183exit:
184 mbedtls_mpi_mod_residue_release( &rA );
185 mbedtls_mpi_mod_residue_release( &rB );
Gabor Mezei809baef2022-12-16 16:31:59 +0100186 mbedtls_mpi_mod_residue_release( &rR );
Gabor Mezeieca74662022-12-13 10:53:50 +0100187 mbedtls_mpi_mod_residue_release( &rX );
188 mbedtls_mpi_mod_modulus_free( &m );
189
Gabor Mezei809baef2022-12-16 16:31:59 +0100190 mbedtls_free( rA.p );
191 mbedtls_free( rB.p );
192 mbedtls_free( rR.p );
Gabor Mezeieca74662022-12-13 10:53:50 +0100193 mbedtls_free( X );
Gabor Mezei809baef2022-12-16 16:31:59 +0100194 mbedtls_free( (mbedtls_mpi_uint *) m.p );
Gabor Mezeieca74662022-12-13 10:53:50 +0100195}
196/* END_CASE */
197
198/* BEGIN_CASE */
199void mpi_mod_mul_neg( char * input_A,
200 char * input_B,
201 char * input_N,
202 char * result,
203 int exp_ret )
204{
Gabor Mezeieca74662022-12-13 10:53:50 +0100205 mbedtls_mpi_uint *X = NULL;
Gabor Mezeieca74662022-12-13 10:53:50 +0100206
207 mbedtls_mpi_mod_modulus m;
208 mbedtls_mpi_mod_modulus_init( &m );
209
Gabor Mezei809baef2022-12-16 16:31:59 +0100210 TEST_EQUAL( test_read_modulus( &m, MBEDTLS_MPI_MOD_REP_MONTGOMERY, input_N ),
211 0 );
Gabor Mezeieca74662022-12-13 10:53:50 +0100212
213 mbedtls_mpi_mod_residue rA;
Gabor Mezei809baef2022-12-16 16:31:59 +0100214 TEST_EQUAL( test_read_residue( &rA, &m, input_A, 1 ), 0 );
Gabor Mezeieca74662022-12-13 10:53:50 +0100215
216 mbedtls_mpi_mod_residue rB;
Gabor Mezei809baef2022-12-16 16:31:59 +0100217 TEST_EQUAL( test_read_residue( &rB, &m, input_B, 1 ), 0 );
218
219 mbedtls_mpi_mod_residue rR;
220 TEST_EQUAL( test_read_residue( &rR, &m, result, 1 ), 0 );
221
222 const size_t limbs = m.limbs;
223
224 ASSERT_ALLOC( X, limbs );
Gabor Mezeieca74662022-12-13 10:53:50 +0100225
226 mbedtls_mpi_mod_residue rX;
Gabor Mezei809baef2022-12-16 16:31:59 +0100227 TEST_EQUAL( mbedtls_mpi_mod_residue_setup( &rX, &m, X, limbs ), 0 );
228 rX.limbs = rR.limbs;
Gabor Mezeieca74662022-12-13 10:53:50 +0100229
230 TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rA, &rB, &m ), exp_ret );
231
Gabor Mezei809baef2022-12-16 16:31:59 +0100232 mbedtls_mpi_mod_modulus fake_m;
233 mbedtls_mpi_mod_modulus_init( &fake_m );
234
Gabor Mezeieca74662022-12-13 10:53:50 +0100235 /* Check when m is not initialized */
236 TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rA, &rB, &fake_m ),
237 MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
238
239exit:
240 mbedtls_mpi_mod_residue_release( &rA );
241 mbedtls_mpi_mod_residue_release( &rB );
Gabor Mezei809baef2022-12-16 16:31:59 +0100242 mbedtls_mpi_mod_residue_release( &rR );
Gabor Mezeieca74662022-12-13 10:53:50 +0100243 mbedtls_mpi_mod_residue_release( &rX );
244 mbedtls_mpi_mod_modulus_free( &m );
245 mbedtls_mpi_mod_modulus_free( &fake_m );
246
Gabor Mezei809baef2022-12-16 16:31:59 +0100247 mbedtls_free( rA.p );
248 mbedtls_free( rB.p );
249 mbedtls_free( rR.p );
Gabor Mezeieca74662022-12-13 10:53:50 +0100250 mbedtls_free( X );
Gabor Mezei809baef2022-12-16 16:31:59 +0100251 mbedtls_free( (mbedtls_mpi_uint *) m.p );
Gabor Mezeieca74662022-12-13 10:53:50 +0100252}
253/* END_CASE */
254
Janos Follath5933f692022-11-02 14:35:17 +0000255/* END MERGE SLOT 2 */
256
257/* BEGIN MERGE SLOT 3 */
Tom Cosgrove62b20482022-12-01 14:27:37 +0000258/* BEGIN_CASE */
259void mpi_mod_sub( char * input_N,
260 char * input_A, char * input_B,
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000261 char * input_D, int expected_ret )
Tom Cosgrove62b20482022-12-01 14:27:37 +0000262{
263 mbedtls_mpi_mod_residue a = { NULL, 0 };
264 mbedtls_mpi_mod_residue b = { NULL, 0 };
265 mbedtls_mpi_mod_residue d = { NULL, 0 };
266 mbedtls_mpi_mod_residue x = { NULL, 0 };
267 mbedtls_mpi_uint *X_raw = NULL;
Janos Follath5933f692022-11-02 14:35:17 +0000268
Tom Cosgrove62b20482022-12-01 14:27:37 +0000269 mbedtls_mpi_mod_modulus m;
270 mbedtls_mpi_mod_modulus_init( &m );
271
272 TEST_EQUAL( 0,
273 test_read_modulus( &m, MBEDTLS_MPI_MOD_REP_MONTGOMERY, input_N ) );
274
275 /* test_read_residue() normally checks that inputs have the same number of
276 * limbs as the modulus. For negative testing we can ask it to skip this
277 * with a non-zero final parameter. */
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000278 TEST_EQUAL( 0, test_read_residue( &a, &m, input_A, expected_ret != 0 ) );
279 TEST_EQUAL( 0, test_read_residue( &b, &m, input_B, expected_ret != 0 ) );
280 TEST_EQUAL( 0, test_read_residue( &d, &m, input_D, expected_ret != 0 ) );
Tom Cosgrove62b20482022-12-01 14:27:37 +0000281
282 size_t limbs = m.limbs;
283 size_t bytes = limbs * sizeof( *X_raw );
284
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000285 if( expected_ret == 0 )
Tom Cosgrove62b20482022-12-01 14:27:37 +0000286 {
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000287 /* Negative test with too many limbs in output */
288 ASSERT_ALLOC( X_raw, limbs + 1 );
Tom Cosgrove62b20482022-12-01 14:27:37 +0000289
Tom Cosgrove62b20482022-12-01 14:27:37 +0000290 x.p = X_raw;
291 x.limbs = limbs + 1;
292 TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
293 mbedtls_mpi_mod_sub( &x, &a, &b, &m ) );
294
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000295 mbedtls_free( X_raw );
296 X_raw = NULL;
297
298 /* Negative test with too few limbs in output */
Tom Cosgrove62b20482022-12-01 14:27:37 +0000299 if( limbs > 1 )
300 {
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000301 ASSERT_ALLOC( X_raw, limbs - 1 );
302
Tom Cosgrove62b20482022-12-01 14:27:37 +0000303 x.p = X_raw;
304 x.limbs = limbs - 1;
305 TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
306 mbedtls_mpi_mod_sub( &x, &a, &b, &m ) );
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000307
308 mbedtls_free( X_raw );
309 X_raw = NULL;
Tom Cosgrove62b20482022-12-01 14:27:37 +0000310 }
311
312 /* Negative testing with too many/too few limbs in a and b is covered by
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000313 * manually-written test cases with expected_ret != 0. */
Tom Cosgrove62b20482022-12-01 14:27:37 +0000314 }
315
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000316 ASSERT_ALLOC( X_raw, limbs );
317
Tom Cosgrove62b20482022-12-01 14:27:37 +0000318 TEST_EQUAL( 0, mbedtls_mpi_mod_residue_setup( &x, &m, X_raw, limbs ) );
319
320 /* a - b => Correct result, or expected error */
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000321 TEST_EQUAL( expected_ret, mbedtls_mpi_mod_sub( &x, &a, &b, &m ) );
322 if( expected_ret != 0 )
Tom Cosgrove62b20482022-12-01 14:27:37 +0000323 goto exit;
324
325 TEST_COMPARE_MPI_RESIDUES( x, d );
326
327 /* a - b: alias x to a => Correct result */
328 memcpy( x.p, a.p, bytes );
329 TEST_EQUAL( 0, mbedtls_mpi_mod_sub( &x, &x, &b, &m ) );
330 TEST_COMPARE_MPI_RESIDUES( x, d );
331
332 /* a - b: alias x to b => Correct result */
333 memcpy( x.p, b.p, bytes );
334 TEST_EQUAL( 0, mbedtls_mpi_mod_sub( &x, &a, &x, &m ) );
335 TEST_COMPARE_MPI_RESIDUES( x, d );
336
337 if ( memcmp( a.p, b.p, bytes ) == 0 )
338 {
339 /* a == b: alias a and b */
340
341 /* a - a => Correct result */
342 TEST_EQUAL( 0, mbedtls_mpi_mod_sub( &x, &a, &a, &m ) );
343 TEST_COMPARE_MPI_RESIDUES( x, d );
344
345 /* a - a: x, a, b all aliased together => Correct result */
346 memcpy( x.p, a.p, bytes );
347 TEST_EQUAL( 0, mbedtls_mpi_mod_sub( &x, &x, &x, &m ) );
348 TEST_COMPARE_MPI_RESIDUES( x, d );
349 }
350
351exit:
352 mbedtls_free( (void *)m.p ); /* mbedtls_mpi_mod_modulus_free() sets m.p = NULL */
353 mbedtls_mpi_mod_modulus_free( &m );
354
355 mbedtls_free( a.p );
356 mbedtls_free( b.p );
357 mbedtls_free( d.p );
358 mbedtls_free( X_raw );
359}
360/* END_CASE */
Tom Cosgrovedc197592022-12-15 16:59:40 +0000361
362/* BEGIN_CASE */
363void mpi_mod_inv_mont( char * input_N,
364 char * input_A, char * input_I,
365 int expected_ret )
366{
367 mbedtls_mpi_mod_residue a = { NULL, 0 }; /* argument */
368 mbedtls_mpi_mod_residue i = { NULL, 0 }; /* expected inverse wrt N */
369 mbedtls_mpi_mod_residue x = { NULL, 0 }; /* output */
370 mbedtls_mpi_uint *X_raw = NULL;
371
372 mbedtls_mpi_mod_modulus N;
373 mbedtls_mpi_mod_modulus_init( &N );
374
375 TEST_EQUAL( 0,
376 test_read_modulus( &N, MBEDTLS_MPI_MOD_REP_MONTGOMERY, input_N ) );
377
378 /* test_read_residue() normally checks that inputs have the same number of
379 * limbs as the modulus. For negative testing we can ask it to skip this
380 * with a non-zero final parameter. */
381 TEST_EQUAL( 0, test_read_residue( &a, &N, input_A, expected_ret != 0 ) );
382 TEST_EQUAL( 0, test_read_residue( &i, &N, input_I, expected_ret != 0 ) );
383
384 size_t limbs = N.limbs;
385 size_t bytes = limbs * sizeof( *X_raw );
386
387 ASSERT_ALLOC( X_raw, limbs );
388
389 TEST_EQUAL( 0, mbedtls_mpi_mod_residue_setup( &x, &N, X_raw, limbs ) );
390
391 TEST_EQUAL( expected_ret, mbedtls_mpi_mod_inv( &x, &a, &N ) );
392 if( expected_ret == 0 )
393 {
394 TEST_COMPARE_MPI_RESIDUES( x, i );
395
396 /* a^-1: alias x to a => Correct result */
397 memcpy( x.p, a.p, bytes );
398 TEST_EQUAL( 0, mbedtls_mpi_mod_inv( &x, &x, &N ) );
399 TEST_COMPARE_MPI_RESIDUES( x, i );
400 }
401
402exit:
403 mbedtls_free( (void *)N.p ); /* mbedtls_mpi_mod_modulus_free() sets N.p = NULL */
404 mbedtls_mpi_mod_modulus_free( &N );
405
406 mbedtls_free( a.p );
407 mbedtls_free( i.p );
408 mbedtls_free( X_raw );
409}
410/* END_CASE */
411
412/* BEGIN_CASE */
413void mpi_mod_inv_non_mont( char * input_N,
414 char * input_A, char * input_I,
415 int expected_ret )
416{
417 mbedtls_mpi_mod_residue a = { NULL, 0 }; /* argument */
418 mbedtls_mpi_mod_residue i = { NULL, 0 }; /* expected inverse wrt N */
419 mbedtls_mpi_mod_residue x = { NULL, 0 }; /* output */
420 mbedtls_mpi_uint *X_raw = NULL;
421
422 mbedtls_mpi_mod_modulus N;
423 mbedtls_mpi_mod_modulus_init( &N );
424
425 TEST_EQUAL( 0,
426 test_read_modulus( &N, MBEDTLS_MPI_MOD_REP_OPT_RED, input_N ) );
427
428 /* test_read_residue() normally checks that inputs have the same number of
429 * limbs as the modulus. For negative testing we can ask it to skip this
430 * with a non-zero final parameter. */
431 TEST_EQUAL( 0, test_read_residue( &a, &N, input_A, expected_ret != 0 ) );
432 TEST_EQUAL( 0, test_read_residue( &i, &N, input_I, expected_ret != 0 ) );
433
434 size_t limbs = N.limbs;
435 size_t bytes = limbs * sizeof( *X_raw );
436
437 ASSERT_ALLOC( X_raw, limbs );
438
439 TEST_EQUAL( 0, mbedtls_mpi_mod_residue_setup( &x, &N, X_raw, limbs ) );
440
441 TEST_EQUAL( expected_ret, mbedtls_mpi_mod_inv( &x, &a, &N ) );
442 if( expected_ret == 0 )
443 {
444 TEST_COMPARE_MPI_RESIDUES( x, i );
445
446 /* a^-1: alias x to a => Correct result */
447 memcpy( x.p, a.p, bytes );
448 TEST_EQUAL( 0, mbedtls_mpi_mod_inv( &x, &x, &N ) );
449 TEST_COMPARE_MPI_RESIDUES( x, i );
450 }
451
452exit:
453 mbedtls_free( (void *)N.p ); /* mbedtls_mpi_mod_modulus_free() sets N.p = NULL */
454 mbedtls_mpi_mod_modulus_free( &N );
455
456 mbedtls_free( a.p );
457 mbedtls_free( i.p );
458 mbedtls_free( X_raw );
459}
460/* END_CASE */
Janos Follath5933f692022-11-02 14:35:17 +0000461/* END MERGE SLOT 3 */
462
463/* BEGIN MERGE SLOT 4 */
464
465/* END MERGE SLOT 4 */
466
467/* BEGIN MERGE SLOT 5 */
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000468/* BEGIN_CASE */
469void mpi_mod_add( char * input_N,
470 char * input_A, char * input_B,
Werner Lewis25690a92022-12-13 17:17:34 +0000471 char * input_S, int expected_ret )
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000472{
473 mbedtls_mpi_mod_residue a = { NULL, 0 };
474 mbedtls_mpi_mod_residue b = { NULL, 0 };
475 mbedtls_mpi_mod_residue s = { NULL, 0 };
476 mbedtls_mpi_mod_residue x = { NULL, 0 };
477 mbedtls_mpi_uint *X_raw = NULL;
Janos Follath5933f692022-11-02 14:35:17 +0000478
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000479 mbedtls_mpi_mod_modulus m;
480 mbedtls_mpi_mod_modulus_init( &m );
481
482 TEST_EQUAL( 0,
483 test_read_modulus( &m, MBEDTLS_MPI_MOD_REP_MONTGOMERY, input_N ) );
484
485 /* test_read_residue() normally checks that inputs have the same number of
486 * limbs as the modulus. For negative testing we can ask it to skip this
487 * with a non-zero final parameter. */
Werner Lewis25690a92022-12-13 17:17:34 +0000488 TEST_EQUAL( 0, test_read_residue( &a, &m, input_A, expected_ret != 0 ) );
489 TEST_EQUAL( 0, test_read_residue( &b, &m, input_B, expected_ret != 0 ) );
490 TEST_EQUAL( 0, test_read_residue( &s, &m, input_S, expected_ret != 0 ) );
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000491
492 size_t limbs = m.limbs;
493 size_t bytes = limbs * sizeof( *X_raw );
494
Werner Lewis25690a92022-12-13 17:17:34 +0000495 if( expected_ret == 0 )
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000496 {
497 /* Negative test with too many limbs in output */
Werner Lewis79341a42022-12-13 17:19:01 +0000498 ASSERT_ALLOC( X_raw, limbs + 1 );
499
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000500 x.p = X_raw;
501 x.limbs = limbs + 1;
502 TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
503 mbedtls_mpi_mod_add( &x, &a, &b, &m ) );
504
Werner Lewis79341a42022-12-13 17:19:01 +0000505 mbedtls_free( X_raw );
506 X_raw = NULL;
507
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000508 /* Negative test with too few limbs in output */
509 if( limbs > 1 )
510 {
Werner Lewis79341a42022-12-13 17:19:01 +0000511 ASSERT_ALLOC( X_raw, limbs - 1 );
512
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000513 x.p = X_raw;
514 x.limbs = limbs - 1;
515 TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
516 mbedtls_mpi_mod_add( &x, &a, &b, &m ) );
Werner Lewis79341a42022-12-13 17:19:01 +0000517
518 mbedtls_free( X_raw );
519 X_raw = NULL;
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000520 }
521
522 /* Negative testing with too many/too few limbs in a and b is covered by
523 * manually-written test cases with oret != 0. */
524 }
525
Werner Lewis79341a42022-12-13 17:19:01 +0000526 /* Allocate correct number of limbs for X_raw */
527 ASSERT_ALLOC( X_raw, limbs );
528
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000529 TEST_EQUAL( 0, mbedtls_mpi_mod_residue_setup( &x, &m, X_raw, limbs ) );
530
531 /* A + B => Correct result or expected error */
Werner Lewis25690a92022-12-13 17:17:34 +0000532 TEST_EQUAL( expected_ret, mbedtls_mpi_mod_add( &x, &a, &b, &m ) );
533 if( expected_ret != 0 )
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000534 goto exit;
535
536 TEST_COMPARE_MPI_RESIDUES( x, s );
537
538 /* a + b: alias x to a => Correct result */
539 memcpy( x.p, a.p, bytes );
540 TEST_EQUAL( 0, mbedtls_mpi_mod_add( &x, &x, &b, &m ) );
541 TEST_COMPARE_MPI_RESIDUES( x, s );
542
543 /* a + b: alias x to b => Correct result */
544 memcpy( x.p, b.p, bytes );
545 TEST_EQUAL( 0, mbedtls_mpi_mod_add( &x, &a, &x, &m ) );
546 TEST_COMPARE_MPI_RESIDUES( x, s );
547
548 if ( memcmp( a.p, b.p, bytes ) == 0 )
549 {
550 /* a == b: alias a and b */
551
552 /* a + a => Correct result */
553 TEST_EQUAL( 0, mbedtls_mpi_mod_add( &x, &a, &a, &m ) );
554 TEST_COMPARE_MPI_RESIDUES( x, s );
555
556 /* a + a: x, a, b all aliased together => Correct result */
557 memcpy( x.p, a.p, bytes );
558 TEST_EQUAL( 0, mbedtls_mpi_mod_add( &x, &x, &x, &m ) );
559 TEST_COMPARE_MPI_RESIDUES( x, s );
560 }
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000561
562exit:
563 mbedtls_free( (void *)m.p ); /* mbedtls_mpi_mod_modulus_free() sets m.p = NULL */
564 mbedtls_mpi_mod_modulus_free( &m );
565
566 mbedtls_free( a.p );
567 mbedtls_free( b.p );
568 mbedtls_free( s.p );
569 mbedtls_free( X_raw );
570}
571/* END_CASE */
Janos Follath5933f692022-11-02 14:35:17 +0000572/* END MERGE SLOT 5 */
573
574/* BEGIN MERGE SLOT 6 */
575
576/* END MERGE SLOT 6 */
577
578/* BEGIN MERGE SLOT 7 */
Minos Galanakis8f242702022-11-10 16:56:02 +0000579/* BEGIN_CASE */
Janos Follath91f3abd2022-11-26 11:47:14 +0000580void mpi_residue_setup( char * input_N, char * input_R, int ret )
Minos Galanakisa17ad482022-11-16 16:29:15 +0000581{
Minos Galanakisa17ad482022-11-16 16:29:15 +0000582 mbedtls_mpi_uint *N = NULL;
583 mbedtls_mpi_uint *R = NULL;
Minos Galanakisaed832a2022-11-24 09:09:47 +0000584 size_t n_limbs, r_limbs;
Minos Galanakisa17ad482022-11-16 16:29:15 +0000585 mbedtls_mpi_mod_modulus m;
586 mbedtls_mpi_mod_residue r;
587
Minos Galanakisa17ad482022-11-16 16:29:15 +0000588 mbedtls_mpi_mod_modulus_init( &m );
589
Minos Galanakisaed832a2022-11-24 09:09:47 +0000590 /* Allocate the memory for intermediate data structures */
Janos Follath91f3abd2022-11-26 11:47:14 +0000591 TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &N, &n_limbs, input_N ) );
592 TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &R, &r_limbs, input_R ) );
Minos Galanakisaed832a2022-11-24 09:09:47 +0000593
Minos Galanakisa17ad482022-11-16 16:29:15 +0000594 TEST_EQUAL( 0, mbedtls_mpi_mod_modulus_setup( &m, N, n_limbs,
Janos Follath91295d22022-11-24 18:20:26 +0000595 MBEDTLS_MPI_MOD_REP_MONTGOMERY ) );
Minos Galanakisa17ad482022-11-16 16:29:15 +0000596
Minos Galanakisaed832a2022-11-24 09:09:47 +0000597 TEST_EQUAL( ret, mbedtls_mpi_mod_residue_setup( &r, &m, R , r_limbs ) );
Minos Galanakisa17ad482022-11-16 16:29:15 +0000598
Janos Follath91f3abd2022-11-26 11:47:14 +0000599 if ( ret == 0 )
600 {
601 TEST_EQUAL( r.limbs, r_limbs );
602 TEST_ASSERT( r.p == R );
603 }
604
Minos Galanakisa17ad482022-11-16 16:29:15 +0000605exit:
606 mbedtls_mpi_mod_modulus_free( &m );
607 mbedtls_free( N );
608 mbedtls_free( R );
Minos Galanakisa17ad482022-11-16 16:29:15 +0000609}
610/* END_CASE */
Minos Galanakisaed832a2022-11-24 09:09:47 +0000611
Minos Galanakisa17ad482022-11-16 16:29:15 +0000612/* BEGIN_CASE */
Janos Follath339b4392022-11-26 12:20:41 +0000613void mpi_mod_io_neg( char * input_N, data_t * buf, int ret )
Minos Galanakis8f242702022-11-10 16:56:02 +0000614{
Minos Galanakis8f242702022-11-10 16:56:02 +0000615 mbedtls_mpi_uint *N = NULL;
616 mbedtls_mpi_uint *R = NULL;
Minos Galanakis8f242702022-11-10 16:56:02 +0000617
618 mbedtls_mpi_mod_modulus m;
Janos Follathe7190a22022-11-26 18:46:54 +0000619 mbedtls_mpi_mod_residue r = { NULL, 0 };
Minos Galanakis96070a52022-11-25 19:32:10 +0000620 mbedtls_mpi_mod_ext_rep endian = MBEDTLS_MPI_MOD_EXT_REP_LE;
Minos Galanakis8f242702022-11-10 16:56:02 +0000621
Janos Follath799eaee2022-11-25 15:57:04 +0000622 mbedtls_mpi_mod_modulus_init( &m );
Janos Follath799eaee2022-11-25 15:57:04 +0000623
Janos Follath339b4392022-11-26 12:20:41 +0000624 size_t n_limbs;
Minos Galanakis96070a52022-11-25 19:32:10 +0000625 TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &N, &n_limbs, input_N ) );
Janos Follath339b4392022-11-26 12:20:41 +0000626 size_t r_limbs = n_limbs;
627 ASSERT_ALLOC( R, r_limbs );
Minos Galanakis8f242702022-11-10 16:56:02 +0000628
Janos Follathe7190a22022-11-26 18:46:54 +0000629 /* modulus->p == NULL || residue->p == NULL ( m has not been set-up ) */
Janos Follath3e3fc912022-11-24 18:02:46 +0000630 TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
Janos Follath566c91d2022-11-26 12:05:50 +0000631 mbedtls_mpi_mod_read( &r, &m, buf->x, buf->len, endian ) );
Minos Galanakis8f242702022-11-10 16:56:02 +0000632
Minos Galanakis96070a52022-11-25 19:32:10 +0000633 TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
Janos Follath566c91d2022-11-26 12:05:50 +0000634 mbedtls_mpi_mod_write( &r, &m, buf->x, buf->len, endian ) );
Minos Galanakis8f242702022-11-10 16:56:02 +0000635
Janos Follathe7190a22022-11-26 18:46:54 +0000636 /* Set up modulus and test with residue->p == NULL */
Minos Galanakis96070a52022-11-25 19:32:10 +0000637 TEST_EQUAL( 0, mbedtls_mpi_mod_modulus_setup( &m, N, n_limbs,
638 MBEDTLS_MPI_MOD_REP_MONTGOMERY ) );
Minos Galanakis96070a52022-11-25 19:32:10 +0000639
Minos Galanakis96070a52022-11-25 19:32:10 +0000640 TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
Janos Follathe7190a22022-11-26 18:46:54 +0000641 mbedtls_mpi_mod_read( &r, &m, buf->x, buf->len, endian ) );
Minos Galanakis96070a52022-11-25 19:32:10 +0000642 TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
Janos Follathe7190a22022-11-26 18:46:54 +0000643 mbedtls_mpi_mod_write( &r, &m, buf->x, buf->len, endian ) );
644
645 /* Do the rest of the tests with a residue set up with the input data */
646 TEST_EQUAL( 0, mbedtls_mpi_mod_residue_setup( &r, &m, R , r_limbs ) );
Minos Galanakis96070a52022-11-25 19:32:10 +0000647
Janos Follathd7bb3522022-11-26 14:59:27 +0000648 /* Fail for r_limbs < m->limbs */
649 r.limbs--;
650 TEST_ASSERT( r.limbs < m.limbs );
Minos Galanakis96070a52022-11-25 19:32:10 +0000651 TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
Janos Follath566c91d2022-11-26 12:05:50 +0000652 mbedtls_mpi_mod_read( &r, &m, buf->x, buf->len, endian ) );
Minos Galanakis96070a52022-11-25 19:32:10 +0000653 TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
Janos Follath566c91d2022-11-26 12:05:50 +0000654 mbedtls_mpi_mod_write( &r, &m, buf->x, buf->len, endian ) );
Janos Follathd7bb3522022-11-26 14:59:27 +0000655 r.limbs++;
656
657 /* Fail for r_limbs > m->limbs */
658 m.limbs--;
659 TEST_ASSERT( r.limbs > m.limbs );
660 TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
661 mbedtls_mpi_mod_read( &r, &m, buf->x, buf->len, endian ) );
662 TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
663 mbedtls_mpi_mod_write( &r, &m, buf->x, buf->len, endian ) );
664 m.limbs++;
Minos Galanakis96070a52022-11-25 19:32:10 +0000665
666 /* Test the read */
Janos Follath566c91d2022-11-26 12:05:50 +0000667 TEST_EQUAL( ret, mbedtls_mpi_mod_read( &r, &m, buf->x, buf->len, endian ) );
Minos Galanakis96070a52022-11-25 19:32:10 +0000668
669 /* Test write overflow only when the representation is large and read is successful */
Janos Follath6ef582f2022-11-26 14:19:02 +0000670 if ( r.limbs > 1 && ret == 0 )
Minos Galanakis96070a52022-11-25 19:32:10 +0000671 TEST_EQUAL( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL,
Janos Follath566c91d2022-11-26 12:05:50 +0000672 mbedtls_mpi_mod_write( &r, &m, buf->x, 1, endian ) );
Janos Follathd7bb3522022-11-26 14:59:27 +0000673
Minos Galanakis8f242702022-11-10 16:56:02 +0000674exit:
Janos Follathd7bb3522022-11-26 14:59:27 +0000675 mbedtls_mpi_mod_residue_release( &r );
Minos Galanakis8f242702022-11-10 16:56:02 +0000676 mbedtls_mpi_mod_modulus_free( &m );
Minos Galanakis8f242702022-11-10 16:56:02 +0000677 mbedtls_free( N );
678 mbedtls_free( R );
Minos Galanakis8f242702022-11-10 16:56:02 +0000679}
680/* END_CASE */
681
682/* BEGIN_CASE */
Janos Follath3e3fc912022-11-24 18:02:46 +0000683void mpi_mod_io( char * input_N, data_t * input_A, int endian )
Minos Galanakis8f242702022-11-10 16:56:02 +0000684{
685 mbedtls_mpi_uint *N = NULL;
686 mbedtls_mpi_uint *R = NULL;
Janos Follath8dfc8c42022-11-26 15:39:02 +0000687 mbedtls_mpi_uint *R_COPY = NULL;
Janos Follath0020df92022-11-26 17:23:16 +0000688 unsigned char *obuf = NULL;
689 unsigned char *ref_buf = NULL;
Minos Galanakis8f242702022-11-10 16:56:02 +0000690 mbedtls_mpi_mod_modulus m;
691 mbedtls_mpi_mod_residue r;
Janos Follath8dfc8c42022-11-26 15:39:02 +0000692 mbedtls_mpi_mod_residue r_copy;
Minos Galanakis8f242702022-11-10 16:56:02 +0000693 size_t n_limbs, n_bytes, a_bytes;
694
Janos Follath799eaee2022-11-25 15:57:04 +0000695 mbedtls_mpi_mod_modulus_init( &m );
696
Minos Galanakis8f242702022-11-10 16:56:02 +0000697 /* Read inputs */
698 TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &N, &n_limbs, input_N ) );
699 n_bytes = n_limbs * sizeof( mbedtls_mpi_uint );
Janos Follath6ef582f2022-11-26 14:19:02 +0000700 a_bytes = input_A->len;
Minos Galanakis8f242702022-11-10 16:56:02 +0000701
702 /* Allocate the memory for intermediate data structures */
703 ASSERT_ALLOC( R, n_bytes );
Janos Follath8dfc8c42022-11-26 15:39:02 +0000704 ASSERT_ALLOC( R_COPY, n_bytes );
Minos Galanakis8f242702022-11-10 16:56:02 +0000705
706 /* Test that input's size is not greater to modulo's */
Janos Follath6ef582f2022-11-26 14:19:02 +0000707 TEST_LE_U( a_bytes, n_bytes );
Minos Galanakis8f242702022-11-10 16:56:02 +0000708
709 /* Init Structures */
Janos Follath91295d22022-11-24 18:20:26 +0000710 TEST_EQUAL( 0, mbedtls_mpi_mod_modulus_setup( &m, N, n_limbs,
Minos Galanakis8f242702022-11-10 16:56:02 +0000711 MBEDTLS_MPI_MOD_REP_MONTGOMERY ) );
712
713 /* Enforcing p_limbs >= m->limbs */
Janos Follath3e3fc912022-11-24 18:02:46 +0000714 TEST_EQUAL( 0, mbedtls_mpi_mod_residue_setup( &r, &m, R, n_limbs ) );
Minos Galanakis8f242702022-11-10 16:56:02 +0000715
Janos Follath3e3fc912022-11-24 18:02:46 +0000716 TEST_EQUAL( 0, mbedtls_mpi_mod_read( &r, &m, input_A->x, input_A->len,
717 endian ) );
Minos Galanakis8f242702022-11-10 16:56:02 +0000718
Janos Follath0020df92022-11-26 17:23:16 +0000719 /* Read a copy for checking that writing didn't change the value of r */
720 TEST_EQUAL( 0, mbedtls_mpi_mod_residue_setup( &r_copy, &m,
721 R_COPY, n_limbs ) );
Janos Follath8dfc8c42022-11-26 15:39:02 +0000722 TEST_EQUAL( 0, mbedtls_mpi_mod_read( &r_copy, &m, input_A->x, input_A->len,
723 endian ) );
Janos Follath8dfc8c42022-11-26 15:39:02 +0000724
Janos Follath0020df92022-11-26 17:23:16 +0000725 /* Get number of bytes without leading zeroes */
726 size_t a_bytes_trimmed = a_bytes;
727 while( a_bytes_trimmed > 0 )
728 {
729 unsigned char* r_byte_array = (unsigned char*) r.p;
730 if( r_byte_array[--a_bytes_trimmed] != 0 )
731 break;
732 }
733 a_bytes_trimmed++;
734
735 /* Test write with three output buffer sizes: tight, same as input and
736 * longer than the input */
737 size_t obuf_sizes[3];
738 const size_t obuf_sizes_len = sizeof( obuf_sizes ) / sizeof( obuf_sizes[0] );
739 obuf_sizes[0] = a_bytes_trimmed;
740 obuf_sizes[1] = a_bytes;
741 obuf_sizes[2] = a_bytes + 8;
742
743 for( size_t i = 0; i < obuf_sizes_len; i++ )
744 {
745 ASSERT_ALLOC( obuf, obuf_sizes[i] );
746 TEST_EQUAL( 0, mbedtls_mpi_mod_write( &r, &m, obuf, obuf_sizes[i], endian ) );
747
748 /* Make sure that writing didn't corrupt the value of r */
749 ASSERT_COMPARE( r.p, r.limbs, r_copy.p, r_copy.limbs );
750
751 /* Set up reference output for checking the result */
752 ASSERT_ALLOC( ref_buf, obuf_sizes[i] );
753 switch( endian )
754 {
755 case MBEDTLS_MPI_MOD_EXT_REP_LE:
756 memcpy( ref_buf, input_A->x, a_bytes_trimmed );
757 break;
758 case MBEDTLS_MPI_MOD_EXT_REP_BE:
759 {
760 size_t a_offset = input_A->len - a_bytes_trimmed;
761 size_t ref_offset = obuf_sizes[i] - a_bytes_trimmed;
762 memcpy( ref_buf + ref_offset, input_A->x + a_offset,
763 a_bytes_trimmed );
764 }
765 break;
766 default:
767 TEST_ASSERT( 0 );
768 }
769
770 /* Check the result */
771 ASSERT_COMPARE( obuf, obuf_sizes[i], ref_buf, obuf_sizes[i] );
772
773 mbedtls_free( ref_buf );
774 ref_buf = NULL;
775 mbedtls_free( obuf );
776 obuf = NULL;
777 }
778
Minos Galanakis8f242702022-11-10 16:56:02 +0000779exit:
780 mbedtls_mpi_mod_modulus_free( &m );
781 mbedtls_free( N );
782 mbedtls_free( R );
Janos Follath8dfc8c42022-11-26 15:39:02 +0000783 mbedtls_free( R_COPY );
Janos Follath0020df92022-11-26 17:23:16 +0000784 mbedtls_free( obuf );
Minos Galanakis8f242702022-11-10 16:56:02 +0000785}
786/* END_CASE */
Janos Follath5933f692022-11-02 14:35:17 +0000787/* END MERGE SLOT 7 */
788
789/* BEGIN MERGE SLOT 8 */
790
791/* END MERGE SLOT 8 */
792
793/* BEGIN MERGE SLOT 9 */
794
795/* END MERGE SLOT 9 */
796
797/* BEGIN MERGE SLOT 10 */
798
799/* END MERGE SLOT 10 */