diff options
author | Matt Mueller <mattm@google.com> | 2021-11-12 13:15:21 -0800 |
---|---|---|
committer | Boringssl LUCI CQ <boringssl-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2021-11-15 16:59:41 +0000 |
commit | 27a67557405dcf18567f4528aa537da25f0a34e2 (patch) | |
tree | 3daab284e9e188b067a14bda24e3c26d5721fcee | |
parent | a9670a8b476470e6f874fef3554e8059683e1413 (diff) | |
download | boringssl-27a67557405dcf18567f4528aa537da25f0a34e2.zip boringssl-27a67557405dcf18567f4528aa537da25f0a34e2.tar.gz boringssl-27a67557405dcf18567f4528aa537da25f0a34e2.tar.bz2 |
Add PKCS7_bundle_raw_certificates function which takes CRYPTO_BUFFERs
Change-Id: I12ab8e9209bd5fdff75c42332d4d35a461302b61
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50425
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
-rw-r--r-- | crypto/pkcs7/pkcs7.c | 29 | ||||
-rw-r--r-- | crypto/pkcs7/pkcs7_test.cc | 50 | ||||
-rw-r--r-- | include/openssl/pkcs7.h | 13 |
3 files changed, 88 insertions, 4 deletions
diff --git a/crypto/pkcs7/pkcs7.c b/crypto/pkcs7/pkcs7.c index 6be5a07..8232af6 100644 --- a/crypto/pkcs7/pkcs7.c +++ b/crypto/pkcs7/pkcs7.c @@ -131,6 +131,35 @@ err: return ret; } +static int pkcs7_bundle_raw_certificates_cb(CBB *out, const void *arg) { + const STACK_OF(CRYPTO_BUFFER) *certs = arg; + CBB certificates; + + // See https://tools.ietf.org/html/rfc2315#section-9.1 + if (!CBB_add_asn1(out, &certificates, + CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) { + return 0; + } + + for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(certs); i++) { + CRYPTO_BUFFER *cert = sk_CRYPTO_BUFFER_value(certs, i); + if (!CBB_add_bytes(&certificates, CRYPTO_BUFFER_data(cert), + CRYPTO_BUFFER_len(cert))) { + return 0; + } + } + + // |certificates| is a implicitly-tagged SET OF. + return CBB_flush_asn1_set_of(&certificates) && CBB_flush(out); +} + +int PKCS7_bundle_raw_certificates(CBB *out, + const STACK_OF(CRYPTO_BUFFER) *certs) { + return pkcs7_add_signed_data(out, /*digest_algos_cb=*/NULL, + pkcs7_bundle_raw_certificates_cb, + /*signer_infos_cb=*/NULL, certs); +} + int pkcs7_add_signed_data(CBB *out, int (*digest_algos_cb)(CBB *out, const void *arg), int (*cert_crl_cb)(CBB *out, const void *arg), diff --git a/crypto/pkcs7/pkcs7_test.cc b/crypto/pkcs7/pkcs7_test.cc index 9cca175..bf85379 100644 --- a/crypto/pkcs7/pkcs7_test.cc +++ b/crypto/pkcs7/pkcs7_test.cc @@ -708,6 +708,56 @@ TEST(PKCS7Test, SortCerts) { check_order(cert2, cert3, cert1); } +// Test that we output certificates in the canonical DER order, using the +// CRYPTO_BUFFER version of the parse and bundle functions. +TEST(PKCS7Test, SortCertsRaw) { + // kPKCS7NSS contains three certificates in the canonical DER order. + CBS pkcs7; + CBS_init(&pkcs7, kPKCS7NSS, sizeof(kPKCS7NSS)); + bssl::UniquePtr<STACK_OF(CRYPTO_BUFFER)> certs(sk_CRYPTO_BUFFER_new_null()); + ASSERT_TRUE(certs); + ASSERT_TRUE(PKCS7_get_raw_certificates(certs.get(), &pkcs7, nullptr)); + ASSERT_EQ(3u, sk_CRYPTO_BUFFER_num(certs.get())); + + CRYPTO_BUFFER *cert1 = sk_CRYPTO_BUFFER_value(certs.get(), 0); + CRYPTO_BUFFER *cert2 = sk_CRYPTO_BUFFER_value(certs.get(), 1); + CRYPTO_BUFFER *cert3 = sk_CRYPTO_BUFFER_value(certs.get(), 2); + + auto check_order = [&](CRYPTO_BUFFER *new_cert1, CRYPTO_BUFFER *new_cert2, + CRYPTO_BUFFER *new_cert3) { + // Bundle the certificates in the new order. + bssl::UniquePtr<STACK_OF(CRYPTO_BUFFER)> new_certs( + sk_CRYPTO_BUFFER_new_null()); + ASSERT_TRUE(new_certs); + ASSERT_TRUE(bssl::PushToStack(new_certs.get(), bssl::UpRef(new_cert1))); + ASSERT_TRUE(bssl::PushToStack(new_certs.get(), bssl::UpRef(new_cert2))); + ASSERT_TRUE(bssl::PushToStack(new_certs.get(), bssl::UpRef(new_cert3))); + bssl::ScopedCBB cbb; + ASSERT_TRUE(CBB_init(cbb.get(), sizeof(kPKCS7NSS))); + ASSERT_TRUE(PKCS7_bundle_raw_certificates(cbb.get(), new_certs.get())); + + // The bundle should be sorted back to the original order. + CBS cbs; + CBS_init(&cbs, CBB_data(cbb.get()), CBB_len(cbb.get())); + bssl::UniquePtr<STACK_OF(CRYPTO_BUFFER)> result( + sk_CRYPTO_BUFFER_new_null()); + ASSERT_TRUE(result); + ASSERT_TRUE(PKCS7_get_raw_certificates(result.get(), &cbs, nullptr)); + ASSERT_EQ(sk_CRYPTO_BUFFER_num(certs.get()), + sk_CRYPTO_BUFFER_num(result.get())); + for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(certs.get()); i++) { + CRYPTO_BUFFER *a = sk_CRYPTO_BUFFER_value(certs.get(), i); + CRYPTO_BUFFER *b = sk_CRYPTO_BUFFER_value(result.get(), i); + EXPECT_EQ(Bytes(CRYPTO_BUFFER_data(a), CRYPTO_BUFFER_len(a)), + Bytes(CRYPTO_BUFFER_data(b), CRYPTO_BUFFER_len(b))); + } + }; + + check_order(cert1, cert2, cert3); + check_order(cert3, cert2, cert1); + check_order(cert2, cert3, cert1); +} + // Test that we output CRLs in the canonical DER order. TEST(PKCS7Test, SortCRLs) { static const char kCRL1[] = R"( diff --git a/include/openssl/pkcs7.h b/include/openssl/pkcs7.h index 429e91c..85f2a4e 100644 --- a/include/openssl/pkcs7.h +++ b/include/openssl/pkcs7.h @@ -49,10 +49,15 @@ OPENSSL_EXPORT int PKCS7_get_raw_certificates( // them into |X509| objects. OPENSSL_EXPORT int PKCS7_get_certificates(STACK_OF(X509) *out_certs, CBS *cbs); -// PKCS7_bundle_certificates appends a PKCS#7, SignedData structure containing -// |certs| to |out|. It returns one on success and zero on error. Note that -// certificates in SignedData structures are unordered. The order in |certs| -// will not be preserved. +// PKCS7_bundle_raw_certificates appends a PKCS#7, SignedData structure +// containing |certs| to |out|. It returns one on success and zero on error. +// Note that certificates in SignedData structures are unordered. The order in +// |certs| will not be preserved. +OPENSSL_EXPORT int PKCS7_bundle_raw_certificates( + CBB *out, const STACK_OF(CRYPTO_BUFFER) *certs); + +// PKCS7_bundle_certificates behaves like |PKCS7_bundle_raw_certificates| but +// takes |X509| objects as input. OPENSSL_EXPORT int PKCS7_bundle_certificates( CBB *out, const STACK_OF(X509) *certs); |