PROV: Adapt the DSA signature implementation to provide Algorithmidentifiers
authorRichard Levitte <levitte@openssl.org>
Tue, 21 Jan 2020 14:05:56 +0000 (15:05 +0100)
committerRichard Levitte <levitte@openssl.org>
Tue, 28 Jan 2020 07:08:22 +0000 (08:08 +0100)
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/10920)

crypto/dsa/build.info
crypto/dsa/dsa_aid.c [new file with mode: 0644]
include/crypto/dsa.h
include/internal/sizes.h
include/openssl/core_names.h
providers/implementations/signature/dsa.c

index 309fda3..2cbea9b 100644 (file)
@@ -1,6 +1,6 @@
 LIBS=../../libcrypto
 
-$COMMON=dsa_sign.c dsa_vrf.c dsa_lib.c dsa_ossl.c
+$COMMON=dsa_sign.c dsa_vrf.c dsa_lib.c dsa_ossl.c dsa_aid.c
 
 SOURCE[../../libcrypto]=$COMMON\
         dsa_gen.c dsa_key.c dsa_asn1.c \
diff --git a/crypto/dsa/dsa_aid.c b/crypto/dsa/dsa_aid.c
new file mode 100644 (file)
index 0000000..759e5c9
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2020 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
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdlib.h>
+
+#include <openssl/objects.h>
+#include "crypto/dsa.h"
+
+#define ASN1_SEQUENCE 0x30
+#define ASN1_OID 0x06
+
+/* dsaWithSHA OIDs are of the form: (1 3 14 3 2 |n|) */
+#define ENCODE_ALGORITHMIDENTIFIER_SHA(name, n)                         \
+    static const unsigned char algorithmidentifier_##name##_der[] = {   \
+        ASN1_SEQUENCE, 0x07,                                            \
+          ASN1_OID, 0x05, 1 * 40 + 3, 14, 3, 2, n                       \
+}
+
+ENCODE_ALGORITHMIDENTIFIER_SHA(sha, 13);
+ENCODE_ALGORITHMIDENTIFIER_SHA(sha1, 27);
+
+/* dsaWithSHA OIDs are of the form: (2 16 840 1 101 3 4 3 |n|) */
+#define ENCODE_ALGORITHMIDENTIFIER_SHAx(name, n)                        \
+    static const unsigned char algorithmidentifier_##name##_der[] = {   \
+        ASN1_SEQUENCE, 0x0b,                                            \
+          ASN1_OID, 0x09, 2 * 40 + 16, 0x86, 0x48, 1, 101, 3, 4, 3, n   \
+}
+
+ENCODE_ALGORITHMIDENTIFIER_SHAx(sha224, 1);
+ENCODE_ALGORITHMIDENTIFIER_SHAx(sha256, 2);
+ENCODE_ALGORITHMIDENTIFIER_SHAx(sha384, 3);
+ENCODE_ALGORITHMIDENTIFIER_SHAx(sha512, 4);
+ENCODE_ALGORITHMIDENTIFIER_SHAx(sha3_224, 5);
+ENCODE_ALGORITHMIDENTIFIER_SHAx(sha3_256, 6);
+ENCODE_ALGORITHMIDENTIFIER_SHAx(sha3_384, 7);
+ENCODE_ALGORITHMIDENTIFIER_SHAx(sha3_512, 8);
+
+#define MD_CASE(name)                                                   \
+    case NID_##name:                                                    \
+        *len = sizeof(algorithmidentifier_##name##_der);                \
+        return algorithmidentifier_##name##_der
+
+const unsigned char *dsa_algorithmidentifier_encoding(int md_nid, size_t *len)
+{
+    switch (md_nid) {
+        MD_CASE(sha);
+        MD_CASE(sha1);
+        MD_CASE(sha224);
+        MD_CASE(sha256);
+        MD_CASE(sha384);
+        MD_CASE(sha512);
+        MD_CASE(sha3_224);
+        MD_CASE(sha3_256);
+        MD_CASE(sha3_384);
+        MD_CASE(sha3_512);
+    default:
+        return NULL;
+    }
+}
index 9afae37..041ebd4 100644 (file)
@@ -11,3 +11,5 @@
 
 int dsa_sign_int(OPENSSL_CTX *libctx, int type, const unsigned char *dgst,
                  int dlen, unsigned char *sig, unsigned int *siglen, DSA *dsa);
+
+const unsigned char *dsa_algorithmidentifier_encoding(int md_nid, size_t *len);
index fab5cbd..00a5d3e 100644 (file)
@@ -16,5 +16,6 @@
  */
 # define OSSL_MAX_NAME_SIZE           50 /* Algorithm name */
 # define OSSL_MAX_PROPQUERY_SIZE     256 /* Property query strings */
+# define OSSL_MAX_ALGORITHM_ID_SIZE  256 /* AlgorithmIdentifier DER */
 
 #endif
index 20b06ff..cd701ab 100644 (file)
@@ -87,7 +87,16 @@ extern "C" {
 #define OSSL_DIGEST_PARAM_FLAGS      "flags"     /* ulong */
 
 /* Known DIGEST names (not a complete list) */
-#define OSSL_DIGEST_NAME_MD5 "MD5"
+#define OSSL_DIGEST_NAME_MD5            "MD5"
+#define OSSL_DIGEST_NAME_SHA1           "SHA1"
+#define OSSL_DIGEST_NAME_SHA2_224       "SHA2-224"
+#define OSSL_DIGEST_NAME_SHA2_256       "SHA2-256"
+#define OSSL_DIGEST_NAME_SHA2_384       "SHA2-384"
+#define OSSL_DIGEST_NAME_SHA2_512       "SHA2-512"
+#define OSSL_DIGEST_NAME_SHA3_224       "SHA3-224"
+#define OSSL_DIGEST_NAME_SHA3_256       "SHA3-256"
+#define OSSL_DIGEST_NAME_SHA3_384       "SHA3-384"
+#define OSSL_DIGEST_NAME_SHA3_512       "SHA3-512"
 #define OSSL_DIGEST_NAME_KECCAK_KMAC128 "KECCAK-KMAC-128"
 #define OSSL_DIGEST_NAME_KECCAK_KMAC256 "KECCAK-KMAC-256"
 
index 9892e6d..e8d9cd0 100644 (file)
@@ -7,13 +7,18 @@
  * https://www.openssl.org/source/license.html
  */
 
+#include <string.h>
+
 #include <openssl/crypto.h>
 #include <openssl/core_numbers.h>
 #include <openssl/core_names.h>
+#include <openssl/err.h>
 #include <openssl/dsa.h>
 #include <openssl/params.h>
 #include <openssl/evp.h>
+#include "internal/nelem.h"
 #include "internal/sizes.h"
+#include "prov/providercommonerr.h"
 #include "prov/implementations.h"
 #include "prov/provider_ctx.h"
 #include "crypto/dsa.h"
@@ -51,6 +56,12 @@ typedef struct {
     DSA *dsa;
     size_t mdsize;
     char mdname[OSSL_MAX_NAME_SIZE];
+
+    /* The Algorithm Identifier of the combined signature agorithm */
+    unsigned char aid[OSSL_MAX_ALGORITHM_ID_SIZE];
+    size_t  aid_len;
+
+    /* main digest */
     EVP_MD *md;
     EVP_MD_CTX *mdctx;
 } PROV_DSA_CTX;
@@ -116,28 +127,88 @@ static int dsa_verify(void *vpdsactx, const unsigned char *sig, size_t siglen,
     return DSA_verify(0, tbs, tbslen, sig, siglen, pdsactx->dsa);
 }
 
+static int get_md_nid(const EVP_MD *md)
+{
+    /*
+     * Because the DSA library deals with NIDs, we need to translate.
+     * We do so using EVP_MD_is_a(), and therefore need a name to NID
+     * map.
+     */
+    static const OSSL_ITEM name_to_nid[] = {
+        { NID_sha1,   OSSL_DIGEST_NAME_SHA1   },
+        { NID_sha224, OSSL_DIGEST_NAME_SHA2_224 },
+        { NID_sha256, OSSL_DIGEST_NAME_SHA2_256 },
+        { NID_sha384, OSSL_DIGEST_NAME_SHA2_384 },
+        { NID_sha512, OSSL_DIGEST_NAME_SHA2_512 },
+        { NID_sha3_224, OSSL_DIGEST_NAME_SHA3_224 },
+        { NID_sha3_256, OSSL_DIGEST_NAME_SHA3_256 },
+        { NID_sha3_384, OSSL_DIGEST_NAME_SHA3_384 },
+        { NID_sha3_512, OSSL_DIGEST_NAME_SHA3_512 },
+    };
+    size_t i;
+    int mdnid = NID_undef;
+
+    if (md == NULL)
+        goto end;
+
+    for (i = 0; i < OSSL_NELEM(name_to_nid); i++) {
+        if (EVP_MD_is_a(md, name_to_nid[i].ptr)) {
+            mdnid = (int)name_to_nid[i].id;
+            break;
+        }
+    }
+
+    if (mdnid == NID_undef)
+        ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST);
+
+ end:
+    return mdnid;
+}
+
 static int dsa_digest_signverify_init(void *vpdsactx, const char *mdname,
                                       const char *props, void *vdsa)
 {
     PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
-    EVP_MD *md;
+    size_t algorithmidentifier_len = 0;
+    const unsigned char *algorithmidentifier;
+
+    EVP_MD_CTX_free(pdsactx->mdctx);
+    EVP_MD_free(pdsactx->md);
+    pdsactx->mdctx = NULL;
+    pdsactx->mdsize = 0;
+    pdsactx->md = NULL;
 
     if (!dsa_signature_init(vpdsactx, vdsa))
         return 0;
 
-    md = EVP_MD_fetch(pdsactx->libctx, mdname, props);
-    if (md == NULL)
-        return 0;
-    pdsactx->md = md;
-    pdsactx->mdsize = EVP_MD_size(md);
+    pdsactx->md = EVP_MD_fetch(pdsactx->libctx, mdname, props);
+    algorithmidentifier =
+        dsa_algorithmidentifier_encoding(get_md_nid(pdsactx->md),
+                                         &algorithmidentifier_len);
+
+    if (algorithmidentifier == NULL)
+        goto error;
+
+    pdsactx->mdsize = EVP_MD_size(pdsactx->md);
     pdsactx->mdctx = EVP_MD_CTX_new();
     if (pdsactx->mdctx == NULL)
-        return 0;
+        goto error;
 
-    if (!EVP_DigestInit_ex(pdsactx->mdctx, md, NULL))
-        return 0;
+    memcpy(pdsactx->aid, algorithmidentifier, algorithmidentifier_len);
+    pdsactx->aid_len = algorithmidentifier_len;
+
+    if (!EVP_DigestInit_ex(pdsactx->mdctx, pdsactx->md, NULL))
+        goto error;
 
     return 1;
+
+ error:
+    EVP_MD_CTX_free(pdsactx->mdctx);
+    EVP_MD_free(pdsactx->md);
+    pdsactx->mdctx = NULL;
+    pdsactx->mdsize = 0;
+    pdsactx->md = NULL;
+    return 0;
 }
 
 int dsa_digest_signverify_update(void *vpdsactx, const unsigned char *data,
@@ -254,6 +325,11 @@ static int dsa_get_ctx_params(void *vpdsactx, OSSL_PARAM *params)
     if (pdsactx == NULL || params == NULL)
         return 0;
 
+    p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID);
+    if (p != NULL
+        && !OSSL_PARAM_set_octet_string(p, pdsactx->aid, pdsactx->aid_len))
+        return 0;
+
     p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE);
     if (p != NULL && !OSSL_PARAM_set_size_t(p, pdsactx->mdsize))
         return 0;
@@ -268,6 +344,7 @@ static int dsa_get_ctx_params(void *vpdsactx, OSSL_PARAM *params)
 }
 
 static const OSSL_PARAM known_gettable_ctx_params[] = {
+    OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0),
     OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL),
     OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
     OSSL_PARAM_END