1 /*
2 * Copyright 2021 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 "trusty_aes_key.h"
18
19 #include <utility>
20
21 #include <assert.h>
22
23 #include <keymaster/logger.h>
24
25 #include <lib/hwwsk/client.h>
26 #include <lib/tipc/tipc.h>
27 #include <uapi/err.h>
28
29 namespace keymaster {
30
get_hwwsk_chan(void) const31 handle_t TrustyAesKeyFactory::get_hwwsk_chan(void) const {
32 handle_t hchan;
33
34 if (hwwsk_chan_ == INVALID_IPC_HANDLE) {
35 // open new connection
36 int rc = tipc_connect(&hchan, HWWSK_PORT);
37 if (rc < 0) {
38 LOG_E("HWWSK: connect failed (%d)", rc);
39 return (handle_t)rc;
40 }
41 hwwsk_chan_ = hchan;
42 }
43 return hwwsk_chan_;
44 }
45
reset_hwwsk_chan(void) const46 void TrustyAesKeyFactory::reset_hwwsk_chan(void) const {
47 if (hwwsk_chan_ != INVALID_IPC_HANDLE) {
48 close(hwwsk_chan_);
49 hwwsk_chan_ = INVALID_IPC_HANDLE;
50 }
51 }
52
CreateHwStorageKeyBlob(const AuthorizationSet & key_description,const KeymasterKeyBlob & input_key_material,KeymasterKeyBlob * output_key_blob,AuthorizationSet * hw_enforced,AuthorizationSet * sw_enforced) const53 keymaster_error_t TrustyAesKeyFactory::CreateHwStorageKeyBlob(
54 const AuthorizationSet& key_description,
55 const KeymasterKeyBlob& input_key_material,
56 KeymasterKeyBlob* output_key_blob,
57 AuthorizationSet* hw_enforced,
58 AuthorizationSet* sw_enforced) const {
59 int rc;
60 handle_t hchan;
61 uint32_t key_size;
62 uint32_t key_flags;
63 uint8_t sk_blob[HWWSK_MAX_MSG_SIZE];
64
65 if (!output_key_blob || !hw_enforced || !sw_enforced) {
66 return KM_ERROR_OUTPUT_PARAMETER_NULL;
67 }
68
69 // If there is a TAG_BLOCK_MODE reject such request.
70 //
71 // Hw wrapped storage key is not intended to work for normal
72 // SW encryption/decryption operations. Removing supported
73 // block mode tag effectively achieves that.
74 //
75 if (key_description.find(TAG_BLOCK_MODE) != -1) {
76 LOG_E("HWWSK: unsupported tag");
77 return KM_ERROR_UNSUPPORTED_TAG;
78 }
79
80 // Get requested key size
81 if (!key_description.GetTagValue(TAG_KEY_SIZE, &key_size)) {
82 LOG_E("HWWSK: missing key size tag");
83 return KM_ERROR_UNSUPPORTED_KEY_SIZE;
84 }
85
86 // HWWSK service handle
87 hchan = get_hwwsk_chan();
88 if (hchan < 0) {
89 return KM_ERROR_UNKNOWN_ERROR;
90 }
91
92 // Build key flags
93 key_flags = 0;
94 if (key_description.GetTagValue(TAG_ROLLBACK_RESISTANCE)) {
95 key_flags |= HWWSK_FLAGS_ROLLBACK_RESISTANCE;
96 }
97
98 // call server to generate hardware wrapped key blob
99 rc = hwwsk_generate_key(hchan, sk_blob, sizeof(sk_blob), key_size,
100 key_flags, input_key_material.key_material,
101 input_key_material.key_material_size);
102 if (rc < 0) {
103 if (rc == ERR_NOT_SUPPORTED &&
104 (key_flags & HWWSK_FLAGS_ROLLBACK_RESISTANCE)) {
105 key_flags &= ~HWWSK_FLAGS_ROLLBACK_RESISTANCE;
106 rc = hwwsk_generate_key(hchan, sk_blob, sizeof(sk_blob), key_size,
107 key_flags, input_key_material.key_material,
108 input_key_material.key_material_size);
109 }
110 if (rc < 0) {
111 if (rc != ERR_NOT_SUPPORTED) {
112 // Reset IPC connection for any error other then
113 // ERR_NOT_SUPPORTED
114 reset_hwwsk_chan();
115 }
116 LOG_E("HWWSK: generate key blob failed(%d)", rc);
117 return KM_ERROR_UNKNOWN_ERROR;
118 }
119 }
120
121 KeymasterKeyBlob hwwsk_key_blob(sk_blob, rc);
122
123 // wrap it with keymaster
124 keymaster_key_origin_t key_origin = input_key_material.key_material_size
125 ? KM_ORIGIN_IMPORTED
126 : KM_ORIGIN_GENERATED;
127
128 return blob_maker_.CreateKeyBlob(key_description, key_origin,
129 hwwsk_key_blob, output_key_blob,
130 hw_enforced, sw_enforced);
131 }
132
GenerateKey(const AuthorizationSet & key_description,UniquePtr<Key>,const KeymasterBlob &,KeymasterKeyBlob * output_key_blob,AuthorizationSet * hw_enforced,AuthorizationSet * sw_enforced,CertificateChain * cert_chain) const133 keymaster_error_t TrustyAesKeyFactory::GenerateKey(
134 const AuthorizationSet& key_description,
135 UniquePtr<Key> /* attestation_signing_key */,
136 const KeymasterBlob& /* issuer_subject */,
137 KeymasterKeyBlob* output_key_blob,
138 AuthorizationSet* hw_enforced,
139 AuthorizationSet* sw_enforced,
140 CertificateChain* cert_chain) const {
141 if (key_description.GetTagValue(TAG_STORAGE_KEY)) {
142 #if WITH_HWWSK_SUPPORT
143 KeymasterKeyBlob input_key_material; // no input data
144
145 return CreateHwStorageKeyBlob(key_description, input_key_material,
146 output_key_blob, hw_enforced,
147 sw_enforced);
148 #else
149 return KM_ERROR_UNSUPPORTED_TAG;
150 #endif
151 }
152
153 return AesKeyFactory::GenerateKey(key_description,
154 {} /* attestation_signing_key */,
155 {} /* issuer_subject */, output_key_blob,
156 hw_enforced, sw_enforced, cert_chain);
157 }
158
ImportKey(const AuthorizationSet & key_description,keymaster_key_format_t input_key_material_format,const KeymasterKeyBlob & input_key_material,UniquePtr<Key>,const KeymasterBlob &,KeymasterKeyBlob * output_key_blob,AuthorizationSet * hw_enforced,AuthorizationSet * sw_enforced,CertificateChain * cert_chain) const159 keymaster_error_t TrustyAesKeyFactory::ImportKey(
160 const AuthorizationSet& key_description,
161 keymaster_key_format_t input_key_material_format,
162 const KeymasterKeyBlob& input_key_material,
163 UniquePtr<Key> /* attestation_signing_key */,
164 const KeymasterBlob& /* issuer_subject */,
165 KeymasterKeyBlob* output_key_blob,
166 AuthorizationSet* hw_enforced,
167 AuthorizationSet* sw_enforced,
168 CertificateChain* cert_chain) const {
169 if (key_description.GetTagValue(TAG_STORAGE_KEY)) {
170 #if WITH_HWWSK_SUPPORT
171 // We expect input data in RAW format
172 if (input_key_material_format != KM_KEY_FORMAT_RAW) {
173 return KM_ERROR_UNSUPPORTED_KEY_FORMAT;
174 }
175
176 return CreateHwStorageKeyBlob(key_description, input_key_material,
177 output_key_blob, hw_enforced,
178 sw_enforced);
179 #else
180 return KM_ERROR_UNSUPPORTED_TAG;
181 #endif
182 }
183
184 return AesKeyFactory::ImportKey(
185 key_description, input_key_material_format, input_key_material,
186 {} /* attestation_signing_key */, {} /* issuer_subject */,
187 output_key_blob, hw_enforced, sw_enforced, cert_chain);
188 }
189
LoadKey(KeymasterKeyBlob && key_material,const AuthorizationSet & additional_params,AuthorizationSet && hw_enforced,AuthorizationSet && sw_enforced,UniquePtr<Key> * key) const190 keymaster_error_t TrustyAesKeyFactory::LoadKey(
191 KeymasterKeyBlob&& key_material,
192 const AuthorizationSet& additional_params,
193 AuthorizationSet&& hw_enforced,
194 AuthorizationSet&& sw_enforced,
195 UniquePtr<Key>* key) const {
196 if (hw_enforced.GetTagValue(TAG_STORAGE_KEY)) {
197 #if WITH_HWWSK_SUPPORT
198 // for storage key
199
200 if (!key) {
201 return KM_ERROR_OUTPUT_PARAMETER_NULL;
202 }
203
204 // If there is a TAG_BLOCK_MODE reject such key
205 if ((hw_enforced.find(TAG_BLOCK_MODE) != -1) ||
206 (sw_enforced.find(TAG_BLOCK_MODE) != -1)) {
207 return KM_ERROR_UNSUPPORTED_TAG;
208 }
209
210 key->reset(new (std::nothrow)
211 HwStorageKey(std::move(key_material), std::move(hw_enforced),
212 std::move(sw_enforced), this));
213 if (!key->get()) {
214 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
215 }
216
217 return KM_ERROR_OK;
218 #else
219 return KM_ERROR_UNSUPPORTED_TAG;
220 #endif
221 }
222
223 return AesKeyFactory::LoadKey(std::move(key_material), additional_params,
224 std::move(hw_enforced), std::move(sw_enforced), key);
225 }
226
formatted_key_material(keymaster_key_format_t fmt,UniquePtr<uint8_t[]> * material,size_t * sz) const227 keymaster_error_t HwStorageKey::formatted_key_material(
228 keymaster_key_format_t fmt,
229 UniquePtr<uint8_t[]>* material,
230 size_t* sz) const {
231 int rc;
232 handle_t hchan;
233
234 if (fmt != KM_KEY_FORMAT_RAW) {
235 return KM_ERROR_UNSUPPORTED_KEY_FORMAT;
236 }
237
238 material->reset(new (std::nothrow) uint8_t[HWWSK_MAX_MSG_SIZE]);
239
240 if (material->get() == nullptr) {
241 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
242 }
243
244 // get HWWSK service handle
245 hchan = ((TrustyAesKeyFactory*)key_factory())->get_hwwsk_chan();
246 if (hchan < 0) {
247 return KM_ERROR_UNKNOWN_ERROR;
248 }
249
250 rc = hwwsk_export_key(hchan, material->get(), HWWSK_MAX_MSG_SIZE,
251 key_material_.key_material,
252 key_material_.key_material_size);
253 if (rc < 0) {
254 if (rc != ERR_NOT_SUPPORTED) {
255 // Reset IPC connection for any error other then ERR_NOT_SUPPORTED
256 ((TrustyAesKeyFactory*)key_factory())->reset_hwwsk_chan();
257 }
258 LOG_E("HWWSK: export key failed (%d)", rc);
259 return KM_ERROR_UNKNOWN_ERROR;
260 }
261
262 *sz = (size_t)rc;
263
264 return KM_ERROR_OK;
265 }
266
267 } // namespace keymaster
268