summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Willden <swillden@google.com>2016-05-02 23:36:36 +0000
committerandroid-build-merger <android-build-merger@google.com>2016-05-02 23:36:36 +0000
commit431dcfa4ec20c75c7b6d48c31b15f6b09e4b00fd (patch)
treea6d387fa4f1542d270ac642bb8a86ae49b7c2904
parentc262f8001fd2cf6c692d9b5d5f97f3dffb17b9f6 (diff)
parentd487dc9e95162f249048bd31d4191a0d50b77496 (diff)
downloadandroid_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.cpp82
-rw-r--r--openssl_utils.h17
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)