diff options
| author | Shawn Willden <swillden@google.com> | 2016-04-25 08:59:48 -0600 |
|---|---|---|
| committer | Shawn Willden <swillden@google.com> | 2016-04-25 08:59:48 -0600 |
| commit | fed2be428f769650ca07c3858ef40880bba2ed18 (patch) | |
| tree | 46397fde30dba966a30fd10e28f99724b47e5c55 | |
| parent | 637dd8429285bfdc0b89622476ea94d782b1eb14 (diff) | |
| download | android_system_keymaster-fed2be428f769650ca07c3858ef40880bba2ed18.tar.gz android_system_keymaster-fed2be428f769650ca07c3858ef40880bba2ed18.tar.bz2 android_system_keymaster-fed2be428f769650ca07c3858ef40880bba2ed18.zip | |
Add authority key ID to attestation certificates.
The attestation certificate chain produced by softkeymaster is hard to
verify because the leaf certificate does not contain the X509v3 Key
Authority ID extension, which provides the ID of the signing key. This
isn't strictly required by the standard, but many tools get badly
confused without the ID extension, including openssl.
Bug: 28321678
Change-Id: I91136f08eaf0b81b5443753488beb8a40af60e6c
| -rw-r--r-- | asymmetric_key.cpp | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/asymmetric_key.cpp b/asymmetric_key.cpp index 4412618..c4e2da5 100644 --- a/asymmetric_key.cpp +++ b/asymmetric_key.cpp @@ -21,6 +21,7 @@ #include <openssl/asn1.h> #include <openssl/stack.h> #include <openssl/x509.h> +#include <openssl/x509v3.h> #include "attestation_record.h" #include "openssl_err.h" @@ -257,12 +258,39 @@ keymaster_error_t AsymmetricKey::GenerateAttestation(const KeymasterContext& con certificate.get(), &error)) return error; - if (!X509_sign(certificate.get(), sign_key.get(), EVP_sha256())) - return TranslateLastOpenSslError(); - if (!copy_attestation_chain(context, sign_algorithm, cert_chain, &error)) return error; + // Copy subject key identifier from cert_chain->entries[1] as authority key_id. + if (cert_chain->entry_count < 2) { + // cert_chain must have at least two entries, one for the cert we're trying to create and + // one for the cert for the key that signs the new cert. + return KM_ERROR_UNKNOWN_ERROR; + } + + const uint8_t* p = cert_chain->entries[1].data; + X509_Ptr signing_cert(d2i_X509(nullptr, &p, cert_chain->entries[1].data_length)); + if (!signing_cert.get()) { + return TranslateLastOpenSslError(); + } + + UniquePtr<X509V3_CTX> x509v3_ctx(new X509V3_CTX); + *x509v3_ctx = {}; + X509V3_set_ctx(x509v3_ctx.get(), signing_cert.get(), certificate.get(), nullptr /* req */, + nullptr /* crl */, 0 /* flags */); + + X509_EXTENSION_Ptr auth_key_id(X509V3_EXT_nconf_nid(nullptr /* conf */, x509v3_ctx.get(), + NID_authority_key_identifier, + const_cast<char*>("keyid:always"))); + if (!auth_key_id.get() || + !X509_add_ext(certificate.get(), auth_key_id.get() /* Don't release; copied */, + -1 /* insert at end */)) { + return TranslateLastOpenSslError(); + } + + if (!X509_sign(certificate.get(), sign_key.get(), EVP_sha256())) + return TranslateLastOpenSslError(); + return get_certificate_blob(certificate.get(), &cert_chain->entries[0]); } |
