blob: 4593f7ea11c43983e1ec73f0a843786ef296ad9f [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"
Shawn Willden567a4a02014-12-31 12:14:46 -070019#include "openssl_err.h"
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060020#include "openssl_utils.h"
21#include "unencrypted_key_blob.h"
22
23namespace keymaster {
24
25const uint32_t ECDSA_DEFAULT_KEY_SIZE = 224;
26
Shawn Willdena278f612014-12-23 11:22:21 -070027class EcdsaKeyFactory : public AsymmetricKeyFactory {
28 public:
29 virtual keymaster_algorithm_t registry_key() const { return KM_ALGORITHM_ECDSA; }
30
Shawn Willden567a4a02014-12-31 12:14:46 -070031 virtual Key* GenerateKey(const AuthorizationSet& key_description, keymaster_error_t* error);
Shawn Willdena278f612014-12-23 11:22:21 -070032 virtual Key* ImportKey(const AuthorizationSet& key_description,
33 keymaster_key_format_t key_format, const uint8_t* key_data,
Shawn Willden567a4a02014-12-31 12:14:46 -070034 size_t key_data_length, keymaster_error_t* error);
35 virtual Key* LoadKey(const UnencryptedKeyBlob& blob, keymaster_error_t* error) {
36 return new EcdsaKey(blob, error);
Shawn Willdena278f612014-12-23 11:22:21 -070037 }
Shawn Willden5fad7852015-01-26 16:10:56 -070038 virtual Key* RescopeKey(const UnencryptedKeyBlob& blob,
39 const AuthorizationSet& new_authorizations, keymaster_error_t* error);
Shawn Willdena278f612014-12-23 11:22:21 -070040
41 private:
42 static EC_GROUP* choose_group(size_t key_size_bits);
43 static keymaster_error_t get_group_size(const EC_GROUP& group, size_t* key_size_bits);
44
45 struct EC_GROUP_Delete {
46 void operator()(EC_GROUP* p) { EC_GROUP_free(p); }
47 };
48};
49static KeyFactoryRegistry::Registration<EcdsaKeyFactory> registration;
50
Shawn Willden567a4a02014-12-31 12:14:46 -070051Key* EcdsaKeyFactory::GenerateKey(const AuthorizationSet& key_description,
Shawn Willdena278f612014-12-23 11:22:21 -070052 keymaster_error_t* error) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060053 if (!error)
54 return NULL;
55
56 AuthorizationSet authorizations(key_description);
57
58 uint32_t key_size = ECDSA_DEFAULT_KEY_SIZE;
59 if (!authorizations.GetTagValue(TAG_KEY_SIZE, &key_size))
60 authorizations.push_back(Authorization(TAG_KEY_SIZE, key_size));
61
Shawn Willdena278f612014-12-23 11:22:21 -070062 UniquePtr<EC_KEY, EcdsaKey::ECDSA_Delete> ecdsa_key(EC_KEY_new());
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060063 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKEY_new());
64 if (ecdsa_key.get() == NULL || pkey.get() == NULL) {
65 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
66 return NULL;
67 }
68
69 UniquePtr<EC_GROUP, EC_GROUP_Delete> group(choose_group(key_size));
70 if (group.get() == NULL) {
71 // Technically, could also have been a memory allocation problem.
72 *error = KM_ERROR_UNSUPPORTED_KEY_SIZE;
73 return NULL;
74 }
75
Shawn Willdenbaf99b62014-09-26 09:38:22 -060076#if !defined(OPENSSL_IS_BORINGSSL)
Adam Langleya550fba2015-02-13 14:44:14 -080077 EC_GROUP_set_point_conversion_form(group.get(), POINT_CONVERSION_UNCOMPRESSED);
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060078 EC_GROUP_set_asn1_flag(group.get(), OPENSSL_EC_NAMED_CURVE);
Shawn Willdenbaf99b62014-09-26 09:38:22 -060079#endif
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060080
81 if (EC_KEY_set_group(ecdsa_key.get(), group.get()) != 1 ||
82 EC_KEY_generate_key(ecdsa_key.get()) != 1 || EC_KEY_check_key(ecdsa_key.get()) < 0) {
Shawn Willden567a4a02014-12-31 12:14:46 -070083 *error = TranslateLastOpenSslError();
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060084 return NULL;
85 }
86
Shawn Willden567a4a02014-12-31 12:14:46 -070087 EcdsaKey* new_key = new EcdsaKey(ecdsa_key.release(), authorizations);
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060088 *error = new_key ? KM_ERROR_OK : KM_ERROR_MEMORY_ALLOCATION_FAILED;
89 return new_key;
90}
91
Shawn Willdena278f612014-12-23 11:22:21 -070092Key* EcdsaKeyFactory::ImportKey(const AuthorizationSet& key_description,
93 keymaster_key_format_t key_format, const uint8_t* key_data,
Shawn Willden567a4a02014-12-31 12:14:46 -070094 size_t key_data_length, 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()) {
Shawn Willden567a4a02014-12-31 12:14:46 -0700106 *error = TranslateLastOpenSslError();
Shawn Willdena278f612014-12-23 11:22:21 -0700107 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;
Shawn Willden567a4a02014-12-31 12:14:46 -0700143 return new EcdsaKey(ecdsa_key.release(), authorizations);
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600144}
145
Shawn Willden5fad7852015-01-26 16:10:56 -0700146Key* EcdsaKeyFactory::RescopeKey(const UnencryptedKeyBlob& blob,
147 const AuthorizationSet& new_authorizations,
148 keymaster_error_t* error) {
149 if (!error)
150 return NULL;
151
152 EcdsaKey original_key(blob, error);
153 if (*error != KM_ERROR_OK)
154 return NULL;
155
156 EcdsaKey* new_key = new EcdsaKey(original_key.ecdsa_key_.release(), new_authorizations);
157 *error = new_key ? KM_ERROR_OK : KM_ERROR_MEMORY_ALLOCATION_FAILED;
158 return new_key;
159}
160
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600161/* static */
Shawn Willdena278f612014-12-23 11:22:21 -0700162EC_GROUP* EcdsaKeyFactory::choose_group(size_t key_size_bits) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600163 switch (key_size_bits) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600164 case 224:
165 return EC_GROUP_new_by_curve_name(NID_secp224r1);
166 break;
167 case 256:
168 return EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
169 break;
170 case 384:
171 return EC_GROUP_new_by_curve_name(NID_secp384r1);
172 break;
173 case 521:
174 return EC_GROUP_new_by_curve_name(NID_secp521r1);
175 break;
176 default:
177 return NULL;
178 break;
179 }
180}
181
182/* static */
Shawn Willdena278f612014-12-23 11:22:21 -0700183keymaster_error_t EcdsaKeyFactory::get_group_size(const EC_GROUP& group, size_t* key_size_bits) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600184 switch (EC_GROUP_get_curve_name(&group)) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600185 case NID_secp224r1:
186 *key_size_bits = 224;
187 break;
188 case NID_X9_62_prime256v1:
189 *key_size_bits = 256;
190 break;
191 case NID_secp384r1:
192 *key_size_bits = 384;
193 break;
194 case NID_secp521r1:
195 *key_size_bits = 521;
196 break;
197 default:
198 return KM_ERROR_UNSUPPORTED_EC_FIELD;
199 }
200 return KM_ERROR_OK;
201}
202
Shawn Willden567a4a02014-12-31 12:14:46 -0700203EcdsaKey::EcdsaKey(const UnencryptedKeyBlob& blob, keymaster_error_t* error) : AsymmetricKey(blob) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600204 if (error)
205 *error = LoadKey(blob);
206}
207
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600208bool EcdsaKey::EvpToInternal(const EVP_PKEY* pkey) {
209 ecdsa_key_.reset(EVP_PKEY_get1_EC_KEY(const_cast<EVP_PKEY*>(pkey)));
210 return ecdsa_key_.get() != NULL;
211}
212
213bool EcdsaKey::InternalToEvp(EVP_PKEY* pkey) const {
214 return EVP_PKEY_set1_EC_KEY(pkey, ecdsa_key_.get()) == 1;
215}
216
217} // namespace keymaster