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]
*) 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
return internal method without any ENGINE dependencies. Add new
tiny fips sign and verify functions. Initial incomplete algorithm
test program.
tiny fips sign and verify functions.
[Steve Henson]
*) 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_DIFFERENT_KEY_TYPES 101
#define EVP_R_DIFFERENT_PARAMETERS 153
#define EVP_R_DISABLED_FOR_FIPS 163
#define EVP_R_ENCODE_ERROR 115
#define EVP_R_EVP_PBE_CIPHERINIT_ERROR 119
#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_DIFFERENT_KEY_TYPES) ,"different key types"},
{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_EVP_PBE_CIPHERINIT_ERROR),"evp pbe cipherinit error"},
{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_INCORE_FINGERPRINT), "FIPS_check_incore_fingerprint"},
{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_MODE_SET), "FIPS_mode_set"},
{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;
EVP_CIPHER_CTX 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 */
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)
{
FIPS_selftest_check();
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,
const unsigned char *dig, int dlen, DSA_SIG *s)
{
FIPS_selftest_check();
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 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 */
#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_INCORE_FINGERPRINT 105
#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_MODE_SET 108
#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 */
unsigned char tmpdinfo[19 + EVP_MAX_MD_SIZE];
FIPS_selftest_check();
md_type = M_EVP_MD_type(mhash);
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);
}
FIPS_selftest_check();
md_type = M_EVP_MD_type(mhash);
s= OPENSSL_malloc((unsigned int)siglen);

View file

@ -78,9 +78,53 @@ EVP_CIPHER_CTX *FIPS_cipher_ctx_new(void)
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,
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)
enc = ctx->encrypt;
else
@ -91,6 +135,14 @@ int FIPS_cipherinit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *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
* (the previous check attempted to avoid this if the same
* 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);
return 0;
}
FIPS_selftest_check();
if(!ctx->cipher->ctrl) {
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,
const unsigned char *in, unsigned int inl)
{
FIPS_selftest_check();
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;
}
/* 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)
{
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 && 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)
{
FIPS_selftest_check();
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;
FIPS_selftest_check();
OPENSSL_assert(ctx->digest->md_size <= EVP_MAX_MD_SIZE);
ret=ctx->digest->final(ctx,md);
if (size != NULL)