1/* BEGIN_HEADER */ 2#include "mbedtls/bignum.h" 3#include "mbedtls/entropy.h" 4#include "bignum_mod.h" 5#include "constant_time_internal.h" 6#include "test/constant_flow.h" 7 8#define TEST_COMPARE_MPI_RESIDUES( a, b ) \ 9 ASSERT_COMPARE( (a).p, (a).limbs * sizeof(mbedtls_mpi_uint), \ 10 (b).p, (b).limbs * sizeof(mbedtls_mpi_uint) ) 11 12static int test_read_modulus( mbedtls_mpi_mod_modulus *m, 13 mbedtls_mpi_mod_rep_selector int_rep, 14 char *input ) 15{ 16 mbedtls_mpi_uint *p = NULL; 17 size_t limbs; 18 19 int ret = mbedtls_test_read_mpi_core( &p, &limbs, input ); 20 if( ret != 0 ) 21 return( ret ); 22 23 return( mbedtls_mpi_mod_modulus_setup( m, p, limbs, int_rep ) ); 24} 25 26static int test_read_residue( mbedtls_mpi_mod_residue *r, 27 const mbedtls_mpi_mod_modulus *m, 28 char *input, 29 int skip_limbs_and_value_checks ) 30{ 31 mbedtls_mpi_uint *p = NULL; 32 size_t limbs; 33 34 int ret = mbedtls_test_read_mpi_core( &p, &limbs, input ); 35 if( ret != 0 ) 36 return( ret ); 37 38 if( skip_limbs_and_value_checks ) 39 { 40 r->p = p; 41 r->limbs = limbs; 42 return( 0 ); 43 } 44 45 /* mbedtls_mpi_mod_residue_setup() checks limbs, and that value < m */ 46 return( mbedtls_mpi_mod_residue_setup( r, m, p, limbs ) ); 47} 48/* END_HEADER */ 49 50/* BEGIN_DEPENDENCIES 51 * depends_on:MBEDTLS_BIGNUM_C 52 * END_DEPENDENCIES 53 */ 54 55/* BEGIN_CASE */ 56void mpi_mod_setup( int int_rep, int iret ) 57{ 58 #define MLIMBS 8 59 mbedtls_mpi_uint mp[MLIMBS]; 60 mbedtls_mpi_mod_modulus m; 61 int ret; 62 63 memset( mp, 0xFF, sizeof(mp) ); 64 65 mbedtls_mpi_mod_modulus_init( &m ); 66 ret = mbedtls_mpi_mod_modulus_setup( &m, mp, MLIMBS, int_rep ); 67 TEST_EQUAL( ret, iret ); 68 69 /* Only test if the constants have been set-up */ 70 if ( ret == 0 && int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY ) 71 { 72 /* Test that the consts have been calculated */ 73 TEST_ASSERT( m.rep.mont.rr != NULL ); 74 TEST_ASSERT( m.rep.mont.mm != 0 ); 75 76 } 77 78 /* Address sanitiser should catch if we try to free mp */ 79 mbedtls_mpi_mod_modulus_free( &m ); 80 81 /* Make sure that the modulus doesn't have reference to mp anymore */ 82 TEST_ASSERT( m.p != mp ); 83 84 /* Only test if the constants have been set-up */ 85 if ( ret == 0 && int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY ) 86 { 87 /* Verify the data and pointers allocated have been properly wiped */ 88 TEST_ASSERT( m.rep.mont.rr == NULL ); 89 TEST_ASSERT( m.rep.mont.mm == 0 ); 90 } 91exit: 92 /* It should be safe to call an mbedtls free several times */ 93 mbedtls_mpi_mod_modulus_free( &m ); 94 95 #undef MLIMBS 96} 97/* END_CASE */ 98 99/* BEGIN MERGE SLOT 1 */ 100 101/* END MERGE SLOT 1 */ 102 103/* BEGIN MERGE SLOT 2 */ 104 105/* END MERGE SLOT 2 */ 106 107/* BEGIN MERGE SLOT 3 */ 108/* BEGIN_CASE */ 109void mpi_mod_sub( char * input_N, 110 char * input_A, char * input_B, 111 char * input_D, int oret ) 112{ 113 mbedtls_mpi_mod_residue a = { NULL, 0 }; 114 mbedtls_mpi_mod_residue b = { NULL, 0 }; 115 mbedtls_mpi_mod_residue d = { NULL, 0 }; 116 mbedtls_mpi_mod_residue x = { NULL, 0 }; 117 mbedtls_mpi_uint *X_raw = NULL; 118 119 mbedtls_mpi_mod_modulus m; 120 mbedtls_mpi_mod_modulus_init( &m ); 121 122 TEST_EQUAL( 0, 123 test_read_modulus( &m, MBEDTLS_MPI_MOD_REP_MONTGOMERY, input_N ) ); 124 125 /* test_read_residue() normally checks that inputs have the same number of 126 * limbs as the modulus. For negative testing we can ask it to skip this 127 * with a non-zero final parameter. */ 128 TEST_EQUAL( 0, test_read_residue( &a, &m, input_A, oret != 0 ) ); 129 TEST_EQUAL( 0, test_read_residue( &b, &m, input_B, oret != 0 ) ); 130 TEST_EQUAL( 0, test_read_residue( &d, &m, input_D, oret != 0 ) ); 131 132 size_t limbs = m.limbs; 133 size_t bytes = limbs * sizeof( *X_raw ); 134 135 /* One spare limb for negative testing */ 136 ASSERT_ALLOC( X_raw, limbs + 1 ); 137 138 if( oret == 0 ) 139 { 140 /* Sneak in a couple of negative tests on known-good data */ 141 142 /* First, negative test with too many limbs in output */ 143 x.p = X_raw; 144 x.limbs = limbs + 1; 145 TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA, 146 mbedtls_mpi_mod_sub( &x, &a, &b, &m ) ); 147 148 /* Then negative test with too few limbs in output */ 149 if( limbs > 1 ) 150 { 151 x.p = X_raw; 152 x.limbs = limbs - 1; 153 TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA, 154 mbedtls_mpi_mod_sub( &x, &a, &b, &m ) ); 155 } 156 157 /* Negative testing with too many/too few limbs in a and b is covered by 158 * manually-written test cases with oret != 0. */ 159 160 /* Back to the normally-scheduled programme */ 161 } 162 163 TEST_EQUAL( 0, mbedtls_mpi_mod_residue_setup( &x, &m, X_raw, limbs ) ); 164 165 /* a - b => Correct result, or expected error */ 166 TEST_EQUAL( oret, mbedtls_mpi_mod_sub( &x, &a, &b, &m ) ); 167 if( oret != 0 ) 168 goto exit; 169 170 TEST_COMPARE_MPI_RESIDUES( x, d ); 171 172 /* a - b: alias x to a => Correct result */ 173 memcpy( x.p, a.p, bytes ); 174 TEST_EQUAL( 0, mbedtls_mpi_mod_sub( &x, &x, &b, &m ) ); 175 TEST_COMPARE_MPI_RESIDUES( x, d ); 176 177 /* a - b: alias x to b => Correct result */ 178 memcpy( x.p, b.p, bytes ); 179 TEST_EQUAL( 0, mbedtls_mpi_mod_sub( &x, &a, &x, &m ) ); 180 TEST_COMPARE_MPI_RESIDUES( x, d ); 181 182 if ( memcmp( a.p, b.p, bytes ) == 0 ) 183 { 184 /* a == b: alias a and b */ 185 186 /* a - a => Correct result */ 187 TEST_EQUAL( 0, mbedtls_mpi_mod_sub( &x, &a, &a, &m ) ); 188 TEST_COMPARE_MPI_RESIDUES( x, d ); 189 190 /* a - a: x, a, b all aliased together => Correct result */ 191 memcpy( x.p, a.p, bytes ); 192 TEST_EQUAL( 0, mbedtls_mpi_mod_sub( &x, &x, &x, &m ) ); 193 TEST_COMPARE_MPI_RESIDUES( x, d ); 194 } 195 196exit: 197 mbedtls_free( (void *)m.p ); /* mbedtls_mpi_mod_modulus_free() sets m.p = NULL */ 198 mbedtls_mpi_mod_modulus_free( &m ); 199 200 mbedtls_free( a.p ); 201 mbedtls_free( b.p ); 202 mbedtls_free( d.p ); 203 mbedtls_free( X_raw ); 204} 205/* END_CASE */ 206/* END MERGE SLOT 3 */ 207 208/* BEGIN MERGE SLOT 4 */ 209 210/* END MERGE SLOT 4 */ 211 212/* BEGIN MERGE SLOT 5 */ 213 214/* END MERGE SLOT 5 */ 215 216/* BEGIN MERGE SLOT 6 */ 217 218/* END MERGE SLOT 6 */ 219 220/* BEGIN MERGE SLOT 7 */ 221/* BEGIN_CASE */ 222void mpi_residue_setup( char * input_N, char * input_R, int ret ) 223{ 224 mbedtls_mpi_uint *N = NULL; 225 mbedtls_mpi_uint *R = NULL; 226 size_t n_limbs, r_limbs; 227 mbedtls_mpi_mod_modulus m; 228 mbedtls_mpi_mod_residue r; 229 230 mbedtls_mpi_mod_modulus_init( &m ); 231 232 /* Allocate the memory for intermediate data structures */ 233 TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &N, &n_limbs, input_N ) ); 234 TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &R, &r_limbs, input_R ) ); 235 236 TEST_EQUAL( 0, mbedtls_mpi_mod_modulus_setup( &m, N, n_limbs, 237 MBEDTLS_MPI_MOD_REP_MONTGOMERY ) ); 238 239 TEST_EQUAL( ret, mbedtls_mpi_mod_residue_setup( &r, &m, R , r_limbs ) ); 240 241 if ( ret == 0 ) 242 { 243 TEST_EQUAL( r.limbs, r_limbs ); 244 TEST_ASSERT( r.p == R ); 245 } 246 247exit: 248 mbedtls_mpi_mod_modulus_free( &m ); 249 mbedtls_free( N ); 250 mbedtls_free( R ); 251} 252/* END_CASE */ 253 254/* BEGIN_CASE */ 255void mpi_mod_io_neg( char * input_N, data_t * buf, int ret ) 256{ 257 mbedtls_mpi_uint *N = NULL; 258 mbedtls_mpi_uint *R = NULL; 259 260 mbedtls_mpi_mod_modulus m; 261 mbedtls_mpi_mod_residue r = { NULL, 0 }; 262 mbedtls_mpi_mod_ext_rep endian = MBEDTLS_MPI_MOD_EXT_REP_LE; 263 264 mbedtls_mpi_mod_modulus_init( &m ); 265 266 size_t n_limbs; 267 TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &N, &n_limbs, input_N ) ); 268 size_t r_limbs = n_limbs; 269 ASSERT_ALLOC( R, r_limbs ); 270 271 /* modulus->p == NULL || residue->p == NULL ( m has not been set-up ) */ 272 TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA, 273 mbedtls_mpi_mod_read( &r, &m, buf->x, buf->len, endian ) ); 274 275 TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA, 276 mbedtls_mpi_mod_write( &r, &m, buf->x, buf->len, endian ) ); 277 278 /* Set up modulus and test with residue->p == NULL */ 279 TEST_EQUAL( 0, mbedtls_mpi_mod_modulus_setup( &m, N, n_limbs, 280 MBEDTLS_MPI_MOD_REP_MONTGOMERY ) ); 281 282 TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA, 283 mbedtls_mpi_mod_read( &r, &m, buf->x, buf->len, endian ) ); 284 TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA, 285 mbedtls_mpi_mod_write( &r, &m, buf->x, buf->len, endian ) ); 286 287 /* Do the rest of the tests with a residue set up with the input data */ 288 TEST_EQUAL( 0, mbedtls_mpi_mod_residue_setup( &r, &m, R , r_limbs ) ); 289 290 /* Fail for r_limbs < m->limbs */ 291 r.limbs--; 292 TEST_ASSERT( r.limbs < m.limbs ); 293 TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA, 294 mbedtls_mpi_mod_read( &r, &m, buf->x, buf->len, endian ) ); 295 TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA, 296 mbedtls_mpi_mod_write( &r, &m, buf->x, buf->len, endian ) ); 297 r.limbs++; 298 299 /* Fail for r_limbs > m->limbs */ 300 m.limbs--; 301 TEST_ASSERT( r.limbs > m.limbs ); 302 TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA, 303 mbedtls_mpi_mod_read( &r, &m, buf->x, buf->len, endian ) ); 304 TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA, 305 mbedtls_mpi_mod_write( &r, &m, buf->x, buf->len, endian ) ); 306 m.limbs++; 307 308 /* Test the read */ 309 TEST_EQUAL( ret, mbedtls_mpi_mod_read( &r, &m, buf->x, buf->len, endian ) ); 310 311 /* Test write overflow only when the representation is large and read is successful */ 312 if ( r.limbs > 1 && ret == 0 ) 313 TEST_EQUAL( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL, 314 mbedtls_mpi_mod_write( &r, &m, buf->x, 1, endian ) ); 315 316exit: 317 mbedtls_mpi_mod_residue_release( &r ); 318 mbedtls_mpi_mod_modulus_free( &m ); 319 mbedtls_free( N ); 320 mbedtls_free( R ); 321} 322/* END_CASE */ 323 324/* BEGIN_CASE */ 325void mpi_mod_io( char * input_N, data_t * input_A, int endian ) 326{ 327 mbedtls_mpi_uint *N = NULL; 328 mbedtls_mpi_uint *R = NULL; 329 mbedtls_mpi_uint *R_COPY = NULL; 330 unsigned char *obuf = NULL; 331 unsigned char *ref_buf = NULL; 332 mbedtls_mpi_mod_modulus m; 333 mbedtls_mpi_mod_residue r; 334 mbedtls_mpi_mod_residue r_copy; 335 size_t n_limbs, n_bytes, a_bytes; 336 337 mbedtls_mpi_mod_modulus_init( &m ); 338 339 /* Read inputs */ 340 TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &N, &n_limbs, input_N ) ); 341 n_bytes = n_limbs * sizeof( mbedtls_mpi_uint ); 342 a_bytes = input_A->len; 343 344 /* Allocate the memory for intermediate data structures */ 345 ASSERT_ALLOC( R, n_bytes ); 346 ASSERT_ALLOC( R_COPY, n_bytes ); 347 348 /* Test that input's size is not greater to modulo's */ 349 TEST_LE_U( a_bytes, n_bytes ); 350 351 /* Init Structures */ 352 TEST_EQUAL( 0, mbedtls_mpi_mod_modulus_setup( &m, N, n_limbs, 353 MBEDTLS_MPI_MOD_REP_MONTGOMERY ) ); 354 355 /* Enforcing p_limbs >= m->limbs */ 356 TEST_EQUAL( 0, mbedtls_mpi_mod_residue_setup( &r, &m, R, n_limbs ) ); 357 358 TEST_EQUAL( 0, mbedtls_mpi_mod_read( &r, &m, input_A->x, input_A->len, 359 endian ) ); 360 361 /* Read a copy for checking that writing didn't change the value of r */ 362 TEST_EQUAL( 0, mbedtls_mpi_mod_residue_setup( &r_copy, &m, 363 R_COPY, n_limbs ) ); 364 TEST_EQUAL( 0, mbedtls_mpi_mod_read( &r_copy, &m, input_A->x, input_A->len, 365 endian ) ); 366 367 /* Get number of bytes without leading zeroes */ 368 size_t a_bytes_trimmed = a_bytes; 369 while( a_bytes_trimmed > 0 ) 370 { 371 unsigned char* r_byte_array = (unsigned char*) r.p; 372 if( r_byte_array[--a_bytes_trimmed] != 0 ) 373 break; 374 } 375 a_bytes_trimmed++; 376 377 /* Test write with three output buffer sizes: tight, same as input and 378 * longer than the input */ 379 size_t obuf_sizes[3]; 380 const size_t obuf_sizes_len = sizeof( obuf_sizes ) / sizeof( obuf_sizes[0] ); 381 obuf_sizes[0] = a_bytes_trimmed; 382 obuf_sizes[1] = a_bytes; 383 obuf_sizes[2] = a_bytes + 8; 384 385 for( size_t i = 0; i < obuf_sizes_len; i++ ) 386 { 387 ASSERT_ALLOC( obuf, obuf_sizes[i] ); 388 TEST_EQUAL( 0, mbedtls_mpi_mod_write( &r, &m, obuf, obuf_sizes[i], endian ) ); 389 390 /* Make sure that writing didn't corrupt the value of r */ 391 ASSERT_COMPARE( r.p, r.limbs, r_copy.p, r_copy.limbs ); 392 393 /* Set up reference output for checking the result */ 394 ASSERT_ALLOC( ref_buf, obuf_sizes[i] ); 395 switch( endian ) 396 { 397 case MBEDTLS_MPI_MOD_EXT_REP_LE: 398 memcpy( ref_buf, input_A->x, a_bytes_trimmed ); 399 break; 400 case MBEDTLS_MPI_MOD_EXT_REP_BE: 401 { 402 size_t a_offset = input_A->len - a_bytes_trimmed; 403 size_t ref_offset = obuf_sizes[i] - a_bytes_trimmed; 404 memcpy( ref_buf + ref_offset, input_A->x + a_offset, 405 a_bytes_trimmed ); 406 } 407 break; 408 default: 409 TEST_ASSERT( 0 ); 410 } 411 412 /* Check the result */ 413 ASSERT_COMPARE( obuf, obuf_sizes[i], ref_buf, obuf_sizes[i] ); 414 415 mbedtls_free( ref_buf ); 416 ref_buf = NULL; 417 mbedtls_free( obuf ); 418 obuf = NULL; 419 } 420 421exit: 422 mbedtls_mpi_mod_modulus_free( &m ); 423 mbedtls_free( N ); 424 mbedtls_free( R ); 425 mbedtls_free( R_COPY ); 426 mbedtls_free( obuf ); 427} 428/* END_CASE */ 429/* END MERGE SLOT 7 */ 430 431/* BEGIN MERGE SLOT 8 */ 432 433/* END MERGE SLOT 8 */ 434 435/* BEGIN MERGE SLOT 9 */ 436 437/* END MERGE SLOT 9 */ 438 439/* BEGIN MERGE SLOT 10 */ 440 441/* END MERGE SLOT 10 */ 442