Embed X509_NAME into X509

Save a couple small allocations, and also avoid x509_new_null.

Bug: 42290417
Change-Id: I0b4f8b9024e0c32f56008be90b792d8224a58735
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/81894
Commit-Queue: David Benjamin <davidben@google.com>
Auto-Submit: 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 f5d2dc4..4310089 100644
--- a/crypto/x509/internal.h
+++ b/crypto/x509/internal.h
@@ -112,14 +112,10 @@
   uint8_t version;  // One of the |X509_VERSION_*| constants.
   ASN1_INTEGER serialNumber;
   X509_ALGOR tbs_sig_alg;
-  // TODO(crbug.com/42290417): When |X509_NAME| no longer uses the macro system,
-  // try to embed this struct.
-  X509_NAME *issuer;
+  X509_NAME issuer;
   ASN1_TIME notBefore;
   ASN1_TIME notAfter;
-  // TODO(crbug.com/42290417): When |X509_NAME| no longer uses the macro system,
-  // try to embed this struct.
-  X509_NAME *subject;
+  X509_NAME subject;
   X509_PUBKEY key;
   ASN1_BIT_STRING *issuerUID;            // [ 1 ] optional in v2
   ASN1_BIT_STRING *subjectUID;           // [ 2 ] optional in v2
@@ -582,6 +578,8 @@
 const X509_NAME_CACHE *x509_name_get_cache(const X509_NAME *name);
 void x509_name_invalidate_cache(X509_NAME *name);
 
+int x509_name_copy(X509_NAME *dst, const X509_NAME *src);
+
 void x509_algor_init(X509_ALGOR *alg);
 void x509_algor_cleanup(X509_ALGOR *alg);
 
diff --git a/crypto/x509/x509_cmp.cc b/crypto/x509/x509_cmp.cc
index e0a4b2a..5bd407a 100644
--- a/crypto/x509/x509_cmp.cc
+++ b/crypto/x509/x509_cmp.cc
@@ -29,11 +29,11 @@
 
 
 int X509_issuer_name_cmp(const X509 *a, const X509 *b) {
-  return X509_NAME_cmp(a->issuer, b->issuer);
+  return X509_NAME_cmp(&a->issuer, &b->issuer);
 }
 
 int X509_subject_name_cmp(const X509 *a, const X509 *b) {
-  return X509_NAME_cmp(a->subject, b->subject);
+  return X509_NAME_cmp(&a->subject, &b->subject);
 }
 
 int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b) {
@@ -46,20 +46,20 @@
 
 X509_NAME *X509_get_issuer_name(const X509 *a) {
   // This function is not const-correct for OpenSSL compatibility.
-  return a->issuer;
+  return const_cast<X509_NAME*>(&a->issuer);
 }
 
 uint32_t X509_issuer_name_hash(const X509 *x) {
-  return X509_NAME_hash(x->issuer);
+  return X509_NAME_hash(&x->issuer);
 }
 
 uint32_t X509_issuer_name_hash_old(const X509 *x) {
-  return X509_NAME_hash_old(x->issuer);
+  return X509_NAME_hash_old(&x->issuer);
 }
 
 X509_NAME *X509_get_subject_name(const X509 *a) {
   // This function is not const-correct for OpenSSL compatibility.
-  return a->subject;
+  return const_cast<X509_NAME*>(&a->subject);
 }
 
 ASN1_INTEGER *X509_get_serialNumber(X509 *a) { return &a->serialNumber; }
@@ -69,11 +69,11 @@
 }
 
 uint32_t X509_subject_name_hash(const X509 *x) {
-  return X509_NAME_hash(x->subject);
+  return X509_NAME_hash(&x->subject);
 }
 
 uint32_t X509_subject_name_hash_old(const X509 *x) {
-  return X509_NAME_hash_old(x->subject);
+  return X509_NAME_hash_old(&x->subject);
 }
 
 // Compare two certificates: they must be identical for this to work. NB:
