ess_lib.c: Changed ERR_LIB_CMS to ERR_LIB_ESS
[openssl.git] / crypto / evp / m_sigver.c
index 0993de0937722cb520b8b4588bdc63566beb3faa..3a979f4bd459213d7d14bc7b23419fb129494361 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -51,15 +51,8 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
     void *provkey = NULL;
     int ret, iter, reinit = 1;
 
-    if (ctx->algctx != NULL) {
-        if (!ossl_assert(ctx->digest != NULL)) {
-            ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
-            return 0;
-        }
-        if (ctx->digest->freectx != NULL)
-            ctx->digest->freectx(ctx->algctx);
-        ctx->algctx = NULL;
-    }
+    if (!evp_md_ctx_free_algctx(ctx))
+        return 0;
 
     if (ctx->pctx == NULL) {
         reinit = 0;
@@ -71,6 +64,8 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
     if (ctx->pctx == NULL)
         return 0;
 
+    EVP_MD_CTX_clear_flags(ctx, EVP_MD_CTX_FLAG_FINALISED);
+
     locpctx = ctx->pctx;
     ERR_set_mark();
 
@@ -231,7 +226,7 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
              * We're about to get a new digest so clear anything associated with
              * an old digest.
              */
-            evp_md_ctx_clear_digest(ctx, 1);
+            evp_md_ctx_clear_digest(ctx, 1, 0);
 
             /* legacy code support for engines */
             ERR_set_mark();
@@ -408,6 +403,11 @@ int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize)
 {
     EVP_PKEY_CTX *pctx = ctx->pctx;
 
+    if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISED) != 0) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR);
+        return 0;
+    }
+
     if (pctx == NULL
             || pctx->operation != EVP_PKEY_OP_SIGNCTX
             || pctx->op.sig.algctx == NULL
@@ -438,6 +438,11 @@ int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize)
 {
     EVP_PKEY_CTX *pctx = ctx->pctx;
 
+    if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISED) != 0) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR);
+        return 0;
+    }
+
     if (pctx == NULL
             || pctx->operation != EVP_PKEY_OP_VERIFYCTX
             || pctx->op.sig.algctx == NULL
@@ -469,7 +474,12 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
                         size_t *siglen)
 {
     int sctx = 0, r = 0;
-    EVP_PKEY_CTX *dctx, *pctx = ctx->pctx;
+    EVP_PKEY_CTX *dctx = NULL, *pctx = ctx->pctx;
+
+    if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISED) != 0) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR);
+        return 0;
+    }
 
     if (pctx == NULL
             || pctx->operation != EVP_PKEY_OP_SIGNCTX
@@ -477,18 +487,19 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
             || pctx->op.sig.signature == NULL)
         goto legacy;
 
-    if (sigret == NULL || (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) != 0)
-        return pctx->op.sig.signature->digest_sign_final(pctx->op.sig.algctx,
-                                                         sigret, siglen,
-                                                         sigret == NULL ? 0 : *siglen);
-    dctx = EVP_PKEY_CTX_dup(pctx);
-    if (dctx == NULL)
-        return 0;
-
-    r = dctx->op.sig.signature->digest_sign_final(dctx->op.sig.algctx,
+    if (sigret != NULL && (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) == 0) {
+        /* try dup */
+        dctx = EVP_PKEY_CTX_dup(pctx);
+        if (dctx != NULL)
+            pctx = dctx;
+    }
+    r = pctx->op.sig.signature->digest_sign_final(pctx->op.sig.algctx,
                                                   sigret, siglen,
-                                                  *siglen);
-    EVP_PKEY_CTX_free(dctx);
+                                                  sigret == NULL ? 0 : *siglen);
+    if (dctx == NULL && sigret != NULL)
+        ctx->flags |= EVP_MD_CTX_FLAG_FINALISED;
+    else
+        EVP_PKEY_CTX_free(dctx);
     return r;
 
  legacy:
