blob: 43b37c65d8820e96d5e7cc3b75475321d3745bd2 [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
Thai Duongf862a762015-03-18 14:10:56 -070017#include "ec_key.h"
18#include "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
Thai Duongf862a762015-03-18 14:10:56 -070027Key* EcKeyFactory::LoadKey(const UnencryptedKeyBlob& blob, keymaster_error_t* error) {
28 return new EcKey(blob, error);
Shawn Willden13011cc2015-03-04 09:41:54 -070029}
30
Thai Duongf862a762015-03-18 14:10:56 -070031Key* EcKeyFactory::GenerateKey(const AuthorizationSet& key_description,
32 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;
Thai Duongf862a762015-03-18 14:10:56 -070039
Shawn Willden3b4e1652015-02-27 13:33:01 -070040 if (!authorizations.GetTagValue(TAG_KEY_SIZE, &key_size)) {
Thai Duongf862a762015-03-18 14:10:56 -070041 LOG_E("%s", "No key size specified for EC key generation");
Shawn Willden3b4e1652015-02-27 13:33:01 -070042 *error = KM_ERROR_UNSUPPORTED_KEY_SIZE;
43 }
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060044
Thai Duongf862a762015-03-18 14:10:56 -070045 UniquePtr<EC_KEY, EcKey::EC_Delete> ec_key(EC_KEY_new());
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060046 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKEY_new());
Thai Duongf862a762015-03-18 14:10:56 -070047 if (ec_key.get() == NULL || pkey.get() == NULL) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060048 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
49 return NULL;
50 }
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060051 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.
Shawn Willdenf01329d2015-03-11 21:51:38 -060054 LOG_E("Unable to get EC group for key of size %d", key_size);
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060055 *error = KM_ERROR_UNSUPPORTED_KEY_SIZE;
56 return NULL;
57 }
58
Thai Duongf862a762015-03-18 14:10:56 -070059 if (EC_KEY_set_group(ec_key.get(), group.get()) != 1 ||
60 EC_KEY_generate_key(ec_key.get()) != 1 || EC_KEY_check_key(ec_key.get()) < 0) {
Shawn Willden567a4a02014-12-31 12:14:46 -070061 *error = TranslateLastOpenSslError();
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060062 return NULL;
63 }
64
Thai Duongf862a762015-03-18 14:10:56 -070065 EcKey* new_key = new EcKey(ec_key.release(), authorizations);
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060066 *error = new_key ? KM_ERROR_OK : KM_ERROR_MEMORY_ALLOCATION_FAILED;
67 return new_key;
68}
69
Thai Duongf862a762015-03-18 14:10:56 -070070Key* EcKeyFactory::ImportKey(const AuthorizationSet& key_description,
71 keymaster_key_format_t key_format, const uint8_t* key_data,
72 size_t key_data_length, keymaster_error_t* error) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060073 if (!error)
74 return NULL;
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060075
Shawn Willdena278f612014-12-23 11:22:21 -070076 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(
Thai Duongf862a762015-03-18 14:10:56 -070077 ExtractEvpKey(key_format, registry_key(), key_data, key_data_length, error));
Shawn Willdena278f612014-12-23 11:22:21 -070078 if (*error != KM_ERROR_OK)
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060079 return NULL;
Shawn Willdena278f612014-12-23 11:22:21 -070080 assert(pkey.get());
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060081
Thai Duongf862a762015-03-18 14:10:56 -070082 UniquePtr<EC_KEY, EcKey::EC_Delete> ec_key(EVP_PKEY_get1_EC_KEY(pkey.get()));
83 if (!ec_key.get()) {
Shawn Willden567a4a02014-12-31 12:14:46 -070084 *error = TranslateLastOpenSslError();
Shawn Willdena278f612014-12-23 11:22:21 -070085 return NULL;
86 }
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060087
88 size_t extracted_key_size_bits;
Thai Duongf862a762015-03-18 14:10:56 -070089 *error = get_group_size(*EC_KEY_get0_group(ec_key.get()), &extracted_key_size_bits);
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060090 if (*error != KM_ERROR_OK)
91 return NULL;
92
Shawn Willdena278f612014-12-23 11:22:21 -070093 AuthorizationSet authorizations(key_description);
94
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060095 uint32_t key_size_bits;
96 if (authorizations.GetTagValue(TAG_KEY_SIZE, &key_size_bits)) {
97 // key_size_bits specified, make sure it matches the key.
98 if (key_size_bits != extracted_key_size_bits) {
99 *error = KM_ERROR_IMPORT_PARAMETER_MISMATCH;
100 return NULL;
101 }
102 } else {
103 // key_size_bits not specified, add it.
104 authorizations.push_back(TAG_KEY_SIZE, extracted_key_size_bits);
105 }
106
107 keymaster_algorithm_t algorithm;
108 if (authorizations.GetTagValue(TAG_ALGORITHM, &algorithm)) {
Thai Duongf862a762015-03-18 14:10:56 -0700109 if (algorithm != registry_key()) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600110 *error = KM_ERROR_IMPORT_PARAMETER_MISMATCH;
111 return NULL;
112 }
113 } else {
Thai Duongf862a762015-03-18 14:10:56 -0700114 authorizations.push_back(TAG_ALGORITHM, registry_key());
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600115 }
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600116 // Don't bother with the other parameters. If the necessary padding, digest, purpose, etc. are
117 // missing, the error will be diagnosed when the key is used (when auth checking is
118 // implemented).
119 *error = KM_ERROR_OK;
Thai Duongf862a762015-03-18 14:10:56 -0700120 return new EcKey(ec_key.release(), authorizations);
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600121}
122
Thai Duongf862a762015-03-18 14:10:56 -0700123Key* EcKeyFactory::RescopeKey(const UnencryptedKeyBlob& blob,
124 const AuthorizationSet& new_authorizations,
125 keymaster_error_t* error) {
Shawn Willden5fad7852015-01-26 16:10:56 -0700126 if (!error)
127 return NULL;
128
Thai Duongf862a762015-03-18 14:10:56 -0700129 EcKey original_key(blob, error);
Shawn Willden5fad7852015-01-26 16:10:56 -0700130 if (*error != KM_ERROR_OK)
131 return NULL;
132
Thai Duongf862a762015-03-18 14:10:56 -0700133 EcKey* new_key = new EcKey(original_key.ec_key_.release(), new_authorizations);
Shawn Willden5fad7852015-01-26 16:10:56 -0700134 *error = new_key ? KM_ERROR_OK : KM_ERROR_MEMORY_ALLOCATION_FAILED;
135 return new_key;
136}
137
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600138/* static */
Thai Duongf862a762015-03-18 14:10:56 -0700139EC_GROUP* EcKeyFactory::choose_group(size_t key_size_bits) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600140 switch (key_size_bits) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600141 case 224:
142 return EC_GROUP_new_by_curve_name(NID_secp224r1);
143 break;
144 case 256:
145 return EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
146 break;
147 case 384:
148 return EC_GROUP_new_by_curve_name(NID_secp384r1);
149 break;
150 case 521:
151 return EC_GROUP_new_by_curve_name(NID_secp521r1);
152 break;
153 default:
154 return NULL;
155 break;
156 }
157}
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600158/* static */
Thai Duongf862a762015-03-18 14:10:56 -0700159keymaster_error_t EcKeyFactory::get_group_size(const EC_GROUP& group, size_t* key_size_bits) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600160 switch (EC_GROUP_get_curve_name(&group)) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600161 case NID_secp224r1:
162 *key_size_bits = 224;
163 break;
164 case NID_X9_62_prime256v1:
165 *key_size_bits = 256;
166 break;
167 case NID_secp384r1:
168 *key_size_bits = 384;
169 break;
170 case NID_secp521r1:
171 *key_size_bits = 521;
172 break;
173 default:
174 return KM_ERROR_UNSUPPORTED_EC_FIELD;
175 }
176 return KM_ERROR_OK;
177}
178
Thai Duongf862a762015-03-18 14:10:56 -0700179EcKey::EcKey(const UnencryptedKeyBlob& blob, keymaster_error_t* error) : AsymmetricKey(blob) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600180 if (error)
181 *error = LoadKey(blob);
182}
183
Thai Duongf862a762015-03-18 14:10:56 -0700184bool EcKey::EvpToInternal(const EVP_PKEY* pkey) {
185 ec_key_.reset(EVP_PKEY_get1_EC_KEY(const_cast<EVP_PKEY*>(pkey)));
186 return ec_key_.get() != NULL;
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600187}
188
Thai Duongf862a762015-03-18 14:10:56 -0700189bool EcKey::InternalToEvp(EVP_PKEY* pkey) const {
190 return EVP_PKEY_set1_EC_KEY(pkey, ec_key_.get()) == 1;
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600191}
192
193} // namespace keymaster