Add EVP_DigestSign and EVP_DigesVerify
authorDr. Stephen Henson <steve@openssl.org>
Mon, 8 May 2017 11:50:13 +0000 (12:50 +0100)
committerDr. Stephen Henson <steve@openssl.org>
Thu, 11 May 2017 11:59:25 +0000 (12:59 +0100)
Add "single part" digest sign and verify functions. These sign and verify
a message in one function. This simplifies some operations and it will later
be used as the API for algorithms which do not support the update/final
mechanism (e.g. PureEdDSA).

Reviewed-by: Andy Polyakov <appro@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/3409)

crypto/asn1/a_sign.c
crypto/asn1/a_verify.c
crypto/evp/m_sigver.c
doc/man3/EVP_DigestSignInit.pod
doc/man3/EVP_DigestVerifyInit.pod
include/openssl/evp.h
ssl/statem/statem_lib.c

index 7e21a5ec9fbde270cb7b381dc529fdd2f5271fa9..4e93b5a7683d5cdf0eee6c96835ea20271f3baa0 100644 (file)
@@ -205,8 +205,7 @@ int ASN1_item_sign_ctx(const ASN1_ITEM *it,
         goto err;
     }
 
-    if (!EVP_DigestSignUpdate(ctx, buf_in, inl)
-        || !EVP_DigestSignFinal(ctx, buf_out, &outl)) {
+    if (!EVP_DigestSign(ctx, buf_out, &outl, buf_in, inl)) {
         outl = 0;
         ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB);
         goto err;
index 00ab136f022347a6293b750a1579d6e2f0af26c7..ec51d3e7cdacceec6d0464aac7558a5b594fb1c7 100644 (file)
@@ -89,7 +89,7 @@ int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
 {
     EVP_MD_CTX *ctx = NULL;
     unsigned char *buf_in = NULL;
-    int ret = -1, inl;
+    int ret = -1, inl = 0;
 
     int mdnid, pknid;
 
@@ -159,24 +159,15 @@ int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
         goto err;
     }
 
-    ret = EVP_DigestVerifyUpdate(ctx, buf_in, inl);
-
-    OPENSSL_clear_free(buf_in, (unsigned int)inl);
-
-    if (!ret) {
-        ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_EVP_LIB);
-        goto err;
-    }
-    ret = -1;
-
-    if (EVP_DigestVerifyFinal(ctx, signature->data,
-                              (size_t)signature->length) <= 0) {
+    ret = EVP_DigestVerify(ctx, signature->data, (size_t)signature->length,
+                           buf_in, inl);
+    if (ret <= 0) {
         ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_EVP_LIB);
-        ret = 0;
         goto err;
     }
     ret = 1;
  err:
+    OPENSSL_clear_free(buf_in, (unsigned int)inl);
     EVP_MD_CTX_free(ctx);
-    return (ret);
+    return ret;
 }
index 3b74f72295155908f1a2ae13c20a8049eaf6b51b..d53e1d6bd2dd439e54cf939b761cffe0203b1880 100644 (file)
@@ -135,6 +135,14 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
     return 1;
 }
 
+int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen,
+                   const unsigned char *tbs, size_t tbslen)
+{
+    if (sigret != NULL && EVP_DigestSignUpdate(ctx, tbs, tbslen) <= 0)
+        return 0;
+    return EVP_DigestSignFinal(ctx, sigret, siglen);
+}
+
 int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig,
                           size_t siglen)
 {
@@ -167,3 +175,11 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig,
         return r;
     return EVP_PKEY_verify(ctx->pctx, sig, siglen, md, mdlen);
 }
+
+int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret,
+                     size_t siglen, const unsigned char *tbs, size_t tbslen)
+{
+    if (EVP_DigestVerifyUpdate(ctx, tbs, tbslen) <= 0)
+        return -1;
+    return EVP_DigestVerifyFinal(ctx, sigret, siglen);
+}
index 7ec06b7a272e6131158bad3b0fc552d6e8e38618..45f337bc31f7df5e59ad49a4ccef86ff207d0e0c 100644 (file)
@@ -2,7 +2,8 @@
 
 =head1 NAME
 
