• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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