Add non-FIPS algorithm blocking and selftest checking.

This commit is contained in:
Dr. Stephen Henson 2011-02-15 16:03:47 +00:00
parent 14567b1451
commit 25c6542944
10 changed files with 119 additions and 10 deletions

View file

@ -4,10 +4,13 @@
Changes between 1.0.1 and 1.1.0 [xx XXX xxxx] Changes between 1.0.1 and 1.1.0 [xx XXX xxxx]
*) Add selftest checks and algorithm block of non-fips algorithms in
FIPS mode. Remove DES2 from selftests.
[Steve Henson]
*) Add ECDSA code to fips module. Add tiny fips_ecdsa_check to just *) Add ECDSA code to fips module. Add tiny fips_ecdsa_check to just
return internal method without any ENGINE dependencies. Add new return internal method without any ENGINE dependencies. Add new
tiny fips sign and verify functions. Initial incomplete algorithm tiny fips sign and verify functions.
test program.
[Steve Henson] [Steve Henson]
*) New build option no-ec2m to disable characteristic 2 code. *) New build option no-ec2m to disable characteristic 2 code.

View file

@ -1319,6 +1319,7 @@ void ERR_load_EVP_strings(void);
#define EVP_R_DECODE_ERROR 114 #define EVP_R_DECODE_ERROR 114
#define EVP_R_DIFFERENT_KEY_TYPES 101 #define EVP_R_DIFFERENT_KEY_TYPES 101
#define EVP_R_DIFFERENT_PARAMETERS 153 #define EVP_R_DIFFERENT_PARAMETERS 153
#define EVP_R_DISABLED_FOR_FIPS 163
#define EVP_R_ENCODE_ERROR 115 #define EVP_R_ENCODE_ERROR 115
#define EVP_R_EVP_PBE_CIPHERINIT_ERROR 119 #define EVP_R_EVP_PBE_CIPHERINIT_ERROR 119
#define EVP_R_EXPECTING_AN_RSA_KEY 127 #define EVP_R_EXPECTING_AN_RSA_KEY 127

View file

@ -162,6 +162,7 @@ static ERR_STRING_DATA EVP_str_reasons[]=
{ERR_REASON(EVP_R_DECODE_ERROR) ,"decode error"}, {ERR_REASON(EVP_R_DECODE_ERROR) ,"decode error"},
{ERR_REASON(EVP_R_DIFFERENT_KEY_TYPES) ,"different key types"}, {ERR_REASON(EVP_R_DIFFERENT_KEY_TYPES) ,"different key types"},
{ERR_REASON(EVP_R_DIFFERENT_PARAMETERS) ,"different parameters"}, {ERR_REASON(EVP_R_DIFFERENT_PARAMETERS) ,"different parameters"},
{ERR_REASON(EVP_R_DISABLED_FOR_FIPS) ,"disabled for fips"},
{ERR_REASON(EVP_R_ENCODE_ERROR) ,"encode error"}, {ERR_REASON(EVP_R_ENCODE_ERROR) ,"encode error"},
{ERR_REASON(EVP_R_EVP_PBE_CIPHERINIT_ERROR),"evp pbe cipherinit error"}, {ERR_REASON(EVP_R_EVP_PBE_CIPHERINIT_ERROR),"evp pbe cipherinit error"},
{ERR_REASON(EVP_R_EXPECTING_AN_RSA_KEY) ,"expecting an rsa key"}, {ERR_REASON(EVP_R_EXPECTING_AN_RSA_KEY) ,"expecting an rsa key"},

View file

