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