blob: f90cf80f6d19b44e6ade688f28d18b865067b883 [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 }
38
39 private:
40 static EC_GROUP* choose_group(size_t key_size_bits);
41 static keymaster_error_t get_group_size(const EC_GROUP& group, size_t* key_size_bits);
42
43 struct EC_GROUP_Delete {
44 void operator()(EC_GROUP* p) { EC_GROUP_free(p); }
45 };
46};
47static KeyFactoryRegistry::Registration<EcdsaKeyFactory> registration;
48
Shawn Willden567a4a02014-12-31 12:14:46 -070049Key* EcdsaKeyFactory::GenerateKey(const AuthorizationSet& key_description,
Shawn Willdena278f612014-12-23 11:22:21 -070050 keymaster_error_t* error) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060051 if (!error)
52 return NULL;
53
54 AuthorizationSet authorizations(key_description);
55
56 uint32_t key_size = ECDSA_DEFAULT_KEY_SIZE;
57 if (!authorizations.GetTagValue(TAG_KEY_SIZE, &key_size))
58 authorizations.push_back(Authorization(TAG_KEY_SIZE, key_size));
59
Shawn Willdena278f612014-12-23 11:22:21 -070060 UniquePtr<EC_KEY, EcdsaKey::ECDSA_Delete> ecdsa_key(EC_KEY_new());
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060061 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKEY_new());
62 if (ecdsa_key.get() == NULL || pkey.get() == NULL) {
63 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
64 return NULL;
65 }
66
67 UniquePtr<EC_GROUP, EC_GROUP_Delete> group(choose_group(key_size));
68 if (group.get() == NULL) {
69 // Technically, could also have been a memory allocation problem.
70 *error = KM_ERROR_UNSUPPORTED_KEY_SIZE;
71 return NULL;
72 }
73
Shawn Willdenbaf99b62014-09-26 09:38:22 -060074#if !defined(OPENSSL_IS_BORINGSSL)
Adam Langleya550fba2015-02-13 14:44:14 -080075 EC_GROUP_set_point_conversion_form(group.get(), POINT_CONVERSION_UNCOMPRESSED);
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060076 EC_GROUP_set_asn1_flag(group.get(), OPENSSL_EC_NAMED_CURVE);
Shawn Willdenbaf99b62014-09-26 09:38:22 -060077#endif
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060078
79 if (EC_KEY_set_group(ecdsa_key.get(), group.get()) != 1 ||
80 EC_KEY_generate_key(ecdsa_key.get()) != 1 || EC_KEY_check_key(ecdsa_key.get()) < 0) {
Shawn Willden567a4a02014-12-31 12:14:46 -070081 *error = TranslateLastOpenSslError();
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060082 return NULL;
83 }
84
Shawn Willden567a4a02014-12-31 12:14:46 -070085 EcdsaKey* new_key = new EcdsaKey(ecdsa_key.release(), authorizations);
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060086 *error = new_key ? KM_ERROR_OK : KM_ERROR_MEMORY_ALLOCATION_FAILED;
87 return new_key;
88}
89
Shawn Willdena278f612014-12-23 11:22:21 -070090Key* EcdsaKeyFactory::ImportKey(const AuthorizationSet& key_description,
91 keymaster_key_format_t key_format, const uint8_t* key_data,
Shawn Willden567a4a02014-12-31 12:14:46 -070092 size_t key_data_length, keymaster_error_t* error) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060093 if (!error)
94 return NULL;
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060095
Shawn Willdena278f612014-12-23 11:22:21 -070096 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(
97 ExtractEvpKey(key_format, KM_ALGORITHM_ECDSA, key_data, key_data_length, error));
98 if (*error != KM_ERROR_OK)
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060099 return NULL;
Shawn Willdena278f612014-12-23 11:22:21 -0700100 assert(pkey.get());
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600101
Shawn Willdena278f612014-12-23 11:22:21 -0700102 UniquePtr<EC_KEY, EcdsaKey::ECDSA_Delete> ecdsa_key(EVP_PKEY_get1_EC_KEY(pkey.get()));
103 if (!ecdsa_key.get()) {
Shawn Willden567a4a02014-12-31 12:14:46 -0700104 *error = TranslateLastOpenSslError();
Shawn Willdena278f612014-12-23 11:22:21 -0700105 return NULL;
106 }
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600107
108 size_t extracted_key_size_bits;
109 *error = get_group_size(*EC_KEY_get0_group(ecdsa_key.get()), &extracted_key_size_bits);
110 if (*error != KM_ERROR_OK)
111 return NULL;
112
Shawn Willdena278f612014-12-23 11:22:21 -0700113 AuthorizationSet authorizations(key_description);
114
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600115 uint32_t key_size_bits;
116 if (authorizations.GetTagValue(TAG_KEY_SIZE, &key_size_bits)) {
117 // key_size_bits specified, make sure it matches the key.
118 if (key_size_bits != extracted_key_size_bits) {
119 *error = KM_ERROR_IMPORT_PARAMETER_MISMATCH;
120 return NULL;
121 }
122 } else {
123 // key_size_bits not specified, add it.
124 authorizations.push_back(TAG_KEY_SIZE, extracted_key_size_bits);
125 }
126
127 keymaster_algorithm_t algorithm;
128 if (authorizations.GetTagValue(TAG_ALGORITHM, &algorithm)) {
129 if (algorithm != KM_ALGORITHM_ECDSA) {
130 *error = KM_ERROR_IMPORT_PARAMETER_MISMATCH;
131 return NULL;
132 }
133 } else {
134 authorizations.push_back(TAG_ALGORITHM, KM_ALGORITHM_ECDSA);
135 }
136
137 // Don't bother with the other parameters. If the necessary padding, digest, purpose, etc. are
138 // missing, the error will be diagnosed when the key is used (when auth checking is
139 // implemented).
140 *error = KM_ERROR_OK;
Shawn Willden567a4a02014-12-31 12:14:46 -0700141 return new EcdsaKey(ecdsa_key.release(), authorizations);
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600142}
143
144/* static */
Shawn Willdena278f612014-12-23 11:22:21 -0700145EC_GROUP* EcdsaKeyFactory::choose_group(size_t key_size_bits) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600146 switch (key_size_bits) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600147 case 224:
148 return EC_GROUP_new_by_curve_name(NID_secp224r1);
149 break;
150 case 256:
151 return EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
152 break;
153 case 384:
154 return EC_GROUP_new_by_curve_name(NID_secp384r1);
155 break;
156 case 521:
157 return EC_GROUP_new_by_curve_name(NID_secp521r1);
158 break;
159 default:
160 return NULL;
161 break;
162 }
163}
164
165/* static */
Shawn Willdena278f612014-12-23 11:22:21 -0700166keymaster_error_t EcdsaKeyFactory::get_group_size(const EC_GROUP& group, size_t* key_size_bits) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600167 switch (EC_GROUP_get_curve_name(&group)) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600168 case NID_secp224r1:
169 *key_size_bits = 224;
170 break;
171 case NID_X9_62_prime256v1:
172 *key_size_bits = 256;
173 break;
174 case NID_secp384r1:
175 *key_size_bits = 384;
176 break;
177 case NID_secp521r1:
178 *key_size_bits = 521;
179 break;
180 default:
181 return KM_ERROR_UNSUPPORTED_EC_FIELD;
182 }
183 return KM_ERROR_OK;
184}
185
Shawn Willden567a4a02014-12-31 12:14:46 -0700186EcdsaKey::EcdsaKey(const UnencryptedKeyBlob& blob, keymaster_error_t* error) : AsymmetricKey(blob) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600187 if (error)
188 *error = LoadKey(blob);
189}
190
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600191bool EcdsaKey::EvpToInternal(const EVP_PKEY* pkey) {
192 ecdsa_key_.reset(EVP_PKEY_get1_EC_KEY(const_cast<EVP_PKEY*>(pkey)));
193 return ecdsa_key_.get() != NULL;
194}
195
196bool EcdsaKey::InternalToEvp(EVP_PKEY* pkey) const {
197 return EVP_PKEY_set1_EC_KEY(pkey, ecdsa_key_.get()) == 1;
198}
199
200} // namespace keymaster