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 <davidben@google.com> Commit-Queue: Steven Valdez <svaldez@google.com> Reviewed-by: Steven Valdez <svaldez@google.com> CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>kris/onging/CECPQ3_patch15
@@ -62,7 +62,6 @@ | |||||
#include <openssl/bytestring.h> | #include <openssl/bytestring.h> | ||||
#include <openssl/nid.h> | #include <openssl/nid.h> | ||||
#include "internal.h" | |||||
#include "../internal.h" | #include "../internal.h" | ||||
@@ -120,22 +119,22 @@ const EVP_MD* EVP_get_digestbynid(int nid) { | |||||
static const struct { | static const struct { | ||||
uint8_t oid[9]; | uint8_t oid[9]; | ||||
uint8_t oid_len; | uint8_t oid_len; | ||||
const EVP_MD *(*md_func) (void); | |||||
int nid; | |||||
} kMDOIDs[] = { | } kMDOIDs[] = { | ||||
// 1.2.840.113549.2.4 | // 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 | // 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 | // 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 | // 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 | // 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 | // 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 | // 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) { | 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 && | if (CBS_len(cbs) == kMDOIDs[i].oid_len && | ||||
OPENSSL_memcmp(CBS_data(cbs), kMDOIDs[i].oid, kMDOIDs[i].oid_len) == | OPENSSL_memcmp(CBS_data(cbs), kMDOIDs[i].oid, kMDOIDs[i].oid_len) == | ||||
0) { | 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; | 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) { | const EVP_MD *EVP_get_digestbyname(const char *name) { | ||||
for (unsigned i = 0; i < OPENSSL_ARRAY_SIZE(nid_to_digest_mapping); i++) { | for (unsigned i = 0; i < OPENSSL_ARRAY_SIZE(nid_to_digest_mapping); i++) { | ||||
const char *short_name = nid_to_digest_mapping[i].short_name; | const char *short_name = nid_to_digest_mapping[i].short_name; | ||||
@@ -21,6 +21,7 @@ | |||||
#include <gtest/gtest.h> | #include <gtest/gtest.h> | ||||
#include <openssl/asn1.h> | #include <openssl/asn1.h> | ||||
#include <openssl/bytestring.h> | |||||
#include <openssl/crypto.h> | #include <openssl/crypto.h> | ||||
#include <openssl/digest.h> | #include <openssl/digest.h> | ||||
#include <openssl/err.h> | #include <openssl/err.h> | ||||
@@ -31,6 +32,7 @@ | |||||
#include <openssl/sha.h> | #include <openssl/sha.h> | ||||
#include "../internal.h" | #include "../internal.h" | ||||
#include "../test/test_util.h" | |||||
struct MD { | 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_md5_sha1(), EVP_get_digestbyobj(OBJ_nid2obj(NID_md5_sha1))); | ||||
EXPECT_EQ(EVP_sha1(), EVP_get_digestbyobj(OBJ_nid2obj(NID_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<uint8_t> 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)); | |||||
} |
@@ -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 <openssl/base.h> | |||||
#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 |
@@ -71,7 +71,6 @@ | |||||
#include "internal.h" | #include "internal.h" | ||||
#include "../bytestring/internal.h" | #include "../bytestring/internal.h" | ||||
#include "../digest_extra/internal.h" | |||||
#include "../internal.h" | #include "../internal.h" | ||||
@@ -201,6 +201,23 @@ OPENSSL_EXPORT size_t EVP_MD_block_size(const EVP_MD *md); | |||||
#define EVP_MD_FLAG_DIGALGID_ABSENT 2 | #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. | // Deprecated functions. | ||||
// EVP_MD_CTX_copy sets |out|, which must /not/ be initialised, to be a copy of | // EVP_MD_CTX_copy sets |out|, which must /not/ be initialised, to be a copy of | ||||