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