int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type)
{
+ EVP_MD_CTX_init(ctx);
return EVP_DigestInit_ex(ctx, type, NULL);
}
+
int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
{
+ EVP_MD_CTX_clear_flags(ctx,EVP_MD_CTX_FLAG_CLEANED);
/* 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
* ENGINE and EVP_MD could be used). */
if(ctx->engine)
ENGINE_finish(ctx->engine);
- if(!impl)
+ if(impl)
+ {
+ if (!ENGINE_init(impl))
+ {
+ EVPerr(EVP_F_EVP_DIGESTINIT, EVP_R_INITIALIZATION_ERROR);
+ return 0;
+ }
+ }
+ else
/* Ask if an ENGINE is reserved for this job */
impl = ENGINE_get_digest_engine(type->type);
if(impl)
ctx->md_data=OPENSSL_malloc(type->ctx_size);
}
skip_to_init:
- return type->init(ctx);
+ return ctx->digest->init(ctx);
}
int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data,
/* The caller can assume that this removes any secret data from the context */
int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
+ {
+ int ret;
+ ret = EVP_DigestFinal_ex(ctx, md, size);
+ EVP_MD_CTX_cleanup(ctx);
+ return ret;
+ }
+
+/* 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;
ret=ctx->digest->final(ctx,md);
if (size != NULL)
*size=ctx->digest->md_size;
- /* FIXME: add a cleanup function to the ctx? */
+ if (ctx->digest->cleanup)
+ {
+ ctx->digest->cleanup(ctx);
+ EVP_MD_CTX_set_flags(ctx,EVP_MD_CTX_FLAG_CLEANED);
+ }
memset(ctx->md_data,0,ctx->digest->ctx_size);
return ret;
}
int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in)
+ {
+ EVP_MD_CTX_init(out);
+ return EVP_MD_CTX_copy_ex(out, in);
+ }
+
+int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
{
if ((in == NULL) || (in->digest == NULL))
{
}
int EVP_Digest(void *data, unsigned int count,
- unsigned char *md, unsigned int *size, const EVP_MD *type)
+ unsigned char *md, unsigned int *size, const EVP_MD *type, ENGINE *impl)
{
EVP_MD_CTX ctx;
int ret;
EVP_MD_CTX_init(&ctx);
EVP_MD_CTX_set_flags(&ctx,EVP_MD_CTX_FLAG_ONESHOT);
- ret=EVP_DigestInit(&ctx, type)
+ ret=EVP_DigestInit_ex(&ctx, type, impl)
&& EVP_DigestUpdate(&ctx, data, count)
- && EVP_DigestFinal(&ctx, md, size);
+ && EVP_DigestFinal_ex(&ctx, md, size);
EVP_MD_CTX_cleanup(&ctx);
return ret;
/* 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)
+ if (ctx->digest && ctx->digest->cleanup
+ && !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)
{