diff options
Diffstat (limited to 'src/lib/libcrypto/bn/bn_lib.c')
-rw-r--r-- | src/lib/libcrypto/bn/bn_lib.c | 336 |
1 files changed, 196 insertions, 140 deletions
diff --git a/src/lib/libcrypto/bn/bn_lib.c b/src/lib/libcrypto/bn/bn_lib.c index 7767d65170..a016cb7f53 100644 --- a/src/lib/libcrypto/bn/bn_lib.c +++ b/src/lib/libcrypto/bn/bn_lib.c | |||
@@ -128,7 +128,7 @@ int BN_get_params(int which) | |||
128 | else return(0); | 128 | else return(0); |
129 | } | 129 | } |
130 | 130 | ||
131 | BIGNUM *BN_value_one(void) | 131 | const BIGNUM *BN_value_one(void) |
132 | { | 132 | { |
133 | static BN_ULONG data_one=1L; | 133 | static BN_ULONG data_one=1L; |
134 | static BIGNUM const_one={&data_one,1,1,0}; | 134 | static BIGNUM const_one={&data_one,1,1,0}; |
@@ -305,172 +305,168 @@ BIGNUM *BN_new(void) | |||
305 | return(ret); | 305 | return(ret); |
306 | } | 306 | } |
307 | 307 | ||
308 | /* This is an internal function that should not be used in applications. | 308 | /* This is used both by bn_expand2() and bn_dup_expand() */ |
309 | * It ensures that 'b' has enough room for a 'words' word number number. | 309 | /* The caller MUST check that words > b->dmax before calling this */ |
310 | * It is mostly used by the various BIGNUM routines. If there is an error, | 310 | static BN_ULONG *bn_expand_internal(const BIGNUM *b, int words) |
311 | * NULL is returned. If not, 'b' is returned. */ | ||
312 | |||
313 | BIGNUM *bn_expand2(BIGNUM *b, int words) | ||
314 | { | 311 | { |
315 | BN_ULONG *A,*a; | 312 | BN_ULONG *A,*a = NULL; |
316 | const BN_ULONG *B; | 313 | const BN_ULONG *B; |
317 | int i; | 314 | int i; |
318 | 315 | ||
319 | bn_check_top(b); | 316 | if (words > (INT_MAX/(4*BN_BITS2))) |
317 | { | ||
318 | BNerr(BN_F_BN_EXPAND_INTERNAL,BN_R_BIGNUM_TOO_LONG); | ||
319 | return NULL; | ||
320 | } | ||
320 | 321 | ||
321 | if (words > b->dmax) | 322 | bn_check_top(b); |
323 | if (BN_get_flags(b,BN_FLG_STATIC_DATA)) | ||
322 | { | 324 | { |
323 | if (words > (INT_MAX/(4*BN_BITS2))) | 325 | BNerr(BN_F_BN_EXPAND_INTERNAL,BN_R_EXPAND_ON_STATIC_BIGNUM_DATA); |
324 | { | 326 | return(NULL); |
325 | BNerr(BN_F_BN_EXPAND2,BN_R_BIGNUM_TOO_LONG); | 327 | } |
326 | return NULL; | 328 | a=A=(BN_ULONG *)OPENSSL_malloc(sizeof(BN_ULONG)*(words+1)); |
327 | } | 329 | if (A == NULL) |
328 | 330 | { | |
329 | bn_check_top(b); | 331 | BNerr(BN_F_BN_EXPAND_INTERNAL,ERR_R_MALLOC_FAILURE); |
330 | if (BN_get_flags(b,BN_FLG_STATIC_DATA)) | 332 | return(NULL); |
333 | } | ||
334 | #if 1 | ||
335 | B=b->d; | ||
336 | /* Check if the previous number needs to be copied */ | ||
337 | if (B != NULL) | ||
338 | { | ||
339 | for (i=b->top>>2; i>0; i--,A+=4,B+=4) | ||
331 | { | 340 | { |
332 | BNerr(BN_F_BN_EXPAND2,BN_R_EXPAND_ON_STATIC_BIGNUM_DATA); | 341 | /* |
333 | return(NULL); | 342 | * The fact that the loop is unrolled |
343 | * 4-wise is a tribute to Intel. It's | ||
344 | * the one that doesn't have enough | ||
345 | * registers to accomodate more data. | ||
346 | * I'd unroll it 8-wise otherwise:-) | ||
347 | * | ||
348 | * <appro@fy.chalmers.se> | ||
349 | */ | ||
350 | BN_ULONG a0,a1,a2,a3; | ||
351 | a0=B[0]; a1=B[1]; a2=B[2]; a3=B[3]; | ||
352 | A[0]=a0; A[1]=a1; A[2]=a2; A[3]=a3; | ||
334 | } | 353 | } |
335 | a=A=(BN_ULONG *)OPENSSL_malloc(sizeof(BN_ULONG)*(words+1)); | 354 | switch (b->top&3) |
336 | if (A == NULL) | ||
337 | { | 355 | { |
338 | BNerr(BN_F_BN_EXPAND2,ERR_R_MALLOC_FAILURE); | 356 | case 3: A[2]=B[2]; |
339 | return(NULL); | 357 | case 2: A[1]=B[1]; |
358 | case 1: A[0]=B[0]; | ||
359 | case 0: /* workaround for ultrix cc: without 'case 0', the optimizer does | ||
360 | * the switch table by doing a=top&3; a--; goto jump_table[a]; | ||
361 | * which fails for top== 0 */ | ||
362 | ; | ||
340 | } | 363 | } |
341 | #if 1 | 364 | } |
342 | B=b->d; | 365 | |
343 | /* Check if the previous number needs to be copied */ | 366 | /* Now need to zero any data between b->top and b->max */ |
344 | if (B != NULL) | 367 | /* XXX Why? */ |
345 | { | 368 | |
346 | #if 0 | 369 | A= &(a[b->top]); |
347 | /* This lot is an unrolled loop to copy b->top | 370 | for (i=(words - b->top)>>3; i>0; i--,A+=8) |
348 | * BN_ULONGs from B to A | 371 | { |
349 | */ | 372 | A[0]=0; A[1]=0; A[2]=0; A[3]=0; |
350 | /* | 373 | A[4]=0; A[5]=0; A[6]=0; A[7]=0; |
351 | * I have nothing against unrolling but it's usually done for | 374 | } |
352 | * several reasons, namely: | 375 | for (i=(words - b->top)&7; i>0; i--,A++) |
353 | * - minimize percentage of decision making code, i.e. branches; | 376 | A[0]=0; |
354 | * - avoid cache trashing; | ||
355 | * - make it possible to schedule loads earlier; | ||
356 | * Now let's examine the code below. The cornerstone of C is | ||
357 | * "programmer is always right" and that's what we love it for:-) | ||
358 | * For this very reason C compilers have to be paranoid when it | ||
359 | * comes to data aliasing and assume the worst. Yeah, but what | ||
360 | * does it mean in real life? This means that loop body below will | ||
361 | * be compiled to sequence of loads immediately followed by stores | ||
362 | * as compiler assumes the worst, something in A==B+1 style. As a | ||
363 | * result CPU pipeline is going to starve for incoming data. Secondly | ||
364 | * if A and B happen to share same cache line such code is going to | ||
365 | * cause severe cache trashing. Both factors have severe impact on | ||
366 | * performance of modern CPUs and this is the reason why this | ||
367 | * particular piece of code is #ifdefed away and replaced by more | ||
368 | * "friendly" version found in #else section below. This comment | ||
369 | * also applies to BN_copy function. | ||
370 | * | ||
371 | * <appro@fy.chalmers.se> | ||
372 | */ | ||
373 | for (i=b->top&(~7); i>0; i-=8) | ||
374 | { | ||
375 | A[0]=B[0]; A[1]=B[1]; A[2]=B[2]; A[3]=B[3]; | ||
376 | A[4]=B[4]; A[5]=B[5]; A[6]=B[6]; A[7]=B[7]; | ||
377 | A+=8; | ||
378 | B+=8; | ||
379 | } | ||
380 | switch (b->top&7) | ||
381 | { | ||
382 | case 7: | ||
383 | A[6]=B[6]; | ||
384 | case 6: | ||
385 | A[5]=B[5]; | ||
386 | case 5: | ||
387 | A[4]=B[4]; | ||
388 | case 4: | ||
389 | A[3]=B[3]; | ||
390 | case 3: | ||
391 | A[2]=B[2]; | ||
392 | case 2: | ||
393 | A[1]=B[1]; | ||
394 | case 1: | ||
395 | A[0]=B[0]; | ||
396 | case 0: | ||
397 | /* I need the 'case 0' entry for utrix cc. | ||
398 | * If the optimizer is turned on, it does the | ||
399 | * switch table by doing | ||
400 | * a=top&7 | ||
401 | * a--; | ||
402 | * goto jump_table[a]; | ||
403 | * If top is 0, this makes us jump to 0xffffffc | ||
404 | * which is rather bad :-(. | ||
405 | * eric 23-Apr-1998 | ||
406 | */ | ||
407 | ; | ||
408 | } | ||
409 | #else | 377 | #else |
410 | for (i=b->top>>2; i>0; i--,A+=4,B+=4) | 378 | memset(A,0,sizeof(BN_ULONG)*(words+1)); |
379 | memcpy(A,b->d,sizeof(b->d[0])*b->top); | ||
380 | #endif | ||
381 | |||
382 | return(a); | ||
383 | } | ||
384 | |||
385 | /* This is an internal function that can be used instead of bn_expand2() | ||
386 | * when there is a need to copy BIGNUMs instead of only expanding the | ||
387 | * data part, while still expanding them. | ||
388 | * Especially useful when needing to expand BIGNUMs that are declared | ||
389 | * 'const' and should therefore not be changed. | ||
390 | * The reason to use this instead of a BN_dup() followed by a bn_expand2() | ||
391 | * is memory allocation overhead. A BN_dup() followed by a bn_expand2() | ||
392 | * will allocate new memory for the BIGNUM data twice, and free it once, | ||
393 | * while bn_dup_expand() makes sure allocation is made only once. | ||
394 | */ | ||
395 | |||
396 | BIGNUM *bn_dup_expand(const BIGNUM *b, int words) | ||
397 | { | ||
398 | BIGNUM *r = NULL; | ||
399 | |||
400 | if (words > b->dmax) | ||
401 | { | ||
402 | BN_ULONG *a = bn_expand_internal(b, words); | ||
403 | |||
404 | if (a) | ||
405 | { | ||
406 | r = BN_new(); | ||
407 | if (r) | ||
411 | { | 408 | { |
412 | /* | 409 | r->top = b->top; |
413 | * The fact that the loop is unrolled | 410 | r->dmax = words; |
414 | * 4-wise is a tribute to Intel. It's | 411 | r->neg = b->neg; |
415 | * the one that doesn't have enough | 412 | r->d = a; |
416 | * registers to accomodate more data. | ||
417 | * I'd unroll it 8-wise otherwise:-) | ||
418 | * | ||
419 | * <appro@fy.chalmers.se> | ||
420 | */ | ||
421 | BN_ULONG a0,a1,a2,a3; | ||
422 | a0=B[0]; a1=B[1]; a2=B[2]; a3=B[3]; | ||
423 | A[0]=a0; A[1]=a1; A[2]=a2; A[3]=a3; | ||
424 | } | 413 | } |
425 | switch (b->top&3) | 414 | else |
426 | { | 415 | { |
427 | case 3: A[2]=B[2]; | 416 | /* r == NULL, BN_new failure */ |
428 | case 2: A[1]=B[1]; | 417 | OPENSSL_free(a); |
429 | case 1: A[0]=B[0]; | ||
430 | case 0: ; /* ultrix cc workaround, see above */ | ||
431 | } | 418 | } |
432 | #endif | ||
433 | OPENSSL_free(b->d); | ||
434 | } | 419 | } |
420 | /* If a == NULL, there was an error in allocation in | ||
421 | bn_expand_internal(), and NULL should be returned */ | ||
422 | } | ||
423 | else | ||
424 | { | ||
425 | r = BN_dup(b); | ||
426 | } | ||
435 | 427 | ||
436 | b->d=a; | 428 | return r; |
437 | b->dmax=words; | 429 | } |
430 | |||
431 | /* This is an internal function that should not be used in applications. | ||
432 | * It ensures that 'b' has enough room for a 'words' word number number. | ||
433 | * It is mostly used by the various BIGNUM routines. If there is an error, | ||
434 | * NULL is returned. If not, 'b' is returned. */ | ||
438 | 435 | ||
439 | /* Now need to zero any data between b->top and b->max */ | 436 | BIGNUM *bn_expand2(BIGNUM *b, int words) |
437 | { | ||
438 | if (words > b->dmax) | ||
439 | { | ||
440 | BN_ULONG *a = bn_expand_internal(b, words); | ||
440 | 441 | ||
441 | A= &(b->d[b->top]); | 442 | if (a) |
442 | for (i=(b->dmax - b->top)>>3; i>0; i--,A+=8) | ||
443 | { | 443 | { |
444 | A[0]=0; A[1]=0; A[2]=0; A[3]=0; | 444 | if (b->d) |
445 | A[4]=0; A[5]=0; A[6]=0; A[7]=0; | 445 | OPENSSL_free(b->d); |
446 | } | ||
447 | for (i=(b->dmax - b->top)&7; i>0; i--,A++) | ||
448 | A[0]=0; | ||
449 | #else | ||
450 | memset(A,0,sizeof(BN_ULONG)*(words+1)); | ||
451 | memcpy(A,b->d,sizeof(b->d[0])*b->top); | ||
452 | b->d=a; | 446 | b->d=a; |
453 | b->max=words; | 447 | b->dmax=words; |
454 | #endif | 448 | } |
455 | 449 | else | |
456 | /* memset(&(p[b->max]),0,((words+1)-b->max)*sizeof(BN_ULONG)); */ | 450 | b = NULL; |
457 | /* { int i; for (i=b->max; i<words+1; i++) p[i]=i;} */ | ||
458 | |||
459 | } | 451 | } |
460 | return(b); | 452 | return b; |
461 | } | 453 | } |
462 | 454 | ||
463 | BIGNUM *BN_dup(const BIGNUM *a) | 455 | BIGNUM *BN_dup(const BIGNUM *a) |
464 | { | 456 | { |
465 | BIGNUM *r; | 457 | BIGNUM *r, *t; |
466 | 458 | ||
467 | if (a == NULL) return NULL; | 459 | if (a == NULL) return NULL; |
468 | 460 | ||
469 | bn_check_top(a); | 461 | bn_check_top(a); |
470 | 462 | ||
471 | r=BN_new(); | 463 | t = BN_new(); |
472 | if (r == NULL) return(NULL); | 464 | if (t == NULL) return(NULL); |
473 | return((BIGNUM *)BN_copy(r,a)); | 465 | r = BN_copy(t, a); |
466 | /* now r == t || r == NULL */ | ||
467 | if (r == NULL) | ||
468 | BN_free(t); | ||
469 | return r; | ||
474 | } | 470 | } |
475 | 471 | ||
476 | BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b) | 472 | BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b) |
@@ -498,7 +494,7 @@ BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b) | |||
498 | case 3: A[2]=B[2]; | 494 | case 3: A[2]=B[2]; |
499 | case 2: A[1]=B[1]; | 495 | case 2: A[1]=B[1]; |
500 | case 1: A[0]=B[0]; | 496 | case 1: A[0]=B[0]; |
501 | case 0: ; /* ultrix cc workaround, see comments in bn_expand2 */ | 497 | case 0: ; /* ultrix cc workaround, see comments in bn_expand_internal */ |
502 | } | 498 | } |
503 | #else | 499 | #else |
504 | memcpy(a->d,b->d,sizeof(b->d[0])*b->top); | 500 | memcpy(a->d,b->d,sizeof(b->d[0])*b->top); |
@@ -512,6 +508,35 @@ BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b) | |||
512 | return(a); | 508 | return(a); |
513 | } | 509 | } |
514 | 510 | ||
511 | void BN_swap(BIGNUM *a, BIGNUM *b) | ||
512 | { | ||
513 | int flags_old_a, flags_old_b; | ||
514 | BN_ULONG *tmp_d; | ||
515 | int tmp_top, tmp_dmax, tmp_neg; | ||
516 | |||
517 | flags_old_a = a->flags; | ||
518 | flags_old_b = b->flags; | ||
519 | |||
520 | tmp_d = a->d; | ||
521 | tmp_top = a->top; | ||
522 | tmp_dmax = a->dmax; | ||
523 | tmp_neg = a->neg; | ||
524 | |||
525 | a->d = b->d; | ||
526 | a->top = b->top; | ||
527 | a->dmax = b->dmax; | ||
528 | a->neg = b->neg; | ||
529 | |||
530 | b->d = tmp_d; | ||
531 | b->top = tmp_top; | ||
532 | b->dmax = tmp_dmax; | ||
533 | b->neg = tmp_neg; | ||
534 | |||
535 | a->flags = (flags_old_a & BN_FLG_MALLOCED) | (flags_old_b & BN_FLG_STATIC_DATA); | ||
536 | b->flags = (flags_old_b & BN_FLG_MALLOCED) | (flags_old_a & BN_FLG_STATIC_DATA); | ||
537 | } | ||
538 | |||
539 | |||
515 | void BN_clear(BIGNUM *a) | 540 | void BN_clear(BIGNUM *a) |
516 | { | 541 | { |
517 | if (a->d != NULL) | 542 | if (a->d != NULL) |
@@ -520,7 +545,7 @@ void BN_clear(BIGNUM *a) | |||
520 | a->neg=0; | 545 | a->neg=0; |
521 | } | 546 | } |
522 | 547 | ||
523 | BN_ULONG BN_get_word(BIGNUM *a) | 548 | BN_ULONG BN_get_word(const BIGNUM *a) |
524 | { | 549 | { |
525 | int i,n; | 550 | int i,n; |
526 | BN_ULONG ret=0; | 551 | BN_ULONG ret=0; |
@@ -568,7 +593,6 @@ int BN_set_word(BIGNUM *a, BN_ULONG w) | |||
568 | return(1); | 593 | return(1); |
569 | } | 594 | } |
570 | 595 | ||
571 | /* ignore negative */ | ||
572 | BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret) | 596 | BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret) |
573 | { | 597 | { |
574 | unsigned int i,m; | 598 | unsigned int i,m; |
@@ -589,6 +613,7 @@ BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret) | |||
589 | i=((n-1)/BN_BYTES)+1; | 613 | i=((n-1)/BN_BYTES)+1; |
590 | m=((n-1)%(BN_BYTES)); | 614 | m=((n-1)%(BN_BYTES)); |
591 | ret->top=i; | 615 | ret->top=i; |
616 | ret->neg=0; | ||
592 | while (n-- > 0) | 617 | while (n-- > 0) |
593 | { | 618 | { |
594 | l=(l<<8L)| *(s++); | 619 | l=(l<<8L)| *(s++); |
@@ -743,7 +768,7 @@ int BN_mask_bits(BIGNUM *a, int n) | |||
743 | return(1); | 768 | return(1); |
744 | } | 769 | } |
745 | 770 | ||
746 | int bn_cmp_words(BN_ULONG *a, BN_ULONG *b, int n) | 771 | int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n) |
747 | { | 772 | { |
748 | int i; | 773 | int i; |
749 | BN_ULONG aa,bb; | 774 | BN_ULONG aa,bb; |
@@ -760,3 +785,34 @@ int bn_cmp_words(BN_ULONG *a, BN_ULONG *b, int n) | |||
760 | return(0); | 785 | return(0); |
761 | } | 786 | } |
762 | 787 | ||
788 | /* Here follows a specialised variants of bn_cmp_words(). It has the | ||
789 | property of performing the operation on arrays of different sizes. | ||
790 | The sizes of those arrays is expressed through cl, which is the | ||
791 | common length ( basicall, min(len(a),len(b)) ), and dl, which is the | ||
792 | delta between the two lengths, calculated as len(a)-len(b). | ||
793 | All lengths are the number of BN_ULONGs... */ | ||
794 | |||
795 | int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, | ||
796 | int cl, int dl) | ||
797 | { | ||
798 | int n,i; | ||
799 | n = cl-1; | ||
800 | |||
801 | if (dl < 0) | ||
802 | { | ||
803 | for (i=dl; i<0; i++) | ||
804 | { | ||
805 | if (b[n-i] != 0) | ||
806 | return -1; /* a < b */ | ||
807 | } | ||
808 | } | ||
809 | if (dl > 0) | ||
810 | { | ||
811 | for (i=dl; i>0; i--) | ||
812 | { | ||
813 | if (a[n+i] != 0) | ||
814 | return 1; /* a > b */ | ||
815 | } | ||
816 | } | ||
817 | return bn_cmp_words(a,b,cl); | ||
818 | } | ||