CHECK_RETVAL_BOOL \ static BOOLEAN selfTestGeneralOps1( void ) { BIGNUM a; /* Simple tests that don't need the support of higher-level routines like importBignum() */ BN_init( &a ); if( !BN_zero( &a ) ) return( FALSE ); if( !BN_is_zero( &a ) || BN_is_one( &a ) ) return( FALSE ); if( !BN_is_word( &a, 0 ) || BN_is_word( &a, 1 ) ) return( FALSE ); if( BN_is_odd( &a ) ) return( FALSE ); if( BN_get_word( &a ) != 0 ) return( FALSE ); if( !BN_one( &a ) ) return( FALSE ); if( BN_is_zero( &a ) || !BN_is_one( &a ) ) return( FALSE ); if( BN_is_word( &a, 0 ) || !BN_is_word( &a, 1 ) ) return( FALSE ); if( !BN_is_odd( &a ) ) return( FALSE ); if( BN_num_bytes( &a ) != 1 ) return( FALSE ); if( BN_get_word( &a ) != 1 ) return( FALSE ); BN_clear( &a ); return( TRUE ); }
int BN_is_prime_fasttest_ex(const BIGNUM *a, int checks, BN_CTX *ctx, int do_trial_division, BN_GENCB *cb) { if (BN_cmp(a, BN_value_one()) <= 0) { return 0; } /* first look for small factors */ if (!BN_is_odd(a)) { /* a is even => a is prime if and only if a == 2 */ return BN_is_word(a, 2); } /* Enhanced Miller-Rabin does not work for three. */ if (BN_is_word(a, 3)) { return 1; } if (do_trial_division) { for (int i = 1; i < NUMPRIMES; i++) { BN_ULONG mod = BN_mod_word(a, primes[i]); if (mod == (BN_ULONG)-1) { return -1; } if (mod == 0) { return BN_is_word(a, primes[i]); } } if (!BN_GENCB_call(cb, 1, -1)) { return -1; } } int ret = -1; BN_CTX *ctx_allocated = NULL; if (ctx == NULL) { ctx_allocated = BN_CTX_new(); if (ctx_allocated == NULL) { return -1; } ctx = ctx_allocated; } enum bn_primality_result_t result; if (!BN_enhanced_miller_rabin_primality_test(&result, a, checks, ctx, cb)) { goto err; } ret = (result == bn_probably_prime); err: BN_CTX_free(ctx_allocated); return ret; }
int DH_check(const DH *dh, int *ret) { int ok = 0; BN_CTX *ctx = NULL; BN_ULONG l; BIGNUM *q = NULL; *ret = 0; ctx = BN_CTX_new(); if (ctx == NULL) goto err; q = BN_new(); if (q == NULL) goto err; if (BN_is_word(dh->g, DH_GENERATOR_2)) { l = BN_mod_word(dh->p, 24); if (l != 11) *ret |= DH_NOT_SUITABLE_GENERATOR; } # if 0 else if (BN_is_word(dh->g, DH_GENERATOR_3)) { l = BN_mod_word(dh->p, 12); if (l != 5) *ret |= DH_NOT_SUITABLE_GENERATOR; } # endif else if (BN_is_word(dh->g, DH_GENERATOR_5)) { l = BN_mod_word(dh->p, 10); if ((l != 3) && (l != 7)) *ret |= DH_NOT_SUITABLE_GENERATOR; } else *ret |= DH_UNABLE_TO_CHECK_GENERATOR; if (!BN_is_prime_ex(dh->p, BN_prime_checks, ctx, NULL)) *ret |= DH_CHECK_P_NOT_PRIME; else { if (!BN_rshift1(q, dh->p)) goto err; if (!BN_is_prime_ex(q, BN_prime_checks, ctx, NULL)) *ret |= DH_CHECK_P_NOT_SAFE_PRIME; } ok = 1; err: if (ctx != NULL) BN_CTX_free(ctx); if (q != NULL) BN_free(q); return (ok); }
/* See FIPS 186-4 C.3.1 Miller Rabin Probabilistic Primality Test. */ int BN_is_prime_fasttest_ex(const BIGNUM *w, int checks, BN_CTX *ctx_passed, int do_trial_division, BN_GENCB *cb) { int i, status, ret = -1; BN_CTX *ctx = NULL; /* w must be bigger than 1 */ if (BN_cmp(w, BN_value_one()) <= 0) return 0; /* w must be odd */ if (BN_is_odd(w)) { /* Take care of the really small prime 3 */ if (BN_is_word(w, 3)) return 1; } else { /* 2 is the only even prime */ return BN_is_word(w, 2); } /* first look for small factors */ if (do_trial_division) { for (i = 1; i < NUMPRIMES; i++) { BN_ULONG mod = BN_mod_word(w, primes[i]); if (mod == (BN_ULONG)-1) return -1; if (mod == 0) return BN_is_word(w, primes[i]); } if (!BN_GENCB_call(cb, 1, -1)) return -1; } if (ctx_passed != NULL) ctx = ctx_passed; else if ((ctx = BN_CTX_new()) == NULL) goto err; ret = bn_miller_rabin_is_prime(w, checks, ctx, cb, 0, &status); if (!ret) goto err; ret = (status == BN_PRIMETEST_PROBABLY_PRIME); err: if (ctx_passed == NULL) BN_CTX_free(ctx); return ret; }
BIGNUM *BN_mod_inverse(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx) { BIGNUM *A,*B,*X,*Y,*M,*D,*T,*R=NULL; BIGNUM *ret=NULL; int sign; if ((BN_get_flags(a, BN_FLG_CONSTTIME) != 0) || (BN_get_flags(n, BN_FLG_CONSTTIME) != 0)) { return BN_mod_inverse_no_branch(in, a, n, ctx); } bn_check_top(a); bn_check_top(n); BN_CTX_start(ctx); A = BN_CTX_get(ctx); B = BN_CTX_get(ctx); X = BN_CTX_get(ctx); D = BN_CTX_get(ctx); M = BN_CTX_get(ctx); Y = BN_CTX_get(ctx); T = BN_CTX_get(ctx); if (T == NULL) goto err; if (in == NULL) R=BN_new(); else R=in; if (R == NULL) goto err; BN_one(X); BN_zero(Y); if (BN_copy(B,a) == NULL) goto err; if (BN_copy(A,n) == NULL) goto err; A->neg = 0; if (B->neg || (BN_ucmp(B, A) >= 0)) { if (!BN_nnmod(B, B, A, ctx)) goto err; } sign = -1; /* From B = a mod |n|, A = |n| it follows that * * 0 <= B < A, * -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|). */ if (BN_is_odd(n) && (BN_num_bits(n) <= (BN_BITS <= 32 ? 450 : 2048))) { /* Binary inversion algorithm; requires odd modulus. * This is faster than the general algorithm if the modulus * is sufficiently small (about 400 .. 500 bits on 32-bit * sytems, but much more on 64-bit systems) */ int shift; while (!BN_is_zero(B)) { /* * 0 < B < |n|, * 0 < A <= |n|, * (1) -sign*X*a == B (mod |n|), * (2) sign*Y*a == A (mod |n|) */ /* Now divide B by the maximum possible power of two in the integers, * and divide X by the same value mod |n|. * When we're done, (1) still holds. */ shift = 0; while (!BN_is_bit_set(B, shift)) /* note that 0 < B */ { shift++; if (BN_is_odd(X)) { if (!BN_uadd(X, X, n)) goto err; } /* now X is even, so we can easily divide it by two */ if (!BN_rshift1(X, X)) goto err; } if (shift > 0) { if (!BN_rshift(B, B, shift)) goto err; } /* Same for A and Y. Afterwards, (2) still holds. */ shift = 0; while (!BN_is_bit_set(A, shift)) /* note that 0 < A */ { shift++; if (BN_is_odd(Y)) { if (!BN_uadd(Y, Y, n)) goto err; } /* now Y is even */ if (!BN_rshift1(Y, Y)) goto err; } if (shift > 0) { if (!BN_rshift(A, A, shift)) goto err; } /* We still have (1) and (2). * Both A and B are odd. * The following computations ensure that * * 0 <= B < |n|, * 0 < A < |n|, * (1) -sign*X*a == B (mod |n|), * (2) sign*Y*a == A (mod |n|), * * and that either A or B is even in the next iteration. */ if (BN_ucmp(B, A) >= 0) { /* -sign*(X + Y)*a == B - A (mod |n|) */ if (!BN_uadd(X, X, Y)) goto err; /* NB: we could use BN_mod_add_quick(X, X, Y, n), but that * actually makes the algorithm slower */ if (!BN_usub(B, B, A)) goto err; } else { /* sign*(X + Y)*a == A - B (mod |n|) */ if (!BN_uadd(Y, Y, X)) goto err; /* as above, BN_mod_add_quick(Y, Y, X, n) would slow things down */ if (!BN_usub(A, A, B)) goto err; } } } else { /* general inversion algorithm */ while (!BN_is_zero(B)) { BIGNUM *tmp; /* * 0 < B < A, * (*) -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|) */ /* (D, M) := (A/B, A%B) ... */ if (BN_num_bits(A) == BN_num_bits(B)) { if (!BN_one(D)) goto err; if (!BN_sub(M,A,B)) goto err; } else if (BN_num_bits(A) == BN_num_bits(B) + 1) { /* A/B is 1, 2, or 3 */ if (!BN_lshift1(T,B)) goto err; if (BN_ucmp(A,T) < 0) { /* A < 2*B, so D=1 */ if (!BN_one(D)) goto err; if (!BN_sub(M,A,B)) goto err; } else { /* A >= 2*B, so D=2 or D=3 */ if (!BN_sub(M,A,T)) goto err; if (!BN_add(D,T,B)) goto err; /* use D (:= 3*B) as temp */ if (BN_ucmp(A,D) < 0) { /* A < 3*B, so D=2 */ if (!BN_set_word(D,2)) goto err; /* M (= A - 2*B) already has the correct value */ } else { /* only D=3 remains */ if (!BN_set_word(D,3)) goto err; /* currently M = A - 2*B, but we need M = A - 3*B */ if (!BN_sub(M,M,B)) goto err; } } } else { if (!BN_div(D,M,A,B,ctx)) goto err; } /* Now * A = D*B + M; * thus we have * (**) sign*Y*a == D*B + M (mod |n|). */ tmp=A; /* keep the BIGNUM object, the value does not matter */ /* (A, B) := (B, A mod B) ... */ A=B; B=M; /* ... so we have 0 <= B < A again */ /* Since the former M is now B and the former B is now A, * (**) translates into * sign*Y*a == D*A + B (mod |n|), * i.e. * sign*Y*a - D*A == B (mod |n|). * Similarly, (*) translates into * -sign*X*a == A (mod |n|). * * Thus, * sign*Y*a + D*sign*X*a == B (mod |n|), * i.e. * sign*(Y + D*X)*a == B (mod |n|). * * So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at * -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|). * Note that X and Y stay non-negative all the time. */ /* most of the time D is very small, so we can optimize tmp := D*X+Y */ if (BN_is_one(D)) { if (!BN_add(tmp,X,Y)) goto err; } else { if (BN_is_word(D,2)) { if (!BN_lshift1(tmp,X)) goto err; } else if (BN_is_word(D,4)) { if (!BN_lshift(tmp,X,2)) goto err; } else if (D->top == 1) { if (!BN_copy(tmp,X)) goto err; if (!BN_mul_word(tmp,D->d[0])) goto err; } else { if (!BN_mul(tmp,D,X,ctx)) goto err; } if (!BN_add(tmp,tmp,Y)) goto err; } M=Y; /* keep the BIGNUM object, the value does not matter */ Y=X; X=tmp; sign = -sign; } } /* * The while loop (Euclid's algorithm) ends when * A == gcd(a,n); * we have * sign*Y*a == A (mod |n|), * where Y is non-negative. */ if (sign < 0) { if (!BN_sub(Y,n,Y)) goto err; } /* Now Y*a == A (mod |n|). */ if (BN_is_one(A)) { /* Y*a == 1 (mod |n|) */ if (!Y->neg && BN_ucmp(Y,n) < 0) { if (!BN_copy(R,Y)) goto err; } else { if (!BN_nnmod(R,Y,n,ctx)) goto err; } } else { BNerr(BN_F_BN_MOD_INVERSE,BN_R_NO_INVERSE); goto err; } ret=R; err: if ((ret == NULL) && (in == NULL)) BN_free(R); BN_CTX_end(ctx); bn_check_top(ret); return(ret); }
int DH_check(const DH *dh, int *ret) { /* Check that p is a safe prime and if g is 2, 3 or 5, check that it is a * suitable generator where: * for 2, p mod 24 == 11 * for 3, p mod 12 == 5 * for 5, p mod 10 == 3 or 7 * should hold. */ int ok = 0, r; BN_CTX *ctx = NULL; BN_ULONG l; BIGNUM *t1 = NULL, *t2 = NULL; *ret = 0; ctx = BN_CTX_new(); if (ctx == NULL) { goto err; } BN_CTX_start(ctx); t1 = BN_CTX_get(ctx); if (t1 == NULL) { goto err; } t2 = BN_CTX_get(ctx); if (t2 == NULL) { goto err; } if (dh->q) { if (BN_cmp(dh->g, BN_value_one()) <= 0) { *ret |= DH_CHECK_NOT_SUITABLE_GENERATOR; } else if (BN_cmp(dh->g, dh->p) >= 0) { *ret |= DH_CHECK_NOT_SUITABLE_GENERATOR; } else { /* Check g^q == 1 mod p */ if (!BN_mod_exp(t1, dh->g, dh->q, dh->p, ctx)) { goto err; } if (!BN_is_one(t1)) { *ret |= DH_CHECK_NOT_SUITABLE_GENERATOR; } } r = BN_is_prime_ex(dh->q, BN_prime_checks, ctx, NULL); if (r < 0) { goto err; } if (!r) { *ret |= DH_CHECK_Q_NOT_PRIME; } /* Check p == 1 mod q i.e. q divides p - 1 */ if (!BN_div(t1, t2, dh->p, dh->q, ctx)) { goto err; } if (!BN_is_one(t2)) { *ret |= DH_CHECK_INVALID_Q_VALUE; } if (dh->j && BN_cmp(dh->j, t1)) { *ret |= DH_CHECK_INVALID_J_VALUE; } } else if (BN_is_word(dh->g, DH_GENERATOR_2)) { l = BN_mod_word(dh->p, 24); if (l == (BN_ULONG)-1) { goto err; } if (l != 11) { *ret |= DH_CHECK_NOT_SUITABLE_GENERATOR; } } else if (BN_is_word(dh->g, DH_GENERATOR_5)) { l = BN_mod_word(dh->p, 10); if (l == (BN_ULONG)-1) { goto err; } if (l != 3 && l != 7) { *ret |= DH_CHECK_NOT_SUITABLE_GENERATOR; } } else { *ret |= DH_CHECK_UNABLE_TO_CHECK_GENERATOR; } r = BN_is_prime_ex(dh->p, BN_prime_checks, ctx, NULL); if (r < 0) { goto err; } if (!r) { *ret |= DH_CHECK_P_NOT_PRIME; } else if (!dh->q) { if (!BN_rshift1(t1, dh->p)) { goto err; } r = BN_is_prime_ex(t1, BN_prime_checks, ctx, NULL); if (r < 0) { goto err; } if (!r) { *ret |= DH_CHECK_P_NOT_SAFE_PRIME; } } ok = 1; err: if (ctx != NULL) { BN_CTX_end(ctx); BN_CTX_free(ctx); } return ok; }
int BN_is_prime_fasttest_ex(const BIGNUM *a, int checks, BN_CTX *ctx_passed, int do_trial_division, BN_GENCB *cb) { int i, j, ret = -1; int k; BN_CTX *ctx = NULL; BIGNUM *A1, *A1_odd, *check; /* taken from ctx */ BN_MONT_CTX *mont = NULL; const BIGNUM *A = NULL; if (BN_cmp(a, BN_value_one()) <= 0) return 0; if (checks == BN_prime_checks) checks = BN_prime_checks_for_size(BN_num_bits(a)); /* first look for small factors */ if (!BN_is_odd(a)) /* a is even => a is prime if and only if a == 2 */ return BN_is_word(a, 2); if (do_trial_division) { for (i = 1; i < NUMPRIMES; i++) if (BN_mod_word(a, primes[i]) == 0) return 0; if(!BN_GENCB_call(cb, 1, -1)) goto err; } if (ctx_passed != NULL) ctx = ctx_passed; else if ((ctx=BN_CTX_new()) == NULL) goto err; BN_CTX_start(ctx); /* A := abs(a) */ if (a->neg) { BIGNUM *t; if ((t = BN_CTX_get(ctx)) == NULL) goto err; BN_copy(t, a); t->neg = 0; A = t; } else A = a; A1 = BN_CTX_get(ctx); A1_odd = BN_CTX_get(ctx); check = BN_CTX_get(ctx); if (check == NULL) goto err; /* compute A1 := A - 1 */ if (!BN_copy(A1, A)) goto err; if (!BN_sub_word(A1, 1)) goto err; if (BN_is_zero(A1)) { ret = 0; goto err; } /* write A1 as A1_odd * 2^k */ k = 1; while (!BN_is_bit_set(A1, k)) k++; if (!BN_rshift(A1_odd, A1, k)) goto err; /* Montgomery setup for computations mod A */ mont = BN_MONT_CTX_new(); if (mont == NULL) goto err; if (!BN_MONT_CTX_set(mont, A, ctx)) goto err; for (i = 0; i < checks; i++) { if (!BN_pseudo_rand_range(check, A1)) goto err; if (!BN_add_word(check, 1)) goto err; /* now 1 <= check < A */ j = witness(check, A, A1, A1_odd, k, ctx, mont); if (j == -1) goto err; if (j) { ret=0; goto err; } if(!BN_GENCB_call(cb, 1, i)) goto err; } ret=1; err: if (ctx != NULL) { BN_CTX_end(ctx); if (ctx_passed == NULL) BN_CTX_free(ctx); } if (mont != NULL) BN_MONT_CTX_free(mont); return(ret); }
// generate_prime sets |out| to a prime with length |bits| such that |out|-1 is // relatively prime to |e|. If |p| is non-NULL, |out| will also not be close to // |p|. |sqrt2| must be ⌊2^(bits-1)×√2⌋ (or a slightly overestimate for large // sizes), and |pow2_bits_100| must be 2^(bits-100). static int generate_prime(BIGNUM *out, int bits, const BIGNUM *e, const BIGNUM *p, const BIGNUM *sqrt2, const BIGNUM *pow2_bits_100, BN_CTX *ctx, BN_GENCB *cb) { if (bits < 128 || (bits % BN_BITS2) != 0) { OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); return 0; } assert(BN_is_pow2(pow2_bits_100)); assert(BN_is_bit_set(pow2_bits_100, bits - 100)); // See FIPS 186-4 appendix B.3.3, steps 4 and 5. Note |bits| here is nlen/2. // Use the limit from steps 4.7 and 5.8 for most values of |e|. When |e| is 3, // the 186-4 limit is too low, so we use a higher one. Note this case is not // reachable from |RSA_generate_key_fips|. if (bits >= INT_MAX/32) { OPENSSL_PUT_ERROR(RSA, RSA_R_MODULUS_TOO_LARGE); return 0; } int limit = BN_is_word(e, 3) ? bits * 32 : bits * 5; int ret = 0, tries = 0, rand_tries = 0; BN_CTX_start(ctx); BIGNUM *tmp = BN_CTX_get(ctx); if (tmp == NULL) { goto err; } for (;;) { // Generate a random number of length |bits| where the bottom bit is set // (steps 4.2, 4.3, 5.2 and 5.3) and the top bit is set (implied by the // bound checked below in steps 4.4 and 5.5). if (!BN_rand(out, bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ODD) || !BN_GENCB_call(cb, BN_GENCB_GENERATED, rand_tries++)) { goto err; } if (p != NULL) { // If |p| and |out| are too close, try again (step 5.4). if (!bn_abs_sub_consttime(tmp, out, p, ctx)) { goto err; } if (BN_cmp(tmp, pow2_bits_100) <= 0) { continue; } } // If out < 2^(bits-1)×√2, try again (steps 4.4 and 5.5). This is equivalent // to out <= ⌊2^(bits-1)×√2⌋, or out <= sqrt2 for FIPS key sizes. // // For larger keys, the comparison is approximate, leaning towards // retrying. That is, we reject a negligible fraction of primes that are // within the FIPS bound, but we will never accept a prime outside the // bound, ensuring the resulting RSA key is the right size. if (BN_cmp(out, sqrt2) <= 0) { continue; } // RSA key generation's bottleneck is discarding composites. If it fails // trial division, do not bother computing a GCD or performing Rabin-Miller. if (!bn_odd_number_is_obviously_composite(out)) { // Check gcd(out-1, e) is one (steps 4.5 and 5.6). int relatively_prime; if (!BN_sub(tmp, out, BN_value_one()) || !bn_is_relatively_prime(&relatively_prime, tmp, e, ctx)) { goto err; } if (relatively_prime) { // Test |out| for primality (steps 4.5.1 and 5.6.1). int is_probable_prime; if (!BN_primality_test(&is_probable_prime, out, BN_prime_checks, ctx, 0, cb)) { goto err; } if (is_probable_prime) { ret = 1; goto err; } } } // If we've tried too many times to find a prime, abort (steps 4.7 and // 5.8). tries++; if (tries >= limit) { OPENSSL_PUT_ERROR(RSA, RSA_R_TOO_MANY_ITERATIONS); goto err; } if (!BN_GENCB_call(cb, 2, tries)) { goto err; } } err: BN_CTX_end(ctx); return ret; }
/* create a new key. we need a way to specify creation of a key with OAEP * padding as well as PKCSv1.5, since signatures will need to be done on * data larger than 20 bytes, which is the max size *regardless of key size* * for an OAEP key signing using the TPM */ static int tpm_rsa_keygen(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb) { TSS_RESULT result; TSS_FLAG initFlags = TSS_KEY_TYPE_LEGACY; UINT32 encScheme, sigScheme; TSS_HKEY hKey; /* XXX allow this to be specified through pre commands */ sigScheme = TSS_SS_RSASSAPKCS1V15_DER; encScheme = TSS_ES_RSAESPKCSV15; DBG("%s", __FUNCTION__); if (!BN_is_word(e, 65537)) { TSSerr(TPM_F_TPM_RSA_KEYGEN, TPM_R_INVALID_EXPONENT); return 0; } /* set e in the RSA object as done in the built-in openssl function */ if (!rsa->e && ((rsa->e = BN_new()) == NULL)) { TSSerr(TPM_F_TPM_RSA_KEYGEN, ERR_R_MALLOC_FAILURE); return 0; } BN_copy(rsa->e, e); switch (bits) { case 512: initFlags |= TSS_KEY_SIZE_512; break; case 1024: initFlags |= TSS_KEY_SIZE_1024; break; case 2048: initFlags |= TSS_KEY_SIZE_2048; break; case 4096: initFlags |= TSS_KEY_SIZE_4096; break; case 8192: initFlags |= TSS_KEY_SIZE_8192; break; case 16384: initFlags |= TSS_KEY_SIZE_16384; break; default: TSSerr(TPM_F_TPM_RSA_KEYGEN, TPM_R_INVALID_KEY_SIZE); return 0; } /* Load the parent key (SRK) which will wrap the new key */ if (!tpm_load_srk(NULL, NULL)) { TSSerr(TPM_F_TPM_RSA_KEYGEN, TPM_R_SRK_LOAD_FAILED); return 0; } /* Create the new key object */ if ((result = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_RSAKEY, initFlags, &hKey))) { TSSerr(TPM_F_TPM_RSA_KEYGEN, TPM_R_REQUEST_FAILED); return 0; } /* set the signature scheme */ if ((result = Tspi_SetAttribUint32(hKey, TSS_TSPATTRIB_KEY_INFO, TSS_TSPATTRIB_KEYINFO_SIGSCHEME, sigScheme))) { Tspi_Context_CloseObject(hContext, hKey); TSSerr(TPM_F_TPM_RSA_KEYGEN, TPM_R_REQUEST_FAILED); return 0; } /* set the encryption scheme */ if ((result = Tspi_SetAttribUint32(hKey, TSS_TSPATTRIB_KEY_INFO, TSS_TSPATTRIB_KEYINFO_ENCSCHEME, encScheme))) { Tspi_Context_CloseObject(hContext, hKey); TSSerr(TPM_F_TPM_RSA_KEYGEN, TPM_R_REQUEST_FAILED); return 0; } /* Call create key using the new object */ if ((result = Tspi_Key_CreateKey(hKey, hSRK, NULL_HPCRS))) { Tspi_Context_CloseObject(hContext, hKey); TSSerr(TPM_F_TPM_RSA_KEYGEN, TPM_R_REQUEST_FAILED); return 0; } if (!fill_out_rsa_object(rsa, hKey)) { Tspi_Context_CloseObject(hContext, hKey); TSSerr(TPM_F_TPM_RSA_KEYGEN, TPM_R_REQUEST_FAILED); return 0; } /* Load the key into the chip so other functions don't need to */ if ((result = Tspi_Key_LoadKey(hKey, hSRK))) { Tspi_Context_CloseObject(hContext, hKey); TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, TPM_R_REQUEST_FAILED); return 0; } return 1; }
soter_status_t soter_engine_specific_to_rsa_priv_key(const soter_engine_specific_rsa_key_t *engine_key, soter_container_hdr_t *key, size_t* key_length) { EVP_PKEY *pkey = (EVP_PKEY *)engine_key; RSA *rsa; soter_status_t res; int rsa_mod_size; size_t output_length; uint32_t *pub_exp; unsigned char *curr_bn = (unsigned char *)(key + 1); if (!key_length) { return SOTER_INVALID_PARAMETER; } if (EVP_PKEY_RSA != EVP_PKEY_id(pkey)) { return SOTER_INVALID_PARAMETER; } rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey); if (NULL == rsa) { return SOTER_FAIL; } rsa_mod_size = RSA_size(rsa); if (!is_mod_size_supported(rsa_mod_size)) { res = SOTER_INVALID_PARAMETER; goto err; } output_length = rsa_priv_key_size(rsa_mod_size); if ((!key) || (output_length > *key_length)) { *key_length = output_length; res = SOTER_BUFFER_TOO_SMALL; goto err; } pub_exp = (uint32_t *)(curr_bn + ((rsa_mod_size * 4) + (rsa_mod_size / 2))); if (BN_is_word(rsa->e, RSA_F4)) { *pub_exp = htonl(RSA_F4); } else if (BN_is_word(rsa->e, RSA_3)) { *pub_exp = htonl(RSA_3); } else { res = SOTER_INVALID_PARAMETER; goto err; } /* Private exponent */ res = bignum_to_bytes(rsa->d, curr_bn, rsa_mod_size); if (SOTER_SUCCESS != res) { goto err; } curr_bn += rsa_mod_size; /* p */ res = bignum_to_bytes(rsa->p, curr_bn, rsa_mod_size / 2); if (SOTER_SUCCESS != res) { goto err; } curr_bn += rsa_mod_size / 2; /* q */ res = bignum_to_bytes(rsa->q, curr_bn, rsa_mod_size / 2); if (SOTER_SUCCESS != res) { goto err; } curr_bn += rsa_mod_size / 2; /* dp */ res = bignum_to_bytes(rsa->dmp1, curr_bn, rsa_mod_size / 2); if (SOTER_SUCCESS != res) { goto err; } curr_bn += rsa_mod_size / 2; /* dq */ res = bignum_to_bytes(rsa->dmq1, curr_bn, rsa_mod_size / 2); if (SOTER_SUCCESS != res) { goto err; } curr_bn += rsa_mod_size / 2; /* qp */ res = bignum_to_bytes(rsa->iqmp, curr_bn, rsa_mod_size / 2); if (SOTER_SUCCESS != res) { goto err; } curr_bn += rsa_mod_size / 2; /* modulus */ res = bignum_to_bytes(rsa->n, curr_bn, rsa_mod_size); if (SOTER_SUCCESS != res) { goto err; } memcpy(key->tag, rsa_priv_key_tag(rsa_mod_size), SOTER_CONTAINER_TAG_LENGTH); key->size = htonl(output_length); soter_update_container_checksum(key); *key_length = output_length; res = SOTER_SUCCESS; err: /* Free extra reference on RSA object provided by EVP_PKEY_get1_RSA */ RSA_free(rsa); // if (SOTER_SUCCESS != res) // { // /* Zero output memory to avoid leaking private key information */ // memset(key, 0, *key_length); // } return res; }
soter_status_t soter_engine_specific_to_rsa_pub_key(const soter_engine_specific_rsa_key_t *engine_key, soter_container_hdr_t *key, size_t* key_length) { EVP_PKEY *pkey = (EVP_PKEY *)engine_key; RSA *rsa; soter_status_t res; int rsa_mod_size; size_t output_length; uint32_t *pub_exp; if (!key_length) { return SOTER_INVALID_PARAMETER; } if (EVP_PKEY_RSA != EVP_PKEY_id(pkey)) { return SOTER_INVALID_PARAMETER; } rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey); if (NULL == rsa) { return SOTER_FAIL; } rsa_mod_size = RSA_size(rsa); if (!is_mod_size_supported(rsa_mod_size)) { res = SOTER_INVALID_PARAMETER; goto err; } output_length = rsa_pub_key_size(rsa_mod_size); if ((!key) || (output_length > *key_length)) { *key_length = output_length; res = SOTER_BUFFER_TOO_SMALL; goto err; } pub_exp = (uint32_t *)((unsigned char *)(key + 1) + rsa_mod_size); if (BN_is_word(rsa->e, RSA_F4)) { *pub_exp = htonl(RSA_F4); } else if (BN_is_word(rsa->e, RSA_3)) { *pub_exp = htonl(RSA_3); } else { res = SOTER_INVALID_PARAMETER; goto err; } res = bignum_to_bytes(rsa->n, (unsigned char *)(key + 1), rsa_mod_size); if (SOTER_SUCCESS != res) { goto err; } memcpy(key->tag, rsa_pub_key_tag(rsa_mod_size), SOTER_CONTAINER_TAG_LENGTH); key->size = htonl(output_length); soter_update_container_checksum(key); *key_length = output_length; res = SOTER_SUCCESS; err: /* Free extra reference on RSA object provided by EVP_PKEY_get1_RSA */ RSA_free(rsa); return res; }
int test_kron(BIO *bp, BN_CTX *ctx) { BIGNUM *a,*b,*r,*t; int i; int legendre, kronecker; int ret = 0; a = BN_new(); b = BN_new(); r = BN_new(); t = BN_new(); if (a == NULL || b == NULL || r == NULL || t == NULL) goto err; /* We test BN_kronecker(a, b, ctx) just for b odd (Jacobi symbol). * In this case we know that if b is prime, then BN_kronecker(a, b, ctx) * is congruent to $a^{(b-1)/2}$, modulo $b$ (Legendre symbol). * So we generate a random prime b and compare these values * for a number of random a's. (That is, we run the Solovay-Strassen * primality test to confirm that b is prime, except that we * don't want to test whether b is prime but whether BN_kronecker * works.) */ if (!BN_generate_prime(b, 512, 0, NULL, NULL, genprime_cb, NULL)) goto err; b->neg = rand_neg(); putc('\n', stderr); for (i = 0; i < num0; i++) { if (!BN_bntest_rand(a, 512, 0, 0)) goto err; a->neg = rand_neg(); /* t := (|b|-1)/2 (note that b is odd) */ if (!BN_copy(t, b)) goto err; t->neg = 0; if (!BN_sub_word(t, 1)) goto err; if (!BN_rshift1(t, t)) goto err; /* r := a^t mod b */ b->neg=0; if (!BN_mod_exp_recp(r, a, t, b, ctx)) goto err; b->neg=1; if (BN_is_word(r, 1)) legendre = 1; else if (BN_is_zero(r)) legendre = 0; else { if (!BN_add_word(r, 1)) goto err; if (0 != BN_ucmp(r, b)) { fprintf(stderr, "Legendre symbol computation failed\n"); goto err; } legendre = -1; } kronecker = BN_kronecker(a, b, ctx); if (kronecker < -1) goto err; /* we actually need BN_kronecker(a, |b|) */ if (a->neg && b->neg) kronecker = -kronecker; if (legendre != kronecker) { fprintf(stderr, "legendre != kronecker; a = "); BN_print_fp(stderr, a); fprintf(stderr, ", b = "); BN_print_fp(stderr, b); fprintf(stderr, "\n"); goto err; } putc('.', stderr); fflush(stderr); } putc('\n', stderr); fflush(stderr); ret = 1; err: if (a != NULL) BN_free(a); if (b != NULL) BN_free(b); if (r != NULL) BN_free(r); if (t != NULL) BN_free(t); return ret; }
int DH_check(const DH *dh, int *ret) { int ok = 0; BN_CTX *ctx = NULL; BN_ULONG l; BIGNUM *t1 = NULL, *t2 = NULL; *ret = 0; ctx = BN_CTX_new(); if (ctx == NULL) goto err; BN_CTX_start(ctx); t1 = BN_CTX_get(ctx); if (t1 == NULL) goto err; t2 = BN_CTX_get(ctx); if (t2 == NULL) goto err; if (dh->q) { if (BN_cmp(dh->g, BN_value_one()) <= 0) *ret |= DH_NOT_SUITABLE_GENERATOR; else if (BN_cmp(dh->g, dh->p) >= 0) *ret |= DH_NOT_SUITABLE_GENERATOR; else { /* Check g^q == 1 mod p */ if (!BN_mod_exp(t1, dh->g, dh->q, dh->p, ctx)) goto err; if (!BN_is_one(t1)) *ret |= DH_NOT_SUITABLE_GENERATOR; } if (!BN_is_prime_ex(dh->q, BN_prime_checks, ctx, NULL)) *ret |= DH_CHECK_Q_NOT_PRIME; /* Check p == 1 mod q i.e. q divides p - 1 */ if (!BN_div(t1, t2, dh->p, dh->q, ctx)) goto err; if (!BN_is_one(t2)) *ret |= DH_CHECK_INVALID_Q_VALUE; if (dh->j && BN_cmp(dh->j, t1)) *ret |= DH_CHECK_INVALID_J_VALUE; } else if (BN_is_word(dh->g, DH_GENERATOR_2)) { l = BN_mod_word(dh->p, 24); if (l != 11) *ret |= DH_NOT_SUITABLE_GENERATOR; } #if 0 else if (BN_is_word(dh->g, DH_GENERATOR_3)) { l = BN_mod_word(dh->p, 12); if (l != 5) *ret |= DH_NOT_SUITABLE_GENERATOR; } #endif else if (BN_is_word(dh->g, DH_GENERATOR_5)) { l = BN_mod_word(dh->p, 10); if ((l != 3) && (l != 7)) *ret |= DH_NOT_SUITABLE_GENERATOR; } else *ret |= DH_UNABLE_TO_CHECK_GENERATOR; if (!BN_is_prime_ex(dh->p, BN_prime_checks, ctx, NULL)) *ret |= DH_CHECK_P_NOT_PRIME; else if (!dh->q) { if (!BN_rshift1(t1, dh->p)) goto err; if (!BN_is_prime_ex(t1, BN_prime_checks, ctx, NULL)) *ret |= DH_CHECK_P_NOT_SAFE_PRIME; } ok = 1; err: if (ctx != NULL) { BN_CTX_end(ctx); BN_CTX_free(ctx); } return (ok); }
CHECK_RETVAL_BOOL \ static BOOLEAN selfTestGeneralOps2( void ) { BIGNUM a; int status; /* More complex tests that need higher-level routines like importBignum(), run after the tests of components of importBignum() have concluded */ BN_init( &a ); #if BN_BITS2 == 64 status = importBignum( &a, "\x01\x00\x00\x00\x00\x00\x00\x00\x00", 9, 1, 128, NULL, KEYSIZE_CHECK_NONE ); #else status = importBignum( &a, "\x01\x00\x00\x00\x00", 5, 1, 128, NULL, KEYSIZE_CHECK_NONE ); #endif /* 64- vs 32-bit */ if( cryptStatusError( status ) ) return( FALSE ); if( BN_is_zero( &a ) || BN_is_one( &a ) ) return( FALSE ); if( BN_is_word( &a, 0 ) || BN_is_word( &a, 1 ) ) return( FALSE ); if( BN_is_odd( &a ) ) return( FALSE ); if( BN_get_word( &a ) != BN_NAN ) return( FALSE ); if( BN_num_bytes( &a ) != ( BN_BITS2 / 8 ) + 1 ) return( FALSE ); if( BN_num_bits( &a ) != BN_BITS2 + 1 ) return( FALSE ); if( !BN_is_bit_set( &a, BN_BITS2 ) ) return( FALSE ); if( BN_is_bit_set( &a, 17 ) || !BN_set_bit( &a, 17 ) || \ !BN_is_bit_set( &a, 17 ) ) return( FALSE ); #if BN_BITS2 == 64 status = importBignum( &a, "\x01\x00\x00\x00\x00\x00\x00\x00\x01", 9, 1, 128, NULL, KEYSIZE_CHECK_NONE ); #else status = importBignum( &a, "\x01\x00\x00\x00\x01", 5, 1, 128, NULL, KEYSIZE_CHECK_NONE ); #endif /* 64- vs 32-bit */ if( cryptStatusError( status ) ) return( FALSE ); if( BN_is_zero( &a ) || BN_is_one( &a ) ) return( FALSE ); if( BN_is_word( &a, 0 ) || BN_is_word( &a, 1 ) ) return( FALSE ); if( !BN_is_odd( &a ) ) return( FALSE ); if( BN_num_bytes( &a ) != ( BN_BITS2 / 8 ) + 1 ) return( FALSE ); if( BN_get_word( &a ) != BN_NAN ) return( FALSE ); if( BN_num_bits( &a ) != BN_BITS2 + 1 ) return( FALSE ); if( !BN_is_bit_set( &a, BN_BITS2 ) ) return( FALSE ); if( BN_is_bit_set( &a, BN_BITS2 + 27 ) || \ !BN_set_bit( &a, BN_BITS2 + 27 ) || \ !BN_is_bit_set( &a, BN_BITS2 + 27 ) ) return( FALSE ); /* Setting a bit off the end of a bignum extends its size, which is why the following value doesn't match the one from a few lines earlier */ if( BN_num_bytes( &a ) != ( BN_BITS2 / 8 ) + 4 ) return( FALSE ); /* The bit index for indexing bits is zero-based (since 1 == 1 << 0) but for counting bits is one-based, which is why the following comparison looks wrong. Yet another one of OpenSSL's many booby-traps */ if( BN_num_bits( &a ) != BN_BITS2 + 28 ) return( FALSE ); BN_clear( &a ); return( TRUE ); }