1 /*
2 **
3 ** Copyright 2018, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 ** http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18 #include "openssl_keymaster_enforcement.h"
19
20 #include <assert.h>
21 #include <inttypes.h>
22 #include <utility>
23
24 #include <openssl/cmac.h>
25 #include <openssl/evp.h>
26 #include <openssl/hmac.h>
27 #include <openssl/rand.h>
28
29 #include <keymaster/km_openssl/ckdf.h>
30 #include <keymaster/km_openssl/openssl_err.h>
31 #include <keymaster/km_openssl/openssl_utils.h>
32
33 #include <lib/hwkey/hwkey.h>
34
35 namespace keymaster {
36
37 namespace {
38
39 constexpr const char* kSharedHmacLabel = "KeymasterSharedMac";
40 constexpr const char* kMacVerificationString = "Keymaster HMAC Verification";
41 constexpr const char* kAuthVerificationLabel = "Auth Verification";
42
43 // Size (in bytes) of the HBK used for UNIQUE_ID generation.
44 static const int kUniqueIdHbkSize = 32;
45
46 // Label used for CKDF derivation of UNIQUE_ID HBK from KAK.
47 constexpr const char* kUniqueIdLabel = "UniqueID HBK 32B";
48
49 class EvpMdCtx {
50 public:
EvpMdCtx()51 EvpMdCtx() { EVP_MD_CTX_init(&ctx_); }
~EvpMdCtx()52 ~EvpMdCtx() { EVP_MD_CTX_cleanup(&ctx_); }
53
get()54 EVP_MD_CTX* get() { return &ctx_; }
55
56 private:
57 EVP_MD_CTX ctx_;
58 };
59
60 } // anonymous namespace
61
CreateKeyId(const keymaster_key_blob_t & key_blob,km_id_t * keyid) const62 bool OpenSSLKeymasterEnforcement::CreateKeyId(
63 const keymaster_key_blob_t& key_blob,
64 km_id_t* keyid) const {
65 EvpMdCtx ctx;
66
67 uint8_t hash[EVP_MAX_MD_SIZE];
68 unsigned int hash_len;
69 if (EVP_DigestInit_ex(ctx.get(), EVP_sha256(), nullptr /* ENGINE */) &&
70 EVP_DigestUpdate(ctx.get(), key_blob.key_material,
71 key_blob.key_material_size) &&
72 EVP_DigestFinal_ex(ctx.get(), hash, &hash_len)) {
73 assert(hash_len >= sizeof(*keyid));
74 memcpy(keyid, hash, sizeof(*keyid));
75 return true;
76 }
77
78 return false;
79 }
80
GetHmacSharingParameters(HmacSharingParameters * params)81 keymaster_error_t OpenSSLKeymasterEnforcement::GetHmacSharingParameters(
82 HmacSharingParameters* params) {
83 if (!have_saved_params_) {
84 saved_params_.seed = {};
85 RAND_bytes(saved_params_.nonce, 32);
86 have_saved_params_ = true;
87 }
88 params->seed = saved_params_.seed;
89 memcpy(params->nonce, saved_params_.nonce, sizeof(params->nonce));
90 return KM_ERROR_OK;
91 }
92
93 namespace {
94
95 DEFINE_OPENSSL_OBJECT_POINTER(HMAC_CTX);
96
hmacSha256(const keymaster_key_blob_t & key,const keymaster_blob_t data_chunks[],size_t data_chunk_count,KeymasterBlob * output)97 keymaster_error_t hmacSha256(const keymaster_key_blob_t& key,
98 const keymaster_blob_t data_chunks[],
99 size_t data_chunk_count,
100 KeymasterBlob* output) {
101 if (!output)
102 return KM_ERROR_UNEXPECTED_NULL_POINTER;
103
104 unsigned digest_len = SHA256_DIGEST_LENGTH;
105 if (!output->Reset(digest_len))
106 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
107
108 HMAC_CTX_Ptr ctx(HMAC_CTX_new());
109 if (!HMAC_Init_ex(ctx.get(), key.key_material, key.key_material_size,
110 EVP_sha256(), nullptr /* engine*/)) {
111 return TranslateLastOpenSslError();
112 }
113
114 for (size_t i = 0; i < data_chunk_count; i++) {
115 auto& chunk = data_chunks[i];
116 if (!HMAC_Update(ctx.get(), chunk.data, chunk.data_length)) {
117 return TranslateLastOpenSslError();
118 }
119 }
120
121 if (!HMAC_Final(ctx.get(), output->writable_data(), &digest_len)) {
122 return TranslateLastOpenSslError();
123 }
124
125 if (digest_len != output->data_length)
126 return KM_ERROR_UNKNOWN_ERROR;
127
128 return KM_ERROR_OK;
129 }
130
131 // Helpers for converting types to keymaster_blob_t, for easy feeding of
132 // hmacSha256.
133 template <typename T>
toBlob(const T & t)134 inline keymaster_blob_t toBlob(const T& t) {
135 return {reinterpret_cast<const uint8_t*>(&t), sizeof(t)};
136 }
toBlob(const char * str)137 inline keymaster_blob_t toBlob(const char* str) {
138 return {reinterpret_cast<const uint8_t*>(str), strlen(str)};
139 }
toBlob(const std::vector<uint8_t> & data)140 inline keymaster_blob_t toBlob(const std::vector<uint8_t>& data) {
141 return {data.data(), data.size()};
142 }
143
144 // Perhaps these shoud be in utils, but the impact of that needs to be
145 // considered carefully. For now, just define it here.
operator ==(const keymaster_blob_t & a,const keymaster_blob_t & b)146 inline bool operator==(const keymaster_blob_t& a, const keymaster_blob_t& b) {
147 if (!a.data_length && !b.data_length)
148 return true;
149 if (!(a.data && b.data))
150 return a.data == b.data;
151 return (a.data_length == b.data_length &&
152 !memcmp(a.data, b.data, a.data_length));
153 }
154
operator ==(const HmacSharingParameters & a,const HmacSharingParameters & b)155 bool operator==(const HmacSharingParameters& a,
156 const HmacSharingParameters& b) {
157 return a.seed == b.seed && !memcmp(a.nonce, b.nonce, sizeof(a.nonce));
158 }
159
160 } // namespace
161
ComputeSharedHmac(const HmacSharingParametersArray & params_array,KeymasterBlob * sharingCheck)162 keymaster_error_t OpenSSLKeymasterEnforcement::ComputeSharedHmac(
163 const HmacSharingParametersArray& params_array,
164 KeymasterBlob* sharingCheck) {
165 KeymasterKeyBlob kak;
166 keymaster_error_t kakError = GetKeyAgreementKey(&kak);
167 if (kakError != KM_ERROR_OK) {
168 return kakError;
169 }
170
171 size_t num_chunks = params_array.num_params * 2;
172 UniquePtr<keymaster_blob_t[]> context_chunks(
173 new (std::nothrow) keymaster_blob_t[num_chunks]);
174 if (!context_chunks.get())
175 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
176
177 bool found_mine = false;
178 auto context_chunks_pos = context_chunks.get();
179 for (auto& params :
180 array_range(params_array.params_array, params_array.num_params)) {
181 *context_chunks_pos++ = params.seed;
182 *context_chunks_pos++ = {params.nonce, sizeof(params.nonce)};
183 found_mine = found_mine || params == saved_params_;
184 }
185 assert(context_chunks_pos - num_chunks == context_chunks.get());
186
187 if (!found_mine)
188 return KM_ERROR_INVALID_ARGUMENT;
189
190 if (!hmac_key_.Reset(SHA256_DIGEST_LENGTH))
191 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
192 keymaster_error_t error = ckdf(
193 std::move(kak),
194 KeymasterBlob(reinterpret_cast<const uint8_t*>(kSharedHmacLabel),
195 strlen(kSharedHmacLabel)),
196 context_chunks.get(), num_chunks, //
197 &hmac_key_);
198 if (error != KM_ERROR_OK)
199 return error;
200
201 keymaster_blob_t data = {
202 reinterpret_cast<const uint8_t*>(kMacVerificationString),
203 strlen(kMacVerificationString)};
204 keymaster_blob_t data_chunks[] = {data};
205 return hmacSha256(hmac_key_, data_chunks, 1, sharingCheck);
206 }
207
VerifyAuthorization(const VerifyAuthorizationRequest & request)208 VerifyAuthorizationResponse OpenSSLKeymasterEnforcement::VerifyAuthorization(
209 const VerifyAuthorizationRequest& request) {
210 // The only thing this implementation provides is timestamp and security
211 // level. Note that this is an acceptable implementation strategy for
212 // production use as well. Additional verification need only be provided by
213 // an implementation if it is interoperating with another implementation
214 // that requires more.
215 VerifyAuthorizationResponse response(request.message_version);
216 response.token.challenge = request.challenge;
217 response.token.timestamp = get_current_time_ms();
218 response.token.security_level = SecurityLevel();
219 keymaster_blob_t data_chunks[] = {
220 toBlob(kAuthVerificationLabel),
221 toBlob(response.token.challenge),
222 toBlob(response.token.timestamp),
223 toBlob(response.token.security_level),
224 {}, // parametersVerified
225 };
226 response.error = hmacSha256(hmac_key_, data_chunks, 5, &response.token.mac);
227
228 return response;
229 }
230
GetKeyAgreementKey(KeymasterKeyBlob * kak) const231 keymaster_error_t OpenSSLKeymasterEnforcement::GetKeyAgreementKey(
232 KeymasterKeyBlob* kak) const {
233 uint32_t keySize = kKeyAgreementKeySize;
234
235 if (!kak->Reset(keySize)) {
236 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
237 }
238
239 int rc = hwkey_open();
240 if (rc < 0) {
241 LOG_E("Failed to connect to hwkey: %d", rc);
242 return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
243 }
244 hwkey_session_t hwkey_session = (hwkey_session_t)rc;
245
246 rc = hwkey_get_keyslot_data(hwkey_session, "com.android.trusty.keymint.kak",
247 kak->writable_data(), &keySize);
248
249 hwkey_close(hwkey_session);
250
251 if (rc < 0) {
252 LOG_E("Getting KAK failed.\n");
253 return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
254 }
255
256 if (keySize != kKeyAgreementKeySize) {
257 LOG_E("KAK has the wrong size: %" PRIu32 " != %zu.\n", keySize,
258 kKeyAgreementKeySize);
259 return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
260 }
261
262 return KM_ERROR_OK;
263 }
264
ComputeHmac(const std::vector<uint8_t> & data_to_mac) const265 KmErrorOr<std::array<uint8_t, 32>> OpenSSLKeymasterEnforcement::ComputeHmac(
266 const std::vector<uint8_t>& data_to_mac) const {
267 keymaster_blob_t data_chunks[] = {toBlob(data_to_mac)};
268 KeymasterBlob mac;
269 auto error = hmacSha256(hmac_key_, data_chunks, 1, &mac);
270 if (error != KM_ERROR_OK) {
271 return error;
272 }
273
274 std::array<uint8_t, 32> retval;
275 if (mac.size() != retval.size()) {
276 return KM_ERROR_UNKNOWN_ERROR;
277 }
278 std::copy(mac.begin(), mac.end(), retval.begin());
279 return retval;
280 }
281
GetHmacKey(keymaster_key_blob_t * key) const282 keymaster_error_t OpenSSLKeymasterEnforcement::GetHmacKey(
283 keymaster_key_blob_t* key) const {
284 if ((key == nullptr) || (key->key_material == nullptr)) {
285 return KM_ERROR_UNEXPECTED_NULL_POINTER;
286 }
287
288 if (hmac_key_.key_material_size != SHA256_DIGEST_LENGTH) {
289 return KM_ERROR_INVALID_ARGUMENT;
290 }
291
292 memcpy((void*)key->key_material, hmac_key_.key_material,
293 hmac_key_.key_material_size);
294 key->key_material_size = hmac_key_.key_material_size;
295
296 return KM_ERROR_OK;
297 }
298
GetUniqueIdKey(KeymasterKeyBlob * key) const299 keymaster_error_t OpenSSLKeymasterEnforcement::GetUniqueIdKey(
300 KeymasterKeyBlob* key) const {
301 // Derive a unique ID HBK from the key agreement key.
302 KeymasterKeyBlob kak;
303 keymaster_error_t kakError = GetKeyAgreementKey(&kak);
304 if (kakError != KM_ERROR_OK) {
305 return kakError;
306 }
307 if (!key->Reset(kUniqueIdHbkSize)) {
308 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
309 }
310
311 return ckdf(std::move(kak),
312 KeymasterBlob(reinterpret_cast<const uint8_t*>(kUniqueIdLabel),
313 strlen(kUniqueIdLabel)),
314 nullptr, 0, key);
315 }
316
317 } // namespace keymaster
318