📄 bignum.c
字号:
*p = ( z < 0 ) ? -z : z; Y.s = ( z < 0 ) ? -1 : 1; Y.n = 1; Y.p = p; return( mpi_cmp_mpi( X, &Y ) );}/* * Unsigned addition: X = |A| + |B| (HAC 14.7) */int mpi_add_abs( mpi *X, mpi *A, mpi *B ){ int ret, i, j; t_int *o, *p, c; if( X == B ) { mpi *T = A; A = X; B = T; } if( X != A ) MPI_CHK( mpi_copy( X, A ) ); for( j = B->n - 1; j >= 0; j-- ) if( B->p[j] != 0 ) break; MPI_CHK( mpi_grow( X, j + 1 ) ); o = B->p; p = X->p; c = 0; for( i = 0; i <= j; i++, o++, p++ ) { *p += c; c = ( *p < c ); *p += *o; c += ( *p < *o ); } while( c != 0 ) { if( i >= X->n ) { MPI_CHK( mpi_grow( X, i + 1 ) ); p = X->p + i; } *p += c; c = ( *p < c ); i++; }cleanup: return( ret );}/* * Helper for mpi substraction */static void mpi_sub_hlp( int n, t_int *s, t_int *d ){ int i; t_int c, z; for( i = c = 0; i < n; i++, s++, d++ ) { z = ( *d < c ); *d -= c; c = ( *d < *s ) + z; *d -= *s; } while( c != 0 ) { z = ( *d < c ); *d -= c; c = z; i++; d++; }}/* * Unsigned substraction: X = |A| - |B| (HAC 14.9) */int mpi_sub_abs( mpi *X, mpi *A, mpi *B ){ mpi TB; int ret, n; if( mpi_cmp_abs( A, B ) < 0 ) return( XYSSL_ERR_MPI_NEGATIVE_VALUE ); mpi_init( &TB, NULL ); if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; } if( X != A ) MPI_CHK( mpi_copy( X, A ) ); ret = 0; for( n = B->n - 1; n >= 0; n-- ) if( B->p[n] != 0 ) break; mpi_sub_hlp( n + 1, B->p, X->p );cleanup: mpi_free( &TB, NULL ); return( ret );}/* * Signed addition: X = A + B */int mpi_add_mpi( mpi *X, mpi *A, mpi *B ){ int ret, s = A->s; if( A->s * B->s < 0 ) { if( mpi_cmp_abs( A, B ) >= 0 ) { MPI_CHK( mpi_sub_abs( X, A, B ) ); X->s = s; } else { MPI_CHK( mpi_sub_abs( X, B, A ) ); X->s = -s; } } else { MPI_CHK( mpi_add_abs( X, A, B ) ); X->s = s; }cleanup: return( ret );}/* * Signed substraction: X = A - B */int mpi_sub_mpi( mpi *X, mpi *A, mpi *B ){ int ret, s = A->s; if( A->s * B->s > 0 ) { if( mpi_cmp_abs( A, B ) >= 0 ) { MPI_CHK( mpi_sub_abs( X, A, B ) ); X->s = s; } else { MPI_CHK( mpi_sub_abs( X, B, A ) ); X->s = -s; } } else { MPI_CHK( mpi_add_abs( X, A, B ) ); X->s = s; }cleanup: return( ret );}/* * Signed addition: X = A + b */int mpi_add_int( mpi *X, mpi *A, int b ){ mpi _B; t_int p[1]; p[0] = ( b < 0 ) ? -b : b; _B.s = ( b < 0 ) ? -1 : 1; _B.n = 1; _B.p = p; return( mpi_add_mpi( X, A, &_B ) );}/* * Signed substraction: X = A - b */int mpi_sub_int( mpi *X, mpi *A, int b ){ mpi _B; t_int p[1]; p[0] = ( b < 0 ) ? -b : b; _B.s = ( b < 0 ) ? -1 : 1; _B.n = 1; _B.p = p; return( mpi_sub_mpi( X, A, &_B ) );}/* * Helper for mpi multiplication */ static void mpi_mul_hlp( int i, t_int *s, t_int *d, t_int b ){ t_int c = 0, t = 0;#if defined(MULADDC_HUIT) for( ; i >= 8; i -= 8 ) { MULADDC_INIT MULADDC_HUIT MULADDC_STOP } for( ; i > 0; i-- ) { MULADDC_INIT MULADDC_CORE MULADDC_STOP }#else for( ; i >= 16; i -= 16 ) { MULADDC_INIT MULADDC_CORE MULADDC_CORE MULADDC_CORE MULADDC_CORE MULADDC_CORE MULADDC_CORE MULADDC_CORE MULADDC_CORE MULADDC_CORE MULADDC_CORE MULADDC_CORE MULADDC_CORE MULADDC_CORE MULADDC_CORE MULADDC_CORE MULADDC_CORE MULADDC_STOP } for( ; i >= 8; i -= 8 ) { MULADDC_INIT MULADDC_CORE MULADDC_CORE MULADDC_CORE MULADDC_CORE MULADDC_CORE MULADDC_CORE MULADDC_CORE MULADDC_CORE MULADDC_STOP } for( ; i > 0; i-- ) { MULADDC_INIT MULADDC_CORE MULADDC_STOP }#endif t++; do { *d += c; c = ( *d < c ); d++; } while( c != 0 );}/* * Baseline multiplication: X = A * B (HAC 14.12) */int mpi_mul_mpi( mpi *X, mpi *A, mpi *B ){ int ret, i, j; mpi TA, TB; mpi_init( &TA, &TB, NULL ); if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; } if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; } for( i = A->n - 1; i >= 0; i-- ) if( A->p[i] != 0 ) break; for( j = B->n - 1; j >= 0; j-- ) if( B->p[j] != 0 ) break; MPI_CHK( mpi_grow( X, i + j + 2 ) ); MPI_CHK( mpi_lset( X, 0 ) ); for( i++; j >= 0; j-- ) mpi_mul_hlp( i, A->p, X->p + j, B->p[j] ); X->s = A->s * B->s;cleanup: mpi_free( &TB, &TA, NULL ); return( ret );}/* * Baseline multiplication: X = A * b */int mpi_mul_int( mpi *X, mpi *A, t_int b ){ mpi _B; t_int p[1]; _B.s = 1; _B.n = 1; _B.p = p; p[0] = b; return( mpi_mul_mpi( X, A, &_B ) );}/* * Division by mpi: A = Q * B + R (HAC 14.20) */int mpi_div_mpi( mpi *Q, mpi *R, mpi *A, mpi *B ){ int ret, i, n, t, k; mpi X, Y, Z, T1, T2; if( mpi_cmp_int( B, 0 ) == 0 ) return( XYSSL_ERR_MPI_DIVISION_BY_ZERO ); mpi_init( &X, &Y, &Z, &T1, &T2, NULL ); if( mpi_cmp_abs( A, B ) < 0 ) { if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) ); if( R != NULL ) MPI_CHK( mpi_copy( R, A ) ); return( 0 ); } MPI_CHK( mpi_copy( &X, A ) ); MPI_CHK( mpi_copy( &Y, B ) ); X.s = Y.s = 1; MPI_CHK( mpi_grow( &Z, A->n + 2 ) ); MPI_CHK( mpi_lset( &Z, 0 ) ); MPI_CHK( mpi_grow( &T1, 2 ) ); MPI_CHK( mpi_grow( &T2, 3 ) ); k = mpi_msb( &Y ) % biL; if( k < (int) biL - 1 ) { k = biL - 1 - k; MPI_CHK( mpi_shift_l( &X, k ) ); MPI_CHK( mpi_shift_l( &Y, k ) ); } else k = 0; n = X.n - 1; t = Y.n - 1; mpi_shift_l( &Y, biL * (n - t) ); while( mpi_cmp_mpi( &X, &Y ) >= 0 ) { Z.p[n - t]++; mpi_sub_mpi( &X, &X, &Y ); } mpi_shift_r( &Y, biL * (n - t) ); for( i = n; i > t ; i-- ) { if( X.p[i] >= Y.p[t] ) Z.p[i - t - 1] = ~0; else {#if defined(XYSSL_HAVE_LONGLONG) t_dbl r; r = (t_dbl) X.p[i] << biL; r |= (t_dbl) X.p[i - 1]; r /= Y.p[t]; if( r > ((t_dbl) 1 << biL) - 1) r = ((t_dbl) 1 << biL) - 1; Z.p[i - t - 1] = (t_int) r;#else /* * __udiv_qrnnd_c, from gmp/longlong.h */ t_int q0, q1, r0, r1; t_int d0, d1, d, m; d = Y.p[t]; d0 = ( d << biH ) >> biH; d1 = ( d >> biH ); q1 = X.p[i] / d1; r1 = X.p[i] - d1 * q1; r1 <<= biH; r1 |= ( X.p[i - 1] >> biH ); m = q1 * d0; if( r1 < m ) { q1--, r1 += d; while( r1 >= d && r1 < m ) q1--, r1 += d; } r1 -= m; q0 = r1 / d1; r0 = r1 - d1 * q0; r0 <<= biH; r0 |= ( X.p[i - 1] << biH ) >> biH; m = q0 * d0; if( r0 < m ) { q0--, r0 += d; while( r0 >= d && r0 < m ) q0--, r0 += d; } r0 -= m; Z.p[i - t - 1] = ( q1 << biH ) | q0;#endif } Z.p[i - t - 1]++; do { Z.p[i - t - 1]--; MPI_CHK( mpi_lset( &T1, 0 ) ); T1.p[0] = (t < 1) ? 0 : Y.p[t - 1]; T1.p[1] = Y.p[t]; MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) ); MPI_CHK( mpi_lset( &T2, 0 ) ); T2.p[0] = (i < 2) ? 0 : X.p[i - 2]; T2.p[1] = (i < 1) ? 0 : X.p[i - 1]; T2.p[2] = X.p[i]; } while( mpi_cmp_mpi( &T1, &T2 ) > 0 ); MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) ); MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) ); MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) ); if( mpi_cmp_int( &X, 0 ) < 0 ) { MPI_CHK( mpi_copy( &T1, &Y ) ); MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) ); MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) ); Z.p[i - t - 1]--; } } if( Q != NULL ) { mpi_copy( Q, &Z ); Q->s = A->s * B->s; } if( R != NULL ) { mpi_shift_r( &X, k ); mpi_copy( R, &X ); R->s = A->s; if( mpi_cmp_int( R, 0 ) == 0 ) R->s = 1; }cleanup: mpi_free( &X, &Y, &Z, &T1, &T2, NULL ); return( ret );}/* * Division by int: A = Q * b + R * * Returns 0 if successful * 1 if memory allocation failed * XYSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0 */int mpi_div_int( mpi *Q, mpi *R, mpi *A, int b ){ mpi _B; t_int p[1]; p[0] = ( b < 0 ) ? -b : b; _B.s = ( b < 0 ) ? -1 : 1; _B.n = 1; _B.p = p; return( mpi_div_mpi( Q, R, A, &_B ) );}/* * Modulo: R = A mod B */int mpi_mod_mpi( mpi *R, mpi *A, mpi *B ){ int ret; MPI_CHK( mpi_div_mpi( NULL, R, A, B ) ); while( mpi_cmp_int( R, 0 ) < 0 ) MPI_CHK( mpi_add_mpi( R, R, B ) ); while( mpi_cmp_mpi( R, B ) >= 0 ) MPI_CHK( mpi_sub_mpi( R, R, B ) );cleanup: return( ret );}/* * Modulo: r = A mod b */int mpi_mod_int( t_int *r, mpi *A, int b ){ int i; t_int x, y, z; if( b == 0 ) return( XYSSL_ERR_MPI_DIVISION_BY_ZERO ); if( b < 0 ) b = -b; /* * handle trivial cases */ if( b == 1 ) { *r = 0; return( 0 ); } if( b == 2 ) { *r = A->p[0] & 1; return( 0 ); } /* * general case */ for( i = A->n - 1, y = 0; i >= 0; i-- ) { x = A->p[i]; y = ( y << biH ) | ( x >> biH ); z = y / b; y -= z * b; x <<= biH; y = ( y << biH ) | ( x >> biH ); z = y / b; y -= z * b; } *r = y; return( 0 );}/* * Fast Montgomery initialization (thanks to Tom St Denis) */static void mpi_montg_init( t_int *mm, mpi *N ){ t_int x, m0 = N->p[0]; x = m0; x += ( ( m0 + 2 ) & 4 ) << 1; x *= ( 2 - ( m0 * x ) ); if( biL >= 16 ) x *= ( 2 - ( m0 * x ) ); if( biL >= 32 ) x *= ( 2 - ( m0 * x ) ); if( biL >= 64 ) x *= ( 2 - ( m0 * x ) ); *mm = ~x + 1;}/* * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) */static void mpi_montmul( mpi *A, mpi *B, mpi *N, t_int mm, mpi *T ){ int i, n, m; t_int u0, u1, *d; memset( T->p, 0, T->n * ciL ); d = T->p; n = N->n; m = ( B->n < n ) ? B->n : n; for( i = 0; i < n; i++ ) { /* * T = (T + u0*B + u1*N) / 2^biL */ u0 = A->p[i]; u1 = ( d[0] + u0 * B->p[0] ) * mm; mpi_mul_hlp( m, B->p, d, u0 ); mpi_mul_hlp( n, N->p, d, u1 ); *d++ = u0; d[n + 1] = 0; } memcpy( A->p, d, (n + 1) * ciL ); if( mpi_cmp_abs( A, N ) >= 0 ) mpi_sub_hlp( n, N->p, A->p ); else /* prevent timing attacks */ mpi_sub_hlp( n, A->p, T->p );}/* * Montgomery reduction: A = A * R^-1 mod N */static void mpi_montred( mpi *A, mpi *N, t_int mm, mpi *T ){ t_int z = 1; mpi U; U.n = U.s = z; U.p = &z; mpi_montmul( A, &U, N, mm, T );}/* * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) */int mpi_exp_mod( mpi *X, mpi *A, mpi *E, mpi *N, mpi *_RR ){ int ret, i, j, wsize, wbits; int bufsize, nblimbs, nbits; t_int ei, mm, state; mpi RR, T, W[64];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -