blob: e87a1fc7d0bc877b9a774c1e6a41855f8eb17bbf [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
Shawn Willdena278f612014-12-23 11:22:21 -070025static KeyFactoryRegistry::Registration<EcdsaKeyFactory> registration;
26
Shawn Willden13011cc2015-03-04 09:41:54 -070027Key* EcdsaKeyFactory::LoadKey(const UnencryptedKeyBlob& blob, keymaster_error_t* error) {
28 return new EcdsaKey(blob, error);
29}
30
Shawn Willden567a4a02014-12-31 12:14:46 -070031Key* EcdsaKeyFactory::GenerateKey(const AuthorizationSet& key_description,
Shawn Willdena278f612014-12-23 11:22:21 -070032 keymaster_error_t* error) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060033 if (!error)
34 return NULL;
35
36 AuthorizationSet authorizations(key_description);
37
Shawn Willden3b4e1652015-02-27 13:33:01 -070038 uint32_t key_size;
39 if (!authorizations.GetTagValue(TAG_KEY_SIZE, &key_size)) {
40 LOG_E("%s", "No key size specified for ECDSA key generation");
41 *error = KM_ERROR_UNSUPPORTED_KEY_SIZE;
42 }
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060043
Shawn Willdena278f612014-12-23 11:22:21 -070044 UniquePtr<EC_KEY, EcdsaKey::ECDSA_Delete> ecdsa_key(EC_KEY_new());
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060045 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKEY_new());
46 if (ecdsa_key.get() == NULL || pkey.get() == NULL) {
47 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
48 return NULL;
49 }
50
51 UniquePtr<EC_GROUP, EC_GROUP_Delete> group(choose_group(key_size));
52 if (group.get() == NULL) {
53 // Technically, could also have been a memory allocation problem.
54 *error = KM_ERROR_UNSUPPORTED_KEY_SIZE;
55 return NULL;
56 }
57
Shawn Willdenbaf99b62014-09-26 09:38:22 -060058#if !defined(OPENSSL_IS_BORINGSSL)
Adam Langleya550fba2015-02-13 14:44:14 -080059 EC_GROUP_set_point_conversion_form(group.get(), POINT_CONVERSION_UNCOMPRESSED);
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060060 EC_GROUP_set_asn1_flag(group.get(), OPENSSL_EC_NAMED_CURVE);
Shawn Willdenbaf99b62014-09-26 09:38:22 -060061#endif
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060062
63 if (EC_KEY_set_group(ecdsa_key.get(), group.get()) != 1 ||
64 EC_KEY_generate_key(ecdsa_key.get()) != 1 || EC_KEY_check_key(ecdsa_key.get()) < 0) {
Shawn Willden567a4a02014-12-31 12:14:46 -070065 *error = TranslateLastOpenSslError();
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060066 return NULL;
67 }
68
Shawn Willden567a4a02014-12-31 12:14:46 -070069 EcdsaKey* new_key = new EcdsaKey(ecdsa_key.release(), authorizations);
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060070 *error = new_key ? KM_ERROR_OK : KM_ERROR_MEMORY_ALLOCATION_FAILED;
71 return new_key;
72}
73
Shawn Willdena278f612014-12-23 11:22:21 -070074Key* EcdsaKeyFactory::ImportKey(const AuthorizationSet& key_description,
75 keymaster_key_format_t key_format, const uint8_t* key_data,
Shawn Willden567a4a02014-12-31 12:14:46 -070076 size_t key_data_length, keymaster_error_t* error) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060077 if (!error)
78 return NULL;
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060079
Shawn Willdena278f612014-12-23 11:22:21 -070080 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(
81 ExtractEvpKey(key_format, KM_ALGORITHM_ECDSA, key_data, key_data_length, error));
82 if (*error != KM_ERROR_OK)
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060083 return NULL;
Shawn Willdena278f612014-12-23 11:22:21 -070084 assert(pkey.get());
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060085
Shawn Willdena278f612014-12-23 11:22:21 -070086 UniquePtr<EC_KEY, EcdsaKey::ECDSA_Delete> ecdsa_key(EVP_PKEY_get1_EC_KEY(pkey.get()));
87 if (!ecdsa_key.get()) {
Shawn Willden567a4a02014-12-31 12:14:46 -070088 *error = TranslateLastOpenSslError();
Shawn Willdena278f612014-12-23 11:22:21 -070089 return NULL;
90 }
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060091
92 size_t extracted_key_size_bits;
93 *error = get_group_size(*EC_KEY_get0_group(ecdsa_key.get()), &extracted_key_size_bits);
94 if (*error != KM_ERROR_OK)
95 return NULL;
96
Shawn Willdena278f612014-12-23 11:22:21 -070097 AuthorizationSet authorizations(key_description);
98
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060099 uint32_t key_size_bits;
100 if (authorizations.GetTagValue(TAG_KEY_SIZE, &key_size_bits)) {
101 // key_size_bits specified, make sure it matches the key.
102 if (key_size_bits != extracted_key_size_bits) {
103 *error = KM_ERROR_IMPORT_PARAMETER_MISMATCH;
104 return NULL;
105 }
106 } else {
107 // key_size_bits not specified, add it.
108 authorizations.push_back(TAG_KEY_SIZE, extracted_key_size_bits);
109 }
110
111 keymaster_algorithm_t algorithm;
112 if (authorizations.GetTagValue(TAG_ALGORITHM, &algorithm)) {
113 if (algorithm != KM_ALGORITHM_ECDSA) {
114 *error = KM_ERROR_IMPORT_PARAMETER_MISMATCH;
115 return NULL;
116 }
117 } else {
118 authorizations.push_back(TAG_ALGORITHM, KM_ALGORITHM_ECDSA);
119 }
120
121 // Don't bother with the other parameters. If the necessary padding, digest, purpose, etc. are
122 // missing, the error will be diagnosed when the key is used (when auth checking is
123 // implemented).
124 *error = KM_ERROR_OK;
Shawn Willden567a4a02014-12-31 12:14:46 -0700125 return new EcdsaKey(ecdsa_key.release(), authorizations);
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600126}
127
Shawn Willden5fad7852015-01-26 16:10:56 -0700128Key* EcdsaKeyFactory::RescopeKey(const UnencryptedKeyBlob& blob,
129 const AuthorizationSet& new_authorizations,
130 keymaster_error_t* error) {
131 if (!error)
132 return NULL;
133
134 EcdsaKey original_key(blob, error);
135 if (*error != KM_ERROR_OK)
136 return NULL;
137
138 EcdsaKey* new_key = new EcdsaKey(original_key.ecdsa_key_.release(), new_authorizations);
139 *error = new_key ? KM_ERROR_OK : KM_ERROR_MEMORY_ALLOCATION_FAILED;
140 return new_key;
141}
142
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600143/* static */
Shawn Willdena278f612014-12-23 11:22:21 -0700144EC_GROUP* EcdsaKeyFactory::choose_group(size_t key_size_bits) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600145 switch (key_size_bits) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600146 case 224:
147 return EC_GROUP_new_by_curve_name(NID_secp224r1);
148 break;
149 case 256:
150 return EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
151 break;
152 case 384:
153 return EC_GROUP_new_by_curve_name(NID_secp384r1);
154 break;
155 case 521:
156 return EC_GROUP_new_by_curve_name(NID_secp521r1);
157 break;
158 default:
159 return NULL;
160 break;
161 }
162}
163
164/* static */
Shawn Willdena278f612014-12-23 11:22:21 -0700165keymaster_error_t EcdsaKeyFactory::get_group_size(const EC_GROUP& group, size_t* key_size_bits) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600166 switch (EC_GROUP_get_curve_name(&group)) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600167 case NID_secp224r1:
168 *key_size_bits = 224;
169 break;
170 case NID_X9_62_prime256v1:
171 *key_size_bits = 256;
172 break;
173 case NID_secp384r1:
174 *key_size_bits = 384;
175 break;
176 case NID_secp521r1:
177 *key_size_bits = 521;
178 break;
179 default:
180 return KM_ERROR_UNSUPPORTED_EC_FIELD;
181 }
182 return KM_ERROR_OK;
183}
184
Shawn Willden567a4a02014-12-31 12:14:46 -0700185EcdsaKey::EcdsaKey(const UnencryptedKeyBlob& blob, keymaster_error_t* error) : AsymmetricKey(blob) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600186 if (error)
187 *error = LoadKey(blob);
188}
189
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600190bool EcdsaKey::EvpToInternal(const EVP_PKEY* pkey) {
191 ecdsa_key_.reset(EVP_PKEY_get1_EC_KEY(const_cast<EVP_PKEY*>(pkey)));
192 return ecdsa_key_.get() != NULL;
193}
194
195bool EcdsaKey::InternalToEvp(EVP_PKEY* pkey) const {
196 return EVP_PKEY_set1_EC_KEY(pkey, ecdsa_key_.get()) == 1;
197}
198
199} // namespace keymaster