blob: 456ffb8053c10d9ec245327080fca63ad77bc408 [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"
Shawn Willden13fbe3e2015-05-23 03:36:30 +000018#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"
Shawn Willden13fbe3e2015-05-23 03:36:30 +000021#include "unencrypted_key_blob.h"
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060022
23namespace keymaster {
24
Shawn Willden13fbe3e2015-05-23 03:36:30 +000025Key* EcKeyFactory::LoadKey(const UnencryptedKeyBlob& blob, keymaster_error_t* error) {
26 return new EcKey(blob, error);
27}
28
29Key* EcKeyFactory::GenerateKey(const AuthorizationSet& key_description,
30 keymaster_error_t* error) {
31 if (!error)
32 return NULL;
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060033
34 AuthorizationSet authorizations(key_description);
35
Shawn Willden3b4e1652015-02-27 13:33:01 -070036 uint32_t key_size;
Shawn Willden13fbe3e2015-05-23 03:36:30 +000037
Shawn Willden3b4e1652015-02-27 13:33:01 -070038 if (!authorizations.GetTagValue(TAG_KEY_SIZE, &key_size)) {
Thai Duongf862a762015-03-18 14:10:56 -070039 LOG_E("%s", "No key size specified for EC key generation");
Shawn Willden13fbe3e2015-05-23 03:36:30 +000040 *error = KM_ERROR_UNSUPPORTED_KEY_SIZE;
Shawn Willden3b4e1652015-02-27 13:33:01 -070041 }
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060042
Thai Duongf862a762015-03-18 14:10:56 -070043 UniquePtr<EC_KEY, EcKey::EC_Delete> ec_key(EC_KEY_new());
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060044 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKEY_new());
Shawn Willden13fbe3e2015-05-23 03:36:30 +000045 if (ec_key.get() == NULL || pkey.get() == NULL) {
46 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
47 return NULL;
48 }
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060049 UniquePtr<EC_GROUP, EC_GROUP_Delete> group(choose_group(key_size));
50 if (group.get() == NULL) {
Shawn Willden13fbe3e2015-05-23 03:36:30 +000051 // Technically, could also have been a memory allocation problem.
Shawn Willdenf01329d2015-03-11 21:51:38 -060052 LOG_E("Unable to get EC group for key of size %d", key_size);
Shawn Willden13fbe3e2015-05-23 03:36:30 +000053 *error = KM_ERROR_UNSUPPORTED_KEY_SIZE;
54 return NULL;
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060055 }
56
Shawn Willdend79791b2015-05-09 12:48:36 +000057#if !defined(OPENSSL_IS_BORINGSSL)
58 EC_GROUP_set_point_conversion_form(group.get(), POINT_CONVERSION_UNCOMPRESSED);
59 EC_GROUP_set_asn1_flag(group.get(), OPENSSL_EC_NAMED_CURVE);
60#endif
61
Thai Duongf862a762015-03-18 14:10:56 -070062 if (EC_KEY_set_group(ec_key.get(), group.get()) != 1 ||
63 EC_KEY_generate_key(ec_key.get()) != 1 || EC_KEY_check_key(ec_key.get()) < 0) {
Shawn Willden13fbe3e2015-05-23 03:36:30 +000064 *error = TranslateLastOpenSslError();
65 return NULL;
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060066 }
67
Shawn Willden13fbe3e2015-05-23 03:36:30 +000068 EcKey* new_key = new EcKey(ec_key.release(), authorizations);
69 *error = new_key ? KM_ERROR_OK : KM_ERROR_MEMORY_ALLOCATION_FAILED;
70 return new_key;
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060071}
72
Shawn Willden13fbe3e2015-05-23 03:36:30 +000073Key* EcKeyFactory::ImportKey(const AuthorizationSet& key_description,
74 keymaster_key_format_t key_format, const uint8_t* key_data,
75 size_t key_data_length, keymaster_error_t* error) {
76 if (!error)
77 return NULL;
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060078
Shawn Willden13fbe3e2015-05-23 03:36:30 +000079 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(
80 ExtractEvpKey(key_format, registry_key(), key_data, key_data_length, error));
81 if (*error != KM_ERROR_OK)
82 return NULL;
83 assert(pkey.get());
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060084
Thai Duongf862a762015-03-18 14:10:56 -070085 UniquePtr<EC_KEY, EcKey::EC_Delete> ec_key(EVP_PKEY_get1_EC_KEY(pkey.get()));
Shawn Willden13fbe3e2015-05-23 03:36:30 +000086 if (!ec_key.get()) {
87 *error = TranslateLastOpenSslError();
88 return NULL;
89 }
Shawn Willdena278f612014-12-23 11:22:21 -070090
Shawn Willden8ba2a042015-05-18 08:35:28 -060091 size_t extracted_key_size_bits;
Shawn Willden13fbe3e2015-05-23 03:36:30 +000092 *error = get_group_size(*EC_KEY_get0_group(ec_key.get()), &extracted_key_size_bits);
93 if (*error != KM_ERROR_OK)
94 return NULL;
95
96 AuthorizationSet authorizations(key_description);
Shawn Willden8ba2a042015-05-18 08:35:28 -060097
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060098 uint32_t key_size_bits;
99 if (authorizations.GetTagValue(TAG_KEY_SIZE, &key_size_bits)) {
100 // key_size_bits specified, make sure it matches the key.
Shawn Willden13fbe3e2015-05-23 03:36:30 +0000101 if (key_size_bits != extracted_key_size_bits) {
102 *error = KM_ERROR_IMPORT_PARAMETER_MISMATCH;
103 return NULL;
104 }
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600105 } else {
106 // key_size_bits not specified, add it.
107 authorizations.push_back(TAG_KEY_SIZE, extracted_key_size_bits);
108 }
109
110 keymaster_algorithm_t algorithm;
111 if (authorizations.GetTagValue(TAG_ALGORITHM, &algorithm)) {
Shawn Willden13fbe3e2015-05-23 03:36:30 +0000112 if (algorithm != registry_key()) {
113 *error = KM_ERROR_IMPORT_PARAMETER_MISMATCH;
114 return NULL;
115 }
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600116 } else {
Thai Duongf862a762015-03-18 14:10:56 -0700117 authorizations.push_back(TAG_ALGORITHM, registry_key());
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600118 }
Shawn Willden13fbe3e2015-05-23 03:36:30 +0000119 // Don't bother with the other parameters. If the necessary padding, digest, purpose, etc. are
120 // missing, the error will be diagnosed when the key is used (when auth checking is
121 // implemented).
122 *error = KM_ERROR_OK;
123 return new EcKey(ec_key.release(), authorizations);
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600124}
125
126/* static */
Thai Duongf862a762015-03-18 14:10:56 -0700127EC_GROUP* EcKeyFactory::choose_group(size_t key_size_bits) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600128 switch (key_size_bits) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600129 case 224:
130 return EC_GROUP_new_by_curve_name(NID_secp224r1);
131 break;
132 case 256:
133 return EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
134 break;
135 case 384:
136 return EC_GROUP_new_by_curve_name(NID_secp384r1);
137 break;
138 case 521:
139 return EC_GROUP_new_by_curve_name(NID_secp521r1);
140 break;
141 default:
142 return NULL;
143 break;
144 }
145}
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600146/* static */
Thai Duongf862a762015-03-18 14:10:56 -0700147keymaster_error_t EcKeyFactory::get_group_size(const EC_GROUP& group, size_t* key_size_bits) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600148 switch (EC_GROUP_get_curve_name(&group)) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600149 case NID_secp224r1:
150 *key_size_bits = 224;
151 break;
152 case NID_X9_62_prime256v1:
153 *key_size_bits = 256;
154 break;
155 case NID_secp384r1:
156 *key_size_bits = 384;
157 break;
158 case NID_secp521r1:
159 *key_size_bits = 521;
160 break;
161 default:
162 return KM_ERROR_UNSUPPORTED_EC_FIELD;
163 }
164 return KM_ERROR_OK;
165}
166
Shawn Willden13fbe3e2015-05-23 03:36:30 +0000167EcKey::EcKey(const UnencryptedKeyBlob& blob, keymaster_error_t* error) : AsymmetricKey(blob) {
168 if (error)
169 *error = LoadKey(blob);
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600170}
171
Thai Duongf862a762015-03-18 14:10:56 -0700172bool EcKey::EvpToInternal(const EVP_PKEY* pkey) {
173 ec_key_.reset(EVP_PKEY_get1_EC_KEY(const_cast<EVP_PKEY*>(pkey)));
174 return ec_key_.get() != NULL;
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600175}
176
Thai Duongf862a762015-03-18 14:10:56 -0700177bool EcKey::InternalToEvp(EVP_PKEY* pkey) const {
178 return EVP_PKEY_set1_EC_KEY(pkey, ec_key_.get()) == 1;
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600179}
180
181} // namespace keymaster