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