@ -80,6 +80,8 @@ static ERR_STRING_DATA FIPS_str_functs[]=
{ERR_FUNC(FIPS_F_FIPS_CHECK_DSA), "FIPS_CHECK_DSA"}, {ERR_FUNC(FIPS_F_FIPS_CHECK_DSA), "FIPS_CHECK_DSA"},
{ERR_FUNC(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT), "FIPS_check_incore_fingerprint"}, {ERR_FUNC(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT), "FIPS_check_incore_fingerprint"},
{ERR_FUNC(FIPS_F_FIPS_CHECK_RSA), "fips_check_rsa"}, {ERR_FUNC(FIPS_F_FIPS_CHECK_RSA), "fips_check_rsa"},
{ERR_FUNC(FIPS_F_FIPS_CIPHERINIT), "FIPS_CIPHERINIT"},
{ERR_FUNC(FIPS_F_FIPS_DIGESTINIT), "FIPS_DIGESTINIT"},
{ERR_FUNC(FIPS_F_FIPS_DSA_CHECK), "FIPS_DSA_CHECK"}, {ERR_FUNC(FIPS_F_FIPS_DSA_CHECK), "FIPS_DSA_CHECK"},
{ERR_FUNC(FIPS_F_FIPS_MODE_SET), "FIPS_mode_set"}, {ERR_FUNC(FIPS_F_FIPS_MODE_SET), "FIPS_mode_set"},
{ERR_FUNC(FIPS_F_FIPS_PKEY_SIGNATURE_TEST), "fips_pkey_signature_test"}, {ERR_FUNC(FIPS_F_FIPS_PKEY_SIGNATURE_TEST), "fips_pkey_signature_test"},

View file

@ -111,14 +111,6 @@ int FIPS_selftest_des()
int n, ret = 0; int n, ret = 0;
EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX ctx;
FIPS_cipher_ctx_init(&ctx); FIPS_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 */ /* Encrypt/decrypt with 3DES and compare to known answers */
for(n=0 ; n < 2 ; ++n) for(n=0 ; n < 2 ; ++n)

View file

@ -84,6 +84,7 @@ DSA_SIG * FIPS_dsa_sign_ctx(DSA *dsa, EVP_MD_CTX *ctx)
DSA_SIG * FIPS_dsa_sign_digest(DSA *dsa, const unsigned char *dig, int dlen) DSA_SIG * FIPS_dsa_sign_digest(DSA *dsa, const unsigned char *dig, int dlen)
{ {
FIPS_selftest_check();
return dsa->meth->dsa_do_sign(dig, dlen, dsa); return dsa->meth->dsa_do_sign(dig, dlen, dsa);
} }
@ -101,6 +102,7 @@ int FIPS_dsa_verify_ctx(DSA *dsa, EVP_MD_CTX *ctx, DSA_SIG *s)
int FIPS_dsa_verify_digest(DSA *dsa, int FIPS_dsa_verify_digest(DSA *dsa,
const unsigned char *dig, int dlen, DSA_SIG *s) const unsigned char *dig, int dlen, DSA_SIG *s)
{ {
FIPS_selftest_check();
return dsa->meth->dsa_do_verify(dig,dlen,s,dsa); return dsa->meth->dsa_do_verify(dig,dlen,s,dsa);
} }

View file

@ -114,6 +114,9 @@ void FIPS_set_locking_callbacks(void (*func)(int mode, int type,
int (*add_cb)(int *pointer, int amount, int (*add_cb)(int *pointer, int amount,
int type, const char *file, int line)); int type, const char *file, int line));
#define FIPS_ERROR_IGNORED(alg) OpenSSLDie(__FILE__, __LINE__, \
alg " previous FIPS forbidden algorithm error ignored");
/* Where necessary redirect standard OpenSSL APIs to FIPS versions */ /* Where necessary redirect standard OpenSSL APIs to FIPS versions */
#if defined(OPENSSL_FIPSCANISTER) && defined(OPENSSL_FIPSAPI) #if defined(OPENSSL_FIPSCANISTER) && defined(OPENSSL_FIPSAPI)
@ -179,6 +182,8 @@ void ERR_load_FIPS_strings(void);
#define FIPS_F_FIPS_CHECK_DSA 104 #define FIPS_F_FIPS_CHECK_DSA 104
#define FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT 105 #define FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT 105
#define FIPS_F_FIPS_CHECK_RSA 106 #define FIPS_F_FIPS_CHECK_RSA 106
#define FIPS_F_FIPS_CIPHERINIT 128
#define FIPS_F_FIPS_DIGESTINIT 127
#define FIPS_F_FIPS_DSA_CHECK 107 #define FIPS_F_FIPS_DSA_CHECK 107
#define FIPS_F_FIPS_MODE_SET 108 #define FIPS_F_FIPS_MODE_SET 108
#define FIPS_F_FIPS_PKEY_SIGNATURE_TEST 109 #define FIPS_F_FIPS_PKEY_SIGNATURE_TEST 109

