/*
- * 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
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;
if (ctx->pctx == NULL)
return 0;
+ EVP_MD_CTX_clear_flags(ctx, EVP_MD_CTX_FLAG_FINALISED);
+
locpctx = ctx->pctx;
ERR_set_mark();
{
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
{
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
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
|| 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:
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;
{
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)
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
|| 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:
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();
{
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)