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);