View file

@ -219,6 +219,8 @@ int FIPS_rsa_sign_digest(RSA *rsa, const unsigned char *md, int md_len,
/* Largest DigestInfo: 19 (max encoding) + max MD */ /* Largest DigestInfo: 19 (max encoding) + max MD */
unsigned char tmpdinfo[19 + EVP_MAX_MD_SIZE]; unsigned char tmpdinfo[19 + EVP_MAX_MD_SIZE];
FIPS_selftest_check();
md_type = M_EVP_MD_type(mhash); md_type = M_EVP_MD_type(mhash);
if (rsa_pad_mode == RSA_X931_PADDING) if (rsa_pad_mode == RSA_X931_PADDING)
@ -326,6 +328,8 @@ int FIPS_rsa_verify_digest(RSA *rsa, const unsigned char *dig, int diglen,
return(0); return(0);
} }
FIPS_selftest_check();
md_type = M_EVP_MD_type(mhash); md_type = M_EVP_MD_type(mhash);
s= OPENSSL_malloc((unsigned int)siglen); s= OPENSSL_malloc((unsigned int)siglen);

View file

@ -78,9 +78,53 @@ EVP_CIPHER_CTX *FIPS_cipher_ctx_new(void)
return ctx; return ctx;
} }
/* The purpose of these is to trap programs that attempt to use non FIPS
* algorithms in FIPS mode and ignore the errors.
*/
static int bad_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{ FIPS_ERROR_IGNORED("Cipher init"); return 0;}
static int bad_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t inl)
{ FIPS_ERROR_IGNORED("Cipher update"); return 0;}
/* NB: no cleanup because it is allowed after failed init */
static int bad_set_asn1(EVP_CIPHER_CTX *ctx, ASN1_TYPE *typ)
{ FIPS_ERROR_IGNORED("Cipher set_asn1"); return 0;}
static int bad_get_asn1(EVP_CIPHER_CTX *ctx, ASN1_TYPE *typ)
{ FIPS_ERROR_IGNORED("Cipher get_asn1"); return 0;}
static int bad_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
{ FIPS_ERROR_IGNORED("Cipher ctrl"); return 0;}
static const EVP_CIPHER bad_cipher =
{
0,
0,
0,
0,
0,
bad_init,
bad_do_cipher,
NULL,
0,
bad_set_asn1,
bad_get_asn1,
bad_ctrl,
NULL
};
int FIPS_cipherinit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, int FIPS_cipherinit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
const unsigned char *key, const unsigned char *iv, int enc) const unsigned char *key, const unsigned char *iv, int enc)
{ {
if(FIPS_selftest_failed())
{
FIPSerr(FIPS_F_FIPS_CIPHERINIT,FIPS_R_FIPS_SELFTEST_FAILED);
ctx->cipher = &bad_cipher;
return 0;
}
if (enc == -1) if (enc == -1)
enc = ctx->encrypt; enc = ctx->encrypt;
else else
@ -91,6 +135,14 @@ int FIPS_cipherinit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
} }
if (cipher) if (cipher)
{ {
/* Only FIPS ciphers allowed */
if (FIPS_mode() && !(cipher->flags & EVP_CIPH_FLAG_FIPS) &&
!(ctx->flags & EVP_CIPH_FLAG_NON_FIPS_ALLOW))
{
EVPerr(EVP_F_FIPS_CIPHERINIT, EVP_R_DISABLED_FOR_FIPS);
ctx->cipher = &bad_cipher;
return 0;
}
/* Ensure a context left lying around from last time is cleared /* Ensure a context left lying around from last time is cleared
* (the previous check attempted to avoid this if the same * (the previous check attempted to avoid this if the same
* ENGINE and EVP_CIPHER could be used). */ * ENGINE and EVP_CIPHER could be used). */
@ -208,6 +260,7 @@ int FIPS_cipher_ctx_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
EVPerr(EVP_F_FIPS_CIPHER_CTX_CTRL, EVP_R_NO_CIPHER_SET); EVPerr(EVP_F_FIPS_CIPHER_CTX_CTRL, EVP_R_NO_CIPHER_SET);
return 0; return 0;
} }
FIPS_selftest_check();
if(!ctx->cipher->ctrl) { if(!ctx->cipher->ctrl) {
EVPerr(EVP_F_FIPS_CIPHER_CTX_CTRL, EVP_R_CTRL_NOT_IMPLEMENTED); EVPerr(EVP_F_FIPS_CIPHER_CTX_CTRL, EVP_R_CTRL_NOT_IMPLEMENTED);
@ -226,5 +279,6 @@ int FIPS_cipher_ctx_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
int FIPS_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, int FIPS_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, unsigned int inl) const unsigned char *in, unsigned int inl)
{ {
FIPS_selftest_check();
return ctx->cipher->do_cipher(ctx,out,in,inl); return ctx->cipher->do_cipher(ctx,out,in,inl);
} }

