Workaround for some CMS signature formats.
[openssl.git] / fips / utl / fips_md.c
index 0038646..5e9fe4e 100644 (file)
@@ -135,9 +135,53 @@ 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;
+               ctx->update = bad_update;
+               return 0;
+               }
+       if(FIPS_module_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;
+               ctx->update = bad_update;
+               return 0;
+               }
        if (ctx->digest != type)
                {
                if (ctx->digest && ctx->digest->ctx_size)
@@ -149,7 +193,7 @@ int FIPS_digestinit(EVP_MD_CTX *ctx, const EVP_MD *type)
                        ctx->md_data=OPENSSL_malloc(type->ctx_size);
                        if (ctx->md_data == NULL)
                                {
-                               EVPerr(EVP_F_EVP_DIGESTINIT_EX,
+                               EVPerr(EVP_F_FIPS_DIGESTINIT,
                                                        ERR_R_MALLOC_FAILURE);
                                return 0;
                                }
@@ -162,6 +206,11 @@ int FIPS_digestinit(EVP_MD_CTX *ctx, const EVP_MD *type)
 
 int FIPS_digestupdate(EVP_MD_CTX *ctx, const void *data, size_t count)
        {
+       if (FIPS_selftest_failed())
+               {
+               FIPSerr(FIPS_F_FIPS_DIGESTUPDATE, FIPS_R_SELFTEST_FAILED);
+               return 0;
+               }
        return ctx->update(ctx,data,count);
        }
 
@@ -170,6 +219,12 @@ int FIPS_digestfinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
        {
        int ret;
 
+       if (FIPS_selftest_failed())
+               {
+               FIPSerr(FIPS_F_FIPS_DIGESTFINAL, FIPS_R_SELFTEST_FAILED);
+               return 0;
+               }
+
        OPENSSL_assert(ctx->digest->md_size <= EVP_MAX_MD_SIZE);
        ret=ctx->digest->final(ctx,md);
        if (size != NULL)
@@ -208,7 +263,7 @@ void FIPS_md_ctx_destroy(EVP_MD_CTX *ctx)
 /* This call frees resources associated with the context */
 int FIPS_md_ctx_cleanup(EVP_MD_CTX *ctx)
        {
-       /* Don't assume ctx->md_data was cleaned in EVP_Digest_Final,
+       /* Don't assume ctx->md_data was cleaned in FIPS_digest_Final,
         * because sometimes only copies of the context are ever finalised.
         */
        if (ctx->digest && ctx->digest->cleanup
@@ -230,7 +285,7 @@ int FIPS_md_ctx_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in)
        unsigned char *tmp_buf;
        if ((in == NULL) || (in->digest == NULL))
                {
-               EVPerr(EVP_F_EVP_MD_CTX_COPY_EX,EVP_R_INPUT_NOT_INITIALIZED);
+               EVPerr(EVP_F_FIPS_MD_CTX_COPY,EVP_R_INPUT_NOT_INITIALIZED);
                return 0;
                }
 
@@ -252,7 +307,7 @@ int FIPS_md_ctx_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in)
                        out->md_data=OPENSSL_malloc(out->digest->ctx_size);
                        if (!out->md_data)
                                {
-                               EVPerr(EVP_F_EVP_MD_CTX_COPY_EX,ERR_R_MALLOC_FAILURE);
+                               EVPerr(EVP_F_FIPS_MD_CTX_COPY,ERR_R_MALLOC_FAILURE);
                                return 0;
                                }
                        }
@@ -266,3 +321,27 @@ int FIPS_md_ctx_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in)
        
        return 1;
        }
+
+const EVP_MD *FIPS_get_digestbynid(int nid)
+       {
+       switch (nid)
+               {
+               case NID_sha1:
+               return EVP_sha1();
+
+               case NID_sha224:
+               return EVP_sha224();
+
+               case NID_sha256:
+               return EVP_sha256();
+
+               case NID_sha384:
+               return EVP_sha384();
+
+               case NID_sha512:
+               return EVP_sha512();
+
+               default:
+               return NULL;
+               }
+       }