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 <keymaster/key_blob_utils/integrity_assured_key_blob.h>
18
19 #include <assert.h>
20
21 #include <openssl/hmac.h>
22 #include <openssl/mem.h>
23
24 #include <keymaster/android_keymaster_utils.h>
25 #include <keymaster/authorization_set.h>
26 #include <keymaster/km_openssl/openssl_err.h>
27 #include <keymaster/new.h>
28
29 namespace keymaster {
30
31 static const uint8_t BLOB_VERSION = 0;
32 static const size_t HMAC_SIZE = 8;
33 static const char HMAC_KEY[] = "IntegrityAssuredBlob0";
34
min(size_t a,size_t b)35 inline size_t min(size_t a, size_t b) {
36 if (a < b)
37 return a;
38 return b;
39 }
40
41 class HmacCleanup {
42 public:
HmacCleanup(HMAC_CTX * ctx)43 explicit HmacCleanup(HMAC_CTX* ctx) : ctx_(ctx) {}
~HmacCleanup()44 ~HmacCleanup() { HMAC_CTX_cleanup(ctx_); }
45
46 private:
47 HMAC_CTX* ctx_;
48 };
49
ComputeHmac(const uint8_t * serialized_data,size_t serialized_data_size,const AuthorizationSet & hidden,uint8_t hmac[HMAC_SIZE])50 static keymaster_error_t ComputeHmac(const uint8_t* serialized_data, size_t serialized_data_size,
51 const AuthorizationSet& hidden, uint8_t hmac[HMAC_SIZE]) {
52 size_t hidden_bytes_size = hidden.SerializedSize();
53 UniquePtr<uint8_t[]> hidden_bytes(new (std::nothrow) uint8_t[hidden_bytes_size]);
54 if (!hidden_bytes.get())
55 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
56 hidden.Serialize(hidden_bytes.get(), hidden_bytes.get() + hidden_bytes_size);
57
58 HMAC_CTX ctx;
59 HMAC_CTX_init(&ctx);
60 const EVP_MD* md = EVP_sha256();
61 if (!HMAC_Init_ex(&ctx, HMAC_KEY, sizeof(HMAC_KEY), md, nullptr /* engine */))
62 return TranslateLastOpenSslError();
63 HmacCleanup cleanup(&ctx);
64
65 uint8_t tmp[EVP_MAX_MD_SIZE];
66 unsigned tmp_len;
67 if (!HMAC_Update(&ctx, serialized_data, serialized_data_size) ||
68 !HMAC_Update(&ctx, hidden_bytes.get(), hidden_bytes_size) || //
69 !HMAC_Final(&ctx, tmp, &tmp_len))
70 return TranslateLastOpenSslError();
71
72 assert(tmp_len >= HMAC_SIZE);
73 memcpy(hmac, tmp, min(HMAC_SIZE, tmp_len));
74
75 return KM_ERROR_OK;
76 }
77
SerializeIntegrityAssuredBlob(const KeymasterKeyBlob & key_material,const AuthorizationSet & hidden,const AuthorizationSet & hw_enforced,const AuthorizationSet & sw_enforced,KeymasterKeyBlob * key_blob)78 keymaster_error_t SerializeIntegrityAssuredBlob(const KeymasterKeyBlob& key_material,
79 const AuthorizationSet& hidden,
80 const AuthorizationSet& hw_enforced,
81 const AuthorizationSet& sw_enforced,
82 KeymasterKeyBlob* key_blob) {
83 size_t size = 1 /* version */ + //
84 key_material.SerializedSize() + //
85 hw_enforced.SerializedSize() + //
86 sw_enforced.SerializedSize() + //
87 HMAC_SIZE;
88
89 if (!key_blob->Reset(size))
90 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
91
92 uint8_t* p = key_blob->writable_data();
93 *p++ = BLOB_VERSION;
94 p = key_material.Serialize(p, key_blob->end());
95 p = hw_enforced.Serialize(p, key_blob->end());
96 p = sw_enforced.Serialize(p, key_blob->end());
97
98 return ComputeHmac(key_blob->key_material, p - key_blob->key_material, hidden, p);
99 }
100
DeserializeIntegrityAssuredBlob(const KeymasterKeyBlob & key_blob,const AuthorizationSet & hidden,KeymasterKeyBlob * key_material,AuthorizationSet * hw_enforced,AuthorizationSet * sw_enforced)101 keymaster_error_t DeserializeIntegrityAssuredBlob(const KeymasterKeyBlob& key_blob,
102 const AuthorizationSet& hidden,
103 KeymasterKeyBlob* key_material,
104 AuthorizationSet* hw_enforced,
105 AuthorizationSet* sw_enforced) {
106 const uint8_t* p = key_blob.begin();
107 const uint8_t* end = key_blob.end();
108
109 if (p > end || p + HMAC_SIZE > end)
110 return KM_ERROR_INVALID_KEY_BLOB;
111
112 uint8_t computed_hmac[HMAC_SIZE];
113 keymaster_error_t error = ComputeHmac(key_blob.begin(), key_blob.key_material_size - HMAC_SIZE,
114 hidden, computed_hmac);
115 if (error != KM_ERROR_OK)
116 return error;
117
118 if (CRYPTO_memcmp(key_blob.end() - HMAC_SIZE, computed_hmac, HMAC_SIZE) != 0)
119 return KM_ERROR_INVALID_KEY_BLOB;
120
121 return DeserializeIntegrityAssuredBlob_NoHmacCheck(key_blob, key_material, hw_enforced,
122 sw_enforced);
123 }
124
DeserializeIntegrityAssuredBlob_NoHmacCheck(const KeymasterKeyBlob & key_blob,KeymasterKeyBlob * key_material,AuthorizationSet * hw_enforced,AuthorizationSet * sw_enforced)125 keymaster_error_t DeserializeIntegrityAssuredBlob_NoHmacCheck(const KeymasterKeyBlob& key_blob,
126 KeymasterKeyBlob* key_material,
127 AuthorizationSet* hw_enforced,
128 AuthorizationSet* sw_enforced) {
129 const uint8_t* p = key_blob.begin();
130 const uint8_t* end = key_blob.end() - HMAC_SIZE;
131
132 if (p > end)
133 return KM_ERROR_INVALID_KEY_BLOB;
134
135 if (*p != BLOB_VERSION)
136 return KM_ERROR_INVALID_KEY_BLOB;
137 ++p;
138
139 if (!key_material->Deserialize(&p, end) || //
140 !hw_enforced->Deserialize(&p, end) || //
141 !sw_enforced->Deserialize(&p, end))
142 return KM_ERROR_INVALID_KEY_BLOB;
143
144 return KM_ERROR_OK;
145 }
146
147 } // namespace keymaster;
148