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.
#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
{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"},
{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"},
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)
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);
}
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);
}
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)
#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
/* 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)
return(0);
}
+ FIPS_selftest_check();
+
md_type = M_EVP_MD_type(mhash);
s= OPENSSL_malloc((unsigned int)siglen);
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
}
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). */
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);
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);
}
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)
int FIPS_digestupdate(EVP_MD_CTX *ctx, const void *data, size_t count)
{
+ FIPS_selftest_check();
return ctx->update(ctx,data,count);
}
{
int ret;
+ FIPS_selftest_check();
+
OPENSSL_assert(ctx->digest->md_size <= EVP_MAX_MD_SIZE);
ret=ctx->digest->final(ctx,md);
if (size != NULL)