View file

@ -135,9 +135,51 @@ EVP_MD_CTX *FIPS_md_ctx_create(void)
return ctx; return ctx;
} }
/* The purpose of these is to trap programs that attempt to use non FIPS
* algorithms in FIPS mode and ignore the errors.
*/
static int bad_init(EVP_MD_CTX *ctx)
{ FIPS_ERROR_IGNORED("Digest init"); return 0;}
static int bad_update(EVP_MD_CTX *ctx,const void *data,size_t count)
{ FIPS_ERROR_IGNORED("Digest update"); return 0;}
static int bad_final(EVP_MD_CTX *ctx,unsigned char *md)
{ FIPS_ERROR_IGNORED("Digest Final"); return 0;}
static const EVP_MD bad_md =
{
0,
0,
0,
0,
bad_init,
bad_update,
bad_final,
NULL,
NULL,
NULL,
0,
{0,0,0,0},
};
int FIPS_digestinit(EVP_MD_CTX *ctx, const EVP_MD *type) int FIPS_digestinit(EVP_MD_CTX *ctx, const EVP_MD *type)
{ {
M_EVP_MD_CTX_clear_flags(ctx,EVP_MD_CTX_FLAG_CLEANED); M_EVP_MD_CTX_clear_flags(ctx,EVP_MD_CTX_FLAG_CLEANED);
if(FIPS_selftest_failed())
{
FIPSerr(FIPS_F_FIPS_DIGESTINIT,FIPS_R_FIPS_SELFTEST_FAILED);
ctx->digest = &bad_md;
return 0;
}
if(FIPS_mode() && !(type->flags & EVP_MD_FLAG_FIPS) &&
!(ctx->flags & EVP_MD_CTX_FLAG_NON_FIPS_ALLOW))
{
EVPerr(EVP_F_FIPS_DIGESTINIT, EVP_R_DISABLED_FOR_FIPS);
ctx->digest = &bad_md;
return 0;
}
if (ctx->digest != type) if (ctx->digest != type)
{ {
if (ctx->digest && ctx->digest->ctx_size) if (ctx->digest && ctx->digest->ctx_size)
@ -162,6 +204,7 @@ int FIPS_digestinit(EVP_MD_CTX *ctx, const EVP_MD *type)
int FIPS_digestupdate(EVP_MD_CTX *ctx, const void *data, size_t count) int FIPS_digestupdate(EVP_MD_CTX *ctx, const void *data, size_t count)
{ {
FIPS_selftest_check();
return ctx->update(ctx,data,count); return ctx->update(ctx,data,count);
} }
@ -170,6 +213,8 @@ int FIPS_digestfinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
{ {
int ret; int ret;
FIPS_selftest_check();
OPENSSL_assert(ctx->digest->md_size <= EVP_MAX_MD_SIZE); OPENSSL_assert(ctx->digest->md_size <= EVP_MAX_MD_SIZE);
ret=ctx->digest->final(ctx,md); ret=ctx->digest->final(ctx,md);
if (size != NULL) if (size != NULL)