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 <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>
This commit is contained in:
David Benjamin 2017-09-25 16:30:28 -04:00 committed by CQ bot account: commit-bot@chromium.org
parent 3a18bf0474
commit 42e93b6cf5
5 changed files with 104 additions and 43 deletions

View File

@ -62,7 +62,6 @@
#include <openssl/bytestring.h>
#include <openssl/nid.h>
#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;

View File

@ -21,6 +21,7 @@
#include <gtest/gtest.h>
#include <openssl/asn1.h>
#include <openssl/bytestring.h>
#include <openssl/crypto.h>
#include <openssl/digest.h>
#include <openssl/err.h>
@ -31,6 +32,7 @@
#include <openssl/sha.h>
#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<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));
}

View File

@ -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

View File

@ -71,7 +71,6 @@
#include "internal.h"
#include "../bytestring/internal.h"
#include "../digest_extra/internal.h"
#include "../internal.h"

View File

@ -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