From 42e93b6cf5e0a5c958b6b59cf4842b3dc275561a Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Mon, 25 Sep 2017 16:30:28 -0400 Subject: [PATCH] Export EVP_parse_digest_algorithm and add EVP_marshal_digest_algorithm. Chromium's OCSP code needs the OIDs and we already have them on hand. Change-Id: Icab012ba4ae15ce029cbfe3ed93f89470137e7f6 Reviewed-on: https://boringssl-review.googlesource.com/20724 Commit-Queue: David Benjamin Commit-Queue: Steven Valdez Reviewed-by: Steven Valdez CQ-Verified: CQ bot account: commit-bot@chromium.org --- crypto/digest_extra/digest_extra.c | 54 ++++++++++++++++++++++++------ crypto/digest_extra/digest_test.cc | 43 ++++++++++++++++++++++++ crypto/digest_extra/internal.h | 32 ------------------ crypto/pkcs8/pkcs8_x509.c | 1 - include/openssl/digest.h | 17 ++++++++++ 5 files changed, 104 insertions(+), 43 deletions(-) delete mode 100644 crypto/digest_extra/internal.h diff --git a/crypto/digest_extra/digest_extra.c b/crypto/digest_extra/digest_extra.c index ab7ff593..4b4bb381 100644 --- a/crypto/digest_extra/digest_extra.c +++ b/crypto/digest_extra/digest_extra.c @@ -62,7 +62,6 @@ #include #include -#include "internal.h" #include "../internal.h" @@ -120,22 +119,22 @@ const EVP_MD* EVP_get_digestbynid(int nid) { static const struct { uint8_t oid[9]; uint8_t oid_len; - const EVP_MD *(*md_func) (void); + int nid; } kMDOIDs[] = { // 1.2.840.113549.2.4 - { {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x04}, 8, EVP_md4 }, + { {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x04}, 8, NID_md4 }, // 1.2.840.113549.2.5 - { {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05}, 8, EVP_md5 }, + { {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05}, 8, NID_md5 }, // 1.3.14.3.2.26 - { {0x2b, 0x0e, 0x03, 0x02, 0x1a}, 5, EVP_sha1 }, + { {0x2b, 0x0e, 0x03, 0x02, 0x1a}, 5, NID_sha1 }, // 2.16.840.1.101.3.4.2.1 - { {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01}, 9, EVP_sha256 }, + { {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01}, 9, NID_sha256 }, // 2.16.840.1.101.3.4.2.2 - { {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02}, 9, EVP_sha384 }, + { {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02}, 9, NID_sha384 }, // 2.16.840.1.101.3.4.2.3 - { {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03}, 9, EVP_sha512 }, + { {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03}, 9, NID_sha512 }, // 2.16.840.1.101.3.4.2.4 - { {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04}, 9, EVP_sha224 }, + { {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04}, 9, NID_sha224 }, }; static const EVP_MD *cbs_to_md(const CBS *cbs) { @@ -143,7 +142,7 @@ static const EVP_MD *cbs_to_md(const CBS *cbs) { if (CBS_len(cbs) == kMDOIDs[i].oid_len && OPENSSL_memcmp(CBS_data(cbs), kMDOIDs[i].oid, kMDOIDs[i].oid_len) == 0) { - return kMDOIDs[i].md_func(); + return EVP_get_digestbynid(kMDOIDs[i].nid); } } @@ -192,6 +191,41 @@ const EVP_MD *EVP_parse_digest_algorithm(CBS *cbs) { return ret; } +int EVP_marshal_digest_algorithm(CBB *cbb, const EVP_MD *md) { + CBB algorithm, oid, null; + if (!CBB_add_asn1(cbb, &algorithm, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT)) { + OPENSSL_PUT_ERROR(DIGEST, ERR_R_MALLOC_FAILURE); + return 0; + } + + int found = 0; + int nid = EVP_MD_type(md); + for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kMDOIDs); i++) { + if (nid == kMDOIDs[i].nid) { + if (!CBB_add_bytes(&oid, kMDOIDs[i].oid, kMDOIDs[i].oid_len)) { + OPENSSL_PUT_ERROR(DIGEST, ERR_R_MALLOC_FAILURE); + return 0; + } + found = 1; + break; + } + } + + if (!found) { + OPENSSL_PUT_ERROR(DIGEST, DIGEST_R_UNKNOWN_HASH); + return 0; + } + + if (!CBB_add_asn1(&algorithm, &null, CBS_ASN1_NULL) || + !CBB_flush(cbb)) { + OPENSSL_PUT_ERROR(DIGEST, ERR_R_MALLOC_FAILURE); + return 0; + } + + return 1; +} + const EVP_MD *EVP_get_digestbyname(const char *name) { for (unsigned i = 0; i < OPENSSL_ARRAY_SIZE(nid_to_digest_mapping); i++) { const char *short_name = nid_to_digest_mapping[i].short_name; diff --git a/crypto/digest_extra/digest_test.cc b/crypto/digest_extra/digest_test.cc index 96fa7786..910c7314 100644 --- a/crypto/digest_extra/digest_test.cc +++ b/crypto/digest_extra/digest_test.cc @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -31,6 +32,7 @@ #include #include "../internal.h" +#include "../test/test_util.h" struct MD { @@ -215,3 +217,44 @@ TEST(DigestTest, Getters) { EXPECT_EQ(EVP_md5_sha1(), EVP_get_digestbyobj(OBJ_nid2obj(NID_md5_sha1))); EXPECT_EQ(EVP_sha1(), EVP_get_digestbyobj(OBJ_nid2obj(NID_sha1))); } + +TEST(DigestTest, ASN1) { + bssl::ScopedCBB cbb; + ASSERT_TRUE(CBB_init(cbb.get(), 0)); + EXPECT_FALSE(EVP_marshal_digest_algorithm(cbb.get(), EVP_md5_sha1())); + + static const uint8_t kSHA256[] = {0x30, 0x0d, 0x06, 0x09, 0x60, + 0x86, 0x48, 0x01, 0x65, 0x03, + 0x04, 0x02, 0x01, 0x05, 0x00}; + static const uint8_t kSHA256NoParam[] = {0x30, 0x0b, 0x06, 0x09, 0x60, + 0x86, 0x48, 0x01, 0x65, 0x03, + 0x04, 0x02, 0x01}; + static const uint8_t kSHA256GarbageParam[] = { + 0x30, 0x0e, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, + 0x65, 0x03, 0x04, 0x02, 0x01, 0x02, 0x01, 0x2a}; + + // Serialize SHA-256. + cbb.Reset(); + ASSERT_TRUE(CBB_init(cbb.get(), 0)); + ASSERT_TRUE(EVP_marshal_digest_algorithm(cbb.get(), EVP_sha256())); + uint8_t *der; + size_t der_len; + ASSERT_TRUE(CBB_finish(cbb.get(), &der, &der_len)); + bssl::UniquePtr free_der(der); + EXPECT_EQ(Bytes(kSHA256), Bytes(der, der_len)); + + // Parse SHA-256. + CBS cbs; + CBS_init(&cbs, kSHA256, sizeof(kSHA256)); + EXPECT_EQ(EVP_sha256(), EVP_parse_digest_algorithm(&cbs)); + EXPECT_EQ(0u, CBS_len(&cbs)); + + // Missing parameters are tolerated for compatibility. + CBS_init(&cbs, kSHA256NoParam, sizeof(kSHA256NoParam)); + EXPECT_EQ(EVP_sha256(), EVP_parse_digest_algorithm(&cbs)); + EXPECT_EQ(0u, CBS_len(&cbs)); + + // Garbage parameters are not. + CBS_init(&cbs, kSHA256GarbageParam, sizeof(kSHA256GarbageParam)); + EXPECT_FALSE(EVP_parse_digest_algorithm(&cbs)); +} diff --git a/crypto/digest_extra/internal.h b/crypto/digest_extra/internal.h deleted file mode 100644 index 1df200ec..00000000 --- a/crypto/digest_extra/internal.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Copyright (c) 2017, Google Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - -#ifndef OPENSSL_HEADER_DIGEST_EXTRA_INTERNAL_H -#define OPENSSL_HEADER_DIGEST_EXTRA_INTERNAL_H - -#include - -#if defined(__cplusplus) -extern "C" { -#endif - - -const EVP_MD *EVP_parse_digest_algorithm(CBS *cbs); - - -#if defined(__cplusplus) -} // extern C -#endif - -#endif // OPENSSL_HEADER_DIGEST_EXTRA_INTERNAL diff --git a/crypto/pkcs8/pkcs8_x509.c b/crypto/pkcs8/pkcs8_x509.c index ace5f33b..b3e2d93f 100644 --- a/crypto/pkcs8/pkcs8_x509.c +++ b/crypto/pkcs8/pkcs8_x509.c @@ -71,7 +71,6 @@ #include "internal.h" #include "../bytestring/internal.h" -#include "../digest_extra/internal.h" #include "../internal.h" diff --git a/include/openssl/digest.h b/include/openssl/digest.h index ad6dd507..9e7f4342 100644 --- a/include/openssl/digest.h +++ b/include/openssl/digest.h @@ -201,6 +201,23 @@ OPENSSL_EXPORT size_t EVP_MD_block_size(const EVP_MD *md); #define EVP_MD_FLAG_DIGALGID_ABSENT 2 +// ASN.1 functions. +// +// These functions allow code to parse and serialize AlgorithmIdentifiers for +// hash functions. + +// EVP_parse_digest_algorithm parses an AlgorithmIdentifier structure containing +// a hash function OID (for example, 2.16.840.1.101.3.4.2.1 is SHA-256) and +// advances |cbs|. The parameters field may either be omitted or a NULL. It +// returns the digest function or NULL on error. +OPENSSL_EXPORT const EVP_MD *EVP_parse_digest_algorithm(CBS *cbs); + +// EVP_marshal_digest_algorithm marshals |md| as an AlgorithmIdentifier +// structure and appends the result to |cbb|. It returns one on success and zero +// on error. +OPENSSL_EXPORT int EVP_marshal_digest_algorithm(CBB *cbb, const EVP_MD *md); + + // Deprecated functions. // EVP_MD_CTX_copy sets |out|, which must /not/ be initialised, to be a copy of