Add support for custom digestsign/digestverify methods.
authorDr. Stephen Henson <steve@openssl.org>
Fri, 19 May 2017 20:31:46 +0000 (21:31 +0100)
committerDr. Stephen Henson <steve@openssl.org>
Tue, 30 May 2017 19:38:19 +0000 (20:38 +0100)
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/3503)

crypto/evp/m_sigver.c
crypto/include/internal/evp_int.h

index d53e1d6..be6bb21 100644 (file)
 #include "internal/evp_int.h"
 #include "evp_locl.h"
 
+static int update(EVP_MD_CTX *ctx, const void *data, size_t datalen)
+{
+    EVPerr(EVP_F_UPDATE, EVP_R_ONLY_ONESHOT_SUPPORTED);
+    return 0;
+}
+
 static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
                           const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey,
                           int ver)
@@ -43,15 +49,23 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
             if (ctx->pctx->pmeth->verifyctx_init(ctx->pctx, ctx) <= 0)
                 return 0;
             ctx->pctx->operation = EVP_PKEY_OP_VERIFYCTX;
-        } else if (EVP_PKEY_verify_init(ctx->pctx) <= 0)
+        } else if (ctx->pctx->pmeth->digestverify != 0) {
+            ctx->pctx->operation = EVP_PKEY_OP_VERIFY;
+            ctx->update = update;
+        } else if (EVP_PKEY_verify_init(ctx->pctx) <= 0) {
             return 0;
+        }
     } else {
         if (ctx->pctx->pmeth->signctx_init) {
             if (ctx->pctx->pmeth->signctx_init(ctx->pctx, ctx) <= 0)
                 return 0;
             ctx->pctx->operation = EVP_PKEY_OP_SIGNCTX;
-        } else if (EVP_PKEY_sign_init(ctx->pctx) <= 0)
+        } else if (ctx->pctx->pmeth->digestsign != 0) {
+            ctx->pctx->operation = EVP_PKEY_OP_SIGN;
+            ctx->update = update;
+        } else if (EVP_PKEY_sign_init(ctx->pctx) <= 0) {
             return 0;
+        }
     }
     if (EVP_PKEY_CTX_set_signature_md(ctx->pctx, type) <= 0)
         return 0;
@@ -138,6 +152,8 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
 int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen,
                    const unsigned char *tbs, size_t tbslen)
 {
+    if (ctx->pctx->pmeth->digestsign != NULL)
+        return ctx->pctx->pmeth->digestsign(ctx, sigret, siglen, tbs, tbslen);
     if (sigret != NULL && EVP_DigestSignUpdate(ctx, tbs, tbslen) <= 0)
         return 0;
     return EVP_DigestSignFinal(ctx, sigret, siglen);
@@ -179,6 +195,8 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig,
 int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret,
                      size_t siglen, const unsigned char *tbs, size_t tbslen)
 {
+    if (ctx->pctx->pmeth->digestverify != NULL)
+        return ctx->pctx->pmeth->digestverify(ctx, sigret, siglen, tbs, tbslen);
     if (EVP_DigestVerifyUpdate(ctx, tbs, tbslen) <= 0)
         return -1;
     return EVP_DigestVerifyFinal(ctx, sigret, siglen);
index 0b0d878..b2b4731 100644 (file)
@@ -70,6 +70,11 @@ struct evp_pkey_method_st {
     int (*derive) (EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen);
     int (*ctrl) (EVP_PKEY_CTX *ctx, int type, int p1, void *p2);
     int (*ctrl_str) (EVP_PKEY_CTX *ctx, const char *type, const char *value);
+    int (*digestsign) (EVP_MD_CTX *ctx, unsigned char *sig, size_t *siglen,
+                       const unsigned char *tbs, size_t tbslen);
+    int (*digestverify) (EVP_MD_CTX *ctx, const unsigned char *sig,
+                         size_t siglen, const unsigned char *tbs,
+                         size_t tbslen);
 } /* EVP_PKEY_METHOD */ ;
 
 DEFINE_STACK_OF_CONST(EVP_PKEY_METHOD)