From 2beb628bfefae72fa6bb84a6235da7e3de532823 Mon Sep 17 00:00:00 2001 From: Shawn Willden Date: Wed, 20 May 2015 16:36:24 -0600 Subject: Delegate RSA keys to keymaster0 in SoftKeymasterDevice. Bug: 20912868 Change-Id: I515a125f1247357d2cd9b4633c3b223590848093 --- integrity_assured_key_blob.cpp | 128 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 integrity_assured_key_blob.cpp (limited to 'integrity_assured_key_blob.cpp') diff --git a/integrity_assured_key_blob.cpp b/integrity_assured_key_blob.cpp new file mode 100644 index 0000000..1376cff --- /dev/null +++ b/integrity_assured_key_blob.cpp @@ -0,0 +1,128 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "integrity_assured_key_blob.h" + +#include + +#include +#include + +#include +#include + +#include "openssl_err.h" + +namespace keymaster { + +static const uint8_t BLOB_VERSION = 0; +static const size_t HMAC_SIZE = 8; +static const char HMAC_KEY[] = "IntegrityAssuredBlob0"; + +inline size_t min(size_t a, size_t b) { + if (a < b) + return a; + return b; +} + +class HmacCleanup { + public: + HmacCleanup(HMAC_CTX* ctx) : ctx_(ctx) {} + ~HmacCleanup() { HMAC_CTX_cleanup(ctx_); } + + private: + HMAC_CTX* ctx_; +}; + +keymaster_error_t ComputeHmac(const uint8_t* serialized_data, size_t serialized_data_size, + const AuthorizationSet& hidden, uint8_t hmac[HMAC_SIZE]) { + size_t hidden_bytes_size = hidden.SerializedSize(); + UniquePtr hidden_bytes(new uint8_t[hidden_bytes_size]); + hidden.Serialize(hidden_bytes.get(), hidden_bytes.get() + hidden_bytes_size); + + HMAC_CTX ctx; + HMAC_CTX_init(&ctx); + const EVP_MD* md = EVP_sha256(); + if (!HMAC_Init_ex(&ctx, HMAC_KEY, sizeof(HMAC_KEY), md, NULL /* engine */)) + return TranslateLastOpenSslError(); + HmacCleanup cleanup(&ctx); + + uint8_t tmp[EVP_MAX_MD_SIZE]; + unsigned tmp_len; + if (!HMAC_Update(&ctx, serialized_data, serialized_data_size) || + !HMAC_Update(&ctx, hidden_bytes.get(), hidden_bytes_size) || // + !HMAC_Final(&ctx, tmp, &tmp_len)) + return TranslateLastOpenSslError(); + + assert(tmp_len >= HMAC_SIZE); + memcpy(hmac, tmp, min(HMAC_SIZE, tmp_len)); + + return KM_ERROR_OK; +} + +keymaster_error_t SerializeIntegrityAssuredBlob(const KeymasterKeyBlob& key_material, + const AuthorizationSet& hidden, + const AuthorizationSet& hw_enforced, + const AuthorizationSet& sw_enforced, + KeymasterKeyBlob* key_blob) { + size_t size = 1 /* version */ + // + key_material.SerializedSize() + // + hw_enforced.SerializedSize() + // + sw_enforced.SerializedSize() + // + HMAC_SIZE; + + if (!key_blob->Reset(size)) + return KM_ERROR_MEMORY_ALLOCATION_FAILED; + + uint8_t* p = key_blob->writable_data(); + *p++ = BLOB_VERSION; + p = key_material.Serialize(p, key_blob->end()); + p = hw_enforced.Serialize(p, key_blob->end()); + p = sw_enforced.Serialize(p, key_blob->end()); + + return ComputeHmac(key_blob->key_material, p - key_blob->key_material, hidden, p); +} + +keymaster_error_t DeserializeIntegrityAssuredBlob(const KeymasterKeyBlob& key_blob, + const AuthorizationSet& hidden, + KeymasterKeyBlob* key_material, + AuthorizationSet* hw_enforced, + AuthorizationSet* sw_enforced) { + const uint8_t* p = key_blob.begin(); + const uint8_t* end = key_blob.end(); + + uint8_t computed_hmac[HMAC_SIZE]; + keymaster_error_t error = ComputeHmac(key_blob.begin(), key_blob.key_material_size - HMAC_SIZE, + hidden, computed_hmac); + if (error != KM_ERROR_OK) + return error; + + if (CRYPTO_memcmp(key_blob.end() - HMAC_SIZE, computed_hmac, HMAC_SIZE) != 0) + return KM_ERROR_INVALID_KEY_BLOB; + + if (*p != BLOB_VERSION) + return KM_ERROR_INVALID_KEY_BLOB; + ++p; + + if (!key_material->Deserialize(&p, end) || // + !hw_enforced->Deserialize(&p, end) || // + !sw_enforced->Deserialize(&p, end)) + return KM_ERROR_INVALID_KEY_BLOB; + + return KM_ERROR_OK; +} + +} // namespace keymaster; -- cgit v1.2.3