summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Willden <swillden@google.com>2016-04-25 08:59:48 -0600
committerShawn Willden <swillden@google.com>2016-04-25 08:59:48 -0600
commitfed2be428f769650ca07c3858ef40880bba2ed18 (patch)
tree46397fde30dba966a30fd10e28f99724b47e5c55
parent637dd8429285bfdc0b89622476ea94d782b1eb14 (diff)
downloadandroid_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.cpp34
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]);
}