-EVP_DigestSignInit, EVP_DigestSignUpdate, EVP_DigestSignFinal - EVP signing functions
+EVP_DigestSignInit, EVP_DigestSignUpdate, EVP_DigestSignFinal,
+EVP_DigestSign - EVP signing functions
 
 =head1 SYNOPSIS
 
@@ -13,6 +14,10 @@ EVP_DigestSignInit, EVP_DigestSignUpdate, EVP_DigestSignFinal - EVP signing func
  int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt);
  int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sig, size_t *siglen);
 
+ int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret,
+                    size_t *siglen, const unsigned char *tbs,
+                    size_t tbslen);
+
 =head1 DESCRIPTION
 
 The EVP signature routines are a high level interface to digital signatures.
@@ -35,12 +40,16 @@ B<siglen> parameter should contain the length of the B<sig> buffer, if the
 call is successful the signature is written to B<sig> and the amount of data
 written to B<siglen>.
 
+EVP_DigestSign() signs B<tbslen> bytes of data at B<tbs> and places the
+signature in B<sig> and its length in B<siglen> in a simiilar way to
+EVP_DigestSignFinal().
+
 =head1 RETURN VALUES
 
-EVP_DigestSignInit() EVP_DigestSignUpdate() and EVP_DigestSignaFinal() return
-1 for success and 0 or a negative value for failure. In particular a return
-value of -2 indicates the operation is not supported by the public key
-algorithm.
+EVP_DigestSignInit(), EVP_DigestSignUpdate(), EVP_DigestSignaFinal() and
+EVP_DigestSign() return 1 for success and 0 or a negative value for failure. In
+particular a return value of -2 indicates the operation is not supported by the
+public key algorithm.
 
 The error codes can be obtained from L<ERR_get_error(3)>.
 
@@ -50,6 +59,10 @@ The B<EVP> interface to digital signatures should almost always be used in
 preference to the low level interfaces. This is because the code then becomes
 transparent to the algorithm used and much more flexible.
 
+EVP_DigestSign() is a single part operation which signs a single block of data
+in one function. It is equivalent to calling EVP_DigestSignUpdate() and
+EVP_DigestSignFinal().
+
 In previous versions of OpenSSL there was a link between message digest types
 and public key algorithms. This meant that "clone" digests such as EVP_dss1()
 needed to be used to sign using SHA1 and DSA. This is no longer necessary and
index ce59422d3e47aff99228d6cbe09635076d7998b5..0132c0634ef440cf2196c400b52a8147adae6d4c 100644 (file)
@@ -2,7 +2,8 @@
 
 =head1 NAME
 
-EVP_DigestVerifyInit, EVP_DigestVerifyUpdate, EVP_DigestVerifyFinal - EVP signature verification functions
+EVP_DigestVerifyInit, EVP_DigestVerifyUpdate, EVP_DigestVerifyFinal,
+EVP_DigestVerify - EVP signature verification functions
 
 =head1 SYNOPSIS
 
@@ -11,7 +12,10 @@ EVP_DigestVerifyInit, EVP_DigestVerifyUpdate, EVP_DigestVerifyFinal - EVP signat
  int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
                         const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey);
  int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt);
- int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig, size_t siglen);
+ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig,
+                           size_t siglen);
+ int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret,
+                      size_t siglen, const unsigned char *tbs, size_t tbslen);
 
 =head1 DESCRIPTION
 
@@ -31,16 +35,19 @@ using a macro.
 EVP_DigestVerifyFinal() verifies the data in B<ctx> against the signature in
 B<sig> of length B<siglen>.
 
+EVP_DogestVerify() verifies B<tbslen> bytes at B<tbs> against the signature
+in B<sig> of length B<siglen>.
+
 =head1 RETURN VALUES
 
 EVP_DigestVerifyInit() and EVP_DigestVerifyUpdate() return 1 for success and 0
 for failure.
 
