diff options
Diffstat (limited to 'src/crypto/evp/digestsign.c')
-rw-r--r-- | src/crypto/evp/digestsign.c | 72 |
1 files changed, 56 insertions, 16 deletions
diff --git a/src/crypto/evp/digestsign.c b/src/crypto/evp/digestsign.c index ccb4de4..c163d40 100644 --- a/src/crypto/evp/digestsign.c +++ b/src/crypto/evp/digestsign.c @@ -62,9 +62,17 @@ #include "../digest/internal.h" +/* md_begin_digset is a callback from the |EVP_MD_CTX| code that is called when + * a new digest is begun. */ +static int md_begin_digest(EVP_MD_CTX *ctx) { + return EVP_PKEY_CTX_ctrl(ctx->pctx, -1, EVP_PKEY_OP_TYPE_SIG, + EVP_PKEY_CTRL_DIGESTINIT, 0, ctx); +} + static const struct evp_md_pctx_ops md_pctx_ops = { EVP_PKEY_CTX_free, EVP_PKEY_CTX_dup, + md_begin_digest, }; static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, @@ -83,16 +91,26 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, } if (type == NULL) { - OPENSSL_PUT_ERROR(EVP, EVP_R_NO_DEFAULT_DIGEST); + OPENSSL_PUT_ERROR(EVP, do_sigver_init, EVP_R_NO_DEFAULT_DIGEST); return 0; } if (is_verify) { - if (!EVP_PKEY_verify_init(ctx->pctx)) { + if (ctx->pctx->pmeth->verifyctx_init) { + if (!ctx->pctx->pmeth->verifyctx_init(ctx->pctx, ctx)) { + return 0; + } + ctx->pctx->operation = EVP_PKEY_OP_VERIFYCTX; + } else if (!EVP_PKEY_verify_init(ctx->pctx)) { return 0; } } else { - if (!EVP_PKEY_sign_init(ctx->pctx)) { + if (ctx->pctx->pmeth->signctx_init) { + if (!ctx->pctx->pmeth->signctx_init(ctx->pctx, ctx)) { + return 0; + } + ctx->pctx->operation = EVP_PKEY_OP_SIGNCTX; + } else if (!EVP_PKEY_sign_init(ctx->pctx)) { return 0; } } @@ -128,37 +146,59 @@ int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t len) { int EVP_DigestSignFinal(EVP_MD_CTX *ctx, uint8_t *out_sig, size_t *out_sig_len) { + int r = 0; + const int has_signctx = ctx->pctx->pmeth->signctx != NULL; + if (out_sig) { EVP_MD_CTX tmp_ctx; - int ret; uint8_t md[EVP_MAX_MD_SIZE]; unsigned int mdlen; EVP_MD_CTX_init(&tmp_ctx); - ret = EVP_MD_CTX_copy_ex(&tmp_ctx, ctx) && - EVP_DigestFinal_ex(&tmp_ctx, md, &mdlen) && - EVP_PKEY_sign(ctx->pctx, out_sig, out_sig_len, md, mdlen); + if (!EVP_MD_CTX_copy_ex(&tmp_ctx, ctx)) { + return 0; + } + if (has_signctx) { + r = tmp_ctx.pctx->pmeth->signctx(tmp_ctx.pctx, out_sig, out_sig_len, &tmp_ctx); + } else { + r = EVP_DigestFinal_ex(&tmp_ctx, md, &mdlen); + if (r) { + r = EVP_PKEY_sign(ctx->pctx, out_sig, out_sig_len, md, mdlen); + } + } EVP_MD_CTX_cleanup(&tmp_ctx); - - return ret; + return r; } else { - size_t s = EVP_MD_size(ctx->digest); - return EVP_PKEY_sign(ctx->pctx, out_sig, out_sig_len, NULL, s); + if (has_signctx) { + return ctx->pctx->pmeth->signctx(ctx->pctx, out_sig, out_sig_len, ctx); + } else { + size_t s = EVP_MD_size(ctx->digest); + return EVP_PKEY_sign(ctx->pctx, out_sig, out_sig_len, NULL, s); + } } } int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig, size_t sig_len) { EVP_MD_CTX tmp_ctx; - int ret; uint8_t md[EVP_MAX_MD_SIZE]; + int r; unsigned int mdlen; EVP_MD_CTX_init(&tmp_ctx); - ret = EVP_MD_CTX_copy_ex(&tmp_ctx, ctx) && - EVP_DigestFinal_ex(&tmp_ctx, md, &mdlen) && - EVP_PKEY_verify(ctx->pctx, sig, sig_len, md, mdlen); + if (!EVP_MD_CTX_copy_ex(&tmp_ctx, ctx)) { + return 0; + } + if (ctx->pctx->pmeth->verifyctx) { + r = tmp_ctx.pctx->pmeth->verifyctx(tmp_ctx.pctx, sig, sig_len, &tmp_ctx); + } else { + r = EVP_DigestFinal_ex(&tmp_ctx, md, &mdlen); + if (r) { + r = EVP_PKEY_verify(ctx->pctx, sig, sig_len, md, mdlen); + } + } + EVP_MD_CTX_cleanup(&tmp_ctx); - return ret; + return r; } |