From 505b41fc5a7a3cb255d2f62cf4902a1a5c1db2dd Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Tue, 21 Jan 2020 15:05:56 +0100 Subject: [PATCH] PROV: Adapt the DSA signature implementation to provide Algorithmidentifiers Reviewed-by: Shane Lontis (Merged from https://github.com/openssl/openssl/pull/10920) --- crypto/dsa/build.info | 2 +- crypto/dsa/dsa_aid.c | 65 ++++++++++++++++ include/crypto/dsa.h | 2 + include/internal/sizes.h | 1 + include/openssl/core_names.h | 11 ++- providers/implementations/signature/dsa.c | 95 ++++++++++++++++++++--- 6 files changed, 165 insertions(+), 11 deletions(-) create mode 100644 crypto/dsa/dsa_aid.c diff --git a/crypto/dsa/build.info b/crypto/dsa/build.info index 309fda323e..2cbea9b961 100644 --- a/crypto/dsa/build.info +++ b/crypto/dsa/build.info @@ -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 index 0000000000..759e5c90e1 --- /dev/null +++ b/crypto/dsa/dsa_aid.c @@ -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 + +#include +#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; + } +} diff --git a/include/crypto/dsa.h b/include/crypto/dsa.h index 9afae37d2a..041ebd4f7f 100644 --- a/include/crypto/dsa.h +++ b/include/crypto/dsa.h @@ -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); diff --git a/include/internal/sizes.h b/include/internal/sizes.h index fab5cbdec7..00a5d3e88e 100644 --- a/include/internal/sizes.h +++ b/include/internal/sizes.h @@ -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 diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h index 20b06ff96b..cd701ab937 100644 --- a/include/openssl/core_names.h +++ b/include/openssl/core_names.h @@ -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" diff --git a/providers/implementations/signature/dsa.c b/providers/implementations/signature/dsa.c index 9892e6d5e4..e8d9cd0b81 100644 --- a/providers/implementations/signature/dsa.c +++ b/providers/implementations/signature/dsa.c @@ -7,13 +7,18 @@ * https://www.openssl.org/source/license.html */ +#include + #include #include #include +#include #include #include #include +#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 -- 2.25.1