Switch easy fields in X509 to UniquePtr Embedded fields still need some work. Also extensions is tied up in some pointer-to-pointer calling convention in the awful config bits. Change-Id: I198403f0baf3a4453999a2677145a97d3f653ae1 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/97153 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/x509/internal.h b/crypto/x509/internal.h index 2d5febc..ccdf687 100644 --- a/crypto/x509/internal.h +++ b/crypto/x509/internal.h
@@ -142,8 +142,8 @@ ASN1_TIME notAfter; X509Name subject; X509Pubkey key; - ASN1_BIT_STRING *issuerUID = nullptr; // [ 1 ] optional in v2 - ASN1_BIT_STRING *subjectUID = nullptr; // [ 2 ] optional in v2 + UniquePtr<ASN1_BIT_STRING> issuerUID; // [ 1 ] optional in v2 + UniquePtr<ASN1_BIT_STRING> subjectUID; // [ 2 ] optional in v2 STACK_OF(X509_EXTENSION) *extensions = nullptr; // [ 3 ] optional in v3 // Certificate fields: X509_ALGOR sig_alg; @@ -152,18 +152,18 @@ // buf, if not nullptr, contains a copy of the serialized Certificate. // TODO(davidben): Now every parsed `X509` has an underlying `CRYPTO_BUFFER`, // but `X509`s created peacemeal do not. Can we make this more uniform? - CRYPTO_BUFFER *buf = nullptr; + UniquePtr<CRYPTO_BUFFER> buf; CRYPTO_EX_DATA ex_data; // These contain copies of various extension values long ex_pathlen = -1; uint32_t ex_flags = 0; uint32_t ex_kusage = 0; uint32_t ex_xkusage = 0; - ASN1_OCTET_STRING *skid = nullptr; - AUTHORITY_KEYID *akid = nullptr; - STACK_OF(DIST_POINT) *crldp = nullptr; - STACK_OF(GENERAL_NAME) *altname = nullptr; - NAME_CONSTRAINTS *nc = nullptr; + UniquePtr<ASN1_OCTET_STRING> skid; + UniquePtr<AUTHORITY_KEYID> akid; + UniquePtr<STACK_OF(DIST_POINT)> crldp; + UniquePtr<STACK_OF(GENERAL_NAME)> altname; + UniquePtr<NAME_CONSTRAINTS> nc; unsigned char cert_hash[SHA256_DIGEST_LENGTH] = {}; bssl::X509_CERT_AUX *aux = nullptr; Mutex lock;
diff --git a/crypto/x509/t_x509.cc b/crypto/x509/t_x509.cc index 1d7de41..a68a7a8 100644 --- a/crypto/x509/t_x509.cc +++ b/crypto/x509/t_x509.cc
@@ -187,7 +187,7 @@ if (BIO_printf(bp, "%8sIssuer Unique ID: ", "") <= 0) { return 0; } - if (!X509_signature_dump(bp, impl->issuerUID, 12)) { + if (!X509_signature_dump(bp, impl->issuerUID.get(), 12)) { return 0; } } @@ -195,7 +195,7 @@ if (BIO_printf(bp, "%8sSubject Unique ID: ", "") <= 0) { return 0; } - if (!X509_signature_dump(bp, impl->subjectUID, 12)) { + if (!X509_signature_dump(bp, impl->subjectUID.get(), 12)) { return 0; } }
diff --git a/crypto/x509/v3_ncons.cc b/crypto/x509/v3_ncons.cc index f439395..d65febf 100644 --- a/crypto/x509/v3_ncons.cc +++ b/crypto/x509/v3_ncons.cc
@@ -734,7 +734,7 @@ // check. const auto *x_impl = FromOpaque(x); size_t name_count = - X509_NAME_entry_count(nm) + sk_GENERAL_NAME_num(x_impl->altname); + X509_NAME_entry_count(nm) + sk_GENERAL_NAME_num(x_impl->altname.get()); size_t constraint_count = sk_GENERAL_SUBTREE_num(nc->permittedSubtrees) + sk_GENERAL_SUBTREE_num(nc->excludedSubtrees); size_t check_count = constraint_count * name_count; @@ -787,7 +787,7 @@ } } - for (const GENERAL_NAME *gen : x_impl->altname) { + for (const GENERAL_NAME *gen : x_impl->altname.get()) { int r = nc_match(gen, nc, /*case_insensitive_exclude_localpart=*/false); if (r != X509_V_OK) { return r;
diff --git a/crypto/x509/v3_purp.cc b/crypto/x509/v3_purp.cc index ec5aa37..c330eb8 100644 --- a/crypto/x509/v3_purp.cc +++ b/crypto/x509/v3_purp.cc
@@ -167,13 +167,13 @@ static int setup_crldp(X509 *x) { int j; auto *impl = FromOpaque(x); - impl->crldp = reinterpret_cast<STACK_OF(DIST_POINT) *>( - X509_get_ext_d2i(x, NID_crl_distribution_points, &j, nullptr)); + impl->crldp.reset(reinterpret_cast<STACK_OF(DIST_POINT) *>( + X509_get_ext_d2i(x, NID_crl_distribution_points, &j, nullptr))); if (impl->crldp == nullptr && j != -1) { return 0; } - for (size_t i = 0; i < sk_DIST_POINT_num(impl->crldp); i++) { - if (!setup_dp(x, sk_DIST_POINT_value(impl->crldp, i))) { + for (size_t i = 0; i < sk_DIST_POINT_num(impl->crldp.get()); i++) { + if (!setup_dp(x, sk_DIST_POINT_value(impl->crldp.get(), i))) { return 0; } } @@ -299,13 +299,13 @@ impl->ex_flags |= EXFLAG_INVALID; } - impl->skid = reinterpret_cast<ASN1_OCTET_STRING *>( - X509_get_ext_d2i(x, NID_subject_key_identifier, &j, nullptr)); + impl->skid.reset(reinterpret_cast<ASN1_OCTET_STRING *>( + X509_get_ext_d2i(x, NID_subject_key_identifier, &j, nullptr))); if (impl->skid == nullptr && j != -1) { impl->ex_flags |= EXFLAG_INVALID; } - impl->akid = reinterpret_cast<AUTHORITY_KEYID *>( - X509_get_ext_d2i(x, NID_authority_key_identifier, &j, nullptr)); + impl->akid.reset(reinterpret_cast<AUTHORITY_KEYID *>( + X509_get_ext_d2i(x, NID_authority_key_identifier, &j, nullptr))); if (impl->akid == nullptr && j != -1) { impl->ex_flags |= EXFLAG_INVALID; } @@ -313,18 +313,18 @@ if (!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x))) { impl->ex_flags |= EXFLAG_SI; // If SKID matches AKID also indicate self signed - if (X509_check_akid(x, impl->akid) == X509_V_OK && + if (X509_check_akid(x, impl->akid.get()) == X509_V_OK && !ku_reject(x, X509v3_KU_KEY_CERT_SIGN)) { impl->ex_flags |= EXFLAG_SS; } } - impl->altname = reinterpret_cast<STACK_OF(GENERAL_NAME) *>( - X509_get_ext_d2i(x, NID_subject_alt_name, &j, nullptr)); + impl->altname.reset(reinterpret_cast<STACK_OF(GENERAL_NAME) *>( + X509_get_ext_d2i(x, NID_subject_alt_name, &j, nullptr))); if (impl->altname == nullptr && j != -1) { impl->ex_flags |= EXFLAG_INVALID; } - impl->nc = reinterpret_cast<NAME_CONSTRAINTS *>( - X509_get_ext_d2i(x, NID_name_constraints, &j, nullptr)); + impl->nc.reset(reinterpret_cast<NAME_CONSTRAINTS *>( + X509_get_ext_d2i(x, NID_name_constraints, &j, nullptr))); if (impl->nc == nullptr && j != -1) { impl->ex_flags |= EXFLAG_INVALID; } @@ -480,7 +480,7 @@ const auto *subject_impl = FromOpaque(subject); if (subject_impl->akid) { - int ret = X509_check_akid(issuer, subject_impl->akid); + int ret = X509_check_akid(issuer, subject_impl->akid.get()); if (ret != X509_V_OK) { return ret; } @@ -500,7 +500,7 @@ // Check key ids (if present) auto *issuer_impl = FromOpaque(issuer); if (akid->keyid && issuer_impl->skid && - ASN1_OCTET_STRING_cmp(akid->keyid, issuer_impl->skid)) { + ASN1_OCTET_STRING_cmp(akid->keyid, issuer_impl->skid.get())) { return X509_V_ERR_AKID_SKID_MISMATCH; } // Check serial number @@ -567,7 +567,7 @@ return nullptr; } auto *impl = FromOpaque(x509); - return impl->skid; + return impl->skid.get(); } const ASN1_OCTET_STRING *X509_get0_authority_key_id(X509 *x509) {
diff --git a/crypto/x509/x509_set.cc b/crypto/x509/x509_set.cc index e55829f..970d2e6 100644 --- a/crypto/x509/x509_set.cc +++ b/crypto/x509/x509_set.cc
@@ -138,10 +138,10 @@ const ASN1_BIT_STRING **out_subject_uid) { const auto *impl = FromOpaque(x509); if (out_issuer_uid != nullptr) { - *out_issuer_uid = impl->issuerUID; + *out_issuer_uid = impl->issuerUID.get(); } if (out_subject_uid != nullptr) { - *out_subject_uid = impl->subjectUID; + *out_subject_uid = impl->subjectUID.get(); } }
diff --git a/crypto/x509/x509_test.cc b/crypto/x509/x509_test.cc index 4e04c77..9e1f60c 100644 --- a/crypto/x509/x509_test.cc +++ b/crypto/x509/x509_test.cc
@@ -3268,12 +3268,12 @@ UniquePtr<X509> root(X509_parse_from_buffer(buf.get())); ASSERT_TRUE(root); - EXPECT_EQ(buf.get(), FromOpaque(root.get())->buf); + EXPECT_EQ(buf.get(), FromOpaque(root.get())->buf.get()); buf.reset(); // This ensures the X509 took a reference to `buf`, otherwise this will be a // reference to free memory and ASAN should notice. - CRYPTO_BUFFER_len(FromOpaque(root.get())->buf); + CRYPTO_BUFFER_len(FromOpaque(root.get())->buf.get()); } TEST(X509Test, TestFromBufferWithTrailingData) { @@ -3332,7 +3332,7 @@ size_t data2_len; UniquePtr<uint8_t> data2; ASSERT_TRUE(PEMToDER(&data2, &data2_len, kLeafPEM)); - EXPECT_EQ(FromOpaque(root.get())->buf, buf.get()); + EXPECT_EQ(FromOpaque(root.get())->buf.get(), buf.get()); // Historically, this function tested the interaction between // `X509_parse_from_buffer` and object reuse. We no longer support object @@ -3345,7 +3345,7 @@ root.reset(raw); ASSERT_EQ(root.get(), ret); - ASSERT_NE(buf.get(), FromOpaque(root.get())->buf); + ASSERT_NE(buf.get(), FromOpaque(root.get())->buf.get()); // Free `data2` and ensure that `root` took its own copy. Otherwise // serializing `root`, below, will trigger a use-after-free.
diff --git a/crypto/x509/x509_vfy.cc b/crypto/x509/x509_vfy.cc index 16625ba..ce54dd6 100644 --- a/crypto/x509/x509_vfy.cc +++ b/crypto/x509/x509_vfy.cc
@@ -569,7 +569,7 @@ // but if it includes constraints it is to be assumed it expects them // to be obeyed. for (j = (int)sk_X509_num(ctx->chain) - 1; j > i; j--) { - NAME_CONSTRAINTS *nc = FromOpaque(sk_X509_value(ctx->chain, j))->nc; + NAME_CONSTRAINTS *nc = FromOpaque(sk_X509_value(ctx->chain, j))->nc.get(); if (nc) { has_name_constraints = 1; rv = NAME_CONSTRAINTS_check(x, nc); @@ -1048,8 +1048,8 @@ return 0; } } - for (size_t i = 0; i < sk_DIST_POINT_num(impl->crldp); i++) { - DIST_POINT *dp = sk_DIST_POINT_value(impl->crldp, i); + for (size_t i = 0; i < sk_DIST_POINT_num(impl->crldp.get()); i++) { + DIST_POINT *dp = sk_DIST_POINT_value(impl->crldp.get(), i); // Skip distribution points with a reasons field or a CRL issuer: // // We do not support CRLs partitioned by reason code. RFC 5280 requires CAs
diff --git a/crypto/x509/x_all.cc b/crypto/x509/x_all.cc index 118c7b0..415d0fc 100644 --- a/crypto/x509/x_all.cc +++ b/crypto/x509/x_all.cc
@@ -78,7 +78,6 @@ } // Discard the cached encoding. (We just modified it.) - CRYPTO_BUFFER_free(impl->buf); impl->buf = nullptr; ScopedCBB cbb;
diff --git a/crypto/x509/x_x509.cc b/crypto/x509/x_x509.cc index 54c3a8c..740124b 100644 --- a/crypto/x509/x_x509.cc +++ b/crypto/x509/x_x509.cc
@@ -63,17 +63,9 @@ x509_algor_cleanup(&tbs_sig_alg); asn1_string_cleanup(¬Before); asn1_string_cleanup(¬After); - ASN1_BIT_STRING_free(issuerUID); - ASN1_BIT_STRING_free(subjectUID); sk_X509_EXTENSION_pop_free(extensions, X509_EXTENSION_free); x509_algor_cleanup(&sig_alg); asn1_string_cleanup(&signature); - CRYPTO_BUFFER_free(buf); - ASN1_OCTET_STRING_free(skid); - AUTHORITY_KEYID_free(akid); - CRL_DIST_POINTS_free(crldp); - GENERAL_NAMES_free(altname); - NAME_CONSTRAINTS_free(nc); X509_CERT_AUX_free(aux); } @@ -94,7 +86,7 @@ } // Save the buffer to cache the original encoding. - ret->buf = UpRef(buf).release(); + ret->buf = UpRef(buf); // Parse the Certificate. CBS cbs, cert, tbs; @@ -157,17 +149,17 @@ // Per RFC 5280, section 4.1.2.8, these fields require v2 or v3: if (ret->version >= X509_VERSION_2 && CBS_peek_asn1_tag(&tbs, kIssuerUIDTag)) { - ret->issuerUID = ASN1_BIT_STRING_new(); + ret->issuerUID.reset(ASN1_BIT_STRING_new()); if (ret->issuerUID == nullptr || - !asn1_parse_bit_string(&tbs, ret->issuerUID, kIssuerUIDTag)) { + !asn1_parse_bit_string(&tbs, ret->issuerUID.get(), kIssuerUIDTag)) { return nullptr; } } if (ret->version >= X509_VERSION_2 && CBS_peek_asn1_tag(&tbs, kSubjectUIDTag)) { - ret->subjectUID = ASN1_BIT_STRING_new(); + ret->subjectUID.reset(ASN1_BIT_STRING_new()); if (ret->subjectUID == nullptr || - !asn1_parse_bit_string(&tbs, ret->subjectUID, kSubjectUIDTag)) { + !asn1_parse_bit_string(&tbs, ret->subjectUID.get(), kSubjectUIDTag)) { return nullptr; } } @@ -225,7 +217,7 @@ // exactly what we parsed. The `CRYPTO_BUFFER` contains the full // Certificate, so we need to find the TBSCertificate portion. CBS cbs, cert, tbs; - CRYPTO_BUFFER_init_CBS(impl->buf, &cbs); + CRYPTO_BUFFER_init_CBS(impl->buf.get(), &cbs); if (!CBS_get_asn1(&cbs, &cert, CBS_ASN1_SEQUENCE) || !CBS_get_asn1_element(&cert, &tbs, CBS_ASN1_SEQUENCE)) { // This should be impossible. @@ -255,9 +247,10 @@ !x509_marshal_name(&tbs, &impl->subject) || !x509_marshal_public_key(&tbs, &impl->key) || (impl->issuerUID != nullptr && - !asn1_marshal_bit_string(&tbs, impl->issuerUID, kIssuerUIDTag)) || + !asn1_marshal_bit_string(&tbs, impl->issuerUID.get(), kIssuerUIDTag)) || (impl->subjectUID != nullptr && - !asn1_marshal_bit_string(&tbs, impl->subjectUID, kSubjectUIDTag))) { + !asn1_marshal_bit_string(&tbs, impl->subjectUID.get(), + kSubjectUIDTag))) { return 0; } if (impl->extensions != nullptr) { @@ -451,7 +444,6 @@ int i2d_re_X509_tbs(X509 *x509, uint8_t **outp) { auto *impl = FromOpaque(x509); - CRYPTO_BUFFER_free(impl->buf); impl->buf = nullptr; return i2d_X509_tbs(x509, outp); }