1 /* 2 * Copyright 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "integrity_assured_key_blob.h" 18 19 #include <assert.h> 20 21 #include <new> 22 23 #include <openssl/hmac.h> 24 #include <openssl/mem.h> 25 26 #include <keymaster/android_keymaster_utils.h> 27 #include <keymaster/authorization_set.h> 28 29 #include "openssl_err.h" 30 31 namespace keymaster { 32 33 static const uint8_t BLOB_VERSION = 0; 34 static const size_t HMAC_SIZE = 8; 35 static const char HMAC_KEY[] = "IntegrityAssuredBlob0"; 36 37 inline size_t min(size_t a, size_t b) { 38 if (a < b) 39 return a; 40 return b; 41 } 42 43 class HmacCleanup { 44 public: 45 explicit HmacCleanup(HMAC_CTX* ctx) : ctx_(ctx) {} 46 ~HmacCleanup() { HMAC_CTX_cleanup(ctx_); } 47 48 private: 49 HMAC_CTX* ctx_; 50 }; 51 52 static keymaster_error_t ComputeHmac(const uint8_t* serialized_data, size_t serialized_data_size, 53 const AuthorizationSet& hidden, uint8_t hmac[HMAC_SIZE]) { 54 size_t hidden_bytes_size = hidden.SerializedSize(); 55 UniquePtr<uint8_t[]> hidden_bytes(new (std::nothrow) uint8_t[hidden_bytes_size]); 56 if (!hidden_bytes.get()) 57 return KM_ERROR_MEMORY_ALLOCATION_FAILED; 58 hidden.Serialize(hidden_bytes.get(), hidden_bytes.get() + hidden_bytes_size); 59 60 HMAC_CTX ctx; 61 HMAC_CTX_init(&ctx); 62 const EVP_MD* md = EVP_sha256(); 63 if (!HMAC_Init_ex(&ctx, HMAC_KEY, sizeof(HMAC_KEY), md, NULL /* engine */)) 64 return TranslateLastOpenSslError(); 65 HmacCleanup cleanup(&ctx); 66 67 uint8_t tmp[EVP_MAX_MD_SIZE]; 68 unsigned tmp_len; 69 if (!HMAC_Update(&ctx, serialized_data, serialized_data_size) || 70 !HMAC_Update(&ctx, hidden_bytes.get(), hidden_bytes_size) || // 71 !HMAC_Final(&ctx, tmp, &tmp_len)) 72 return TranslateLastOpenSslError(); 73 74 assert(tmp_len >= HMAC_SIZE); 75 memcpy(hmac, tmp, min(HMAC_SIZE, tmp_len)); 76 77 return KM_ERROR_OK; 78 } 79 80 keymaster_error_t SerializeIntegrityAssuredBlob(const KeymasterKeyBlob& key_material, 81 const AuthorizationSet& hidden, 82 const AuthorizationSet& hw_enforced, 83 const AuthorizationSet& sw_enforced, 84 KeymasterKeyBlob* key_blob) { 85 size_t size = 1 /* version */ + // 86 key_material.SerializedSize() + // 87 hw_enforced.SerializedSize() + // 88 sw_enforced.SerializedSize() + // 89 HMAC_SIZE; 90 91 if (!key_blob->Reset(size)) 92 return KM_ERROR_MEMORY_ALLOCATION_FAILED; 93 94 uint8_t* p = key_blob->writable_data(); 95 *p++ = BLOB_VERSION; 96 p = key_material.Serialize(p, key_blob->end()); 97 p = hw_enforced.Serialize(p, key_blob->end()); 98 p = sw_enforced.Serialize(p, key_blob->end()); 99 100 return ComputeHmac(key_blob->key_material, p - key_blob->key_material, hidden, p); 101 } 102 103 keymaster_error_t DeserializeIntegrityAssuredBlob(const KeymasterKeyBlob& key_blob, 104 const AuthorizationSet& hidden, 105 KeymasterKeyBlob* key_material, 106 AuthorizationSet* hw_enforced, 107 AuthorizationSet* sw_enforced) { 108 const uint8_t* p = key_blob.begin(); 109 const uint8_t* end = key_blob.end(); 110 111 if (p > end || p + HMAC_SIZE > end) 112 return KM_ERROR_INVALID_KEY_BLOB; 113 114 uint8_t computed_hmac[HMAC_SIZE]; 115 keymaster_error_t error = ComputeHmac(key_blob.begin(), key_blob.key_material_size - HMAC_SIZE, 116 hidden, computed_hmac); 117 if (error != KM_ERROR_OK) 118 return error; 119 120 if (CRYPTO_memcmp(key_blob.end() - HMAC_SIZE, computed_hmac, HMAC_SIZE) != 0) 121 return KM_ERROR_INVALID_KEY_BLOB; 122 123 return DeserializeIntegrityAssuredBlob_NoHmacCheck(key_blob, key_material, hw_enforced, 124 sw_enforced); 125 } 126 127 keymaster_error_t DeserializeIntegrityAssuredBlob_NoHmacCheck(const KeymasterKeyBlob& key_blob, 128 KeymasterKeyBlob* key_material, 129 AuthorizationSet* hw_enforced, 130 AuthorizationSet* sw_enforced) { 131 const uint8_t* p = key_blob.begin(); 132 const uint8_t* end = key_blob.end() - HMAC_SIZE; 133 134 if (p > end) 135 return KM_ERROR_INVALID_KEY_BLOB; 136 137 if (*p != BLOB_VERSION) 138 return KM_ERROR_INVALID_KEY_BLOB; 139 ++p; 140 141 if (!key_material->Deserialize(&p, end) || // 142 !hw_enforced->Deserialize(&p, end) || // 143 !sw_enforced->Deserialize(&p, end)) 144 return KM_ERROR_INVALID_KEY_BLOB; 145 146 return KM_ERROR_OK; 147 } 148 149 } // namespace keymaster; 150