Add version field to generated TLS certificates

Chrome requires the version field to be populated and set to V3. This
patch also adds DVLOGs, since currently generating a certificate
requires stepping through a debugger.

Change-Id: Id6e803834f11a4fba265684ff2be745197282279
Reviewed-on: https://chromium-review.googlesource.com/c/openscreen/+/2489927
Reviewed-by: Brandon Tolsch <btolsch@chromium.org>
Commit-Queue: Jordan Bayles <jophba@chromium.org>
diff --git a/util/crypto/certificate_utils.cc b/util/crypto/certificate_utils.cc
index 8f18b7e..a9b7d9a 100644
--- a/util/crypto/certificate_utils.cc
+++ b/util/crypto/certificate_utils.cc
@@ -63,11 +63,19 @@
     issuer_key = &key_pair;
   }
 
+  // Certificate versions are zero indexed, so V1 = 0.
+  const int kCertificateVersion3 = 2;
+  if (X509_set_version(certificate.get(), kCertificateVersion3) != 1) {
+    OSP_DVLOG << "Failed to set certificate version";
+    return nullptr;
+  }
+
   // Serial numbers must be unique for this session. As a pretend CA, we should
   // not issue certificates with the same serial number in the same session.
   static int serial_number(1);
   if (ASN1_INTEGER_set(X509_get_serialNumber(certificate.get()),
                        serial_number++) != 1) {
+    OSP_DVLOG << "Failed to set serial number.";
     return nullptr;
   }
 
@@ -77,11 +85,13 @@
 
   if ((X509_set_notBefore(certificate.get(), now.get()) != 1) ||
       (X509_set_notAfter(certificate.get(), expiration_time.get()) != 1)) {
+    OSP_DVLOG << "Failed to set before and after ranges.";
     return nullptr;
   }
 
   X509_NAME* certificate_name = X509_get_subject_name(certificate.get());
   if (!AddCertificateField(certificate_name, "CN", name)) {
+    OSP_DVLOG << "Failed to set subject name";
     return nullptr;
   }
 
@@ -91,6 +101,7 @@
     ASN1_BIT_STRING_set_bit(x.get(), KeyUsageBits::kKeyCertSign, 1);
   }
   if (X509_add1_ext_i2d(certificate.get(), NID_key_usage, x.get(), 0, 0) != 1) {
+    OSP_DVLOG << "Failed to set key usage extension";
     return nullptr;
   }
   if (make_ca) {
@@ -101,6 +112,7 @@
         X509V3_EXT_nconf_nid(nullptr, &ctx, NID_basic_constraints,
                              const_cast<char*>("critical,CA:TRUE")));
     if (!ex) {
+      OSP_DVLOG << "Failed to set constraints extension";
       return nullptr;
     }
     void* thing = X509V3_EXT_d2i(ex.get());
@@ -115,6 +127,7 @@
       // the size of the signature in bytes.
       (X509_sign(certificate.get(), issuer_key, EVP_sha256()) <= 0) ||
       (X509_verify(certificate.get(), issuer_key) != 1)) {
+    OSP_DVLOG << "Failed to set pubkey, set issuer, sign, or verify";
     return nullptr;
   }