Introduce EVP_MD_CTX_set_pkey_ctx
[openssl.git] / crypto / evp / digest.c
index 051fc7b19dbbbc2d381e170aa1936154dd0af922..8a2d162df186cbcfeb4be1fbffa748e3ddabb0e1 100644 (file)
@@ -32,11 +32,16 @@ int EVP_MD_CTX_reset(EVP_MD_CTX *ctx)
         && !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_REUSE)) {
         OPENSSL_clear_free(ctx->md_data, ctx->digest->ctx_size);
     }
-    EVP_PKEY_CTX_free(ctx->pctx);
+    /*
+     * pctx should be freed by the user of EVP_MD_CTX
+     * if EVP_MD_CTX_FLAG_NEGLECT_PCTX is set
+     */
+    if (!EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_NEGLECT_PCTX))
+        EVP_PKEY_CTX_free(ctx->pctx);
 #ifndef OPENSSL_NO_ENGINE
     ENGINE_finish(ctx->engine);
 #endif
-    memset(ctx, 0, sizeof(*ctx));
+    OPENSSL_cleanse(ctx, sizeof(*ctx));
 
     return 1;
 }
@@ -68,10 +73,8 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
      * previous handle, re-querying for an ENGINE, and having a
      * reinitialisation, when it may all be unnecessary.
      */
-    if (ctx->engine && ctx->digest && (!type ||
-                                       (type
-                                        && (type->type ==
-                                            ctx->digest->type))))
+    if (ctx->engine && ctx->digest &&
+        (type == NULL || (type->type == ctx->digest->type)))
         goto skip_to_init;
     if (type) {
         /*
@@ -117,7 +120,7 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
 #endif
     if (ctx->digest != type) {
         if (ctx->digest && ctx->digest->ctx_size) {
-            OPENSSL_free(ctx->md_data);
+            OPENSSL_clear_free(ctx->md_data, ctx->digest->ctx_size);
             ctx->md_data = NULL;
         }
         ctx->digest = type;
@@ -172,7 +175,28 @@ int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
         ctx->digest->cleanup(ctx);
         EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
     }
-    memset(ctx->md_data, 0, ctx->digest->ctx_size);
+    OPENSSL_cleanse(ctx->md_data, ctx->digest->ctx_size);
+    return ret;
+}
+
+int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md, size_t size)
+{
+    int ret = 0;
+
+    if (ctx->digest->flags & EVP_MD_FLAG_XOF
+        && size <= INT_MAX
+        && ctx->digest->md_ctrl(ctx, EVP_MD_CTRL_XOF_LEN, (int)size, NULL)) {
+        ret = ctx->digest->final(ctx, md);
+
+        if (ctx->digest->cleanup != NULL) {
+            ctx->digest->cleanup(ctx);
+            EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
+        }
+        OPENSSL_cleanse(ctx->md_data, ctx->digest->ctx_size);
+    } else {
+        EVPerr(EVP_F_EVP_DIGESTFINALXOF, EVP_R_NOT_XOF_OR_INVALID_LENGTH);
+    }
+
     return ret;
 }