diff options
author | Shawn Willden <swillden@google.com> | 2016-05-02 23:36:36 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2016-05-02 23:36:36 +0000 |
commit | 431dcfa4ec20c75c7b6d48c31b15f6b09e4b00fd (patch) | |
tree | a6d387fa4f1542d270ac642bb8a86ae49b7c2904 | |
parent | c262f8001fd2cf6c692d9b5d5f97f3dffb17b9f6 (diff) | |
parent | d487dc9e95162f249048bd31d4191a0d50b77496 (diff) | |
download | android_system_keymaster-431dcfa4ec20c75c7b6d48c31b15f6b09e4b00fd.tar.gz android_system_keymaster-431dcfa4ec20c75c7b6d48c31b15f6b09e4b00fd.tar.bz2 android_system_keymaster-431dcfa4ec20c75c7b6d48c31b15f6b09e4b00fd.zip |
Add key usage extension to attestation certificates.
am: d487dc9e95
* commit 'd487dc9e95162f249048bd31d4191a0d50b77496':
Add key usage extension to attestation certificates.
Change-Id: I176d672267ed8b3bbff14466ad02c8285f098f52
-rw-r--r-- | asymmetric_key.cpp | 82 | ||||
-rw-r--r-- | openssl_utils.h | 17 |
2 files changed, 90 insertions, 9 deletions
diff --git a/asymmetric_key.cpp b/asymmetric_key.cpp index c4e2da5..782e87b 100644 --- a/asymmetric_key.cpp +++ b/asymmetric_key.cpp @@ -30,9 +30,85 @@ namespace keymaster { namespace { + +constexpr int kDigitalSignatureKeyUsageBit = 0; +constexpr int kKeyEnciphermentKeyUsageBit = 2; +constexpr int kDataEnciphermentKeyUsageBit = 3; +constexpr int kMaxKeyUsageBit = 8; + template <typename T> T min(T a, T b) { return (a < b) ? a : b; } + +static keymaster_error_t add_key_usage_extension(const AuthorizationSet& tee_enforced, + const AuthorizationSet& sw_enforced, + X509* certificate) { + // Build BIT_STRING with correct contents. + ASN1_BIT_STRING_Ptr key_usage(ASN1_BIT_STRING_new()); + + for (size_t i = 0; i <= kMaxKeyUsageBit; ++i) { + if (!ASN1_BIT_STRING_set_bit(key_usage.get(), i, 0)) { + return TranslateLastOpenSslError(); + } + } + + if (tee_enforced.Contains(TAG_PURPOSE, KM_PURPOSE_SIGN) || + tee_enforced.Contains(TAG_PURPOSE, KM_PURPOSE_VERIFY) || + sw_enforced.Contains(TAG_PURPOSE, KM_PURPOSE_SIGN) || + sw_enforced.Contains(TAG_PURPOSE, KM_PURPOSE_VERIFY)) { + if (!ASN1_BIT_STRING_set_bit(key_usage.get(), kDigitalSignatureKeyUsageBit, 1)) { + return TranslateLastOpenSslError(); + } + } + + if (tee_enforced.Contains(TAG_PURPOSE, KM_PURPOSE_ENCRYPT) || + tee_enforced.Contains(TAG_PURPOSE, KM_PURPOSE_DECRYPT) || + sw_enforced.Contains(TAG_PURPOSE, KM_PURPOSE_ENCRYPT) || + sw_enforced.Contains(TAG_PURPOSE, KM_PURPOSE_DECRYPT)) { + if (!ASN1_BIT_STRING_set_bit(key_usage.get(), kKeyEnciphermentKeyUsageBit, 1) || + !ASN1_BIT_STRING_set_bit(key_usage.get(), kDataEnciphermentKeyUsageBit, 1)) { + return TranslateLastOpenSslError(); + } + } + + // Convert to octets + int len = i2d_ASN1_BIT_STRING(key_usage.get(), nullptr); + if (len < 0) { + return TranslateLastOpenSslError(); + } + UniquePtr<uint8_t[]> asn1_key_usage(new uint8_t[len]); + if (!asn1_key_usage.get()) { + return KM_ERROR_MEMORY_ALLOCATION_FAILED; + } + uint8_t* p = asn1_key_usage.get(); + len = i2d_ASN1_BIT_STRING(key_usage.get(), &p); + if (len < 0) { + return TranslateLastOpenSslError(); + } + + // Build OCTET_STRING + ASN1_OCTET_STRING_Ptr key_usage_str(ASN1_OCTET_STRING_new()); + if (!key_usage_str.get() || + !ASN1_OCTET_STRING_set(key_usage_str.get(), asn1_key_usage.get(), len)) { + return TranslateLastOpenSslError(); + } + + X509_EXTENSION_Ptr key_usage_extension(X509_EXTENSION_create_by_NID(nullptr, // + NID_key_usage, // + false /* critical */, + key_usage_str.get())); + if (!key_usage_extension.get()) { + return TranslateLastOpenSslError(); + } + + if (!X509_add_ext(certificate, key_usage_extension.get() /* Don't release; copied */, + -1 /* insert at end */)) { + return TranslateLastOpenSslError(); + } + + return KM_ERROR_OK; +} + } // anonymous namespace keymaster_error_t AsymmetricKey::formatted_key_material(keymaster_key_format_t format, @@ -249,7 +325,11 @@ keymaster_error_t AsymmetricKey::GenerateAttestation(const KeymasterContext& con !X509_set_notAfter(certificate.get(), notAfter.get() /* Don't release; copied */)) return TranslateLastOpenSslError(); - keymaster_error_t error = KM_ERROR_OK; + keymaster_error_t error = add_key_usage_extension(tee_enforced, sw_enforced, certificate.get()); + if (error != KM_ERROR_OK) { + return error; + } + EVP_PKEY_Ptr sign_key(context.AttestationKey(sign_algorithm, &error)); if (!sign_key.get() || // diff --git a/openssl_utils.h b/openssl_utils.h index 016aea8..dd22bdf 100644 --- a/openssl_utils.h +++ b/openssl_utils.h @@ -49,18 +49,19 @@ template <typename T, void (*FreeFunc)(T*)> struct OpenSslObjectDeleter { typedef OpenSslObjectDeleter<name, name##_free> name##_Delete; \ typedef UniquePtr<name, name##_Delete> name##_Ptr; +DEFINE_OPENSSL_OBJECT_POINTER(ASN1_BIT_STRING) DEFINE_OPENSSL_OBJECT_POINTER(ASN1_INTEGER) DEFINE_OPENSSL_OBJECT_POINTER(ASN1_OBJECT) DEFINE_OPENSSL_OBJECT_POINTER(ASN1_OCTET_STRING) DEFINE_OPENSSL_OBJECT_POINTER(ASN1_TIME) -DEFINE_OPENSSL_OBJECT_POINTER(BN_CTX); -DEFINE_OPENSSL_OBJECT_POINTER(EC_GROUP); -DEFINE_OPENSSL_OBJECT_POINTER(EC_KEY); -DEFINE_OPENSSL_OBJECT_POINTER(EC_POINT); -DEFINE_OPENSSL_OBJECT_POINTER(ENGINE); -DEFINE_OPENSSL_OBJECT_POINTER(EVP_PKEY); -DEFINE_OPENSSL_OBJECT_POINTER(PKCS8_PRIV_KEY_INFO); -DEFINE_OPENSSL_OBJECT_POINTER(RSA); +DEFINE_OPENSSL_OBJECT_POINTER(BN_CTX) +DEFINE_OPENSSL_OBJECT_POINTER(EC_GROUP) +DEFINE_OPENSSL_OBJECT_POINTER(EC_KEY) +DEFINE_OPENSSL_OBJECT_POINTER(EC_POINT) +DEFINE_OPENSSL_OBJECT_POINTER(ENGINE) +DEFINE_OPENSSL_OBJECT_POINTER(EVP_PKEY) +DEFINE_OPENSSL_OBJECT_POINTER(PKCS8_PRIV_KEY_INFO) +DEFINE_OPENSSL_OBJECT_POINTER(RSA) DEFINE_OPENSSL_OBJECT_POINTER(X509) DEFINE_OPENSSL_OBJECT_POINTER(X509_EXTENSION) DEFINE_OPENSSL_OBJECT_POINTER(X509_NAME) |