int fips_check_dsa_prng(DSA *dsa, size_t L, size_t N) { int strength; if (!FIPS_mode()) return 1; if (dsa->flags & (DSA_FLAG_NON_FIPS_ALLOW|DSA_FLAG_FIPS_CHECKED)) return 1; if (!L || !N) { L = BN_num_bits(dsa->p); N = BN_num_bits(dsa->q); } if (!dsa2_valid_parameters(L, N)) { FIPSerr(FIPS_F_FIPS_CHECK_DSA_PRNG, FIPS_R_INVALID_PARAMETERS); return 0; } strength = fips_ffc_strength(L, N); if (!strength) { FIPSerr(FIPS_F_FIPS_CHECK_DSA_PRNG,FIPS_R_KEY_TOO_SHORT); return 0; } if (FIPS_rand_strength() >= strength) return 1; FIPSerr(FIPS_F_FIPS_CHECK_DSA_PRNG,FIPS_R_PRNG_STRENGTH_TOO_LOW); return 0; }
int FIPS_selftest_aes() { int n; /* Encrypt and check against known ciphertext */ for(n=0 ; n < 1 ; ++n) { AES_KEY key; unsigned char buf[16]; AES_set_encrypt_key(tests[n].key,128,&key); AES_encrypt(tests[n].plaintext,buf,&key); if(memcmp(buf,tests[n].ciphertext,sizeof buf)) { FIPSerr(FIPS_F_FIPS_SELFTEST_AES,FIPS_R_SELFTEST_FAILED); return 0; } } /* Decrypt and check against known plaintext */ for(n=0 ; n < 1 ; ++n) { AES_KEY key; unsigned char buf[16]; AES_set_decrypt_key(tests[n].key,128,&key); AES_decrypt(tests[n].ciphertext,buf,&key); if(memcmp(buf,tests[n].plaintext,sizeof buf)) { FIPSerr(FIPS_F_FIPS_SELFTEST_AES,FIPS_R_SELFTEST_FAILED); return 0; } } return 1; }
int FIPS_check_incore_fingerprint(void) { unsigned char sig[EVP_MAX_MD_SIZE]; unsigned int len; int rv = 0; #if defined(__sgi) && (defined(__mips) || defined(mips)) extern int __dso_displacement[]; #else extern int OPENSSL_NONPIC_relocated; #endif if (!fips_post_started(FIPS_TEST_INTEGRITY, 0, NULL)) return 1; if (FIPS_text_start()==NULL) { FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT,FIPS_R_UNSUPPORTED_PLATFORM); goto err; } len=FIPS_incore_fingerprint(sig,sizeof(sig)); if (len!=sizeof(FIPS_signature) || memcmp(FIPS_signature,sig,sizeof(FIPS_signature))) { if (FIPS_signature>=FIPS_rodata_start && FIPS_signature<FIPS_rodata_end) FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT,FIPS_R_FINGERPRINT_DOES_NOT_MATCH_SEGMENT_ALIASING); #if defined(__sgi) && (defined(__mips) || defined(mips)) else if (__dso_displacement!=NULL) #else else if (OPENSSL_NONPIC_relocated) #endif FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT,FIPS_R_FINGERPRINT_DOES_NOT_MATCH_NONPIC_RELOCATED); else FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT,FIPS_R_FINGERPRINT_DOES_NOT_MATCH); #ifdef OPENSSL_FIPS_DEBUGGER rv = 1; #endif goto err; } rv = 1; err: if (rv == 0) fips_post_failed(FIPS_TEST_INTEGRITY, 0, NULL); else if (!fips_post_success(FIPS_TEST_INTEGRITY, 0, NULL)) return 0; return rv; }
int FIPS_cipher_ctx_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) { int ret; if (FIPS_selftest_failed()) { FIPSerr(FIPS_F_FIPS_CIPHER_CTX_CTRL, FIPS_R_SELFTEST_FAILED); return 0; } if(!ctx->cipher) { EVPerr(EVP_F_FIPS_CIPHER_CTX_CTRL, EVP_R_NO_CIPHER_SET); return 0; } if(!ctx->cipher->ctrl) { EVPerr(EVP_F_FIPS_CIPHER_CTX_CTRL, EVP_R_CTRL_NOT_IMPLEMENTED); return 0; } ret = ctx->cipher->ctrl(ctx, type, arg, ptr); if(ret == -1) { EVPerr(EVP_F_FIPS_CIPHER_CTX_CTRL, EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED); return 0; } return ret; }
int FIPS_selftest_des() { int n, ret = 0; EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX_init(&ctx); /* Encrypt/decrypt with 2-key 3DES and compare to known answers */ for (n = 0; n < 2; ++n) { if (!fips_cipher_test(&ctx, EVP_des_ede_ecb(), tests2[n].key, NULL, tests2[n].plaintext, tests2[n].ciphertext, 8)) goto err; } /* Encrypt/decrypt with 3DES and compare to known answers */ for (n = 0; n < 2; ++n) { if (!fips_cipher_test(&ctx, EVP_des_ede3_ecb(), tests3[n].key, NULL, tests3[n].plaintext, tests3[n].ciphertext, 8)) goto err; } ret = 1; err: EVP_CIPHER_CTX_cleanup(&ctx); if (ret == 0) FIPSerr(FIPS_F_FIPS_SELFTEST_DES, FIPS_R_SELFTEST_FAILED); return ret; }
void FIPS_rand_add(const void *buf, int num, double entropy) { if (!fips_approved_rand_meth && FIPS_module_mode()) { FIPSerr(FIPS_F_FIPS_RAND_ADD, FIPS_R_NON_FIPS_METHOD); return; } if (fips_rand_meth && fips_rand_meth->add) fips_rand_meth->add(buf, num, entropy); }
int FIPS_selftest_rng() { FIPS_rand_reset(); if (!FIPS_rand_test_mode()) { FIPSerr(FIPS_F_FIPS_SELFTEST_RNG,FIPS_R_SELFTEST_FAILED); return 0; } if (!fips_rand_test(aes_128_key,aes_128_tv) || !fips_rand_test(aes_192_key, aes_192_tv) || !fips_rand_test(aes_256_key, aes_256_tv)) { FIPSerr(FIPS_F_FIPS_SELFTEST_RNG,FIPS_R_SELFTEST_FAILED); return 0; } FIPS_rand_reset(); return 1; }
int fips_check_rsa(RSA *rsa) { const unsigned char tbs[] = "RSA Pairwise Check Data"; unsigned char *ctbuf = NULL, *ptbuf = NULL; int len, ret = 0; EVP_PKEY pk; pk.type = EVP_PKEY_RSA; pk.pkey.rsa = rsa; /* Perform pairwise consistency signature test */ if (!fips_pkey_signature_test(FIPS_TEST_PAIRWISE, &pk, tbs, 0, NULL, 0, NULL, RSA_PKCS1_PADDING, NULL) || !fips_pkey_signature_test(FIPS_TEST_PAIRWISE, &pk, tbs, 0, NULL, 0, NULL, RSA_X931_PADDING, NULL) || !fips_pkey_signature_test(FIPS_TEST_PAIRWISE, &pk, tbs, 0, NULL, 0, NULL, RSA_PKCS1_PSS_PADDING, NULL)) goto err; /* Now perform pairwise consistency encrypt/decrypt test */ ctbuf = OPENSSL_malloc(RSA_size(rsa)); if (!ctbuf) goto err; len = RSA_public_encrypt(sizeof(tbs) - 1, tbs, ctbuf, rsa, RSA_PKCS1_PADDING); if (len <= 0) goto err; /* Check ciphertext doesn't match plaintext */ if ((len == (sizeof(tbs) - 1)) && !memcmp(tbs, ctbuf, len)) goto err; ptbuf = OPENSSL_malloc(RSA_size(rsa)); if (!ptbuf) goto err; len = RSA_private_decrypt(len, ctbuf, ptbuf, rsa, RSA_PKCS1_PADDING); if (len != (sizeof(tbs) - 1)) goto err; if (memcmp(ptbuf, tbs, len)) goto err; ret = 1; if (!ptbuf) goto err; err: if (ret == 0) { fips_set_selftest_fail(); FIPSerr(FIPS_F_FIPS_CHECK_RSA,FIPS_R_PAIRWISE_TEST_FAILED); } if (ctbuf) OPENSSL_free(ctbuf); if (ptbuf) OPENSSL_free(ptbuf); return ret; }
int FIPS_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl) { if (FIPS_selftest_failed()) { FIPSerr(FIPS_F_FIPS_CIPHER, FIPS_R_SELFTEST_FAILED); return -1; } return ctx->cipher->do_cipher(ctx,out,in,inl); }
int FIPS_rand_seed(const void *buf, FIPS_RAND_SIZE_T num) { if (!fips_approved_rand_meth && FIPS_module_mode()) { FIPSerr(FIPS_F_FIPS_RAND_SEED, FIPS_R_NON_FIPS_METHOD); return 0; } if (fips_rand_meth && fips_rand_meth->seed) fips_rand_meth->seed(buf, num); return 1; }
int FIPS_rand_status(void) { if (!fips_approved_rand_meth && FIPS_module_mode()) { FIPSerr(FIPS_F_FIPS_RAND_STATUS, FIPS_R_NON_FIPS_METHOD); return 0; } if (fips_rand_meth && fips_rand_meth->status) return fips_rand_meth->status(); return 0; }
int FIPS_rand_pseudo_bytes(unsigned char *buf, int num) { if (!fips_approved_rand_meth && FIPS_module_mode()) { FIPSerr(FIPS_F_FIPS_RAND_PSEUDO_BYTES, FIPS_R_NON_FIPS_METHOD); return 0; } if (fips_rand_meth && fips_rand_meth->pseudorand) return fips_rand_meth->pseudorand(buf, num); return -1; }
int FIPS_rand_bytes(unsigned char *buf, FIPS_RAND_SIZE_T num) { if (!fips_approved_rand_meth && FIPS_module_mode()) { FIPSerr(FIPS_F_FIPS_RAND_BYTES, FIPS_R_NON_FIPS_METHOD); return 0; } if (fips_rand_meth && fips_rand_meth->bytes) return fips_rand_meth->bytes(buf, num); return 0; }
int fips_check_ec_prng(EC_KEY *ec) { int bits, strength; if (!FIPS_module_mode()) return 1; if (ec->flags & (EC_FLAG_NON_FIPS_ALLOW|EC_FLAG_FIPS_CHECKED)) return 1; if (!ec->group) return 1; bits = BN_num_bits(&ec->group->order); if (bits < 160) { FIPSerr(FIPS_F_FIPS_CHECK_EC_PRNG,FIPS_R_KEY_TOO_SHORT); return 0; } /* Comparable algorithm strengths: from SP800-57 table 2 */ if (bits >= 512) strength = 256; else if (bits >= 384) strength = 192; else if (bits >= 256) strength = 128; else if (bits >= 224) strength = 112; else strength = 80; if (FIPS_rand_strength() >= strength) return 1; FIPSerr(FIPS_F_FIPS_CHECK_EC_PRNG,FIPS_R_PRNG_STRENGTH_TOO_LOW); return 0; }
static int fips_check_dsa(DSA *dsa) { EVP_PKEY pk; unsigned char tbs[] = "DSA Pairwise Check Data"; pk.type = EVP_PKEY_DSA; pk.pkey.dsa = dsa; if (!fips_pkey_signature_test(&pk, tbs, -1, NULL, 0, EVP_dss1(), 0, NULL)) { FIPSerr(FIPS_F_FIPS_CHECK_DSA, FIPS_R_PAIRWISE_TEST_FAILED); fips_set_selftest_fail(); return 0; } return 1; }
static int fips_check_dsa(DSA *dsa) { static const unsigned char str1[]="12345678901234567890"; unsigned char sig[256]; unsigned int siglen; DSA_sign(0, str1, 20, sig, &siglen, dsa); if(DSA_verify(0, str1, 20, sig, siglen, dsa) != 1) { FIPSerr(FIPS_F_FIPS_CHECK_DSA,FIPS_R_PAIRWISE_TEST_FAILED); return 0; } return 1; }
int FIPS_dsa_check(struct dsa_st *dsa) { if(dsa->meth != &openssl_dsa_meth || dsa->meth->dsa_do_sign != dsa_do_sign || dsa->meth->dsa_sign_setup != dsa_sign_setup || dsa->meth->dsa_mod_exp != dsa_mod_exp || dsa->meth->bn_mod_exp != dsa_bn_mod_exp || dsa->meth->init != dsa_init || dsa->meth->finish != dsa_finish) { FIPSerr(FIPS_F_FIPS_DSA_CHECK,FIPS_R_NON_FIPS_METHOD); return 0; } return 1; }
int fips_check_rsa_prng(RSA *rsa, int bits) { int strength; if (!FIPS_module_mode()) return 1; if (rsa->flags & (RSA_FLAG_NON_FIPS_ALLOW|RSA_FLAG_CHECKED)) return 1; if (bits == 0) bits = BN_num_bits(rsa->n); /* Should never happen */ if (bits < 1024) { FIPSerr(FIPS_F_FIPS_CHECK_RSA_PRNG,FIPS_R_KEY_TOO_SHORT); return 0; } /* From SP800-57 */ if (bits < 2048) strength = 80; else if (bits < 3072) strength = 112; else if (bits < 7680) strength = 128; else if (bits < 15360) strength = 192; else strength = 256; if (FIPS_rand_strength() >= strength) return 1; FIPSerr(FIPS_F_FIPS_CHECK_RSA_PRNG,FIPS_R_PRNG_STRENGTH_TOO_LOW); return 0; }
static int fips_check_ec(EC_KEY *key) { EVP_PKEY pk; unsigned char tbs[] = "ECDSA Pairwise Check Data"; pk.type = EVP_PKEY_EC; pk.pkey.ec = key; if (!fips_pkey_signature_test(FIPS_TEST_PAIRWISE, &pk, tbs, 0, NULL, 0, NULL, 0, NULL)) { FIPSerr(FIPS_F_FIPS_CHECK_EC,FIPS_R_PAIRWISE_TEST_FAILED); fips_set_selftest_fail(); return 0; } return 1; }
int FIPS_selftest_cmac() { size_t n, outlen; unsigned char out[32]; const EVP_CIPHER *cipher; CMAC_CTX *ctx = CMAC_CTX_new(); const CMAC_KAT *t; int rv = 1; for (n = 0, t = vector; n < sizeof(vector) / sizeof(vector[0]); n++, t++) { cipher = FIPS_get_cipherbynid(t->nid); if (!cipher) { rv = -1; goto err; } if (!CMAC_Init(ctx, t->key, t->keysize / 8, cipher, 0)) { rv = -1; goto err; } if (!CMAC_Update(ctx, t->msg, t->msgsize / 8)) { rv = -1; goto err; } if (!CMAC_Final(ctx, out, &outlen)) { rv = -1; goto err; } CMAC_CTX_cleanup(ctx); if (outlen < t->macsize / 8 || memcmp(out, t->mac, t->macsize / 8)) { rv = 0; } } err: CMAC_CTX_free(ctx); if (rv == -1) { rv = 0; } if (!rv) FIPSerr(FIPS_F_FIPS_SELFTEST_CMAC, FIPS_R_SELFTEST_FAILED); return rv; }
int FIPS_selftest_sha1() { int n; for(n=0 ; n<sizeof(test)/sizeof(test[0]) ; ++n) { unsigned char md[SHA_DIGEST_LENGTH]; EVP_Digest(test[n],strlen(test[n]),md, NULL, EVP_sha1(), NULL); if(memcmp(md,ret[n],sizeof md)) { FIPSerr(FIPS_F_FIPS_SELFTEST_SHA1,FIPS_R_SELFTEST_FAILED); return 0; } } return 1; }
int FIPS_rand_set_method(const RAND_METHOD *meth) { if (!fips_rand_bits) { if (meth == FIPS_drbg_method()) fips_approved_rand_meth = 1; else if (meth == FIPS_x931_method()) fips_approved_rand_meth = 2; else { fips_approved_rand_meth = 0; if (FIPS_module_mode()) { FIPSerr(FIPS_F_FIPS_RAND_SET_METHOD, FIPS_R_NON_FIPS_METHOD); return 0; } } } fips_rand_meth = meth; return 1; }
int FIPS_selftest_hmac() { int n; unsigned int outlen; unsigned char out[EVP_MAX_MD_SIZE]; const EVP_MD *md; const HMAC_KAT *t; for(n=0,t=vector; n<sizeof(vector)/sizeof(vector[0]); n++,t++) { md = (*t->alg)(); HMAC(md,t->key,strlen(t->key), (const unsigned char *)t->iv,strlen(t->iv), out,&outlen); if(memcmp(out,t->kaval,outlen)) { FIPSerr(FIPS_F_FIPS_SELFTEST_HMAC,FIPS_R_SELFTEST_FAILED); return 0; } } return 1; }
int FIPS_rsa_sign_digest(RSA *rsa, const unsigned char *md, int md_len, const EVP_MD *mhash, int rsa_pad_mode, int saltlen, const EVP_MD *mgf1Hash, unsigned char *sigret, unsigned int *siglen) { int i=0,j,ret=0; unsigned int dlen; const unsigned char *der; int md_type; /* Largest DigestInfo: 19 (max encoding) + max MD */ unsigned char tmpdinfo[19 + EVP_MAX_MD_SIZE]; if (FIPS_selftest_failed()) { FIPSerr(FIPS_F_FIPS_RSA_SIGN_DIGEST, FIPS_R_SELFTEST_FAILED); return 0; } if (!mhash && rsa_pad_mode == RSA_PKCS1_PADDING) md_type = saltlen; else md_type = M_EVP_MD_type(mhash); if (rsa_pad_mode == RSA_X931_PADDING) { int hash_id; memcpy(tmpdinfo, md, md_len); hash_id = RSA_X931_hash_id(md_type); if (hash_id == -1) { RSAerr(RSA_F_FIPS_RSA_SIGN_DIGEST,RSA_R_UNKNOWN_ALGORITHM_TYPE); return 0; } tmpdinfo[md_len] = (unsigned char)hash_id; i = md_len + 1; } else if (rsa_pad_mode == RSA_PKCS1_PADDING) { der = fips_digestinfo_encoding(md_type, &dlen); if (!der) { RSAerr(RSA_F_FIPS_RSA_SIGN_DIGEST,RSA_R_UNKNOWN_ALGORITHM_TYPE); return 0; } memcpy(tmpdinfo, der, dlen); memcpy(tmpdinfo + dlen, md, md_len); i = dlen + md_len; } else if (rsa_pad_mode == RSA_PKCS1_PSS_PADDING) { unsigned char *sbuf; i = RSA_size(rsa); sbuf = OPENSSL_malloc(RSA_size(rsa)); if (!sbuf) { RSAerr(RSA_F_FIPS_RSA_SIGN_DIGEST,ERR_R_MALLOC_FAILURE); goto psserr; } if (!RSA_padding_add_PKCS1_PSS_mgf1(rsa, sbuf, md, mhash, mgf1Hash, saltlen)) goto psserr; j=rsa->meth->rsa_priv_enc(i,sbuf,sigret,rsa,RSA_NO_PADDING); if (j > 0) { ret=1; *siglen=j; } psserr: OPENSSL_cleanse(sbuf, i); OPENSSL_free(sbuf); return ret; } j=RSA_size(rsa); if (i > (j-RSA_PKCS1_PADDING_SIZE)) { RSAerr(RSA_F_FIPS_RSA_SIGN_DIGEST,RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY); goto done; } /* NB: call underlying method directly to avoid FIPS blocking */ j=rsa->meth->rsa_priv_enc(i,tmpdinfo,sigret,rsa,rsa_pad_mode); if (j > 0) { ret=1; *siglen=j; } done: OPENSSL_cleanse(tmpdinfo,i); return ret; }
int FIPS_rsa_verify_digest(RSA *rsa, const unsigned char *dig, int diglen, const EVP_MD *mhash, int rsa_pad_mode, int saltlen, const EVP_MD *mgf1Hash, const unsigned char *sigbuf, unsigned int siglen) { int i,ret=0; unsigned int dlen; unsigned char *s; const unsigned char *der; int md_type; int rsa_dec_pad_mode; if (FIPS_selftest_failed()) { FIPSerr(FIPS_F_FIPS_RSA_VERIFY_DIGEST, FIPS_R_SELFTEST_FAILED); return 0; } if (siglen != (unsigned int)RSA_size(rsa)) { RSAerr(RSA_F_FIPS_RSA_VERIFY_DIGEST,RSA_R_WRONG_SIGNATURE_LENGTH); return(0); } if (!mhash && rsa_pad_mode == RSA_PKCS1_PADDING) md_type = saltlen; else md_type = M_EVP_MD_type(mhash); s= OPENSSL_malloc((unsigned int)siglen); if (s == NULL) { RSAerr(RSA_F_FIPS_RSA_VERIFY_DIGEST,ERR_R_MALLOC_FAILURE); goto err; } if (rsa_pad_mode == RSA_PKCS1_PSS_PADDING) rsa_dec_pad_mode = RSA_NO_PADDING; else rsa_dec_pad_mode = rsa_pad_mode; /* NB: call underlying method directly to avoid FIPS blocking */ i=rsa->meth->rsa_pub_dec((int)siglen,sigbuf,s, rsa, rsa_dec_pad_mode); if (i <= 0) goto err; if (rsa_pad_mode == RSA_X931_PADDING) { int hash_id; if (i != (int)(diglen + 1)) { RSAerr(RSA_F_FIPS_RSA_VERIFY_DIGEST,RSA_R_BAD_SIGNATURE); goto err; } hash_id = RSA_X931_hash_id(md_type); if (hash_id == -1) { RSAerr(RSA_F_FIPS_RSA_VERIFY_DIGEST,RSA_R_UNKNOWN_ALGORITHM_TYPE); goto err; } if (s[diglen] != (unsigned char)hash_id) { RSAerr(RSA_F_FIPS_RSA_VERIFY_DIGEST,RSA_R_BAD_SIGNATURE); goto err; } if (memcmp(s, dig, diglen)) { RSAerr(RSA_F_FIPS_RSA_VERIFY_DIGEST,RSA_R_BAD_SIGNATURE); goto err; } ret = 1; } else if (rsa_pad_mode == RSA_PKCS1_PADDING) { der = fips_digestinfo_encoding(md_type, &dlen); if (!der) { RSAerr(RSA_F_FIPS_RSA_VERIFY_DIGEST,RSA_R_UNKNOWN_ALGORITHM_TYPE); return(0); } /* Compare, DigestInfo length, DigestInfo header and finally * digest value itself */ /* If length mismatch try alternate encoding */ if (i != (int)(dlen + diglen)) der = fips_digestinfo_nn_encoding(md_type, &dlen); if ((i != (int)(dlen + diglen)) || memcmp(der, s, dlen) || memcmp(s + dlen, dig, diglen)) { RSAerr(RSA_F_FIPS_RSA_VERIFY_DIGEST,RSA_R_BAD_SIGNATURE); goto err; } ret = 1; } else if (rsa_pad_mode == RSA_PKCS1_PSS_PADDING) { ret = RSA_verify_PKCS1_PSS_mgf1(rsa, dig, mhash, mgf1Hash, s, saltlen); if (ret < 0) ret = 0; } err: if (s != NULL) { OPENSSL_cleanse(s, siglen); OPENSSL_free(s); } return(ret); }
/* The purpose of this is to ensure the error code exists and the function * name is to keep the error checking script quiet */ void hash_final(void) { FIPSerr(FIPS_F_HASH_FINAL,FIPS_R_NON_FIPS_METHOD); }
int FIPS_module_mode_set(int onoff, const char *auth) { int ret = 0; fips_w_lock(); fips_started = 1; fips_set_owning_thread(); if(onoff) { fips_selftest_fail = 0; if (!fips_check_auth(auth)) { fips_auth_fail = 1; fips_selftest_fail = 1; FIPSerr(FIPS_F_FIPS_MODULE_MODE_SET,FIPS_R_AUTHENTICATION_FAILURE); return 0; } /* Don't go into FIPS mode twice, just so we can do automagic seeding */ if(FIPS_module_mode()) { FIPSerr(FIPS_F_FIPS_MODULE_MODE_SET,FIPS_R_FIPS_MODE_ALREADY_SET); fips_selftest_fail = 1; ret = 0; goto end; } #ifdef OPENSSL_IA32_SSE2 { extern unsigned int OPENSSL_ia32cap_P[2]; if ((OPENSSL_ia32cap_P[0] & (1<<25|1<<26)) != (1<<25|1<<26)) { FIPSerr(FIPS_F_FIPS_MODULE_MODE_SET,FIPS_R_UNSUPPORTED_PLATFORM); fips_selftest_fail = 1; ret = 0; goto end; } OPENSSL_ia32cap_P[0] |= (1<<28); /* set "shared cache" */ OPENSSL_ia32cap_P[1] &= ~(1<<(60-32)); /* clear AVX */ } #endif if(fips_signature_witness() != FIPS_signature) { FIPSerr(FIPS_F_FIPS_MODULE_MODE_SET,FIPS_R_CONTRADICTING_EVIDENCE); fips_selftest_fail = 1; ret = 0; goto end; } if(FIPS_selftest()) fips_set_mode(onoff); else { fips_selftest_fail = 1; ret = 0; goto end; } ret = 1; goto end; } fips_set_mode(0); fips_selftest_fail = 0; ret = 1; end: fips_clear_owning_thread(); fips_w_unlock(); return ret; }
/* This implementation is based on the following primitives in the IEEE 1363 standard: * - ECKAS-DH1 * - ECSVDP-DH * Finally an optional KDF is applied. */ static int ecdh_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh, void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen)) { BN_CTX *ctx; EC_POINT *tmp=NULL; BIGNUM *x=NULL, *y=NULL; const BIGNUM *priv_key; const EC_GROUP* group; int ret= -1; size_t buflen, len; unsigned char *buf=NULL; #ifdef OPENSSL_FIPS if(FIPS_selftest_failed()) { FIPSerr(FIPS_F_ECDH_COMPUTE_KEY,FIPS_R_FIPS_SELFTEST_FAILED); return -1; } #endif if (outlen > INT_MAX) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE); /* sort of, anyway */ return -1; } if ((ctx = BN_CTX_new()) == NULL) goto err; BN_CTX_start(ctx); x = BN_CTX_get(ctx); y = BN_CTX_get(ctx); priv_key = EC_KEY_get0_private_key(ecdh); if (priv_key == NULL) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_NO_PRIVATE_VALUE); goto err; } group = EC_KEY_get0_group(ecdh); if ((tmp=EC_POINT_new(group)) == NULL) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_mul(group, tmp, NULL, pub_key, priv_key, ctx)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE); goto err; } if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(group, tmp, x, y, ctx)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE); goto err; } } #ifndef OPENSSL_NO_EC2M else { if (!EC_POINT_get_affine_coordinates_GF2m(group, tmp, x, y, ctx)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE); goto err; } } #endif buflen = (EC_GROUP_get_degree(group) + 7)/8; len = BN_num_bytes(x); if (len > buflen) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_INTERNAL_ERROR); goto err; } if ((buf = OPENSSL_malloc(buflen)) == NULL) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE); goto err; } memset(buf, 0, buflen - len); if (len != (size_t)BN_bn2bin(x, buf + buflen - len)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_BN_LIB); goto err; } if (KDF != 0) { if (KDF(buf, buflen, out, &outlen) == NULL) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_KDF_FAILED); goto err; } ret = outlen; } else { /* no KDF, just copy as much as we can */ if (outlen > buflen) outlen = buflen; memcpy(out, buf, outlen); ret = outlen; } err: if (tmp) EC_POINT_free(tmp); if (ctx) BN_CTX_end(ctx); if (ctx) BN_CTX_free(ctx); if (buf) OPENSSL_free(buf); return(ret); }
int fips_pkey_signature_test(int id, EVP_PKEY *pkey, const unsigned char *tbs, size_t tbslen, const unsigned char *kat, size_t katlen, const EVP_MD *digest, int pad_mode, const char *fail_str) { int subid; void *ex = NULL; int ret = 0; unsigned char *sig = NULL; unsigned int siglen; static const unsigned char str1[]="12345678901234567890"; DSA_SIG *dsig = NULL; ECDSA_SIG *esig = NULL; EVP_MD_CTX mctx; FIPS_md_ctx_init(&mctx); if (tbs == NULL) tbs = str1; if (tbslen == 0) tbslen = strlen((char *)tbs); if (digest == NULL) digest = EVP_sha256(); subid = M_EVP_MD_type(digest); if (!fips_post_started(id, subid, pkey)) return 1; if (!pkey || pkey->type == EVP_PKEY_RSA) { size_t sigsize; if (!pkey) sigsize = EVP_MAX_MD_SIZE; else sigsize = RSA_size(pkey->pkey.rsa); sig = OPENSSL_malloc(sigsize); if (!sig) { FIPSerr(FIPS_F_FIPS_PKEY_SIGNATURE_TEST,ERR_R_MALLOC_FAILURE); goto error; } } if (!FIPS_digestinit(&mctx, digest)) goto error; if (!FIPS_digestupdate(&mctx, tbs, tbslen)) goto error; if (!fips_post_corrupt(id, subid, pkey)) { if (!FIPS_digestupdate(&mctx, tbs, 1)) goto error; } if (pkey == NULL) { if (!FIPS_digestfinal(&mctx, sig, &siglen)) goto error; } else if (pkey->type == EVP_PKEY_RSA) { if (!FIPS_rsa_sign_ctx(pkey->pkey.rsa, &mctx, pad_mode, 0, NULL, sig, &siglen)) goto error; } else if (pkey->type == EVP_PKEY_DSA) { dsig = FIPS_dsa_sign_ctx(pkey->pkey.dsa, &mctx); if (!dsig) goto error; } else if (pkey->type == EVP_PKEY_EC) { esig = FIPS_ecdsa_sign_ctx(pkey->pkey.ec, &mctx); if (!esig) goto error; } if (kat && ((siglen != katlen) || memcmp(kat, sig, katlen))) goto error; #if 0 { /* Debug code to print out self test KAT discrepancies */ unsigned int i; fprintf(stderr, "%s=", fail_str); for (i = 0; i < siglen; i++) fprintf(stderr, "%02X", sig[i]); fprintf(stderr, "\n"); goto error; } #endif /* If just digest test we've finished */ if (pkey == NULL) { ret = 1; /* Well actually sucess as we've set ret to 1 */ goto error; } if (!FIPS_digestinit(&mctx, digest)) goto error; if (!FIPS_digestupdate(&mctx, tbs, tbslen)) goto error; if (pkey->type == EVP_PKEY_RSA) { ret = FIPS_rsa_verify_ctx(pkey->pkey.rsa, &mctx, pad_mode, 0, NULL, sig, siglen); } else if (pkey->type == EVP_PKEY_DSA) { ret = FIPS_dsa_verify_ctx(pkey->pkey.dsa, &mctx, dsig); } else if (pkey->type == EVP_PKEY_EC) { ret = FIPS_ecdsa_verify_ctx(pkey->pkey.ec, &mctx, esig); } error: if (dsig != NULL) FIPS_dsa_sig_free(dsig); if (esig != NULL) FIPS_ecdsa_sig_free(esig); if (sig) OPENSSL_free(sig); FIPS_md_ctx_cleanup(&mctx); if (ret != 1) { FIPSerr(FIPS_F_FIPS_PKEY_SIGNATURE_TEST,FIPS_R_TEST_FAILURE); if (fail_str) FIPS_add_error_data(2, "Type=", fail_str); fips_post_failed(id, subid, ex); return 0; } return fips_post_success(id, subid, pkey); }
static int ssleay_rand_bytes(unsigned char *buf, int num) { static volatile int stirred_pool = 0; int i,j,k,st_num,st_idx; int num_ceil; int ok; long md_c[2]; unsigned char local_md[MD_DIGEST_LENGTH]; EVP_MD_CTX m; #ifndef GETPID_IS_MEANINGLESS pid_t curr_pid = getpid(); #endif int do_stir_pool = 0; #ifdef OPENSSL_FIPS if(FIPS_mode()) { FIPSerr(FIPS_F_SSLEAY_RAND_BYTES,FIPS_R_NON_FIPS_METHOD); return 0; } #endif #ifdef PREDICT if (rand_predictable) { static unsigned char val=0; for (i=0; i<num; i++) buf[i]=val++; return(1); } #endif if (num <= 0) return 1; EVP_MD_CTX_init(&m); /* round upwards to multiple of MD_DIGEST_LENGTH/2 */ num_ceil = (1 + (num-1)/(MD_DIGEST_LENGTH/2)) * (MD_DIGEST_LENGTH/2); /* * (Based on the rand(3) manpage:) * * For each group of 10 bytes (or less), we do the following: * * Input into the hash function the local 'md' (which is initialized from * the global 'md' before any bytes are generated), the bytes that are to * be overwritten by the random bytes, and bytes from the 'state' * (incrementing looping index). From this digest output (which is kept * in 'md'), the top (up to) 10 bytes are returned to the caller and the * bottom 10 bytes are xored into the 'state'. * * Finally, after we have finished 'num' random bytes for the * caller, 'count' (which is incremented) and the local and global 'md' * are fed into the hash function and the results are kept in the * global 'md'. */ CRYPTO_w_lock(CRYPTO_LOCK_RAND); /* prevent ssleay_rand_bytes() from trying to obtain the lock again */ CRYPTO_w_lock(CRYPTO_LOCK_RAND2); locking_thread = CRYPTO_thread_id(); CRYPTO_w_unlock(CRYPTO_LOCK_RAND2); crypto_lock_rand = 1; if (!initialized) { RAND_poll(); initialized = 1; } if (!stirred_pool) do_stir_pool = 1; ok = (entropy >= ENTROPY_NEEDED); if (!ok) { /* If the PRNG state is not yet unpredictable, then seeing * the PRNG output may help attackers to determine the new * state; thus we have to decrease the entropy estimate. * Once we've had enough initial seeding we don't bother to * adjust the entropy count, though, because we're not ambitious * to provide *information-theoretic* randomness. * * NOTE: This approach fails if the program forks before * we have enough entropy. Entropy should be collected * in a separate input pool and be transferred to the * output pool only when the entropy limit has been reached. */ entropy -= num; if (entropy < 0) entropy = 0; } if (do_stir_pool) { /* In the output function only half of 'md' remains secret, * so we better make sure that the required entropy gets * 'evenly distributed' through 'state', our randomness pool. * The input function (ssleay_rand_add) chains all of 'md', * which makes it more suitable for this purpose. */ int n = STATE_SIZE; /* so that the complete pool gets accessed */ while (n > 0) { #if MD_DIGEST_LENGTH > 20 # error "Please adjust DUMMY_SEED." #endif #define DUMMY_SEED "...................." /* at least MD_DIGEST_LENGTH */ /* Note that the seed does not matter, it's just that * ssleay_rand_add expects to have something to hash. */ ssleay_rand_add(DUMMY_SEED, MD_DIGEST_LENGTH, 0.0); n -= MD_DIGEST_LENGTH; } if (ok) stirred_pool = 1; } st_idx=state_index; st_num=state_num; md_c[0] = md_count[0]; md_c[1] = md_count[1]; memcpy(local_md, md, sizeof md); state_index+=num_ceil; if (state_index > state_num) state_index %= state_num; /* state[st_idx], ..., state[(st_idx + num_ceil - 1) % st_num] * are now ours (but other threads may use them too) */ md_count[0] += 1; /* before unlocking, we must clear 'crypto_lock_rand' */ crypto_lock_rand = 0; CRYPTO_w_unlock(CRYPTO_LOCK_RAND); while (num > 0) { /* num_ceil -= MD_DIGEST_LENGTH/2 */ j=(num >= MD_DIGEST_LENGTH/2)?MD_DIGEST_LENGTH/2:num; num-=j; MD_Init(&m); #ifndef GETPID_IS_MEANINGLESS if (curr_pid) /* just in the first iteration to save time */ { MD_Update(&m,(unsigned char*)&curr_pid,sizeof curr_pid); curr_pid = 0; } #endif MD_Update(&m,local_md,MD_DIGEST_LENGTH); MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c)); #ifndef PURIFY MD_Update(&m,buf,j); /* purify complains */ #endif k=(st_idx+MD_DIGEST_LENGTH/2)-st_num; if (k > 0) { MD_Update(&m,&(state[st_idx]),MD_DIGEST_LENGTH/2-k); MD_Update(&m,&(state[0]),k); } else MD_Update(&m,&(state[st_idx]),MD_DIGEST_LENGTH/2); MD_Final(&m,local_md); for (i=0; i<MD_DIGEST_LENGTH/2; i++) { state[st_idx++]^=local_md[i]; /* may compete with other threads */ if (st_idx >= st_num) st_idx=0; if (i < j) *(buf++)=local_md[i+MD_DIGEST_LENGTH/2]; } } MD_Init(&m); MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c)); MD_Update(&m,local_md,MD_DIGEST_LENGTH); CRYPTO_w_lock(CRYPTO_LOCK_RAND); MD_Update(&m,md,MD_DIGEST_LENGTH); MD_Final(&m,md); CRYPTO_w_unlock(CRYPTO_LOCK_RAND); EVP_MD_CTX_cleanup(&m); if (ok) return(1); else { RANDerr(RAND_F_SSLEAY_RAND_BYTES,RAND_R_PRNG_NOT_SEEDED); ERR_add_error_data(1, "You need to read the OpenSSL FAQ, " "http://www.openssl.org/support/faq.html"); return(0); } }