-EVP_DigestVerifyFinal() returns 1 for success; any other value indicates
-failure.  A return value of zero indicates that the signature did not verify
-successfully (that is, tbs did not match the original data or the signature had
-an invalid form), while other values indicate a more serious error (and
-sometimes also indicate an invalid signature form).
+EVP_DigestVerifyFinal() and EVP_DigestVerify() return 1 for success; any other
+value indicates failure.  A return value of zero indicates that the signature
+did not verify successfully (that is, B<tbs> did not match the original data or
+the signature had an invalid form), while other values indicate a more serious
+error (and sometimes also indicate an invalid signature form).
 
 The error codes can be obtained from L<ERR_get_error(3)>.
 
@@ -50,6 +57,10 @@ The B<EVP> interface to digital signatures should almost always be used in
 preference to the low level interfaces. This is because the code then becomes
 transparent to the algorithm used and much more flexible.
 
+EVP_DigesVerify() is a single part operation which verifies a single block of
+data in one function. It is equivalent to calling EVP_DigestVerifyUpdate() and
+EVP_DigestVerifyFinal().
+
 In previous versions of OpenSSL there was a link between message digest types
 and public key algorithms. This meant that "clone" digests such as EVP_dss1()
 needed to be used to sign using SHA1 and DSA. This is no longer necessary and
index fec4c5bed59cc8b77acd8edb8a81966a7131824c..26a8b7c8d174a9dc3db4e354bb7a231d912cade6 100644 (file)
@@ -603,9 +603,17 @@ __owur int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm,
 __owur int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s,
                          EVP_PKEY *pkey);
 
+__owur int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret,
+                          size_t *siglen, const unsigned char *tbs,
+                          size_t tbslen);
+
 __owur int EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf,
                            unsigned int siglen, EVP_PKEY *pkey);
 
+__owur int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret,
+                            size_t siglen, const unsigned char *tbs,
+                            size_t tbslen);
+
 /*__owur*/ int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
                                   const EVP_MD *type, ENGINE *e,
                                   EVP_PKEY *pkey);
index 33206c6ea96c9e7f2bf8e5e4fe56b5d91e3f9d32..8b1dddaa3be6c3e2a571b3e7f6eaa0040fc30a55 100644 (file)
@@ -249,8 +249,7 @@ int tls_construct_cert_verify(SSL *s, WPACKET *pkt)
         goto err;
     }
 
-    if (EVP_DigestSignInit(mctx, &pctx, md, NULL, pkey) <= 0
-            || EVP_DigestSignUpdate(mctx, hdata, hdatalen) <= 0) {
+    if (EVP_DigestSignInit(mctx, &pctx, md, NULL, pkey) <= 0) {
         SSLerr(SSL_F_TLS_CONSTRUCT_CERT_VERIFY, ERR_R_EVP_LIB);
         goto err;
     }
@@ -271,7 +270,7 @@ int tls_construct_cert_verify(SSL *s, WPACKET *pkt)
         }
     }
 
-    if (EVP_DigestSignFinal(mctx, sig, &siglen) <= 0) {
+    if (EVP_DigestSign(mctx, sig, &siglen, hdata, hdatalen) <= 0) {
         SSLerr(SSL_F_TLS_CONSTRUCT_CERT_VERIFY, ERR_R_EVP_LIB);
         goto err;
     }
@@ -409,8 +408,7 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
 #ifdef SSL_DEBUG
     fprintf(stderr, "Using client verify alg %s\n", EVP_MD_name(md));
 #endif
-    if (EVP_DigestVerifyInit(mctx, &pctx, md, NULL, pkey) <= 0
-            || EVP_DigestVerifyUpdate(mctx, hdata, hdatalen) <= 0) {
+    if (EVP_DigestVerifyInit(mctx, &pctx, md, NULL, pkey) <= 0) {
         SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_EVP_LIB);
         goto f_err;
     }
@@ -445,7 +443,12 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
         goto f_err;
     }
 
-    if (EVP_DigestVerifyFinal(mctx, data, len) <= 0) {
+    j = EVP_DigestVerify(mctx, data, len, hdata, hdatalen);
+
+    if (j < 0) {
+        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_EVP_LIB);
+        goto f_err;
+    } else if (j == 0) {
         al = SSL_AD_DECRYPT_ERROR;
         SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_BAD_SIGNATURE);
         goto f_err;