@@ -506,9 +517,10 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
     if (pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) {
         if (sigret == NULL)
             return pctx->pmeth->signctx(pctx, sigret, siglen, ctx);
-        if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE)
+        if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISE) != 0) {
             r = pctx->pmeth->signctx(pctx, sigret, siglen, ctx);
-        else {
+            ctx->flags |= EVP_MD_CTX_FLAG_FINALISED;
+        } else {
             dctx = EVP_PKEY_CTX_dup(pctx);
             if (dctx == NULL)
                 return 0;
@@ -569,15 +581,23 @@ int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen,
 {
     EVP_PKEY_CTX *pctx = ctx->pctx;
 
+    if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISED) != 0) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR);
+        return 0;
+    }
+
     if (pctx != NULL
             && pctx->operation == EVP_PKEY_OP_SIGNCTX
             && pctx->op.sig.algctx != NULL
             && pctx->op.sig.signature != NULL) {
-        if (pctx->op.sig.signature->digest_sign != NULL)
+        if (pctx->op.sig.signature->digest_sign != NULL) {
+            if (sigret != NULL)
+                ctx->flags |= EVP_MD_CTX_FLAG_FINALISED;
             return pctx->op.sig.signature->digest_sign(pctx->op.sig.algctx,
                                                        sigret, siglen,
                                                        sigret == NULL ? 0 : *siglen,
                                                        tbs, tbslen);
+        }
     } else {
         /* legacy */
         if (ctx->pctx->pmeth != NULL && ctx->pctx->pmeth->digestsign != NULL)
@@ -596,7 +616,12 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig,
     int r = 0;
     unsigned int mdlen = 0;
     int vctx = 0;
-    EVP_PKEY_CTX *dctx, *pctx = ctx->pctx;
+    EVP_PKEY_CTX *dctx = NULL, *pctx = ctx->pctx;
+
+    if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISED) != 0) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR);
+        return 0;
+    }
 
     if (pctx == NULL
             || pctx->operation != EVP_PKEY_OP_VERIFYCTX
@@ -604,16 +629,18 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig,
             || pctx->op.sig.signature == NULL)
         goto legacy;
 
-    if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISE) != 0)
-        return pctx->op.sig.signature->digest_verify_final(pctx->op.sig.algctx,
-                                                           sig, siglen);
-    dctx = EVP_PKEY_CTX_dup(pctx);
-    if (dctx == NULL)
-        return 0;
-
-    r = dctx->op.sig.signature->digest_verify_final(dctx->op.sig.algctx,
+    if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISE) == 0) {
+        /* try dup */
+        dctx = EVP_PKEY_CTX_dup(pctx);
+        if (dctx != NULL)
+            pctx = dctx;
+    }
+    r = pctx->op.sig.signature->digest_verify_final(pctx->op.sig.algctx,
                                                     sig, siglen);
-    EVP_PKEY_CTX_free(dctx);
+    if (dctx == NULL)
+        ctx->flags |= EVP_MD_CTX_FLAG_FINALISED;
+    else
+        EVP_PKEY_CTX_free(dctx);
     return r;
 
  legacy:
@@ -633,9 +660,10 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig,
     else
         vctx = 0;
     if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) {
-        if (vctx)
+        if (vctx) {
             r = pctx->pmeth->verifyctx(pctx, sig, siglen, ctx);
-        else
+            ctx->flags |= EVP_MD_CTX_FLAG_FINALISED;
+        } else
             r = EVP_DigestFinal_ex(ctx, md, &mdlen);
     } else {
         EVP_MD_CTX *tmp_ctx = EVP_MD_CTX_new();
@@ -662,14 +690,21 @@ int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret,
 {
     EVP_PKEY_CTX *pctx = ctx->pctx;
 
+    if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISED) != 0) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR);
+        return 0;
+    }
+
     if (pctx != NULL
             && pctx->operation == EVP_PKEY_OP_VERIFYCTX
             && pctx->op.sig.algctx != NULL
             && pctx->op.sig.signature != NULL) {
-        if (pctx->op.sig.signature->digest_verify != NULL)
+        if (pctx->op.sig.signature->digest_verify != NULL) {
+            ctx->flags |= EVP_MD_CTX_FLAG_FINALISED;
             return pctx->op.sig.signature->digest_verify(pctx->op.sig.algctx,
                                                          sigret, siglen,
                                                          tbs, tbslen);
+        }
     } else {
         /* legacy */
         if (ctx->pctx->pmeth != NULL && ctx->pctx->pmeth->digestverify != NULL)