blob: c92bab055a9514a49d2d8fd3291b5e7fa404e4ac [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 -070032static KeyFactoryRegistry::Registration<RsaKeyFactory> registration;
33
Shawn Willden13011cc2015-03-04 09:41:54 -070034Key* RsaKeyFactory::LoadKey(const UnencryptedKeyBlob& blob, keymaster_error_t* error) {
35 return new RsaKey(blob, error);
36}
37
Shawn Willden567a4a02014-12-31 12:14:46 -070038Key* RsaKeyFactory::GenerateKey(const AuthorizationSet& key_description, keymaster_error_t* error) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060039 if (!error)
40 return NULL;
41
42 AuthorizationSet authorizations(key_description);
43
Shawn Willden3b4e1652015-02-27 13:33:01 -070044 uint64_t public_exponent;
45 if (!authorizations.GetTagValue(TAG_RSA_PUBLIC_EXPONENT, &public_exponent)) {
46 LOG_E("%s", "No public exponent specified for RSA key generation");
47 *error = KM_ERROR_INVALID_ARGUMENT;
48 return NULL;
49 }
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060050
Shawn Willden3b4e1652015-02-27 13:33:01 -070051 uint32_t key_size;
52 if (!authorizations.GetTagValue(TAG_KEY_SIZE, &key_size)) {
53 LOG_E("%s", "No key size specified for RSA key generation");
54 *error = KM_ERROR_UNSUPPORTED_KEY_SIZE;
55 return NULL;
56 }
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060057
58 UniquePtr<BIGNUM, BIGNUM_Delete> exponent(BN_new());
Shawn Willdena278f612014-12-23 11:22:21 -070059 UniquePtr<RSA, RsaKey::RSA_Delete> rsa_key(RSA_new());
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060060 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKEY_new());
Shawn Willden3b4e1652015-02-27 13:33:01 -070061 if (exponent.get() == NULL || rsa_key.get() == NULL || pkey.get() == NULL) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060062 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
63 return NULL;
64 }
65
66 if (!BN_set_word(exponent.get(), public_exponent) ||
67 !RSA_generate_key_ex(rsa_key.get(), key_size, exponent.get(), NULL /* callback */)) {
Shawn Willden567a4a02014-12-31 12:14:46 -070068 *error = TranslateLastOpenSslError();
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060069 return NULL;
70 }
71
Shawn Willden567a4a02014-12-31 12:14:46 -070072 RsaKey* new_key = new RsaKey(rsa_key.release(), authorizations);
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060073 *error = new_key ? KM_ERROR_OK : KM_ERROR_MEMORY_ALLOCATION_FAILED;
74 return new_key;
75}
76
Shawn Willdena278f612014-12-23 11:22:21 -070077Key* RsaKeyFactory::ImportKey(const AuthorizationSet& key_description,
78 keymaster_key_format_t key_format, const uint8_t* key_data,
Shawn Willden567a4a02014-12-31 12:14:46 -070079 size_t key_data_length, keymaster_error_t* error) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060080 if (!error)
81 return NULL;
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060082
Shawn Willdena278f612014-12-23 11:22:21 -070083 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(
84 ExtractEvpKey(key_format, KM_ALGORITHM_RSA, key_data, key_data_length, error));
85 if (*error != KM_ERROR_OK)
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060086 return NULL;
Shawn Willdena278f612014-12-23 11:22:21 -070087 assert(pkey.get());
88
89 UniquePtr<RSA, RsaKey::RSA_Delete> rsa_key(EVP_PKEY_get1_RSA(pkey.get()));
90 if (!rsa_key.get()) {
Shawn Willden567a4a02014-12-31 12:14:46 -070091 *error = TranslateLastOpenSslError();
Shawn Willdena278f612014-12-23 11:22:21 -070092 return NULL;
93 }
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060094
95 AuthorizationSet authorizations(key_description);
96
97 uint64_t public_exponent;
98 if (authorizations.GetTagValue(TAG_RSA_PUBLIC_EXPONENT, &public_exponent)) {
99 // public_exponent specified, make sure it matches the key
100 UniquePtr<BIGNUM, BIGNUM_Delete> public_exponent_bn(BN_new());
101 if (!BN_set_word(public_exponent_bn.get(), public_exponent))
102 return NULL;
103 if (BN_cmp(public_exponent_bn.get(), rsa_key->e) != 0) {
104 *error = KM_ERROR_IMPORT_PARAMETER_MISMATCH;
105 return NULL;
106 }
107 } else {
108 // public_exponent not specified, use the one from the key.
109 public_exponent = BN_get_word(rsa_key->e);
110 if (public_exponent == 0xffffffffL) {
111 *error = KM_ERROR_IMPORT_PARAMETER_MISMATCH;
112 return NULL;
113 }
114 authorizations.push_back(TAG_RSA_PUBLIC_EXPONENT, public_exponent);
115 }
116
117 uint32_t key_size;
118 if (authorizations.GetTagValue(TAG_KEY_SIZE, &key_size)) {
119 // key_size specified, make sure it matches the key.
Shawn Willden2c242002015-02-27 07:01:02 -0700120 if (RSA_size(rsa_key.get()) * 8 != (openssl_size_t)key_size) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600121 *error = KM_ERROR_IMPORT_PARAMETER_MISMATCH;
122 return NULL;
123 }
124 } else {
125 key_size = RSA_size(rsa_key.get()) * 8;
126 authorizations.push_back(TAG_KEY_SIZE, key_size);
127 }
128
129 keymaster_algorithm_t algorithm;
130 if (authorizations.GetTagValue(TAG_ALGORITHM, &algorithm)) {
131 if (algorithm != KM_ALGORITHM_RSA) {
132 *error = KM_ERROR_IMPORT_PARAMETER_MISMATCH;
133 return NULL;
134 }
135 } else {
136 authorizations.push_back(TAG_ALGORITHM, KM_ALGORITHM_RSA);
137 }
138
139 // Don't bother with the other parameters. If the necessary padding, digest, purpose, etc. are
140 // missing, the error will be diagnosed when the key is used (when auth checking is
141 // implemented).
142 *error = KM_ERROR_OK;
Shawn Willden567a4a02014-12-31 12:14:46 -0700143 return new RsaKey(rsa_key.release(), authorizations);
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600144}
145
Shawn Willden5fad7852015-01-26 16:10:56 -0700146Key* RsaKeyFactory::RescopeKey(const UnencryptedKeyBlob& blob,
147 const AuthorizationSet& new_authorizations,
148 keymaster_error_t* error) {
149 if (!error)
150 return NULL;
151
152 RsaKey original_key(blob, error);
153 if (*error != KM_ERROR_OK)
154 return NULL;
155
156 RsaKey* new_key = new RsaKey(original_key.rsa_key_.release(), new_authorizations);
157 *error = new_key ? KM_ERROR_OK : KM_ERROR_MEMORY_ALLOCATION_FAILED;
158 return new_key;
159}
160
Shawn Willden567a4a02014-12-31 12:14:46 -0700161RsaKey::RsaKey(const UnencryptedKeyBlob& blob, keymaster_error_t* error) : AsymmetricKey(blob) {
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600162 if (error)
163 *error = LoadKey(blob);
164}
165
Shawn Willden63ac0432014-12-29 14:07:08 -0700166RSA* RsaKey::key() const {
167 return rsa_key_.get();
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600168}
169
170bool RsaKey::EvpToInternal(const EVP_PKEY* pkey) {
171 rsa_key_.reset(EVP_PKEY_get1_RSA(const_cast<EVP_PKEY*>(pkey)));
172 return rsa_key_.get() != NULL;
173}
174
175bool RsaKey::InternalToEvp(EVP_PKEY* pkey) const {
176 return EVP_PKEY_set1_RSA(pkey, rsa_key_.get()) == 1;
177}
178
Shawn Willden4200f212014-12-02 07:01:21 -0700179bool RsaKey::SupportedMode(keymaster_purpose_t purpose, keymaster_padding_t padding) {
180 switch (purpose) {
181 case KM_PURPOSE_SIGN:
182 case KM_PURPOSE_VERIFY:
Shawn Willdenf90f2352014-12-18 23:01:15 -0700183 return padding == KM_PAD_NONE || padding == KM_PAD_RSA_PSS ||
184 padding == KM_PAD_RSA_PKCS1_1_5_SIGN;
Shawn Willden4200f212014-12-02 07:01:21 -0700185 break;
186 case KM_PURPOSE_ENCRYPT:
187 case KM_PURPOSE_DECRYPT:
188 return padding == KM_PAD_RSA_OAEP || padding == KM_PAD_RSA_PKCS1_1_5_ENCRYPT;
189 break;
190 };
191 return false;
192}
193
194bool RsaKey::SupportedMode(keymaster_purpose_t purpose, keymaster_digest_t digest) {
195 switch (purpose) {
196 case KM_PURPOSE_SIGN:
197 case KM_PURPOSE_VERIFY:
Shawn Willden61902362014-12-18 10:33:24 -0700198 return digest == KM_DIGEST_NONE || digest == KM_DIGEST_SHA_2_256;
Shawn Willden4200f212014-12-02 07:01:21 -0700199 break;
200 case KM_PURPOSE_ENCRYPT:
201 case KM_PURPOSE_DECRYPT:
202 /* Don't care */
203 break;
204 };
205 return true;
206}
207
Shawn Willden2c8dd3e2014-09-18 15:16:31 -0600208} // namespace keymaster