Parse X509's signature algorithm with the CBS/CBB functions

In doing so, embed it into the struct and save a small malloc.

Bug: 42290417
Change-Id: Iaf6c679b577a27876b489d688c57c78a69d9130c
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/81778
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/x509/internal.h b/crypto/x509/internal.h
index 3ec7bf7..60c6ae0 100644
--- a/crypto/x509/internal.h
+++ b/crypto/x509/internal.h
@@ -117,7 +117,7 @@
 
 struct x509_st {
   X509_CINF *cert_info;
-  X509_ALGOR *sig_alg;
+  X509_ALGOR sig_alg;
   ASN1_BIT_STRING signature;
   CRYPTO_refcount_t references;
   CRYPTO_EX_DATA ex_data;
diff --git a/crypto/x509/t_x509.cc b/crypto/x509/t_x509.cc
index 765d551..2e18daf 100644
--- a/crypto/x509/t_x509.cc
+++ b/crypto/x509/t_x509.cc
@@ -203,7 +203,7 @@
   }
 
   if (!(cflag & X509_FLAG_NO_SIGDUMP)) {
-    if (X509_signature_print(bp, x->sig_alg, &x->signature) <= 0) {
+    if (X509_signature_print(bp, &x->sig_alg, &x->signature) <= 0) {
       return 0;
     }
   }
diff --git a/crypto/x509/x_all.cc b/crypto/x509/x_all.cc
index 493eb05..2290255 100644
--- a/crypto/x509/x_all.cc
+++ b/crypto/x509/x_all.cc
@@ -29,11 +29,11 @@
 
 
 int X509_verify(X509 *x509, EVP_PKEY *pkey) {
-  if (X509_ALGOR_cmp(x509->sig_alg, x509->cert_info->signature)) {
+  if (X509_ALGOR_cmp(&x509->sig_alg, x509->cert_info->signature)) {
     OPENSSL_PUT_ERROR(X509, X509_R_SIGNATURE_ALGORITHM_MISMATCH);
     return 0;
   }
-  return ASN1_item_verify(ASN1_ITEM_rptr(X509_CINF), x509->sig_alg,
+  return ASN1_item_verify(ASN1_ITEM_rptr(X509_CINF), &x509->sig_alg,
                           &x509->signature, x509->cert_info, pkey);
 }
 
@@ -45,13 +45,13 @@
 int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md) {
   asn1_encoding_clear(&x->cert_info->enc);
   return (ASN1_item_sign(ASN1_ITEM_rptr(X509_CINF), x->cert_info->signature,
-                         x->sig_alg, &x->signature, x->cert_info, pkey, md));
+                         &x->sig_alg, &x->signature, x->cert_info, pkey, md));
 }
 
 int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx) {
   asn1_encoding_clear(&x->cert_info->enc);
   return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CINF), x->cert_info->signature,
-                            x->sig_alg, &x->signature, x->cert_info, ctx);
+                            &x->sig_alg, &x->signature, x->cert_info, ctx);
 }
 
 int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md) {
diff --git a/crypto/x509/x_x509.cc b/crypto/x509/x_x509.cc
index a110368..c8cf7e0 100644
--- a/crypto/x509/x_x509.cc
+++ b/crypto/x509/x_x509.cc
@@ -57,6 +57,7 @@
 
   ret->references = 1;
   ret->ex_pathlen = -1;
+  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);
@@ -70,8 +71,7 @@
   }
 
   ret->cert_info = X509_CINF_new();
-  ret->sig_alg = X509_ALGOR_new();
-  if (ret->cert_info == NULL || ret->sig_alg == NULL) {
+  if (ret->cert_info == NULL) {
     X509_free(ret);
     return NULL;
   }
@@ -87,7 +87,7 @@
   CRYPTO_free_ex_data(&g_ex_data_class, &x509->ex_data);
 
   X509_CINF_free(x509->cert_info);
-  X509_ALGOR_free(x509->sig_alg);
+  x509_algor_cleanup(&x509->sig_alg);
   asn1_string_cleanup(&x509->signature);
   ASN1_OCTET_STRING_free(x509->skid);
   AUTHORITY_KEYID_free(x509->akid);
@@ -106,13 +106,13 @@
     return nullptr;
   }
 
-  CBS cert, tbs, sigalg;
+  CBS cert, tbs;
   if (!CBS_get_asn1(cbs, &cert, CBS_ASN1_SEQUENCE) ||
       // Bound the length to comfortably fit in an int. Lengths in this
       // module often omit overflow checks.
       CBS_len(&cert) > INT_MAX / 2 ||
       !CBS_get_asn1_element(&cert, &tbs, CBS_ASN1_SEQUENCE) ||
-      !CBS_get_asn1_element(&cert, &sigalg, CBS_ASN1_SEQUENCE) ||
+      !x509_parse_algorithm(&cert, &ret->sig_alg) ||
       // For just the signature field, we accept non-minimal BER lengths, though
       // not indefinite-length encoding. See b/18228011.
       //
@@ -135,12 +135,6 @@
     return nullptr;
   }
 
-  inp = CBS_data(&sigalg);
-  ret->sig_alg = d2i_X509_ALGOR(nullptr, &inp, CBS_len(&sigalg));
-  if (ret->sig_alg == nullptr || inp != CBS_data(&sigalg) + CBS_len(&sigalg)) {
-    return nullptr;
-  }
-
   // The version must be one of v1(0), v2(1), or v3(2).
   long version = X509_VERSION_1;
   if (ret->cert_info->version != nullptr) {
@@ -196,7 +190,7 @@
         if (len < 0 ||  //
             !CBB_add_space(&cert, &out, static_cast<size_t>(len)) ||
             i2d_X509_CINF(x509->cert_info, &out) != len ||
-            !x509_marshal_algorithm(&cert, x509->sig_alg) ||
+            !x509_marshal_algorithm(&cert, &x509->sig_alg) ||
             !asn1_marshal_bit_string(&cert, &x509->signature, /*tag=*/0) ||
             !CBB_flush(cbb)) {
           return false;
@@ -398,7 +392,7 @@
 }
 
 int X509_set1_signature_algo(X509 *x509, const X509_ALGOR *algo) {
-  return X509_ALGOR_copy(x509->sig_alg, algo) &&
+  return X509_ALGOR_copy(&x509->sig_alg, algo) &&
          X509_ALGOR_copy(x509->cert_info->signature, algo);
 }
 
@@ -417,10 +411,10 @@
     *psig = &x->signature;
   }
   if (palg) {
-    *palg = x->sig_alg;
+    *palg = &x->sig_alg;
   }
 }
 
 int X509_get_signature_nid(const X509 *x) {
-  return OBJ_obj2nid(x->sig_alg->algorithm);
+  return OBJ_obj2nid(x->sig_alg.algorithm);
 }