Add non-FIPS algorithm blocking and selftest checking.
This commit is contained in:
parent
14567b1451
commit
25c6542944
10 changed files with 119 additions and 10 deletions
7
CHANGES
7
CHANGES
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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"},
|
||||||
|
|
|
@ -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"},
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue