Add subject key ID and authority key ID accessors.

Although extensions are accessible via X509_get_ext_d2i, OpenSSL's X509
object carries caches of a number of extensions. OpenSSL added accessors
for some of these in 1.1.0 (X509_get0_subject_key_id) and 1.1.1d (the
others), so mirror this. Note that, although they look like simpler
getters, the error-handling is tricky.

(For now I'm just looking to mirror OpenSSL's accessors and finally make
the structs opaque. Go's x509.Certificate structure also recognizes a
collection of built-in certificate fields, but error-handling is in the
parser. That could be one path out of this cached fields mess, at the
cost of making the parse operation do more work.)

Change-Id: I051512aa296bd103229ba6eb2b5639d79e9eb63f
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42624
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/x509v3/v3_purp.c b/crypto/x509v3/v3_purp.c
index e77a3d1..51783a4 100644
--- a/crypto/x509v3/v3_purp.c
+++ b/crypto/x509v3/v3_purp.c
@@ -880,3 +880,35 @@
         return x->ex_xkusage;
     return UINT32_MAX;
 }
+
+const ASN1_OCTET_STRING *X509_get0_subject_key_id(X509 *x509)
+{
+    if (!x509v3_cache_extensions(x509)) {
+        return NULL;
+    }
+    return x509->skid;
+}
+
+const ASN1_OCTET_STRING *X509_get0_authority_key_id(X509 *x509)
+{
+    if (!x509v3_cache_extensions(x509)) {
+        return NULL;
+    }
+    return x509->akid != NULL ? x509->akid->keyid : NULL;
+}
+
+const GENERAL_NAMES *X509_get0_authority_issuer(X509 *x509)
+{
+    if (!x509v3_cache_extensions(x509)) {
+        return NULL;
+    }
+    return x509->akid != NULL ? x509->akid->issuer : NULL;
+}
+
+const ASN1_INTEGER *X509_get0_authority_serial(X509 *x509)
+{
+    if (!x509v3_cache_extensions(x509)) {
+        return NULL;
+    }
+    return x509->akid != NULL ? x509->akid->serial : NULL;
+}
diff --git a/include/openssl/x509v3.h b/include/openssl/x509v3.h
index aff7c0b..2b2b4d9 100644
--- a/include/openssl/x509v3.h
+++ b/include/openssl/x509v3.h
@@ -651,6 +651,48 @@
 OPENSSL_EXPORT uint32_t X509_get_key_usage(X509 *x);
 OPENSSL_EXPORT uint32_t X509_get_extended_key_usage(X509 *x);
 
+// X509_get0_subject_key_id returns |x509|'s subject key identifier, if present.
+// (See RFC5280, section 4.2.1.2.) It returns NULL if the extension is not
+// present or if some extension in |x509| was invalid.
+//
+// Note that decoding an |X509| object will not check for invalid extensions. To
+// detect the error case, call |X509_get_extensions_flags| and check the
+// |EXFLAG_INVALID| bit.
+OPENSSL_EXPORT const ASN1_OCTET_STRING *X509_get0_subject_key_id(X509 *x509);
+
+// X509_get0_authority_key_id returns keyIdentifier of |x509|'s authority key
+// identifier, if the extension and field are present. (See RFC5280,
+// section 4.2.1.1.) It returns NULL if the extension is not present, if it is
+// present but lacks a keyIdentifier field, or if some extension in |x509| was
+// invalid.
+//
+// Note that decoding an |X509| object will not check for invalid extensions. To
+// detect the error case, call |X509_get_extensions_flags| and check the
+// |EXFLAG_INVALID| bit.
+OPENSSL_EXPORT const ASN1_OCTET_STRING *X509_get0_authority_key_id(X509 *x509);
+
+// X509_get0_authority_issuer returns the authorityCertIssuer of |x509|'s
+// authority key identifier, if the extension and field are present. (See
+// RFC5280, section 4.2.1.1.) It returns NULL if the extension is not present,
+// if it is present but lacks a authorityCertIssuer field, or if some extension
+// in |x509| was invalid.
+//
+// Note that decoding an |X509| object will not check for invalid extensions. To
+// detect the error case, call |X509_get_extensions_flags| and check the
+// |EXFLAG_INVALID| bit.
+OPENSSL_EXPORT const GENERAL_NAMES *X509_get0_authority_issuer(X509 *x509);
+
+// X509_get0_authority_serial returns the authorityCertSerialNumber of |x509|'s
+// authority key identifier, if the extension and field are present. (See
+// RFC5280, section 4.2.1.1.) It returns NULL if the extension is not present,
+// if it is present but lacks a authorityCertSerialNumber field, or if some
+// extension in |x509| was invalid.
+//
+// Note that decoding an |X509| object will not check for invalid extensions. To
+// detect the error case, call |X509_get_extensions_flags| and check the
+// |EXFLAG_INVALID| bit.
+OPENSSL_EXPORT const ASN1_INTEGER *X509_get0_authority_serial(X509 *x509);
+
 OPENSSL_EXPORT int X509_PURPOSE_get_count(void);
 OPENSSL_EXPORT X509_PURPOSE * X509_PURPOSE_get0(int idx);
 OPENSSL_EXPORT int X509_PURPOSE_get_by_sname(char *sname);