blob: 655bc12760e6ef75141765002a50e9e0095029c0 [file] [log] [blame]
Shawn Willden0cb69422015-05-26 08:31:37 -06001/*
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 "auth_encrypted_key_blob.h"
18
19#include <keymaster/android_keymaster_utils.h>
20#include <keymaster/authorization_set.h>
21#include <keymaster/logger.h>
22
23#include "ocb_utils.h"
24
25namespace keymaster {
26
27const uint32_t CURRENT_BLOB_VERSION = 0;
28
29keymaster_error_t SerializeAuthEncryptedBlob(const KeymasterKeyBlob& encrypted_key_material,
30 const AuthorizationSet& hw_enforced,
31 const AuthorizationSet& sw_enforced,
32
33 const Buffer& nonce, const Buffer& tag,
34 KeymasterKeyBlob* key_blob) {
35 size_t size = 1 /* version byte */ + nonce.SerializedSize() +
36 encrypted_key_material.SerializedSize() + tag.SerializedSize() +
37 hw_enforced.SerializedSize() + sw_enforced.SerializedSize();
38
39 if (!key_blob->Reset(size))
40 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
41
42 uint8_t* buf = key_blob->writable_data();
43 const uint8_t* end = key_blob->key_material + key_blob->key_material_size;
44
45 *buf++ = CURRENT_BLOB_VERSION;
46 buf = nonce.Serialize(buf, end);
47 buf = encrypted_key_material.Serialize(buf, end);
48 buf = tag.Serialize(buf, end);
49 buf = hw_enforced.Serialize(buf, end);
50 buf = sw_enforced.Serialize(buf, end);
51 if (buf != key_blob->key_material + key_blob->key_material_size)
52 return KM_ERROR_UNKNOWN_ERROR;
53
54 return KM_ERROR_OK;
55}
56
Shawn Willdenc7fe06d2015-06-11 15:50:04 -060057static keymaster_error_t DeserializeUnversionedBlob(const KeymasterKeyBlob& key_blob,
58 KeymasterKeyBlob* encrypted_key_material,
59 AuthorizationSet* hw_enforced,
60 AuthorizationSet* sw_enforced, Buffer* nonce,
61 Buffer* tag) {
62 const uint8_t* tmp = key_blob.key_material;
63 const uint8_t** buf_ptr = &tmp;
64 const uint8_t* end = tmp + key_blob.key_material_size;
65
66 if (!nonce->reserve(OCB_NONCE_LENGTH) || !tag->reserve(OCB_TAG_LENGTH))
67 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
68
69 if (!copy_from_buf(buf_ptr, end, nonce->peek_write(), OCB_NONCE_LENGTH) ||
70 !encrypted_key_material->Deserialize(buf_ptr, end) ||
71 !copy_from_buf(buf_ptr, end, tag->peek_write(), OCB_TAG_LENGTH) ||
72 !hw_enforced->Deserialize(buf_ptr, end) || //
73 !sw_enforced->Deserialize(buf_ptr, end)) {
Shawn Willden2612fb52015-07-27 16:58:30 -060074 LOG_D("Failed to deserialize unversioned blob (may be a HW-backed key)", 0);
Shawn Willdenc7fe06d2015-06-11 15:50:04 -060075 return KM_ERROR_INVALID_KEY_BLOB;
76 }
Shawn Willden0f906ec2015-06-20 09:16:30 -060077 if (!nonce->advance_write(OCB_NONCE_LENGTH) || !tag->advance_write(OCB_TAG_LENGTH))
78 return KM_ERROR_UNKNOWN_ERROR;
Shawn Willdenc7fe06d2015-06-11 15:50:04 -060079 return KM_ERROR_OK;
80}
81
Shawn Willden0cb69422015-05-26 08:31:37 -060082keymaster_error_t DeserializeAuthEncryptedBlob(const KeymasterKeyBlob& key_blob,
83 KeymasterKeyBlob* encrypted_key_material,
84 AuthorizationSet* hw_enforced,
85 AuthorizationSet* sw_enforced, Buffer* nonce,
86 Buffer* tag) {
Shawn Willden0f906ec2015-06-20 09:16:30 -060087 if (!key_blob.key_material || key_blob.key_material_size == 0)
88 return KM_ERROR_INVALID_KEY_BLOB;
89
Shawn Willden0cb69422015-05-26 08:31:37 -060090 const uint8_t* tmp = key_blob.key_material;
91 const uint8_t** buf_ptr = &tmp;
92 const uint8_t* end = tmp + key_blob.key_material_size;
93
Shawn Willden0f906ec2015-06-20 09:16:30 -060094 if (end <= *buf_ptr)
95 return KM_ERROR_INVALID_KEY_BLOB;
96
Shawn Willden0cb69422015-05-26 08:31:37 -060097 uint8_t version = *(*buf_ptr)++;
98 if (version != CURRENT_BLOB_VERSION || //
99 !nonce->Deserialize(buf_ptr, end) || nonce->available_read() != OCB_NONCE_LENGTH ||
100 !encrypted_key_material->Deserialize(buf_ptr, end) || //
101 !tag->Deserialize(buf_ptr, end) || tag->available_read() != OCB_TAG_LENGTH ||
102 !hw_enforced->Deserialize(buf_ptr, end) || //
Shawn Willdenc7fe06d2015-06-11 15:50:04 -0600103 !sw_enforced->Deserialize(buf_ptr, end)) {
104 // This blob failed to parse. Either it's corrupted or it's a blob generated by an earlier
105 // version of keymaster using a previous blob format which did not include the version byte
106 // or the nonce or tag length fields. So we try to parse it as that previous version.
107 //
108 // Note that it's not really a problem if we erronously parse a corrupted blob, because
109 // decryption will fail the authentication check.
110 //
111 // A bigger potential problem is: What if a valid unversioned blob appears to parse
112 // correctly as a versioned blob? It would then be rejected during decryption, causing a
113 // valid key to become unusable. If this is a disk encryption key, upgrading to a keymaster
114 // version with the new format would destroy the user's data.
115 //
116 // What is the probability that an unversioned key could be successfully parsed as a version
117 // 0 key? The first 12 bytes of an unversioned key are the nonce, which, in the only
118 // keymaster version released with unversioned keys, is chosen randomly. In order for an
119 // unversioned key to parse as a version 0 key, the following must be true about the first
120 // five of those random bytes:
121 //
122 // 1. The first byte must be zero. This will happen with probability 1/2^8.
123 //
124 // 2. The second through fifth bytes must contain an unsigned integer value equal to
125 // NONCE_LENGTH. This will happen with probability 1/2^32.
126 //
127 // Based on those two checks alone, the probability of interpreting an unversioned blob as a
128 // version 0 blob is 1/2^40. That's small enough to be negligible, but there are additional
129 // checks which lower it further.
Shawn Willden2612fb52015-07-27 16:58:30 -0600130 LOG_D("Failed to deserialize versioned key blob. Assuming unversioned.", 0);
Shawn Willdenc7fe06d2015-06-11 15:50:04 -0600131 return DeserializeUnversionedBlob(key_blob, encrypted_key_material, hw_enforced,
132 sw_enforced, nonce, tag);
133 }
Shawn Willden0cb69422015-05-26 08:31:37 -0600134 return KM_ERROR_OK;
135}
136
137} // namespace keymaster