summaryrefslogtreecommitdiffstats
path: root/crypto/evp/digest.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/evp/digest.c')
-rw-r--r--crypto/evp/digest.c217
1 files changed, 81 insertions, 136 deletions
diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c
index 10a3607..467e6b5 100644
--- a/crypto/evp/digest.c
+++ b/crypto/evp/digest.c
@@ -116,7 +116,10 @@
#ifndef OPENSSL_NO_ENGINE
#include <openssl/engine.h>
#endif
-#include "evp_locl.h"
+
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
void EVP_MD_CTX_init(EVP_MD_CTX *ctx)
{
@@ -139,77 +142,18 @@ int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type)
return EVP_DigestInit_ex(ctx, type, NULL);
}
-#ifdef OPENSSL_FIPS
-
-/* 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 =
+int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
{
- 0,
- 0,
- 0,
- 0,
- bad_init,
- bad_update,
- bad_final,
- NULL,
- NULL,
- NULL,
- 0,
- {0,0,0,0},
- };
-
-#endif
-
+ EVP_MD_CTX_clear_flags(ctx,EVP_MD_CTX_FLAG_CLEANED);
#ifndef OPENSSL_NO_ENGINE
-
-#ifdef OPENSSL_FIPS
-
-static int do_engine_null(ENGINE *impl) { return 0;}
-static int do_evp_md_engine_null(EVP_MD_CTX *ctx,
- const EVP_MD **ptype, ENGINE *impl)
- { return 1; }
-
-static int (*do_engine_init)(ENGINE *impl)
- = do_engine_null;
-
-static int (*do_engine_finish)(ENGINE *impl)
- = do_engine_null;
-
-static int (*do_evp_md_engine)
- (EVP_MD_CTX *ctx, const EVP_MD **ptype, ENGINE *impl)
- = do_evp_md_engine_null;
-
-void int_EVP_MD_set_engine_callbacks(
- int (*eng_md_init)(ENGINE *impl),
- int (*eng_md_fin)(ENGINE *impl),
- int (*eng_md_evp)
- (EVP_MD_CTX *ctx, const EVP_MD **ptype, ENGINE *impl))
- {
- do_engine_init = eng_md_init;
- do_engine_finish = eng_md_fin;
- do_evp_md_engine = eng_md_evp;
- }
-
-#else
-
-#define do_engine_init ENGINE_init
-#define do_engine_finish ENGINE_finish
-
-static int do_evp_md_engine(EVP_MD_CTX *ctx, const EVP_MD **ptype, ENGINE *impl)
- {
- if (*ptype)
+ /* Whether it's nice or not, "Inits" can be used on "Final"'d contexts
+ * so this context may already have an ENGINE! Try to avoid releasing
+ * the previous handle, re-querying for an ENGINE, and having a
+ * reinitialisation, when it may all be unecessary. */
+ if (ctx->engine && ctx->digest && (!type ||
+ (type && (type->type == ctx->digest->type))))
+ goto skip_to_init;
+ if (type)
{
/* Ensure an ENGINE left lying around from last time is cleared
* (the previous check attempted to avoid this if the same
@@ -220,26 +164,26 @@ static int do_evp_md_engine(EVP_MD_CTX *ctx, const EVP_MD **ptype, ENGINE *impl)
{
if (!ENGINE_init(impl))
{
- EVPerr(EVP_F_DO_EVP_MD_ENGINE,EVP_R_INITIALIZATION_ERROR);
+ EVPerr(EVP_F_EVP_DIGESTINIT_EX,EVP_R_INITIALIZATION_ERROR);
return 0;
}
}
else
/* Ask if an ENGINE is reserved for this job */
- impl = ENGINE_get_digest_engine((*ptype)->type);
+ impl = ENGINE_get_digest_engine(type->type);
if(impl)
{
/* There's an ENGINE for this job ... (apparently) */
- const EVP_MD *d = ENGINE_get_digest(impl, (*ptype)->type);
+ const EVP_MD *d = ENGINE_get_digest(impl, type->type);
if(!d)
{
/* Same comment from evp_enc.c */
- EVPerr(EVP_F_DO_EVP_MD_ENGINE,EVP_R_INITIALIZATION_ERROR);
+ EVPerr(EVP_F_EVP_DIGESTINIT_EX,EVP_R_INITIALIZATION_ERROR);
ENGINE_finish(impl);
return 0;
}
/* We'll use the ENGINE's private digest definition */
- *ptype = d;
+ type = d;
/* Store the ENGINE functional reference so we know
* 'type' came from an ENGINE and we need to release
* it when done. */
@@ -251,78 +195,60 @@ static int do_evp_md_engine(EVP_MD_CTX *ctx, const EVP_MD **ptype, ENGINE *impl)
else
if(!ctx->digest)
{
- EVPerr(EVP_F_DO_EVP_MD_ENGINE,EVP_R_NO_DIGEST_SET);
+ EVPerr(EVP_F_EVP_DIGESTINIT_EX,EVP_R_NO_DIGEST_SET);
return 0;
}
- return 1;
- }
-
-#endif
-
-#endif
-
-int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
- {
- M_EVP_MD_CTX_clear_flags(ctx,EVP_MD_CTX_FLAG_CLEANED);
-#ifdef OPENSSL_FIPS
- if(FIPS_selftest_failed())
- {
- FIPSerr(FIPS_F_EVP_DIGESTINIT_EX,FIPS_R_FIPS_SELFTEST_FAILED);
- ctx->digest = &bad_md;
- return 0;
- }
-#endif
-#ifndef OPENSSL_NO_ENGINE
- /* Whether it's nice or not, "Inits" can be used on "Final"'d contexts
- * so this context may already have an ENGINE! Try to avoid releasing
- * the previous handle, re-querying for an ENGINE, and having a
- * reinitialisation, when it may all be unecessary. */
- if (ctx->engine && ctx->digest && (!type ||
- (type && (type->type == ctx->digest->type))))
- goto skip_to_init;
- if (!do_evp_md_engine(ctx, &type, impl))
- return 0;
#endif
if (ctx->digest != type)
{
-#ifdef OPENSSL_FIPS
- if (FIPS_mode())
- {
- if (!(type->flags & EVP_MD_FLAG_FIPS)
- && !(ctx->flags & EVP_MD_CTX_FLAG_NON_FIPS_ALLOW))
- {
- EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_DISABLED_FOR_FIPS);
- ctx->digest = &bad_md;
- return 0;
- }
- }
-#endif
if (ctx->digest && ctx->digest->ctx_size)
OPENSSL_free(ctx->md_data);
ctx->digest=type;
- if (type->ctx_size)
+ if (!(ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) && type->ctx_size)
{
+ ctx->update = type->update;
ctx->md_data=OPENSSL_malloc(type->ctx_size);
- if (!ctx->md_data)
+ if (ctx->md_data == NULL)
{
- EVPerr(EVP_F_EVP_DIGESTINIT_EX, ERR_R_MALLOC_FAILURE);
+ EVPerr(EVP_F_EVP_DIGESTINIT_EX,
+ ERR_R_MALLOC_FAILURE);
return 0;
}
}
}
#ifndef OPENSSL_NO_ENGINE
- skip_to_init:
+skip_to_init:
+#endif
+ if (ctx->pctx)
+ {
+ int r;
+ r = EVP_PKEY_CTX_ctrl(ctx->pctx, -1, EVP_PKEY_OP_TYPE_SIG,
+ EVP_PKEY_CTRL_DIGESTINIT, 0, ctx);
+ if (r <= 0 && (r != -2))
+ return 0;
+ }
+ if (ctx->flags & EVP_MD_CTX_FLAG_NO_INIT)
+ return 1;
+#ifdef OPENSSL_FIPS
+ if (FIPS_mode())
+ {
+ if (FIPS_digestinit(ctx, type))
+ return 1;
+ OPENSSL_free(ctx->md_data);
+ ctx->md_data = NULL;
+ return 0;
+ }
#endif
return ctx->digest->init(ctx);
}
-int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data,
- size_t count)
+int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, size_t count)
{
#ifdef OPENSSL_FIPS
- FIPS_selftest_check();
+ return FIPS_digestupdate(ctx, data, count);
+#else
+ return ctx->update(ctx,data,count);
#endif
- return ctx->digest->update(ctx,data,count);
}
/* The caller can assume that this removes any secret data from the context */
@@ -337,11 +263,10 @@ int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
/* The caller can assume that this removes any secret data from the context */
int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
{
- int ret;
#ifdef OPENSSL_FIPS
- FIPS_selftest_check();
-#endif
-
+ return FIPS_digestfinal(ctx, md, size);
+#else
+ int ret;
OPENSSL_assert(ctx->digest->md_size <= EVP_MAX_MD_SIZE);
ret=ctx->digest->final(ctx,md);
if (size != NULL)
@@ -349,10 +274,11 @@ int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
if (ctx->digest->cleanup)
{
ctx->digest->cleanup(ctx);
- M_EVP_MD_CTX_set_flags(ctx,EVP_MD_CTX_FLAG_CLEANED);
+ EVP_MD_CTX_set_flags(ctx,EVP_MD_CTX_FLAG_CLEANED);
}
memset(ctx->md_data,0,ctx->digest->ctx_size);
return ret;
+#endif
}
int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in)
@@ -371,7 +297,7 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
}
#ifndef OPENSSL_NO_ENGINE
/* Make sure it's safe to copy a digest context using an ENGINE */
- if (in->engine && !do_engine_init(in->engine))
+ if (in->engine && !ENGINE_init(in->engine))
{
EVPerr(EVP_F_EVP_MD_CTX_COPY_EX,ERR_R_ENGINE_LIB);
return 0;
@@ -381,13 +307,13 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
if (out->digest == in->digest)
{
tmp_buf = out->md_data;
- M_EVP_MD_CTX_set_flags(out,EVP_MD_CTX_FLAG_REUSE);
+ EVP_MD_CTX_set_flags(out,EVP_MD_CTX_FLAG_REUSE);
}
else tmp_buf = NULL;
EVP_MD_CTX_cleanup(out);
memcpy(out,in,sizeof *out);
- if (out->digest->ctx_size)
+ if (in->md_data && out->digest->ctx_size)
{
if (tmp_buf)
out->md_data = tmp_buf;
@@ -403,6 +329,18 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
memcpy(out->md_data,in->md_data,out->digest->ctx_size);
}
+ out->update = in->update;
+
+ if (in->pctx)
+ {
+ out->pctx = EVP_PKEY_CTX_dup(in->pctx);
+ if (!out->pctx)
+ {
+ EVP_MD_CTX_cleanup(out);
+ return 0;
+ }
+ }
+
if (out->digest->copy)
return out->digest->copy(out,in);
@@ -416,7 +354,7 @@ int EVP_Digest(const void *data, size_t count,
int ret;
EVP_MD_CTX_init(&ctx);
- M_EVP_MD_CTX_set_flags(&ctx,EVP_MD_CTX_FLAG_ONESHOT);
+ EVP_MD_CTX_set_flags(&ctx,EVP_MD_CTX_FLAG_ONESHOT);
ret=EVP_DigestInit_ex(&ctx, type, impl)
&& EVP_DigestUpdate(&ctx, data, count)
&& EVP_DigestFinal_ex(&ctx, md, size);
@@ -434,23 +372,30 @@ void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx)
/* This call frees resources associated with the context */
int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx)
{
+#ifndef OPENSSL_FIPS
/* Don't assume ctx->md_data was cleaned in EVP_Digest_Final,
* because sometimes only copies of the context are ever finalised.
*/
if (ctx->digest && ctx->digest->cleanup
- && !M_EVP_MD_CTX_test_flags(ctx,EVP_MD_CTX_FLAG_CLEANED))
+ && !EVP_MD_CTX_test_flags(ctx,EVP_MD_CTX_FLAG_CLEANED))
ctx->digest->cleanup(ctx);
if (ctx->digest && ctx->digest->ctx_size && ctx->md_data
- && !M_EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_REUSE))
+ && !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_REUSE))
{
OPENSSL_cleanse(ctx->md_data,ctx->digest->ctx_size);
OPENSSL_free(ctx->md_data);
}
+#endif
+ if (ctx->pctx)
+ EVP_PKEY_CTX_free(ctx->pctx);
#ifndef OPENSSL_NO_ENGINE
if(ctx->engine)
/* The EVP_MD we used belongs to an ENGINE, release the
* functional reference we held for this reason. */
- do_engine_finish(ctx->engine);
+ ENGINE_finish(ctx->engine);
+#endif
+#ifdef OPENSSL_FIPS
+ FIPS_md_ctx_cleanup(ctx);
#endif
memset(ctx,'\0',sizeof *ctx);
OpenPOWER on IntegriCloud