blob: b499fdb73e6ad2a9e66c76411adb8d493ee2d61d [file] [log] [blame]
Shawn Willden2c8dd3e2014-09-18 15:16:31 -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 "ecdsa_key.h"
18#include "ecdsa_operation.h"
19#include "openssl_utils.h"
20#include "unencrypted_key_blob.h"
21
22namespace keymaster {
23
24const uint32_t ECDSA_DEFAULT_KEY_SIZE = 224;
25
Shawn Willdena278f612014-12-23 11:22:21 -070026class EcdsaKeyFactory : public AsymmetricKeyFactory {
27 public:
28 virtual keymaster_algorithm_t registry_key() const { return KM_ALGORITHM_ECDSA; }
29
30 virtual Key* GenerateKey(const AuthorizationSet& key_description, const Logger& logger,
31 keymaster_error_t* error);
32 virtual Key* ImportKey(const AuthorizationSet& key_description,
33 keymaster_key_format_t key_format, const uint8_t* key_data,
34 size_t key_data_length, const Logger& logger, keymaster_error_t* error);
35 virtual Key* LoadKey(const UnencryptedKeyBlob& blob, const Logger& logger,
36 keymaster_error_t* error) {
37 return new EcdsaKey(blob, logger, error);
38 }
39
40 private:
41 static EC_GROUP* choose_group(size_t key_size_bits);
42 static keymaster_error_t get_group_size(const EC_GROUP& group, size_t* key_size_bits);
43
44 struct EC_GROUP_Delete {
45 void operator()(EC_GROUP* p) { EC_GROUP_free(p); }
46 };
47};
48static KeyFactoryRegistry::Registration<EcdsaKeyFactory> registration;
49
50Key* EcdsaKeyFactory::GenerateKey(const AuthorizationSet& key_description, const Logger& logger,
51 keymaster_error_t* error) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060052 if (!error)
53 return NULL;
54
55 AuthorizationSet authorizations(key_description);
56
57 uint32_t key_size = ECDSA_DEFAULT_KEY_SIZE;
58 if (!authorizations.GetTagValue(TAG_KEY_SIZE, &key_size))
59 authorizations.push_back(Authorization(TAG_KEY_SIZE, key_size));
60
Shawn Willdena278f612014-12-23 11:22:21 -070061 UniquePtr<EC_KEY, EcdsaKey::ECDSA_Delete> ecdsa_key(EC_KEY_new());
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060062 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKEY_new());
63 if (ecdsa_key.get() == NULL || pkey.get() == NULL) {
64 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
65 return NULL;
66 }
67
68 UniquePtr<EC_GROUP, EC_GROUP_Delete> group(choose_group(key_size));
69 if (group.get() == NULL) {
70 // Technically, could also have been a memory allocation problem.
71 *error = KM_ERROR_UNSUPPORTED_KEY_SIZE;
72 return NULL;
73 }
74
Shawn Willdenbaf99b62014-09-26 09:38:22 -060075#if !defined(OPENSSL_IS_BORINGSSL)
Adam Langleya550fba2015-02-13 14:44:14 -080076 EC_GROUP_set_point_conversion_form(group.get(), POINT_CONVERSION_UNCOMPRESSED);
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060077 EC_GROUP_set_asn1_flag(group.get(), OPENSSL_EC_NAMED_CURVE);
Shawn Willdenbaf99b62014-09-26 09:38:22 -060078#endif
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060079
80 if (EC_KEY_set_group(ecdsa_key.get(), group.get()) != 1 ||
81 EC_KEY_generate_key(ecdsa_key.get()) != 1 || EC_KEY_check_key(ecdsa_key.get()) < 0) {
82 *error = KM_ERROR_UNKNOWN_ERROR;
83 return NULL;
84 }
85
86 EcdsaKey* new_key = new EcdsaKey(ecdsa_key.release(), authorizations, logger);
87 *error = new_key ? KM_ERROR_OK : KM_ERROR_MEMORY_ALLOCATION_FAILED;
88 return new_key;
89}
90
Shawn Willdena278f612014-12-23 11:22:21 -070091Key* EcdsaKeyFactory::ImportKey(const AuthorizationSet& key_description,
92 keymaster_key_format_t key_format, const uint8_t* key_data,
93 size_t key_data_length, const Logger& logger,
94 keymaster_error_t* error) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060095 if (!error)
96 return NULL;
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060097
Shawn Willdena278f612014-12-23 11:22:21 -070098 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(
99 ExtractEvpKey(key_format, KM_ALGORITHM_ECDSA, key_data, key_data_length, error));
100 if (*error != KM_ERROR_OK)
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600101 return NULL;
Shawn Willdena278f612014-12-23 11:22:21 -0700102 assert(pkey.get());
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600103
Shawn Willdena278f612014-12-23 11:22:21 -0700104 UniquePtr<EC_KEY, EcdsaKey::ECDSA_Delete> ecdsa_key(EVP_PKEY_get1_EC_KEY(pkey.get()));
105 if (!ecdsa_key.get()) {
106 *error = KM_ERROR_UNKNOWN_ERROR;
107 return NULL;
108 }
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600109
110 size_t extracted_key_size_bits;
111 *error = get_group_size(*EC_KEY_get0_group(ecdsa_key.get()), &extracted_key_size_bits);
112 if (*error != KM_ERROR_OK)
113 return NULL;
114
Shawn Willdena278f612014-12-23 11:22:21 -0700115 AuthorizationSet authorizations(key_description);
116
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600117 uint32_t key_size_bits;
118 if (authorizations.GetTagValue(TAG_KEY_SIZE, &key_size_bits)) {
119 // key_size_bits specified, make sure it matches the key.
120 if (key_size_bits != extracted_key_size_bits) {
121 *error = KM_ERROR_IMPORT_PARAMETER_MISMATCH;
122 return NULL;
123 }
124 } else {
125 // key_size_bits not specified, add it.
126 authorizations.push_back(TAG_KEY_SIZE, extracted_key_size_bits);
127 }
128
129 keymaster_algorithm_t algorithm;
130 if (authorizations.GetTagValue(TAG_ALGORITHM, &algorithm)) {
131 if (algorithm != KM_ALGORITHM_ECDSA) {
132 *error = KM_ERROR_IMPORT_PARAMETER_MISMATCH;
133 return NULL;
134 }
135 } else {
136 authorizations.push_back(TAG_ALGORITHM, KM_ALGORITHM_ECDSA);
137 }
138
139 // Don't bother with the other parameters. If the necessary padding, digest, purpose, etc. are
140 // missing, the error will be diagnosed when the key is used (when auth checking is
141 // implemented).
142 *error = KM_ERROR_OK;
143 return new EcdsaKey(ecdsa_key.release(), authorizations, logger);
144}
145
146/* static */
Shawn Willdena278f612014-12-23 11:22:21 -0700147EC_GROUP* EcdsaKeyFactory::choose_group(size_t key_size_bits) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600148 switch (key_size_bits) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600149 case 224:
150 return EC_GROUP_new_by_curve_name(NID_secp224r1);
151 break;
152 case 256:
153 return EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
154 break;
155 case 384:
156 return EC_GROUP_new_by_curve_name(NID_secp384r1);
157 break;
158 case 521:
159 return EC_GROUP_new_by_curve_name(NID_secp521r1);
160 break;
161 default:
162 return NULL;
163 break;
164 }
165}
166
167/* static */
Shawn Willdena278f612014-12-23 11:22:21 -0700168keymaster_error_t EcdsaKeyFactory::get_group_size(const EC_GROUP& group, size_t* key_size_bits) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600169 switch (EC_GROUP_get_curve_name(&group)) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600170 case NID_secp224r1:
171 *key_size_bits = 224;
172 break;
173 case NID_X9_62_prime256v1:
174 *key_size_bits = 256;
175 break;
176 case NID_secp384r1:
177 *key_size_bits = 384;
178 break;
179 case NID_secp521r1:
180 *key_size_bits = 521;
181 break;
182 default:
183 return KM_ERROR_UNSUPPORTED_EC_FIELD;
184 }
185 return KM_ERROR_OK;
186}
187
188EcdsaKey::EcdsaKey(const UnencryptedKeyBlob& blob, const Logger& logger, keymaster_error_t* error)
189 : AsymmetricKey(blob, logger) {
190 if (error)
191 *error = LoadKey(blob);
192}
193
Shawn Willden96599212014-09-26 12:07:44 -0600194Operation* EcdsaKey::CreateOperation(keymaster_purpose_t purpose, keymaster_error_t* error) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600195 Operation* op;
196 switch (purpose) {
197 case KM_PURPOSE_SIGN:
Shawn Willdenb15d77e2014-12-17 16:44:29 -0700198 op = new EcdsaSignOperation(purpose, logger_, ecdsa_key_.release());
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600199 break;
200 case KM_PURPOSE_VERIFY:
Shawn Willdenb15d77e2014-12-17 16:44:29 -0700201 op = new EcdsaVerifyOperation(purpose, logger_, ecdsa_key_.release());
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600202 break;
203 default:
204 *error = KM_ERROR_UNIMPLEMENTED;
205 return NULL;
206 }
207 *error = op ? KM_ERROR_OK : KM_ERROR_MEMORY_ALLOCATION_FAILED;
208 return op;
209}
210
211bool EcdsaKey::EvpToInternal(const EVP_PKEY* pkey) {
212 ecdsa_key_.reset(EVP_PKEY_get1_EC_KEY(const_cast<EVP_PKEY*>(pkey)));
213 return ecdsa_key_.get() != NULL;
214}
215
216bool EcdsaKey::InternalToEvp(EVP_PKEY* pkey) const {
217 return EVP_PKEY_set1_EC_KEY(pkey, ecdsa_key_.get()) == 1;
218}
219
220} // namespace keymaster