blob: e42b9a5f97fc789dad60fedc637ccfbc99c90929 [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
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060017#include "rsa_key.h"
Shawn Willden567a4a02014-12-31 12:14:46 -070018
19#include "openssl_err.h"
20#include "openssl_utils.h"
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060021#include "rsa_operation.h"
22#include "unencrypted_key_blob.h"
23
Adam Langleya550fba2015-02-13 14:44:14 -080024#if defined(OPENSSL_IS_BORINGSSL)
25typedef size_t openssl_size_t;
26#else
27typedef int openssl_size_t;
28#endif
29
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060030namespace keymaster {
31
Shawn Willdena278f612014-12-23 11:22:21 -070032class RsaKeyFactory : public AsymmetricKeyFactory {
33 public:
34 virtual keymaster_algorithm_t registry_key() const { return KM_ALGORITHM_RSA; }
Shawn Willden567a4a02014-12-31 12:14:46 -070035 virtual Key* GenerateKey(const AuthorizationSet& key_description, keymaster_error_t* error);
Shawn Willdena278f612014-12-23 11:22:21 -070036 virtual Key* ImportKey(const AuthorizationSet& key_description,
37 keymaster_key_format_t key_format, const uint8_t* key_data,
Shawn Willden567a4a02014-12-31 12:14:46 -070038 size_t key_data_length, keymaster_error_t* error);
39 virtual Key* LoadKey(const UnencryptedKeyBlob& blob, keymaster_error_t* error) {
40 return new RsaKey(blob, error);
Shawn Willdena278f612014-12-23 11:22:21 -070041 }
Shawn Willden5fad7852015-01-26 16:10:56 -070042 virtual Key* RescopeKey(const UnencryptedKeyBlob& blob,
43 const AuthorizationSet& new_authorizations, keymaster_error_t* error);
Shawn Willdena278f612014-12-23 11:22:21 -070044};
45static KeyFactoryRegistry::Registration<RsaKeyFactory> registration;
46
Shawn Willden567a4a02014-12-31 12:14:46 -070047Key* RsaKeyFactory::GenerateKey(const AuthorizationSet& key_description, keymaster_error_t* error) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060048 if (!error)
49 return NULL;
50
51 AuthorizationSet authorizations(key_description);
52
Shawn Willden3b4e1652015-02-27 13:33:01 -070053 uint64_t public_exponent;
54 if (!authorizations.GetTagValue(TAG_RSA_PUBLIC_EXPONENT, &public_exponent)) {
55 LOG_E("%s", "No public exponent specified for RSA key generation");
56 *error = KM_ERROR_INVALID_ARGUMENT;
57 return NULL;
58 }
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060059
Shawn Willden3b4e1652015-02-27 13:33:01 -070060 uint32_t key_size;
61 if (!authorizations.GetTagValue(TAG_KEY_SIZE, &key_size)) {
62 LOG_E("%s", "No key size specified for RSA key generation");
63 *error = KM_ERROR_UNSUPPORTED_KEY_SIZE;
64 return NULL;
65 }
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060066
67 UniquePtr<BIGNUM, BIGNUM_Delete> exponent(BN_new());
Shawn Willdena278f612014-12-23 11:22:21 -070068 UniquePtr<RSA, RsaKey::RSA_Delete> rsa_key(RSA_new());
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060069 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKEY_new());
Shawn Willden3b4e1652015-02-27 13:33:01 -070070 if (exponent.get() == NULL || rsa_key.get() == NULL || pkey.get() == NULL) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060071 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
72 return NULL;
73 }
74
75 if (!BN_set_word(exponent.get(), public_exponent) ||
76 !RSA_generate_key_ex(rsa_key.get(), key_size, exponent.get(), NULL /* callback */)) {
Shawn Willden567a4a02014-12-31 12:14:46 -070077 *error = TranslateLastOpenSslError();
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060078 return NULL;
79 }
80
Shawn Willden567a4a02014-12-31 12:14:46 -070081 RsaKey* new_key = new RsaKey(rsa_key.release(), authorizations);
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060082 *error = new_key ? KM_ERROR_OK : KM_ERROR_MEMORY_ALLOCATION_FAILED;
83 return new_key;
84}
85
Shawn Willdena278f612014-12-23 11:22:21 -070086Key* RsaKeyFactory::ImportKey(const AuthorizationSet& key_description,
87 keymaster_key_format_t key_format, const uint8_t* key_data,
Shawn Willden567a4a02014-12-31 12:14:46 -070088 size_t key_data_length, keymaster_error_t* error) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060089 if (!error)
90 return NULL;
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060091
Shawn Willdena278f612014-12-23 11:22:21 -070092 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(
93 ExtractEvpKey(key_format, KM_ALGORITHM_RSA, key_data, key_data_length, error));
94 if (*error != KM_ERROR_OK)
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060095 return NULL;
Shawn Willdena278f612014-12-23 11:22:21 -070096 assert(pkey.get());
97
98 UniquePtr<RSA, RsaKey::RSA_Delete> rsa_key(EVP_PKEY_get1_RSA(pkey.get()));
99 if (!rsa_key.get()) {
Shawn Willden567a4a02014-12-31 12:14:46 -0700100 *error = TranslateLastOpenSslError();
Shawn Willdena278f612014-12-23 11:22:21 -0700101 return NULL;
102 }
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600103
104 AuthorizationSet authorizations(key_description);
105
106 uint64_t public_exponent;
107 if (authorizations.GetTagValue(TAG_RSA_PUBLIC_EXPONENT, &public_exponent)) {
108 // public_exponent specified, make sure it matches the key
109 UniquePtr<BIGNUM, BIGNUM_Delete> public_exponent_bn(BN_new());
110 if (!BN_set_word(public_exponent_bn.get(), public_exponent))
111 return NULL;
112 if (BN_cmp(public_exponent_bn.get(), rsa_key->e) != 0) {
113 *error = KM_ERROR_IMPORT_PARAMETER_MISMATCH;
114 return NULL;
115 }
116 } else {
117 // public_exponent not specified, use the one from the key.
118 public_exponent = BN_get_word(rsa_key->e);
119 if (public_exponent == 0xffffffffL) {
120 *error = KM_ERROR_IMPORT_PARAMETER_MISMATCH;
121 return NULL;
122 }
123 authorizations.push_back(TAG_RSA_PUBLIC_EXPONENT, public_exponent);
124 }
125
126 uint32_t key_size;
127 if (authorizations.GetTagValue(TAG_KEY_SIZE, &key_size)) {
128 // key_size specified, make sure it matches the key.
Shawn Willden2c242002015-02-27 07:01:02 -0700129 if (RSA_size(rsa_key.get()) * 8 != (openssl_size_t)key_size) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600130 *error = KM_ERROR_IMPORT_PARAMETER_MISMATCH;
131 return NULL;
132 }
133 } else {
134 key_size = RSA_size(rsa_key.get()) * 8;
135 authorizations.push_back(TAG_KEY_SIZE, key_size);
136 }
137
138 keymaster_algorithm_t algorithm;
139 if (authorizations.GetTagValue(TAG_ALGORITHM, &algorithm)) {
140 if (algorithm != KM_ALGORITHM_RSA) {
141 *error = KM_ERROR_IMPORT_PARAMETER_MISMATCH;
142 return NULL;
143 }
144 } else {
145 authorizations.push_back(TAG_ALGORITHM, KM_ALGORITHM_RSA);
146 }
147
148 // Don't bother with the other parameters. If the necessary padding, digest, purpose, etc. are
149 // missing, the error will be diagnosed when the key is used (when auth checking is
150 // implemented).
151 *error = KM_ERROR_OK;
Shawn Willden567a4a02014-12-31 12:14:46 -0700152 return new RsaKey(rsa_key.release(), authorizations);
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600153}
154
Shawn Willden5fad7852015-01-26 16:10:56 -0700155Key* RsaKeyFactory::RescopeKey(const UnencryptedKeyBlob& blob,
156 const AuthorizationSet& new_authorizations,
157 keymaster_error_t* error) {
158 if (!error)
159 return NULL;
160
161 RsaKey original_key(blob, error);
162 if (*error != KM_ERROR_OK)
163 return NULL;
164
165 RsaKey* new_key = new RsaKey(original_key.rsa_key_.release(), new_authorizations);
166 *error = new_key ? KM_ERROR_OK : KM_ERROR_MEMORY_ALLOCATION_FAILED;
167 return new_key;
168}
169
Shawn Willden567a4a02014-12-31 12:14:46 -0700170RsaKey::RsaKey(const UnencryptedKeyBlob& blob, keymaster_error_t* error) : AsymmetricKey(blob) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600171 if (error)
172 *error = LoadKey(blob);
173}
174
Shawn Willden63ac0432014-12-29 14:07:08 -0700175RSA* RsaKey::key() const {
176 return rsa_key_.get();
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600177}
178
179bool RsaKey::EvpToInternal(const EVP_PKEY* pkey) {
180 rsa_key_.reset(EVP_PKEY_get1_RSA(const_cast<EVP_PKEY*>(pkey)));
181 return rsa_key_.get() != NULL;
182}
183
184bool RsaKey::InternalToEvp(EVP_PKEY* pkey) const {
185 return EVP_PKEY_set1_RSA(pkey, rsa_key_.get()) == 1;
186}
187
Shawn Willden4200f212014-12-02 07:01:21 -0700188bool RsaKey::SupportedMode(keymaster_purpose_t purpose, keymaster_padding_t padding) {
189 switch (purpose) {
190 case KM_PURPOSE_SIGN:
191 case KM_PURPOSE_VERIFY:
Shawn Willdenf90f2352014-12-18 23:01:15 -0700192 return padding == KM_PAD_NONE || padding == KM_PAD_RSA_PSS ||
193 padding == KM_PAD_RSA_PKCS1_1_5_SIGN;
Shawn Willden4200f212014-12-02 07:01:21 -0700194 break;
195 case KM_PURPOSE_ENCRYPT:
196 case KM_PURPOSE_DECRYPT:
197 return padding == KM_PAD_RSA_OAEP || padding == KM_PAD_RSA_PKCS1_1_5_ENCRYPT;
198 break;
199 };
200 return false;
201}
202
203bool RsaKey::SupportedMode(keymaster_purpose_t purpose, keymaster_digest_t digest) {
204 switch (purpose) {
205 case KM_PURPOSE_SIGN:
206 case KM_PURPOSE_VERIFY:
Shawn Willden61902362014-12-18 10:33:24 -0700207 return digest == KM_DIGEST_NONE || digest == KM_DIGEST_SHA_2_256;
Shawn Willden4200f212014-12-02 07:01:21 -0700208 break;
209 case KM_PURPOSE_ENCRYPT:
210 case KM_PURPOSE_DECRYPT:
211 /* Don't care */
212 break;
213 };
214 return true;
215}
216
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600217} // namespace keymaster