blob: f7c74088d1de75e57815ec0e8694c64e8f076ed8 [file] [log] [blame]
Shawn Willdend67afae2014-08-19 12:36:27 -06001/*
2 * Copyright 2014 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 "asymmetric_key.h"
18#include "dsa_operation.h"
19#include "ecdsa_operation.h"
20#include "key_blob.h"
21#include "keymaster_defs.h"
22#include "openssl_utils.h"
23#include "rsa_operation.h"
24
25namespace keymaster {
26
27const uint32_t RSA_DEFAULT_KEY_SIZE = 2048;
28const uint64_t RSA_DEFAULT_EXPONENT = 65537;
29
30const uint32_t DSA_DEFAULT_KEY_SIZE = 2048;
31
32const uint32_t ECDSA_DEFAULT_KEY_SIZE = 192;
33
34keymaster_error_t AsymmetricKey::LoadKey(const KeyBlob& blob) {
35 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> evp_key(EVP_PKEY_new());
36 if (evp_key.get() == NULL)
37 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
38
39 EVP_PKEY* tmp_pkey = evp_key.get();
40 const uint8_t* key_material = blob.key_material();
41 if (d2i_PrivateKey(evp_key_type(), &tmp_pkey, &key_material, blob.key_material_length()) ==
42 NULL) {
43 return KM_ERROR_INVALID_KEY_BLOB;
44 }
45 if (!EvpToInternal(evp_key.get()))
46 return KM_ERROR_UNKNOWN_ERROR;
47
48 return KM_ERROR_OK;
49}
50
51keymaster_error_t AsymmetricKey::key_material(UniquePtr<uint8_t[]>* material, size_t* size) const {
52 if (material == NULL || size == NULL)
53 return KM_ERROR_OUTPUT_PARAMETER_NULL;
54
55 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKEY_new());
56 if (pkey.get() == NULL)
57 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
58
59 if (!InternalToEvp(pkey.get()))
60 return KM_ERROR_UNKNOWN_ERROR;
61
62 *size = i2d_PrivateKey(pkey.get(), NULL /* key_data*/);
63 if (*size <= 0)
64 return KM_ERROR_UNKNOWN_ERROR;
65
66 material->reset(new uint8_t[*size]);
67 uint8_t* tmp = material->get();
68 i2d_PrivateKey(pkey.get(), &tmp);
69
70 return KM_ERROR_OK;
71}
72
73keymaster_error_t AsymmetricKey::formatted_key_material(UniquePtr<uint8_t[]>* material,
74 size_t* size) const {
75 if (material == NULL || size == NULL)
76 return KM_ERROR_OUTPUT_PARAMETER_NULL;
77
78 return KM_ERROR_UNIMPLEMENTED;
79}
80
81Operation* AsymmetricKey::CreateOperation(keymaster_purpose_t purpose, keymaster_error_t* error) {
82 keymaster_digest_t digest;
83 if (!authorizations().GetTagValue(TAG_DIGEST, &digest) || digest != KM_DIGEST_NONE) {
84 *error = KM_ERROR_UNSUPPORTED_DIGEST;
85 return NULL;
86 }
87
88 keymaster_padding_t padding;
89 if (!authorizations().GetTagValue(TAG_PADDING, &padding) || padding != KM_PAD_NONE) {
90 *error = KM_ERROR_UNSUPPORTED_PADDING_MODE;
91 return NULL;
92 }
93
94 return CreateOperation(purpose, digest, padding, error);
95}
96
97/* static */
98RsaKey* RsaKey::GenerateKey(const AuthorizationSet& key_description, keymaster_error_t* error) {
99 if (!error)
100 return NULL;
101
102 AuthorizationSet authorizations(key_description);
103
104 uint64_t public_exponent = RSA_DEFAULT_EXPONENT;
105 if (!authorizations.GetTagValue(TAG_RSA_PUBLIC_EXPONENT, &public_exponent))
106 authorizations.push_back(Authorization(TAG_RSA_PUBLIC_EXPONENT, public_exponent));
107
108 uint32_t key_size = RSA_DEFAULT_KEY_SIZE;
109 if (!authorizations.GetTagValue(TAG_KEY_SIZE, &key_size))
110 authorizations.push_back(Authorization(TAG_KEY_SIZE, key_size));
111
112 UniquePtr<BIGNUM, BIGNUM_Delete> exponent(BN_new());
113 UniquePtr<RSA, RSA_Delete> rsa_key(RSA_new());
114 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKEY_new());
115 if (rsa_key.get() == NULL || pkey.get() == NULL) {
116 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
117 return NULL;
118 }
119
120 if (!BN_set_word(exponent.get(), public_exponent) ||
121 !RSA_generate_key_ex(rsa_key.get(), key_size, exponent.get(), NULL /* callback */)) {
122 *error = KM_ERROR_UNKNOWN_ERROR;
123 return NULL;
124 }
125
126 RsaKey* new_key = new RsaKey(rsa_key.release(), authorizations);
127 *error = new_key ? KM_ERROR_OK : KM_ERROR_MEMORY_ALLOCATION_FAILED;
128 return new_key;
129}
130
131RsaKey::RsaKey(const KeyBlob& blob, keymaster_error_t* error) : AsymmetricKey(blob) {
132 if (error)
133 *error = LoadKey(blob);
134}
135
136Operation* RsaKey::CreateOperation(keymaster_purpose_t purpose, keymaster_digest_t digest,
137 keymaster_padding_t padding, keymaster_error_t* error) {
138 Operation* op;
139 switch (purpose) {
140 case KM_PURPOSE_SIGN:
141 op = new RsaSignOperation(purpose, digest, padding, rsa_key_.release());
142 break;
143 case KM_PURPOSE_VERIFY:
144 op = new RsaVerifyOperation(purpose, digest, padding, rsa_key_.release());
145 break;
146 default:
147 *error = KM_ERROR_UNIMPLEMENTED;
148 return NULL;
149 }
150 *error = op ? KM_ERROR_OK : KM_ERROR_MEMORY_ALLOCATION_FAILED;
151 return op;
152}
153
154bool RsaKey::EvpToInternal(const EVP_PKEY* pkey) {
155 rsa_key_.reset(EVP_PKEY_get1_RSA(const_cast<EVP_PKEY*>(pkey)));
156 return rsa_key_.get() != NULL;
157}
158
159bool RsaKey::InternalToEvp(EVP_PKEY* pkey) const {
160 return EVP_PKEY_set1_RSA(pkey, rsa_key_.get()) == 1;
161}
162
163template <keymaster_tag_t Tag>
164static void GetDsaParamData(const AuthorizationSet& auths, TypedTag<KM_BIGNUM, Tag> tag,
165 keymaster_blob_t* blob) {
166 if (!auths.GetTagValue(tag, blob))
167 blob->data = NULL;
168}
169
170// Store the specified DSA param in auths
171template <keymaster_tag_t Tag>
172static void SetDsaParamData(AuthorizationSet* auths, TypedTag<KM_BIGNUM, Tag> tag, BIGNUM* number) {
173 keymaster_blob_t blob;
174 convert_bn_to_blob(number, &blob);
175 auths->push_back(Authorization(tag, blob));
176 delete[] blob.data;
177}
178
179DsaKey* DsaKey::GenerateKey(const AuthorizationSet& key_description, keymaster_error_t* error) {
180 if (!error)
181 return NULL;
182
183 AuthorizationSet authorizations(key_description);
184
185 keymaster_blob_t g_blob;
186 GetDsaParamData(authorizations, TAG_DSA_GENERATOR, &g_blob);
187
188 keymaster_blob_t p_blob;
189 GetDsaParamData(authorizations, TAG_DSA_P, &p_blob);
190
191 keymaster_blob_t q_blob;
192 GetDsaParamData(authorizations, TAG_DSA_Q, &q_blob);
193
194 uint32_t key_size = DSA_DEFAULT_KEY_SIZE;
195 if (!authorizations.GetTagValue(TAG_KEY_SIZE, &key_size))
196 authorizations.push_back(Authorization(TAG_KEY_SIZE, key_size));
197
198 UniquePtr<uint8_t[]> key_data;
199 size_t key_data_size;
200
201 UniquePtr<DSA, DSA_Delete> dsa_key(DSA_new());
202 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKEY_new());
203 if (dsa_key.get() == NULL || pkey.get() == NULL) {
204 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
205 return NULL;
206 }
207
208 // If anything goes wrong in the next section, it's a param problem.
209 *error = KM_ERROR_INVALID_DSA_PARAMS;
210
211 if (g_blob.data == NULL && p_blob.data == NULL && q_blob.data == NULL) {
212 // No params provided, generate them.
213 if (!DSA_generate_parameters_ex(dsa_key.get(), key_size, NULL /* seed */, 0 /* seed_len */,
214 NULL /* counter_ret */, NULL /* h_ret */,
215 NULL /* callback */))
216 // TODO(swillden): return a more precise error, depending on ERR_get_error();
217 return NULL;
218
219 SetDsaParamData(&authorizations, TAG_DSA_GENERATOR, dsa_key->g);
220 SetDsaParamData(&authorizations, TAG_DSA_P, dsa_key->p);
221 SetDsaParamData(&authorizations, TAG_DSA_Q, dsa_key->q);
222 } else if (g_blob.data == NULL || p_blob.data == NULL || q_blob.data == NULL) {
223 // Some params provided: that's an error. Provide them all or provide none.
224 return NULL;
225 } else {
226 // All params provided. Use them.
227 dsa_key->g = BN_bin2bn(g_blob.data, g_blob.data_length, NULL);
228 dsa_key->p = BN_bin2bn(p_blob.data, p_blob.data_length, NULL);
229 dsa_key->q = BN_bin2bn(q_blob.data, q_blob.data_length, NULL);
230
231 if (dsa_key->g == NULL || dsa_key->p == NULL || dsa_key->q == NULL)
232 return NULL;
233 }
234
235 if (!DSA_generate_key(dsa_key.get())) {
236 *error = KM_ERROR_UNKNOWN_ERROR;
237 return NULL;
238 }
239
240 DsaKey* new_key = new DsaKey(dsa_key.release(), authorizations);
241 *error = new_key ? KM_ERROR_OK : KM_ERROR_MEMORY_ALLOCATION_FAILED;
242 return new_key;
243}
244
245DsaKey::DsaKey(const KeyBlob& blob, keymaster_error_t* error) : AsymmetricKey(blob) {
246 if (error)
247 *error = LoadKey(blob);
248}
249
250Operation* DsaKey::CreateOperation(keymaster_purpose_t purpose, keymaster_digest_t digest,
251 keymaster_padding_t padding, keymaster_error_t* error) {
252 Operation* op;
253 switch (purpose) {
254 case KM_PURPOSE_SIGN:
255 op = new DsaSignOperation(purpose, digest, padding, dsa_key_.release());
256 break;
257 case KM_PURPOSE_VERIFY:
258 op = new DsaVerifyOperation(purpose, digest, padding, dsa_key_.release());
259 break;
260 default:
261 *error = KM_ERROR_UNIMPLEMENTED;
262 return NULL;
263 }
264 *error = op ? KM_ERROR_OK : KM_ERROR_MEMORY_ALLOCATION_FAILED;
265 return op;
266}
267
268bool DsaKey::EvpToInternal(const EVP_PKEY* pkey) {
269 dsa_key_.reset(EVP_PKEY_get1_DSA(const_cast<EVP_PKEY*>(pkey)));
270 return dsa_key_.get() != NULL;
271}
272
273bool DsaKey::InternalToEvp(EVP_PKEY* pkey) const {
274 return EVP_PKEY_set1_DSA(pkey, dsa_key_.get()) == 1;
275}
276
277/* static */
278EcdsaKey* EcdsaKey::GenerateKey(const AuthorizationSet& key_description, keymaster_error_t* error) {
279 if (!error)
280 return NULL;
281
282 AuthorizationSet authorizations(key_description);
283
284 uint32_t key_size = ECDSA_DEFAULT_KEY_SIZE;
285 if (!authorizations.GetTagValue(TAG_KEY_SIZE, &key_size))
286 authorizations.push_back(Authorization(TAG_KEY_SIZE, key_size));
287
288 UniquePtr<EC_KEY, ECDSA_Delete> ecdsa_key(EC_KEY_new());
289 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKEY_new());
290 if (ecdsa_key.get() == NULL || pkey.get() == NULL) {
291 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
292 return NULL;
293 }
294
295 UniquePtr<EC_GROUP, EC_GROUP_Delete> group(choose_group(key_size));
296 if (group.get() == NULL) {
297 // Technically, could also have been a memory allocation problem.
298 *error = KM_ERROR_UNSUPPORTED_KEY_SIZE;
299 return NULL;
300 }
301
302 EC_GROUP_set_point_conversion_form(group.get(), POINT_CONVERSION_UNCOMPRESSED);
303 EC_GROUP_set_asn1_flag(group.get(), OPENSSL_EC_NAMED_CURVE);
304
305 if (EC_KEY_set_group(ecdsa_key.get(), group.get()) != 1 ||
306 EC_KEY_generate_key(ecdsa_key.get()) != 1 || EC_KEY_check_key(ecdsa_key.get()) < 0) {
307 *error = KM_ERROR_UNKNOWN_ERROR;
308 return NULL;
309 }
310
311 EcdsaKey* new_key = new EcdsaKey(ecdsa_key.release(), authorizations);
312 *error = new_key ? KM_ERROR_OK : KM_ERROR_MEMORY_ALLOCATION_FAILED;
313 return new_key;
314}
315
316/* static */
317EC_GROUP* EcdsaKey::choose_group(size_t key_size_bits) {
318 switch (key_size_bits) {
319 case 192:
320 return EC_GROUP_new_by_curve_name(NID_X9_62_prime192v1);
321 break;
322 case 224:
323 return EC_GROUP_new_by_curve_name(NID_secp224r1);
324 break;
325 case 256:
326 return EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
327 break;
328 case 384:
329 return EC_GROUP_new_by_curve_name(NID_secp384r1);
330 break;
331 case 521:
332 return EC_GROUP_new_by_curve_name(NID_secp521r1);
333 break;
334 default:
335 return NULL;
336 break;
337 }
338}
339
340EcdsaKey::EcdsaKey(const KeyBlob& blob, keymaster_error_t* error) : AsymmetricKey(blob) {
341 if (error)
342 *error = LoadKey(blob);
343}
344
345Operation* EcdsaKey::CreateOperation(keymaster_purpose_t purpose, keymaster_digest_t digest,
346 keymaster_padding_t padding, keymaster_error_t* error) {
347 Operation* op;
348 switch (purpose) {
349 case KM_PURPOSE_SIGN:
350 op = new EcdsaSignOperation(purpose, digest, padding, ecdsa_key_.release());
351 break;
352 case KM_PURPOSE_VERIFY:
353 op = new EcdsaVerifyOperation(purpose, digest, padding, ecdsa_key_.release());
354 break;
355 default:
356 *error = KM_ERROR_UNIMPLEMENTED;
357 return NULL;
358 }
359 *error = op ? KM_ERROR_OK : KM_ERROR_MEMORY_ALLOCATION_FAILED;
360 return op;
361}
362
363bool EcdsaKey::EvpToInternal(const EVP_PKEY* pkey) {
364 ecdsa_key_.reset(EVP_PKEY_get1_EC_KEY(const_cast<EVP_PKEY*>(pkey)));
365 return ecdsa_key_.get() != NULL;
366}
367
368bool EcdsaKey::InternalToEvp(EVP_PKEY* pkey) const {
369 return EVP_PKEY_set1_EC_KEY(pkey, ecdsa_key_.get()) == 1;
370}
371
372} // namespace keymaster