• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/auth_encrypted_key_blob.h>
18 
19 #include <openssl/digest.h>
20 #include <openssl/evp.h>
21 #include <openssl/hkdf.h>
22 
23 #include <keymaster/android_keymaster_utils.h>
24 #include <keymaster/authorization_set.h>
25 #include <keymaster/key_blob_utils/ocb_utils.h>
26 #include <keymaster/km_openssl/openssl_err.h>
27 #include <keymaster/logger.h>
28 #include <keymaster/random_source.h>
29 
30 namespace keymaster {
31 
32 namespace {
33 
34 constexpr uint8_t kAesGcmDescriptor1[] = "AES-256-GCM-HKDF-SHA-256, version 1";
35 constexpr uint8_t kAesGcmDescriptor2[] = "AES-256-GCM-HKDF-SHA-256, version 2";
36 constexpr size_t kAesGcmNonceLength = 12;
37 constexpr size_t kAesGcmTagLength = 16;
38 constexpr size_t kAes256KeyLength = 256 / 8;
39 
generate_nonce(const RandomSource & random,size_t size)40 KmErrorOr<Buffer> generate_nonce(const RandomSource& random, size_t size) {
41     Buffer nonce;
42     if (!nonce.Reinitialize(size)) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
43 
44     random.GenerateRandom(nonce.peek_write(), size);
45     nonce.advance_write(size);
46     return nonce;
47 }
48 
BuildDerivationInfo(const AuthEncryptedBlobFormat format,const AuthorizationSet & hw_enforced,const AuthorizationSet & sw_enforced,const AuthorizationSet & hidden,const SecureDeletionData & secure_deletion_data)49 KmErrorOr<Buffer> BuildDerivationInfo(const AuthEncryptedBlobFormat format,  //
50                                       const AuthorizationSet& hw_enforced,   //
51                                       const AuthorizationSet& sw_enforced,   //
52                                       const AuthorizationSet& hidden,
53                                       const SecureDeletionData& secure_deletion_data) {
54     bool use_sdd = requiresSecureDeletion(format);
55 
56     size_t info_len =
57         hidden.SerializedSize() + hw_enforced.SerializedSize() + sw_enforced.SerializedSize();
58     if (use_sdd) {
59         info_len += sizeof(kAesGcmDescriptor2) +
60                     secure_deletion_data.factory_reset_secret.SerializedSize() +
61                     secure_deletion_data.secure_deletion_secret.SerializedSize() +
62                     sizeof(secure_deletion_data.key_slot);
63     } else {
64         info_len += sizeof(kAesGcmDescriptor1);
65     }
66 
67     Buffer info(info_len);
68     info.write(use_sdd ? kAesGcmDescriptor2 : kAesGcmDescriptor1);
69     uint8_t* buf = info.peek_write();
70     const uint8_t* end = info.peek_write() + info.available_write();
71     buf = hidden.Serialize(buf, end);
72     buf = hw_enforced.Serialize(buf, end);
73     buf = sw_enforced.Serialize(buf, end);
74 
75     if (use_sdd) {
76         buf = secure_deletion_data.factory_reset_secret.Serialize(buf, end);
77         buf = secure_deletion_data.secure_deletion_secret.Serialize(buf, end);
78         static_assert(std::is_same_v<decltype(secure_deletion_data.key_slot), uint32_t>);
79         buf = append_uint32_to_buf(buf, end, secure_deletion_data.key_slot);
80     }
81 
82     if (!buf || buf != end || !info.advance_write(buf - info.peek_write())) {
83         LOG_S("Buffer management error", 0);
84         return KM_ERROR_UNKNOWN_ERROR;
85     }
86 
87     return info;
88 }
89 
DeriveAesGcmKeyEncryptionKey(const AuthEncryptedBlobFormat format,const AuthorizationSet & hw_enforced,const AuthorizationSet & sw_enforced,const AuthorizationSet & hidden,const SecureDeletionData & secure_deletion_data,const KeymasterKeyBlob & master_key)90 KmErrorOr<Buffer> DeriveAesGcmKeyEncryptionKey(const AuthEncryptedBlobFormat format,            //
91                                                const AuthorizationSet& hw_enforced,             //
92                                                const AuthorizationSet& sw_enforced,             //
93                                                const AuthorizationSet& hidden,                  //
94                                                const SecureDeletionData& secure_deletion_data,  //
95                                                const KeymasterKeyBlob& master_key) {
96     Buffer prk(EVP_MAX_MD_SIZE);
97     size_t out_len = EVP_MAX_MD_SIZE;
98     if (!HKDF_extract(prk.peek_write(), &out_len, EVP_sha256(), master_key.key_material,
99                       master_key.key_material_size, nullptr /* salt */, 0 /* salt_len */)) {
100         return TranslateLastOpenSslError();
101     }
102 
103     KmErrorOr<Buffer> info =
104         BuildDerivationInfo(format, hw_enforced, sw_enforced, hidden, secure_deletion_data);
105     if (!info) return info.error();
106 
107     if (!prk.advance_write(out_len) || !prk.available_read() || !info->available_read()) {
108         return KM_ERROR_UNKNOWN_ERROR;
109     }
110 
111     Buffer keyEncryptionKey(kAes256KeyLength);
112     if (!HKDF_expand(keyEncryptionKey.peek_write(), keyEncryptionKey.available_write(),  //
113                      EVP_sha256(),                                                       //
114                      prk.peek_read(), prk.available_read(),                              //
115                      info->peek_read(), info->available_read())) {
116         return TranslateLastOpenSslError();
117     }
118 
119     return keyEncryptionKey;
120 }
121 
AesGcmEncryptKey(const AuthorizationSet & hw_enforced,const AuthorizationSet & sw_enforced,const AuthorizationSet & hidden,const SecureDeletionData & secure_deletion_data,const KeymasterKeyBlob & master_key,const KeymasterKeyBlob & plaintext,const AuthEncryptedBlobFormat format,Buffer nonce)122 KmErrorOr<EncryptedKey> AesGcmEncryptKey(const AuthorizationSet& hw_enforced,             //
123                                          const AuthorizationSet& sw_enforced,             //
124                                          const AuthorizationSet& hidden,                  //
125                                          const SecureDeletionData& secure_deletion_data,  //
126                                          const KeymasterKeyBlob& master_key,              //
127                                          const KeymasterKeyBlob& plaintext,               //
128                                          const AuthEncryptedBlobFormat format,            //
129                                          Buffer nonce) {
130     KmErrorOr<Buffer> kek = DeriveAesGcmKeyEncryptionKey(format, hw_enforced, sw_enforced, hidden,
131                                                          secure_deletion_data, master_key);
132     if (!kek) return kek.error();
133 
134     bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
135     if (!ctx) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
136 
137     int ciphertext_len = plaintext.size();
138     int unused_len = 0;
139     EncryptedKey retval;
140     retval.format = format;
141     retval.ciphertext = KeymasterKeyBlob(ciphertext_len);
142     retval.nonce = move(nonce);
143     retval.tag = Buffer(kAesGcmTagLength);
144 
145     if (!(EVP_EncryptInit_ex(ctx.get(), EVP_aes_256_gcm(), nullptr /* engine */, kek->peek_read(),
146                              retval.nonce.peek_read()) &&
147           EVP_EncryptUpdate(ctx.get(), retval.ciphertext.writable_data(), &ciphertext_len,
148                             plaintext.key_material, plaintext.size()) &&
149           EVP_EncryptFinal_ex(ctx.get(), retval.ciphertext.writable_data() /* not written to */,
150                               &unused_len) &&
151           EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_GET_TAG, kAesGcmTagLength,
152                               retval.tag.peek_write()))) {
153         return TranslateLastOpenSslError();
154     }
155 
156     if (plaintext.size() != static_cast<size_t>(ciphertext_len) || 0 != unused_len ||
157         !retval.tag.advance_write(kAesGcmTagLength)) {
158         return KM_ERROR_UNKNOWN_ERROR;
159     }
160 
161     return retval;
162 }
163 
AesGcmDecryptKey(const DeserializedKey & key,const AuthorizationSet & hidden,const SecureDeletionData & secure_deletion_data,const KeymasterKeyBlob & master_key)164 KmErrorOr<KeymasterKeyBlob> AesGcmDecryptKey(const DeserializedKey& key,
165                                              const AuthorizationSet& hidden,
166                                              const SecureDeletionData& secure_deletion_data,
167                                              const KeymasterKeyBlob& master_key) {
168     KmErrorOr<Buffer> kek =
169         DeriveAesGcmKeyEncryptionKey(key.encrypted_key.format, key.hw_enforced, key.sw_enforced,
170                                      hidden, secure_deletion_data, master_key);
171     if (!kek) return kek.error();
172 
173     bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
174     if (!ctx) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
175 
176     int plaintext_len = key.encrypted_key.ciphertext.size();
177     int unused_len = 0;
178     KeymasterKeyBlob plaintext(plaintext_len);
179     if (!(EVP_DecryptInit_ex(ctx.get(), EVP_aes_256_gcm(), nullptr /* engine */, kek->peek_read(),
180                              key.encrypted_key.nonce.peek_read()) &&
181           EVP_DecryptUpdate(ctx.get(), plaintext.writable_data(), &plaintext_len,
182                             key.encrypted_key.ciphertext.key_material,
183                             key.encrypted_key.ciphertext.size()) &&
184           EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_TAG, kAesGcmTagLength,
185                               const_cast<uint8_t*>(key.encrypted_key.tag.peek_read())))) {
186         return TranslateLastOpenSslError();
187     }
188 
189     if (!EVP_DecryptFinal_ex(ctx.get(), plaintext.writable_data() /* not written to */,
190                              &unused_len)) {
191         return KM_ERROR_INVALID_KEY_BLOB;
192     }
193 
194     if (key.encrypted_key.ciphertext.size() != plaintext.size() || 0 != unused_len) {
195         return KM_ERROR_UNKNOWN_ERROR;
196     }
197 
198     return plaintext;
199 }
200 
201 }  // namespace
202 
SerializeAuthEncryptedBlob(const EncryptedKey & encrypted_key,const AuthorizationSet & hw_enforced,const AuthorizationSet & sw_enforced,uint32_t key_slot)203 KmErrorOr<KeymasterKeyBlob> SerializeAuthEncryptedBlob(const EncryptedKey& encrypted_key,
204                                                        const AuthorizationSet& hw_enforced,
205                                                        const AuthorizationSet& sw_enforced,
206                                                        uint32_t key_slot) {
207     bool use_key_slot = requiresSecureDeletion(encrypted_key.format);
208 
209     size_t size = 1 /* version byte */ + encrypted_key.nonce.SerializedSize() +
210                   encrypted_key.ciphertext.SerializedSize() + encrypted_key.tag.SerializedSize() +
211                   hw_enforced.SerializedSize() + sw_enforced.SerializedSize();
212     if (use_key_slot) size += sizeof(key_slot);
213     if (isVersionedFormat(encrypted_key.format)) {
214         size += sizeof(encrypted_key.kdf_version);
215         size += sizeof(encrypted_key.addl_info);
216     }
217     KeymasterKeyBlob retval;
218     if (!retval.Reset(size)) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
219 
220     uint8_t* buf = retval.writable_data();
221     const uint8_t* end = retval.end();
222 
223     *buf++ = encrypted_key.format;
224     buf = encrypted_key.nonce.Serialize(buf, end);
225     buf = encrypted_key.ciphertext.Serialize(buf, end);
226     buf = encrypted_key.tag.Serialize(buf, end);
227     if (isVersionedFormat(encrypted_key.format)) {
228         buf = append_uint32_to_buf(buf, end, encrypted_key.kdf_version);
229         buf = append_uint32_to_buf(buf, end, encrypted_key.addl_info);
230     }
231     buf = hw_enforced.Serialize(buf, end);
232     buf = sw_enforced.Serialize(buf, end);
233     if (use_key_slot) buf = append_uint32_to_buf(buf, end, key_slot);
234 
235     if (buf != retval.end()) return KM_ERROR_UNKNOWN_ERROR;
236 
237     return retval;
238 }
239 
DeserializeAuthEncryptedBlob(const KeymasterKeyBlob & key_blob)240 KmErrorOr<DeserializedKey> DeserializeAuthEncryptedBlob(const KeymasterKeyBlob& key_blob) {
241     if (!key_blob.key_material || key_blob.key_material_size == 0) return KM_ERROR_INVALID_KEY_BLOB;
242 
243     const uint8_t* tmp = key_blob.key_material;
244     const uint8_t** buf_ptr = &tmp;
245     const uint8_t* end = tmp + key_blob.key_material_size;
246 
247     if (end <= *buf_ptr) return KM_ERROR_INVALID_KEY_BLOB;
248 
249     DeserializedKey retval{};
250     retval.encrypted_key.format = static_cast<AuthEncryptedBlobFormat>(*(*buf_ptr)++);
251     if (!retval.encrypted_key.nonce.Deserialize(buf_ptr, end) ||       //
252         !retval.encrypted_key.ciphertext.Deserialize(buf_ptr, end) ||  //
253         !retval.encrypted_key.tag.Deserialize(buf_ptr, end)) {
254         return KM_ERROR_INVALID_KEY_BLOB;
255     }
256 
257     if (isVersionedFormat(retval.encrypted_key.format)) {
258         if (!copy_uint32_from_buf(buf_ptr, end, &retval.encrypted_key.kdf_version) ||
259             !copy_uint32_from_buf(buf_ptr, end, &retval.encrypted_key.addl_info)) {
260             return KM_ERROR_INVALID_KEY_BLOB;
261         }
262     }
263 
264     if (!retval.hw_enforced.Deserialize(buf_ptr, end) ||  //
265         !retval.sw_enforced.Deserialize(buf_ptr, end)) {
266         return KM_ERROR_INVALID_KEY_BLOB;
267     }
268 
269     if (requiresSecureDeletion(retval.encrypted_key.format)) {
270         if (!copy_uint32_from_buf(buf_ptr, end, &retval.key_slot)) {
271             return KM_ERROR_INVALID_KEY_BLOB;
272         }
273     }
274 
275     if (*buf_ptr != end) return KM_ERROR_INVALID_KEY_BLOB;
276 
277     switch (retval.encrypted_key.format) {
278     case AES_OCB:
279         if (retval.encrypted_key.nonce.available_read() != OCB_NONCE_LENGTH ||
280             retval.encrypted_key.tag.available_read() != OCB_TAG_LENGTH) {
281             return KM_ERROR_INVALID_KEY_BLOB;
282         }
283         return retval;
284 
285     case AES_GCM_WITH_SW_ENFORCED:
286     case AES_GCM_WITH_SECURE_DELETION:
287     case AES_GCM_WITH_SW_ENFORCED_VERSIONED:
288     case AES_GCM_WITH_SECURE_DELETION_VERSIONED:
289         if (retval.encrypted_key.nonce.available_read() != kAesGcmNonceLength ||
290             retval.encrypted_key.tag.available_read() != kAesGcmTagLength) {
291             return KM_ERROR_INVALID_KEY_BLOB;
292         }
293         return retval;
294     }
295 
296     LOG_E("Invalid key blob format %d", retval.encrypted_key.format);
297     return KM_ERROR_INVALID_KEY_BLOB;
298 }
299 
300 KmErrorOr<EncryptedKey>
EncryptKey(const KeymasterKeyBlob & plaintext,AuthEncryptedBlobFormat format,const AuthorizationSet & hw_enforced,const AuthorizationSet & sw_enforced,const AuthorizationSet & hidden,const SecureDeletionData & secure_deletion_data,const KeymasterKeyBlob & master_key,const RandomSource & random)301 EncryptKey(const KeymasterKeyBlob& plaintext, AuthEncryptedBlobFormat format,
302            const AuthorizationSet& hw_enforced, const AuthorizationSet& sw_enforced,
303            const AuthorizationSet& hidden, const SecureDeletionData& secure_deletion_data,
304            const KeymasterKeyBlob& master_key, const RandomSource& random) {
305     switch (format) {
306     case AES_OCB: {
307         EncryptedKey retval;
308         retval.format = format;
309         auto nonce = generate_nonce(random, OCB_NONCE_LENGTH);
310         if (!nonce) return nonce.error();
311         retval.nonce = std::move(*nonce);
312         retval.tag.Reinitialize(OCB_TAG_LENGTH);
313         keymaster_error_t error =
314             OcbEncryptKey(hw_enforced, sw_enforced, hidden, master_key, plaintext, retval.nonce,
315                           &retval.ciphertext, &retval.tag);
316         if (error != KM_ERROR_OK) return error;
317         return retval;
318     }
319 
320     case AES_GCM_WITH_SW_ENFORCED:
321     case AES_GCM_WITH_SECURE_DELETION:
322     case AES_GCM_WITH_SW_ENFORCED_VERSIONED:
323     case AES_GCM_WITH_SECURE_DELETION_VERSIONED: {
324         auto nonce = generate_nonce(random, kAesGcmNonceLength);
325         if (!nonce) return nonce.error();
326         return AesGcmEncryptKey(hw_enforced, sw_enforced, hidden, secure_deletion_data, master_key,
327                                 plaintext, format, std::move(*nonce));
328     }
329     }
330 
331     LOG_E("Invalid key blob format %d", format);
332     return KM_ERROR_UNKNOWN_ERROR;
333 }
334 
DecryptKey(const DeserializedKey & key,const AuthorizationSet & hidden,const SecureDeletionData & secure_deletion_data,const KeymasterKeyBlob & master_key)335 KmErrorOr<KeymasterKeyBlob> DecryptKey(const DeserializedKey& key, const AuthorizationSet& hidden,
336                                        const SecureDeletionData& secure_deletion_data,
337                                        const KeymasterKeyBlob& master_key) {
338     KeymasterKeyBlob retval;
339     switch (key.encrypted_key.format) {
340     case AES_OCB: {
341         keymaster_error_t error = OcbDecryptKey(
342             key.hw_enforced, key.sw_enforced, hidden, master_key, key.encrypted_key.ciphertext,
343             key.encrypted_key.nonce, key.encrypted_key.tag, &retval);
344         if (error != KM_ERROR_OK) return error;
345         return retval;
346     }
347 
348     case AES_GCM_WITH_SW_ENFORCED:
349     case AES_GCM_WITH_SECURE_DELETION:
350     case AES_GCM_WITH_SW_ENFORCED_VERSIONED:
351     case AES_GCM_WITH_SECURE_DELETION_VERSIONED:
352         return AesGcmDecryptKey(key, hidden, secure_deletion_data, master_key);
353     }
354 
355     LOG_E("Invalid key blob format %d", key.encrypted_key.format);
356     return KM_ERROR_INVALID_KEY_BLOB;
357 }
358 
requiresSecureDeletion(const AuthEncryptedBlobFormat & fmt)359 bool requiresSecureDeletion(const AuthEncryptedBlobFormat& fmt) {
360     return fmt == AES_GCM_WITH_SECURE_DELETION || fmt == AES_GCM_WITH_SECURE_DELETION_VERSIONED;
361 }
362 
isVersionedFormat(const AuthEncryptedBlobFormat & fmt)363 bool isVersionedFormat(const AuthEncryptedBlobFormat& fmt) {
364     return fmt == AES_GCM_WITH_SW_ENFORCED_VERSIONED ||
365            fmt == AES_GCM_WITH_SECURE_DELETION_VERSIONED;
366 }
367 
368 }  // namespace keymaster
369