X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=fips%2Ffips.c;h=36ac8d1b0c18650dfd82d75f64523bc5537c65ef;hp=42f400311956288e89165bc29ad251134f968b17;hb=647f360e2e86818cee1f2d0429e071d14814e0b5;hpb=cab0595c1426b2f70d88b824028c6d1ef4a4476e diff --git a/fips/fips.c b/fips/fips.c index 42f4003119..36ac8d1b0c 100644 --- a/fips/fips.c +++ b/fips/fips.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 2003 The OpenSSL Project. All rights reserved. + * Copyright (c) 2011 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -61,6 +61,7 @@ #include #include #include "fips_locl.h" +#include "fips_auth.h" #ifdef OPENSSL_FIPS @@ -70,10 +71,12 @@ #define PATH_MAX 1024 #endif -static int fips_selftest_fail; -static int fips_mode; +#define atox(c) ((c)>='a'?((c)-'a'+10):((c)>='A'?(c)-'A'+10:(c)-'0')) + +static int fips_selftest_fail = 0; +static int fips_auth_fail = 0; +static int fips_mode = 0; static int fips_started = 0; -static const void *fips_rand_check; static int fips_is_owning_thread(void); static int fips_set_owning_thread(void); @@ -97,19 +100,7 @@ static void fips_set_mode(int onoff) } } -static void fips_set_rand_check(const void *rand_check) - { - int owning_thread = fips_is_owning_thread(); - - if (fips_started) - { - if (!owning_thread) fips_w_lock(); - fips_rand_check = rand_check; - if (!owning_thread) fips_w_unlock(); - } - } - -int FIPS_mode(void) +int FIPS_module_mode(void) { int ret = 0; int owning_thread = fips_is_owning_thread(); @@ -123,20 +114,6 @@ int FIPS_mode(void) return ret; } -const void *FIPS_rand_check(void) - { - const void *ret = 0; - int owning_thread = fips_is_owning_thread(); - - if (fips_started) - { - if (!owning_thread) fips_r_lock(); - ret = fips_rand_check; - if (!owning_thread) fips_r_unlock(); - } - return ret; - } - int FIPS_selftest_failed(void) { int ret = 0; @@ -169,23 +146,10 @@ void fips_set_selftest_fail(void) fips_selftest_fail = 1; } -int FIPS_selftest(void) - { - - return FIPS_selftest_sha1() - && FIPS_selftest_hmac() - && FIPS_selftest_cmac() - && FIPS_selftest_aes() - && FIPS_selftest_aes_gcm() - && FIPS_selftest_des() - && FIPS_selftest_rsa() - && FIPS_selftest_ecdsa() - && FIPS_selftest_dsa(); - } - extern const void *FIPS_text_start(), *FIPS_text_end(); extern const unsigned char FIPS_rodata_start[], FIPS_rodata_end[]; unsigned char FIPS_signature [20] = { 0 }; +__fips_constseg static const char FIPS_hmac_key[]="etaonrishdlcupfm"; unsigned int FIPS_incore_fingerprint(unsigned char *sig,unsigned int len) @@ -219,6 +183,9 @@ unsigned int FIPS_incore_fingerprint(unsigned char *sig,unsigned int len) else HMAC_Update(&c,p3,(size_t)p4-(size_t)p3); + if (!fips_post_corrupt(FIPS_TEST_INTEGRITY, 0, NULL)) + HMAC_Update(&c, (unsigned char *)FIPS_hmac_key, 1); + HMAC_Final(&c,sig,&len); HMAC_CTX_cleanup(&c); @@ -229,19 +196,23 @@ 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); - return 0; + goto err; } - len=FIPS_incore_fingerprint (sig,sizeof(sig)); + len=FIPS_incore_fingerprint(sig,sizeof(sig)); if (len!=sizeof(FIPS_signature) || memcmp(FIPS_signature,sig,sizeof(FIPS_signature))) @@ -257,18 +228,61 @@ int FIPS_check_incore_fingerprint(void) else FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT,FIPS_R_FINGERPRINT_DOES_NOT_MATCH); #ifdef OPENSSL_FIPS_DEBUGGER - return 1; -#else - return 0; + 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; + } + +static int fips_asc_check(const unsigned char *sig, const char *asc_sig) + { + char tsig[20]; + const char *p; + int i; + if (strlen(asc_sig) != 40) + return 0; + for (i = 0, p = asc_sig; i < 20; i++, p += 2) + tsig[i] = (atox(p[0]) << 4) | atox(p[1]); + if (memcmp(tsig, sig, 20)) + return 0; return 1; } -int FIPS_mode_set(int onoff) +static int fips_check_auth(const char *auth) + { + unsigned char auth_hmac[20]; + unsigned int hmac_len; + if (fips_auth_fail) + return 0; + if (strlen(auth) < FIPS_AUTH_MIN_LEN) + return 0; + if (!HMAC(EVP_sha1(), FIPS_AUTH_KEY, strlen(FIPS_AUTH_KEY), + (unsigned char *)auth, strlen(auth), auth_hmac, &hmac_len)) + return 0; + if (hmac_len != sizeof(auth_hmac)) + return 0; + + if (fips_asc_check(auth_hmac, FIPS_AUTH_CRYPTO_OFFICER)) + return 1; + + if (fips_asc_check(auth_hmac, FIPS_AUTH_CRYPTO_USER)) + return 1; + + return 0; + } + + + +int FIPS_module_mode_set(int onoff, const char *auth) { - int fips_set_owning_thread(); - int fips_clear_owning_thread(); int ret = 0; fips_w_lock(); @@ -279,80 +293,49 @@ int FIPS_mode_set(int 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_mode()) + if(FIPS_module_mode()) { - FIPSerr(FIPS_F_FIPS_MODE_SET,FIPS_R_FIPS_MODE_ALREADY_SET); + 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 - if ((OPENSSL_ia32cap & (1<<25|1<<26)) != (1<<25|1<<26)) + { + extern unsigned int OPENSSL_ia32cap_P[2]; + if ((OPENSSL_ia32cap_P[0] & (1<<25|1<<26)) != (1<<25|1<<26)) { - FIPSerr(FIPS_F_FIPS_MODE_SET,FIPS_R_UNSUPPORTED_PLATFORM); + 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_MODE_SET,FIPS_R_CONTRADICTING_EVIDENCE); - fips_selftest_fail = 1; - ret = 0; - goto end; - } - - if(!FIPS_check_incore_fingerprint()) - { + FIPSerr(FIPS_F_FIPS_MODULE_MODE_SET,FIPS_R_CONTRADICTING_EVIDENCE); fips_selftest_fail = 1; ret = 0; goto end; } - if (!FIPS_selftest_drbg()) - { - fips_selftest_fail = 1; - ret = 0; - goto end; - } - - /* Perform RNG KAT before seeding */ - if (!FIPS_selftest_x931()) - { - fips_selftest_fail = 1; - ret = 0; - goto end; - } -#if 0 - /* automagically seed PRNG if not already seeded */ - if(!FIPS_rand_status()) - { - unsigned char buf[48]; - if(RAND_bytes(buf,sizeof buf) <= 0) - { - fips_selftest_fail = 1; - ret = 0; - goto end; - } - FIPS_rand_set_key(buf,32); - FIPS_rand_seed(buf+32,16); - } - - /* now switch into FIPS mode */ - fips_set_rand_check(FIPS_rand_method()); - RAND_set_rand_method(FIPS_rand_method()); -#else - fips_set_rand_check(FIPS_drbg_method()); - RAND_set_rand_method(FIPS_drbg_method()); -#endif if(FIPS_selftest()) - fips_set_mode(1); + fips_set_mode(onoff); else { fips_selftest_fail = 1; @@ -436,140 +419,14 @@ unsigned char *fips_signature_witness(void) return FIPS_signature; } -/* Generalized public key test routine. Signs and verifies the data - * supplied in tbs using mesage digest md and setting RSA padding mode - * pad_mode. If the 'kat' parameter is not NULL it will - * additionally check the signature matches it: a known answer test - * The string "fail_str" is used for identification purposes in case - * of failure. - */ - -int fips_pkey_signature_test(EVP_PKEY *pkey, - const unsigned char *tbs, int tbslen, - const unsigned char *kat, unsigned int katlen, - const EVP_MD *digest, int pad_mode, - const char *fail_str) - { - int ret = 0; - unsigned char sigtmp[256], *sig = sigtmp; - unsigned int siglen; - DSA_SIG *dsig = NULL; - ECDSA_SIG *esig = NULL; - EVP_MD_CTX mctx; - FIPS_md_ctx_init(&mctx); - - if ((pkey->type == EVP_PKEY_RSA) - && ((size_t)RSA_size(pkey->pkey.rsa) > sizeof(sigtmp))) - { - sig = OPENSSL_malloc(RSA_size(pkey->pkey.rsa)); - if (!sig) - { - FIPSerr(FIPS_F_FIPS_PKEY_SIGNATURE_TEST,ERR_R_MALLOC_FAILURE); - return 0; - } - } - - if (tbslen == -1) - tbslen = strlen((char *)tbs); - - if (digest == NULL) - digest = EVP_sha256(); - - if (!FIPS_digestinit(&mctx, digest)) - goto error; - if (!FIPS_digestupdate(&mctx, tbs, tbslen)) - goto error; - 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 0 - else if (!EVP_SignFinal(&mctx, sig, &siglen, pkey)) - goto error; -#endif - - if (kat && ((siglen != katlen) || memcmp(kat, sig, katlen))) - 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); - } -#if 0 - else - ret = EVP_VerifyFinal(&mctx, sig, siglen, pkey); -#endif - - error: - if (dsig != NULL) - FIPS_dsa_sig_free(dsig); - if (esig != NULL) - FIPS_ecdsa_sig_free(esig); - if (sig != sigtmp) - 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); - return 0; - } - return 1; +unsigned long FIPS_module_version(void) + { + return FIPS_MODULE_VERSION_NUMBER; } -/* Generalized symmetric cipher test routine. Encrypt data, verify result - * against known answer, decrypt and compare with original plaintext. - */ - -int fips_cipher_test(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, - const unsigned char *key, - const unsigned char *iv, - const unsigned char *plaintext, - const unsigned char *ciphertext, - int len) +const char *FIPS_module_version_text(void) { - unsigned char pltmp[FIPS_MAX_CIPHER_TEST_SIZE]; - unsigned char citmp[FIPS_MAX_CIPHER_TEST_SIZE]; - OPENSSL_assert(len <= FIPS_MAX_CIPHER_TEST_SIZE); - if (FIPS_cipherinit(ctx, cipher, key, iv, 1) <= 0) - return 0; - FIPS_cipher(ctx, citmp, plaintext, len); - if (memcmp(citmp, ciphertext, len)) - return 0; - if (FIPS_cipherinit(ctx, cipher, key, iv, 0) <= 0) - return 0; - FIPS_cipher(ctx, pltmp, citmp, len); - if (memcmp(pltmp, plaintext, len)) - return 0; - return 1; + return FIPS_MODULE_VERSION_TEXT; } #if 0