diff --git a/crypto/x509/x509_set.cc b/crypto/x509/x509_set.cc
index 0da8cc5..12953a4 100644
--- a/crypto/x509/x509_set.cc
+++ b/crypto/x509/x509_set.cc
@@ -47,17 +47,17 @@
 }
 
 int X509_set_issuer_name(X509 *x, const X509_NAME *name) {
-  if (x == NULL) {
+  if (x == nullptr) {
     return 0;
   }
-  return (X509_NAME_set(&x->issuer, name));
+  return x509_name_copy(&x->issuer, name);
 }
 
 int X509_set_subject_name(X509 *x, const X509_NAME *name) {
-  if (x == NULL) {
+  if (x == nullptr) {
     return 0;
   }
-  return (X509_NAME_set(&x->subject, name));
+  return x509_name_copy(&x->subject, name);
 }
 
 int X509_set1_notBefore(X509 *x, const ASN1_TIME *tm) {
diff --git a/crypto/x509/x_name.cc b/crypto/x509/x_name.cc
index 973741a..54493cb 100644
--- a/crypto/x509/x_name.cc
+++ b/crypto/x509/x_name.cc
@@ -263,18 +263,25 @@
   return CBB_add_bytes(out, cache->der, cache->der_len);
 }
 
-X509_NAME *X509_NAME_dup(const X509_NAME *name) {
-  const X509_NAME_CACHE *cache = x509_name_get_cache(name);
+int x509_name_copy(X509_NAME *dst, const X509_NAME *src) {
+  const X509_NAME_CACHE *cache = x509_name_get_cache(src);
   if (cache == nullptr) {
-    return nullptr;
+    return 0;
   }
   CBS cbs;
   CBS_init(&cbs, cache->der, cache->der_len);
-  bssl::UniquePtr<X509_NAME> copy(X509_NAME_new());
-  if (copy == nullptr || !x509_parse_name(&cbs, copy.get())) {
-    return nullptr;
+  if (!x509_parse_name(&cbs, dst)) {
+    return 0;
   }
   assert(CBS_len(&cbs) == 0);
+  return 1;
+}
+
+X509_NAME *X509_NAME_dup(const X509_NAME *name) {
+  bssl::UniquePtr<X509_NAME> copy(X509_NAME_new());
+  if (copy == nullptr || !x509_name_copy(copy.get(), name)) {
+    return nullptr;
+  }
   return copy.release();
 }
 
diff --git a/crypto/x509/x_x509.cc b/crypto/x509/x_x509.cc
index c9cc309..26c39fd 100644
--- a/crypto/x509/x_x509.cc
+++ b/crypto/x509/x_x509.cc
@@ -40,9 +40,7 @@
 static constexpr CBS_ASN1_TAG kExtensionsTag =
     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 3;
 
-// x509_new_null returns a new |X509| object where the |issuer| and |subject|
-// fields are not yet filled in.
-static bssl::UniquePtr<X509> x509_new_null(void) {
+X509 *X509_new(void) {
   bssl::UniquePtr<X509> ret(
       reinterpret_cast<X509 *>(OPENSSL_zalloc(sizeof(X509))));
   if (ret == nullptr) {
@@ -54,29 +52,15 @@
   ret->version = X509_VERSION_1;
   asn1_string_init(&ret->serialNumber, V_ASN1_INTEGER);
   x509_algor_init(&ret->tbs_sig_alg);
+  x509_name_init(&ret->issuer);
   asn1_string_init(&ret->notBefore, -1);
   asn1_string_init(&ret->notAfter, -1);
+  x509_name_init(&ret->subject);
   x509_pubkey_init(&ret->key);
   x509_algor_init(&ret->sig_alg);
   asn1_string_init(&ret->signature, V_ASN1_BIT_STRING);
   CRYPTO_new_ex_data(&ret->ex_data);
   CRYPTO_MUTEX_init(&ret->lock);
-  return ret;
-}
-
-X509 *X509_new(void) {
-  bssl::UniquePtr<X509> ret = x509_new_null();
-  if (ret == nullptr) {
-    return nullptr;
-  }
-  // TODO(crbug.com/42290417): When the |X509_NAME| parser is CBS-based and
-  // writes into a pre-existing |X509_NAME|, we will no longer need the
-  // |X509_new| and |x509_new_null| split.
-  ret->issuer = X509_NAME_new();
-  ret->subject = X509_NAME_new();
-  if (ret->issuer == nullptr || ret->subject == nullptr) {
-    return nullptr;
-  }
   return ret.release();
 }
 
@@ -89,10 +73,10 @@
 
   asn1_string_cleanup(&x509->serialNumber);
   x509_algor_cleanup(&x509->tbs_sig_alg);
-  X509_NAME_free(x509->issuer);
+  x509_name_cleanup(&x509->issuer);
   asn1_string_cleanup(&x509->notBefore);
   asn1_string_cleanup(&x509->notAfter);
-  X509_NAME_free(x509->subject);
+  x509_name_cleanup(&x509->subject);
   x509_pubkey_cleanup(&x509->key);
   ASN1_BIT_STRING_free(x509->issuerUID);
   ASN1_BIT_STRING_free(x509->subjectUID);
@@ -111,23 +95,10 @@
   OPENSSL_free(x509);
 }
 
-static int parse_name(CBS *cbs, X509_NAME **out) {
-  // TODO(crbug.com/42290417): Make the |X509_NAME| parser CBS-based and avoid
-  // this awkward conversion.
-  const uint8_t *p = CBS_data(cbs);
-  X509_NAME_free(*out);
-  *out = d2i_X509_NAME(nullptr, &p, CBS_len(cbs));
-  if (*out == nullptr) {
-    return 0;
-  }
-  BSSL_CHECK(CBS_skip(cbs, p - CBS_data(cbs)));
-  return 1;
-}
-
 X509 *X509_parse_with_algorithms(CRYPTO_BUFFER *buf,
                                  const EVP_PKEY_ALG *const *algs,
                                  size_t num_algs) {
-  bssl::UniquePtr<X509> ret(x509_new_null());
+  bssl::UniquePtr<X509> ret(X509_new());
   if (ret == nullptr) {
     return nullptr;
   }
@@ -181,14 +152,14 @@
   CBS validity;
   if (!asn1_parse_integer(&tbs, &ret->serialNumber, /*tag=*/0) ||
       !x509_parse_algorithm(&tbs, &ret->tbs_sig_alg) ||
-      !parse_name(&tbs, &ret->issuer) ||
+      !x509_parse_name(&tbs, &ret->issuer) ||
       !CBS_get_asn1(&tbs, &validity, CBS_ASN1_SEQUENCE) ||
       !asn1_parse_time(&validity, &ret->notBefore,
                        /*allow_utc_timezone_offset=*/1) ||
       !asn1_parse_time(&validity, &ret->notAfter,
                        /*allow_utc_timezone_offset=*/1) ||
       CBS_len(&validity) != 0 ||  //
-      !parse_name(&tbs, &ret->subject) ||
+      !x509_parse_name(&tbs, &ret->subject) ||
       !x509_parse_public_key(&tbs, &ret->key, bssl::Span(algs, num_algs))) {
     OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
     return nullptr;
@@ -285,11 +256,11 @@
   }
   if (!asn1_marshal_integer(&tbs, &x509->serialNumber, /*tag=*/0) ||
       !x509_marshal_algorithm(&tbs, &x509->tbs_sig_alg) ||
-      !x509_marshal_name(&tbs, x509->issuer) ||
+      !x509_marshal_name(&tbs, &x509->issuer) ||
       !CBB_add_asn1(&tbs, &validity, CBS_ASN1_SEQUENCE) ||
       !asn1_marshal_time(&validity, &x509->notBefore) ||
       !asn1_marshal_time(&validity, &x509->notAfter) ||
-      !x509_marshal_name(&tbs, x509->subject) ||
+      !x509_marshal_name(&tbs, &x509->subject) ||
       !x509_marshal_public_key(&tbs, &x509->key) ||
       (x509->issuerUID != nullptr &&
        !asn1_marshal_bit_string(&tbs, x509->issuerUID, kIssuerUIDTag)) ||