1 /*
2 * Copyright 2017 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 "import_key.h"
18 #include "proto_utils.h"
19
20 #include <android-base/logging.h>
21
22 #include <openssl/ec.h>
23 #include <openssl/evp.h>
24 #include <openssl/mem.h>
25 #include <openssl/rsa.h>
26 #include <openssl/pkcs8.h>
27
28 namespace android {
29 namespace hardware {
30 namespace keymaster {
31
32 // HAL
33 using ::android::hardware::keymaster::V4_0::Algorithm;
34 using ::android::hardware::keymaster::V4_0::EcCurve;
35 using ::android::hardware::keymaster::V4_0::KeyFormat;
36 using ::android::hardware::keymaster::V4_0::Tag;
37 using ::android::hardware::keymaster::V4_0::TagType;
38
39 // App
40 using ::nugget::app::keymaster::ECKey;
41
42 // BoringSSL
43 using bssl::UniquePtr;
44
45 // std
46 using std::unique_ptr;
47
evp_from_pkcs8_bytes(const uint8_t * bytes,size_t len)48 static EVP_PKEY *evp_from_pkcs8_bytes(const uint8_t *bytes, size_t len)
49 {
50 bssl::UniquePtr<PKCS8_PRIV_KEY_INFO> pkcs8(
51 d2i_PKCS8_PRIV_KEY_INFO(NULL, &bytes, len));
52 if (pkcs8.get() == NULL) {
53 // Translate error.
54 return nullptr;
55 }
56
57 return EVP_PKCS82PKEY(pkcs8.get());
58 }
59
import_key_rsa(const tag_map_t & params,const hidl_vec<uint8_t> & keyData,ImportKeyRequest * request)60 static ErrorCode import_key_rsa(const tag_map_t& params,
61 const hidl_vec<uint8_t>& keyData,
62 ImportKeyRequest *request)
63 {
64 const uint32_t *keySize = nullptr;
65 if (params.find(Tag::KEY_SIZE) != params.end()) {
66 const vector<KeyParameter>& v = params.find(Tag::KEY_SIZE)->second;
67 keySize = &v[0].f.integer;
68 }
69 const uint64_t *publicExponent = nullptr;
70 if (params.find(Tag::RSA_PUBLIC_EXPONENT) != params.end()) {
71 const vector<KeyParameter>& v =
72 params.find(Tag::RSA_PUBLIC_EXPONENT)->second;
73 publicExponent = &v[0].f.longInteger;
74 }
75
76 bssl::UniquePtr<EVP_PKEY> pkey;
77 pkey.reset(evp_from_pkcs8_bytes(&keyData[0], keyData.size()));
78 if (pkey.get() == nullptr) {
79 // Parse error.
80 LOG(ERROR) << "ImportKey request: failed to parse PKCS8";
81 return ErrorCode::INVALID_ARGUMENT;
82 }
83
84 const RSA *rsa = EVP_PKEY_get0_RSA(pkey.get());
85 if (rsa == nullptr) {
86 LOG(ERROR) << "ImportKey request: PKCS8 key is not RSA";
87 return ErrorCode::INVALID_ARGUMENT;
88 }
89
90 size_t parsedKeySize = RSA_size(rsa) * 8;
91 if (keySize != nullptr && parsedKeySize != *keySize) {
92 // If specified, key size must match the PKCS8 blob.
93 LOG(ERROR) << "ImportKey request: key size parameter mis-match";
94 return ErrorCode::IMPORT_PARAMETER_MISMATCH;
95 }
96
97 const BIGNUM *n;
98 const BIGNUM *e;
99 const BIGNUM *d;
100 RSA_get0_key(rsa, &n, &e, &d);
101 if (publicExponent != nullptr && BN_get_word(e) != *publicExponent) {
102 // If specified, the public exponent must match the PKCS8 blob.
103 LOG(ERROR) << "ImportKey request: invalid publicExponent tag: "
104 << *publicExponent
105 << " expected: "
106 << BN_get_word(e);
107 return ErrorCode::IMPORT_PARAMETER_MISMATCH;
108 }
109
110 // Key data may be invalid, and will be validated on the device
111 // anyway, so avoid duplicate work here.
112
113 // Public exponent.
114 request->mutable_rsa()->set_e(BN_get_word(e));
115
116 // Private exponent, zero-pad upto size of n.
117 bssl::UniquePtr<uint8_t> d_buf(
118 reinterpret_cast<uint8_t *>(OPENSSL_malloc(BN_num_bytes(n))));
119 if (!BN_bn2le_padded(d_buf.get(), BN_num_bytes(n), d)) {
120 LOG(ERROR) << "ImportKey request: bn2le failed";
121 return ErrorCode::UNKNOWN_ERROR;
122 }
123 request->mutable_rsa()->set_d(d_buf.get(), BN_num_bytes(n));
124
125 // Modulus.
126 bssl::UniquePtr<uint8_t> n_buf(
127 reinterpret_cast<uint8_t *>(OPENSSL_malloc(BN_num_bytes(n))));
128 if (!BN_bn2le_padded(n_buf.get(), BN_num_bytes(n), n)) {
129 LOG(ERROR) << "ImportKey request: bn2le_padded failed";
130 return ErrorCode::UNKNOWN_ERROR;
131 }
132 request->mutable_rsa()->set_n(n_buf.get(), BN_num_bytes(n));
133
134 return ErrorCode::OK;
135 }
136
import_key_ec(const tag_map_t & params,const hidl_vec<uint8_t> & keyData,ImportKeyRequest * request)137 static ErrorCode import_key_ec(const tag_map_t& params,
138 const hidl_vec<uint8_t>& keyData,
139 ImportKeyRequest *request)
140 {
141 const EcCurve *curve_id = nullptr;
142 if (params.find(Tag::EC_CURVE) != params.end()) {
143 const vector<KeyParameter>& v = params.find(Tag::EC_CURVE)->second;
144 curve_id = &v[0].f.ecCurve;
145 }
146 const uint32_t *key_size = nullptr;
147 if (params.find(Tag::KEY_SIZE) != params.end()) {
148 const vector<KeyParameter>& v = params.find(Tag::KEY_SIZE)->second;
149 key_size = &v[0].f.integer;
150 }
151
152 bssl::UniquePtr<EVP_PKEY> pkey;
153 pkey.reset(evp_from_pkcs8_bytes(&keyData[0], keyData.size()));
154 if (pkey.get() == nullptr) {
155 // Parse error.
156 LOG(ERROR) << "ImportKey request: failed to parse PKCS8";
157 return ErrorCode::INVALID_ARGUMENT;
158 }
159
160 const EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey.get());
161 if (ec_key == nullptr) {
162 LOG(ERROR) << "ImportKey request: PKCS8 key is not EC";
163 return ErrorCode::INVALID_ARGUMENT;
164 }
165
166 EcCurve parsed_curve_id;
167 size_t parsed_key_size;
168 const EC_GROUP *group = EC_KEY_get0_group(ec_key);
169 switch (EC_GROUP_get_curve_name(group)) {
170 case NID_secp224r1:
171 parsed_curve_id = EcCurve::P_224;
172 parsed_key_size = 224;
173 break;
174 case NID_X9_62_prime256v1:
175 parsed_curve_id = EcCurve::P_256;
176 parsed_key_size = 256;
177 break;
178 case NID_secp384r1:
179 parsed_curve_id = EcCurve::P_384;
180 parsed_key_size = 384;
181 break;
182 case NID_secp521r1:
183 parsed_curve_id = EcCurve::P_521;
184 parsed_key_size = 521;
185 break;
186 default:
187 // Unsupported curve.
188 return ErrorCode::INVALID_ARGUMENT;
189 }
190
191 if (curve_id != nullptr && *curve_id != parsed_curve_id) {
192 // Parameter mis-match.
193 LOG(ERROR) << "ImportKey: curve-id does not match PKCS8";
194 return ErrorCode::IMPORT_PARAMETER_MISMATCH;
195 }
196 if (key_size != nullptr && *key_size != parsed_key_size) {
197 // Parameter mis-match.
198 LOG(ERROR) << "ImportKey: key-size does not match PKCS8";
199 return ErrorCode::IMPORT_PARAMETER_MISMATCH;
200 }
201
202 const BIGNUM *d = EC_KEY_get0_private_key(ec_key);
203 const EC_POINT *pub_key = EC_KEY_get0_public_key(ec_key);
204 bssl::UniquePtr<BIGNUM> x(BN_new());
205 bssl::UniquePtr<BIGNUM> y(BN_new());
206
207 if (!EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec_key),
208 pub_key, x.get(), y.get(), NULL)) {
209 LOG(ERROR) << "ImportKey: failed to get public key in affine coordinates";
210 return ErrorCode::INVALID_ARGUMENT;
211 }
212
213 // Key data may be invalid, and will be validated on the device
214 // anyway, so avoid duplicate work here.
215
216 // Curve parameter.
217 request->mutable_ec()->set_curve_id((uint32_t)parsed_curve_id);
218
219 // Private key.
220 const size_t field_size = (parsed_key_size + 7) >> 3;
221 unique_ptr<uint8_t[]> d_buf(new uint8_t[field_size]);
222 if (!BN_bn2le_padded(d_buf.get(), field_size, d)) {
223 LOG(ERROR) << "ImportKey request: bn2le(d) failed";
224 return ErrorCode::UNKNOWN_ERROR;
225 }
226 request->mutable_ec()->set_d(d_buf.get(), field_size);
227
228 // Public key.
229 unique_ptr<uint8_t[]> x_buf(new uint8_t[field_size]);
230 if (!BN_bn2le_padded(x_buf.get(), field_size, x.get())) {
231 LOG(ERROR) << "ImportKey request: bn2le(x) failed";
232 return ErrorCode::UNKNOWN_ERROR;
233 }
234 request->mutable_ec()->set_x(x_buf.get(), field_size);
235
236 unique_ptr<uint8_t[]> y_buf(new uint8_t[field_size]);
237 if (!BN_bn2le_padded(y_buf.get(), field_size, y.get())) {
238 LOG(ERROR) << "ImportKey request: bn2le(y) failed";
239 return ErrorCode::UNKNOWN_ERROR;
240 }
241 request->mutable_ec()->set_y(y_buf.get(), field_size);
242
243 return ErrorCode::OK;
244 }
245
import_key_raw(const tag_map_t & params,Algorithm algorithm,const hidl_vec<uint8_t> & keyData,ImportKeyRequest * request)246 static ErrorCode import_key_raw(const tag_map_t& params,
247 Algorithm algorithm,
248 const hidl_vec<uint8_t>& keyData,
249 ImportKeyRequest *request)
250 {
251 if (algorithm != Algorithm::AES && algorithm != Algorithm::TRIPLE_DES &&
252 algorithm != Algorithm::HMAC) {
253 LOG(ERROR) << "ImportKey request: unsupported algorithm";
254 return ErrorCode::UNSUPPORTED_ALGORITHM;
255 }
256
257 const uint32_t *key_size = nullptr;
258 if (params.find(Tag::KEY_SIZE) != params.end()) {
259 const vector<KeyParameter>& v = params.find(Tag::KEY_SIZE)->second;
260 key_size = &v[0].f.integer;
261 }
262
263 if (algorithm != Algorithm::TRIPLE_DES) {
264 if (key_size != nullptr && *key_size != keyData.size() * 8) {
265 LOG(ERROR) << "ImportKey request: mis-matched KEY_SIZE tag: "
266 << ((key_size == NULL) ? -1 : *key_size)
267 << " provided data size: "
268 << keyData.size();
269 return ErrorCode::IMPORT_PARAMETER_MISMATCH;
270 }
271 } else {
272 if ((key_size != nullptr && *key_size != 168) ||
273 keyData.size() != 24) {
274 LOG(ERROR) << "ImportKey request: mis-matched DES KEY_SIZE tag: "
275 << ((key_size == NULL) ? -1 : *key_size)
276 << " provided data size: "
277 << keyData.size();
278 return ErrorCode::IMPORT_PARAMETER_MISMATCH;
279 }
280 LOG(ERROR) << "ImportKey request: DES OK: ";
281 }
282
283 if (keyData.size() == 0) {
284 LOG(ERROR) << "ImportKey request: invalid key size 0";
285 return ErrorCode::IMPORT_PARAMETER_MISMATCH;
286 }
287
288 request->mutable_symmetric_key()->set_material(
289 keyData.data(), keyData.size());
290
291 return ErrorCode::OK;
292 }
293
import_key_request(const hidl_vec<KeyParameter> & params,KeyFormat keyFormat,const hidl_vec<uint8_t> & keyData,ImportKeyRequest * request)294 ErrorCode import_key_request(const hidl_vec<KeyParameter>& params,
295 KeyFormat keyFormat,
296 const hidl_vec<uint8_t>& keyData,
297 ImportKeyRequest *request) {
298 const enum Algorithm *algorithm;
299
300 if (keyFormat != KeyFormat::PKCS8 && keyFormat != KeyFormat::RAW) {
301 return ErrorCode::UNSUPPORTED_KEY_FORMAT;
302 }
303
304 ErrorCode error;
305 tag_map_t tag_map;
306 error = hidl_params_to_map(params, &tag_map);
307 if (error != ErrorCode::OK) {
308 return error;
309 }
310
311 if (tag_map.find(Tag::ALGORITHM) != tag_map.end()) {
312 // Algorithm is a required parameter.
313 const vector<KeyParameter>& v = tag_map.find(Tag::ALGORITHM)->second;
314 algorithm = &v[0].f.algorithm;
315 } else {
316 LOG(ERROR) << "ImportKey request: Algorithm Tag missing";
317 return ErrorCode::INVALID_ARGUMENT;
318 }
319
320 if (keyFormat == KeyFormat::PKCS8) {
321 switch (*algorithm) {
322 case Algorithm::RSA:
323 error = import_key_rsa(tag_map, keyData, request);
324 break;
325 case Algorithm::EC:
326 error = import_key_ec(tag_map, keyData, request);
327 break;
328 default:
329 LOG(ERROR) << "ImportKey request: unsupported algoritm: "
330 << (uint32_t)*algorithm;
331 return ErrorCode::UNSUPPORTED_ALGORITHM;
332 break;
333 }
334 } else {
335 error = import_key_raw(tag_map, *algorithm, keyData, request);
336 }
337
338 if (error != ErrorCode::OK) {
339 return error;
340 }
341
342 error = map_params_to_pb(tag_map, request->mutable_params());
343 if (error != ErrorCode::OK) {
344 LOG(ERROR) << "ImportKey request: failed to map params to pb: "
345 << (uint32_t) error;
346 return error;
347 }
348
349 return ErrorCode::OK;
350 }
351
352 } // namespace keymaster
353 } // hardware
354 } // android
355