blob: 903f570690649d72201f5ec78aa050e3e89ea948 [file] [log] [blame]
Shawn Willden0a4df7e2014-08-28 16:09:05 -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 Willden63ac0432014-12-29 14:07:08 -070017#include "rsa_operation.h"
18
Shawn Willden4200f212014-12-02 07:01:21 -070019#include <limits.h>
20
21#include <openssl/err.h>
Shawn Willden0a4df7e2014-08-28 16:09:05 -060022
Shawn Willden567a4a02014-12-31 12:14:46 -070023#include <keymaster/logger.h>
24
25#include "openssl_err.h"
Shawn Willden0a4df7e2014-08-28 16:09:05 -060026#include "openssl_utils.h"
Shawn Willden63ac0432014-12-29 14:07:08 -070027#include "rsa_key.h"
Shawn Willden0a4df7e2014-08-28 16:09:05 -060028
29namespace keymaster {
30
Shawn Willdenf90f2352014-12-18 23:01:15 -070031static const int MIN_PSS_SALT_LEN = 8 /* salt len */ + 2 /* overhead */;
32
Shawn Willden3ad5f052015-05-08 14:05:13 -060033bool RsaOperationFactory::GetAndValidatePadding(const AuthorizationSet& begin_params,
34 const Key& key, keymaster_padding_t* padding,
Shawn Willden63ac0432014-12-29 14:07:08 -070035 keymaster_error_t* error) const {
36 *error = KM_ERROR_UNSUPPORTED_PADDING_MODE;
Shawn Willden3ad5f052015-05-08 14:05:13 -060037 if (!begin_params.GetTagValue(TAG_PADDING, padding)) {
38 LOG_E("%d padding modes specified in begin params", begin_params.GetTagCount(TAG_PADDING));
Shawn Willdend9d7acf2015-02-25 17:37:20 -070039 return false;
Shawn Willden3ad5f052015-05-08 14:05:13 -060040 } else if (!supported(*padding)) {
41 LOG_E("Padding mode %d not supported", *padding);
Shawn Willden63ac0432014-12-29 14:07:08 -070042 return false;
Shawn Willden3ad5f052015-05-08 14:05:13 -060043 } else if (!key.authorizations().Contains(TAG_PADDING, *padding) &&
44 !key.authorizations().Contains(TAG_PADDING_OLD, *padding)) {
45 LOG_E("Padding mode %d was specified, but not authorized by key", *padding);
46 *error = KM_ERROR_INCOMPATIBLE_PADDING_MODE;
47 return false;
48 }
Shawn Willden63ac0432014-12-29 14:07:08 -070049
Shawn Willdend92591d2014-12-30 18:19:10 -070050 *error = KM_ERROR_OK;
51 return true;
Shawn Willden63ac0432014-12-29 14:07:08 -070052}
53
Shawn Willden226746b2015-05-08 11:36:56 -060054bool RsaOperationFactory::GetAndValidateDigest(const AuthorizationSet& begin_params, const Key& key,
55 keymaster_digest_t* digest,
Shawn Willden63ac0432014-12-29 14:07:08 -070056 keymaster_error_t* error) const {
57 *error = KM_ERROR_UNSUPPORTED_DIGEST;
Shawn Willden226746b2015-05-08 11:36:56 -060058 if (!begin_params.GetTagValue(TAG_DIGEST, digest)) {
59 LOG_E("%d digests specified in begin params", begin_params.GetTagCount(TAG_DIGEST));
Shawn Willden0bd61a82015-04-13 19:09:32 -070060 return false;
Shawn Willden226746b2015-05-08 11:36:56 -060061 } else if (!supported(*digest)) {
62 LOG_E("Digest %d not supported", *digest);
Shawn Willden63ac0432014-12-29 14:07:08 -070063 return false;
Shawn Willden226746b2015-05-08 11:36:56 -060064 } else if (!key.authorizations().Contains(TAG_DIGEST, *digest) &&
65 !key.authorizations().Contains(TAG_DIGEST_OLD, *digest)) {
66 LOG_E("Digest %d was specified, but not authorized by key", *digest);
67 *error = KM_ERROR_INCOMPATIBLE_DIGEST;
68 return false;
69 }
Shawn Willdend92591d2014-12-30 18:19:10 -070070 *error = KM_ERROR_OK;
71 return true;
Shawn Willden63ac0432014-12-29 14:07:08 -070072}
73
74/* static */
75RSA* RsaOperationFactory::GetRsaKey(const Key& key, keymaster_error_t* error) {
76 const RsaKey* rsa_key = static_cast<const RsaKey*>(&key);
77 assert(rsa_key);
78 if (!rsa_key || !rsa_key->key()) {
79 *error = KM_ERROR_UNKNOWN_ERROR;
80 return NULL;
81 }
Shawn Willden28eed512015-02-25 19:16:36 -070082 RSA_up_ref(rsa_key->key());
83 return rsa_key->key();
Shawn Willden63ac0432014-12-29 14:07:08 -070084}
85
Shawn Willden61902362014-12-18 10:33:24 -070086static const keymaster_digest_t supported_digests[] = {KM_DIGEST_NONE, KM_DIGEST_SHA_2_256};
Shawn Willdenf90f2352014-12-18 23:01:15 -070087static const keymaster_padding_t supported_sig_padding[] = {KM_PAD_NONE, KM_PAD_RSA_PKCS1_1_5_SIGN,
88 KM_PAD_RSA_PSS};
Shawn Willden63ac0432014-12-29 14:07:08 -070089
Shawn Willden06298102015-05-25 23:12:48 -060090const keymaster_digest_t*
91RsaDigestingOperationFactory::SupportedDigests(size_t* digest_count) const {
92 *digest_count = array_length(supported_digests);
93 return supported_digests;
94}
Shawn Willden63ac0432014-12-29 14:07:08 -070095
Shawn Willden06298102015-05-25 23:12:48 -060096const keymaster_padding_t*
97RsaDigestingOperationFactory::SupportedPaddingModes(size_t* padding_mode_count) const {
98 *padding_mode_count = array_length(supported_sig_padding);
99 return supported_sig_padding;
100}
Shawn Willden63ac0432014-12-29 14:07:08 -0700101
Shawn Willden3ed6d062015-04-15 13:39:38 -0600102Operation* RsaDigestingOperationFactory::CreateOperation(const Key& key,
Shawn Willden226746b2015-05-08 11:36:56 -0600103 const AuthorizationSet& begin_params,
Shawn Willden3ed6d062015-04-15 13:39:38 -0600104 keymaster_error_t* error) {
Shawn Willden63ac0432014-12-29 14:07:08 -0700105 keymaster_padding_t padding;
106 keymaster_digest_t digest;
107 RSA* rsa;
Shawn Willden226746b2015-05-08 11:36:56 -0600108 if (!GetAndValidateDigest(begin_params, key, &digest, error) ||
Shawn Willden3ad5f052015-05-08 14:05:13 -0600109 !GetAndValidatePadding(begin_params, key, &padding, error) ||
110 !(rsa = GetRsaKey(key, error)))
Shawn Willden63ac0432014-12-29 14:07:08 -0700111 return NULL;
112
Shawn Willden567a4a02014-12-31 12:14:46 -0700113 Operation* op = InstantiateOperation(digest, padding, rsa);
Shawn Willden63ac0432014-12-29 14:07:08 -0700114 if (!op)
115 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
116 return op;
117}
118
119static const keymaster_padding_t supported_crypt_padding[] = {KM_PAD_RSA_OAEP,
120 KM_PAD_RSA_PKCS1_1_5_ENCRYPT};
121
Shawn Willden3ed6d062015-04-15 13:39:38 -0600122Operation* RsaCryptingOperationFactory::CreateOperation(const Key& key,
Shawn Willden3ad5f052015-05-08 14:05:13 -0600123 const AuthorizationSet& begin_params,
Shawn Willden3ed6d062015-04-15 13:39:38 -0600124 keymaster_error_t* error) {
Shawn Willden63ac0432014-12-29 14:07:08 -0700125 keymaster_padding_t padding;
126 RSA* rsa;
Shawn Willden3ad5f052015-05-08 14:05:13 -0600127 if (!GetAndValidatePadding(begin_params, key, &padding, error) ||
128 !(rsa = GetRsaKey(key, error)))
Shawn Willden63ac0432014-12-29 14:07:08 -0700129 return NULL;
130
Shawn Willden567a4a02014-12-31 12:14:46 -0700131 Operation* op = InstantiateOperation(padding, rsa);
Shawn Willden63ac0432014-12-29 14:07:08 -0700132 if (!op)
133 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
134 return op;
135}
136
Shawn Willden06298102015-05-25 23:12:48 -0600137const keymaster_padding_t*
138RsaCryptingOperationFactory::SupportedPaddingModes(size_t* padding_mode_count) const {
139 *padding_mode_count = array_length(supported_crypt_padding);
140 return supported_crypt_padding;
141}
Shawn Willden63ac0432014-12-29 14:07:08 -0700142
Shawn Willden06298102015-05-25 23:12:48 -0600143const keymaster_digest_t*
144RsaCryptingOperationFactory::SupportedDigests(size_t* digest_count) const {
145 *digest_count = 0;
146 return NULL;
147}
Shawn Willden63ac0432014-12-29 14:07:08 -0700148
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600149RsaOperation::~RsaOperation() {
150 if (rsa_key_ != NULL)
151 RSA_free(rsa_key_);
152}
153
Shawn Willden6bfbff02015-02-06 19:48:24 -0700154keymaster_error_t RsaOperation::Update(const AuthorizationSet& /* additional_params */,
155 const Buffer& input, Buffer* /* output */,
Shawn Willdenb7361132014-12-08 08:15:14 -0700156 size_t* input_consumed) {
157 assert(input_consumed);
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600158 switch (purpose()) {
159 default:
160 return KM_ERROR_UNIMPLEMENTED;
161 case KM_PURPOSE_SIGN:
162 case KM_PURPOSE_VERIFY:
Shawn Willden4200f212014-12-02 07:01:21 -0700163 case KM_PURPOSE_ENCRYPT:
164 case KM_PURPOSE_DECRYPT:
Shawn Willdenb7361132014-12-08 08:15:14 -0700165 return StoreData(input, input_consumed);
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600166 }
167}
168
Shawn Willdenb7361132014-12-08 08:15:14 -0700169keymaster_error_t RsaOperation::StoreData(const Buffer& input, size_t* input_consumed) {
170 assert(input_consumed);
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600171 if (!data_.reserve(data_.available_read() + input.available_read()) ||
172 !data_.write(input.peek_read(), input.available_read()))
173 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willdenb7361132014-12-08 08:15:14 -0700174 *input_consumed = input.available_read();
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600175 return KM_ERROR_OK;
176}
177
Shawn Willden61902362014-12-18 10:33:24 -0700178RsaDigestingOperation::RsaDigestingOperation(keymaster_purpose_t purpose, keymaster_digest_t digest,
179 keymaster_padding_t padding, RSA* key)
180 : RsaOperation(purpose, padding, key), digest_(digest), digest_algorithm_(NULL) {
181 EVP_MD_CTX_init(&digest_ctx_);
182}
183RsaDigestingOperation::~RsaDigestingOperation() {
184 EVP_MD_CTX_cleanup(&digest_ctx_);
Shawn Willdenf90f2352014-12-18 23:01:15 -0700185 memset_s(digest_buf_, 0, sizeof(digest_buf_));
Shawn Willden61902362014-12-18 10:33:24 -0700186}
187
188keymaster_error_t RsaDigestingOperation::Begin(const AuthorizationSet& /* input_params */,
189 AuthorizationSet* /* output_params */) {
Shawn Willdenf90f2352014-12-18 23:01:15 -0700190 if (require_digest() && digest_ == KM_DIGEST_NONE)
191 return KM_ERROR_INCOMPATIBLE_DIGEST;
192 return InitDigest();
193}
Shawn Willden61902362014-12-18 10:33:24 -0700194
Shawn Willdenf90f2352014-12-18 23:01:15 -0700195keymaster_error_t RsaDigestingOperation::Update(const AuthorizationSet& additional_params,
196 const Buffer& input, Buffer* output,
197 size_t* input_consumed) {
198 if (digest_ == KM_DIGEST_NONE)
199 return RsaOperation::Update(additional_params, input, output, input_consumed);
200 else
201 return UpdateDigest(input, input_consumed);
202}
203
204keymaster_error_t RsaDigestingOperation::InitDigest() {
Shawn Willden61902362014-12-18 10:33:24 -0700205 switch (digest_) {
Shawn Willdenf90f2352014-12-18 23:01:15 -0700206 case KM_DIGEST_NONE:
207 return KM_ERROR_OK;
Shawn Willden61902362014-12-18 10:33:24 -0700208 case KM_DIGEST_SHA_2_256:
209 digest_algorithm_ = EVP_sha256();
210 break;
211 default:
212 return KM_ERROR_UNSUPPORTED_DIGEST;
213 }
214
215 if (!EVP_DigestInit_ex(&digest_ctx_, digest_algorithm_, NULL /* engine */)) {
216 int err = ERR_get_error();
217 LOG_E("Failed to initialize digest: %d %s", err, ERR_error_string(err, NULL));
218 return KM_ERROR_UNKNOWN_ERROR;
219 }
Shawn Willden61902362014-12-18 10:33:24 -0700220 return KM_ERROR_OK;
221}
222
Shawn Willdenf90f2352014-12-18 23:01:15 -0700223keymaster_error_t RsaDigestingOperation::UpdateDigest(const Buffer& input, size_t* input_consumed) {
Shawn Willden61902362014-12-18 10:33:24 -0700224 if (!EVP_DigestUpdate(&digest_ctx_, input.peek_read(), input.available_read())) {
225 int err = ERR_get_error();
226 LOG_E("Failed to update digest: %d %s", err, ERR_error_string(err, NULL));
227 return KM_ERROR_UNKNOWN_ERROR;
228 }
229 *input_consumed = input.available_read();
230 return KM_ERROR_OK;
231}
232
Shawn Willdenf90f2352014-12-18 23:01:15 -0700233keymaster_error_t RsaDigestingOperation::FinishDigest(unsigned* digest_size) {
Shawn Willden61902362014-12-18 10:33:24 -0700234 assert(digest_algorithm_ != NULL);
Shawn Willdenf90f2352014-12-18 23:01:15 -0700235 if (!EVP_DigestFinal_ex(&digest_ctx_, digest_buf_, digest_size)) {
Shawn Willden61902362014-12-18 10:33:24 -0700236 int err = ERR_get_error();
237 LOG_E("Failed to finalize digest: %d %s", err, ERR_error_string(err, NULL));
Shawn Willdenf90f2352014-12-18 23:01:15 -0700238 return KM_ERROR_UNKNOWN_ERROR;
Shawn Willden61902362014-12-18 10:33:24 -0700239 }
240 assert(*digest_size == static_cast<unsigned>(EVP_MD_size(digest_algorithm_)));
Shawn Willdenf90f2352014-12-18 23:01:15 -0700241 return KM_ERROR_OK;
Shawn Willden61902362014-12-18 10:33:24 -0700242}
243
Shawn Willden6bfbff02015-02-06 19:48:24 -0700244keymaster_error_t RsaSignOperation::Finish(const AuthorizationSet& /* additional_params */,
245 const Buffer& /* signature */, Buffer* output) {
Shawn Willdenb7361132014-12-08 08:15:14 -0700246 assert(output);
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600247 output->Reinitialize(RSA_size(rsa_key_));
Shawn Willdenf90f2352014-12-18 23:01:15 -0700248 if (digest_ == KM_DIGEST_NONE)
249 return SignUndigested(output);
250 else
251 return SignDigested(output);
252}
Shawn Willden61902362014-12-18 10:33:24 -0700253
Shawn Willdenf90f2352014-12-18 23:01:15 -0700254keymaster_error_t RsaSignOperation::SignUndigested(Buffer* output) {
255 int bytes_encrypted;
256 switch (padding_) {
257 case KM_PAD_NONE:
258 bytes_encrypted = RSA_private_encrypt(data_.available_read(), data_.peek_read(),
259 output->peek_write(), rsa_key_, RSA_NO_PADDING);
260 break;
261 case KM_PAD_RSA_PKCS1_1_5_SIGN:
262 bytes_encrypted = RSA_private_encrypt(data_.available_read(), data_.peek_read(),
263 output->peek_write(), rsa_key_, RSA_PKCS1_PADDING);
264 break;
265 default:
266 return KM_ERROR_UNSUPPORTED_PADDING_MODE;
267 }
Shawn Willden61902362014-12-18 10:33:24 -0700268
Shawn Willdenf90f2352014-12-18 23:01:15 -0700269 if (bytes_encrypted <= 0)
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600270 return KM_ERROR_UNKNOWN_ERROR;
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600271 output->advance_write(bytes_encrypted);
272 return KM_ERROR_OK;
273}
274
Shawn Willdenf90f2352014-12-18 23:01:15 -0700275keymaster_error_t RsaSignOperation::SignDigested(Buffer* output) {
276 unsigned digest_size = 0;
277 keymaster_error_t error = FinishDigest(&digest_size);
278 if (error != KM_ERROR_OK)
279 return error;
280
281 UniquePtr<uint8_t[]> padded_digest;
282 switch (padding_) {
283 case KM_PAD_NONE:
Shawn Willden3ad5f052015-05-08 14:05:13 -0600284 LOG_E("Digesting requires padding", 0);
285 return KM_ERROR_INCOMPATIBLE_PADDING_MODE;
Shawn Willdenf90f2352014-12-18 23:01:15 -0700286 case KM_PAD_RSA_PKCS1_1_5_SIGN:
287 return PrivateEncrypt(digest_buf_, digest_size, RSA_PKCS1_PADDING, output);
288 case KM_PAD_RSA_PSS:
289 // OpenSSL doesn't verify that the key is large enough for the digest size. This can cause
290 // a segfault in some cases, and in others can result in a unsafely-small salt.
Shawn Willden3ad5f052015-05-08 14:05:13 -0600291 if ((unsigned)RSA_size(rsa_key_) < MIN_PSS_SALT_LEN + digest_size) {
292 LOG_E("%d-byte too small for PSS padding and %d-byte digest", RSA_size(rsa_key_),
293 digest_size);
Shawn Willden2c242002015-02-27 07:01:02 -0700294 // TODO(swillden): Add a better return code for this.
Shawn Willdenf90f2352014-12-18 23:01:15 -0700295 return KM_ERROR_INCOMPATIBLE_DIGEST;
Shawn Willden3ad5f052015-05-08 14:05:13 -0600296 }
Shawn Willdenf90f2352014-12-18 23:01:15 -0700297
298 if ((error = PssPadDigest(&padded_digest)) != KM_ERROR_OK)
299 return error;
300 return PrivateEncrypt(padded_digest.get(), RSA_size(rsa_key_), RSA_NO_PADDING, output);
301 default:
302 return KM_ERROR_UNSUPPORTED_PADDING_MODE;
303 }
Shawn Willden61902362014-12-18 10:33:24 -0700304}
305
Shawn Willdenf90f2352014-12-18 23:01:15 -0700306keymaster_error_t RsaSignOperation::PssPadDigest(UniquePtr<uint8_t[]>* padded_digest) {
307 padded_digest->reset(new uint8_t[RSA_size(rsa_key_)]);
308 if (!padded_digest->get())
309 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
310
Adam Langleyadb0f332015-03-05 19:57:29 -0800311 if (!RSA_padding_add_PKCS1_PSS_mgf1(rsa_key_, padded_digest->get(), digest_buf_,
312 digest_algorithm_, NULL,
313 -2 /* Indicates maximum salt length */)) {
Shawn Willdenf90f2352014-12-18 23:01:15 -0700314 LOG_E("%s", "Failed to apply PSS padding");
Shawn Willden61902362014-12-18 10:33:24 -0700315 return KM_ERROR_UNKNOWN_ERROR;
Shawn Willdenf90f2352014-12-18 23:01:15 -0700316 }
317 return KM_ERROR_OK;
318}
319
320keymaster_error_t RsaSignOperation::PrivateEncrypt(uint8_t* to_encrypt, size_t len,
321 int openssl_padding, Buffer* output) {
322 int bytes_encrypted =
323 RSA_private_encrypt(len, to_encrypt, output->peek_write(), rsa_key_, openssl_padding);
324 if (bytes_encrypted <= 0)
325 return KM_ERROR_UNKNOWN_ERROR;
326 output->advance_write(bytes_encrypted);
327 return KM_ERROR_OK;
Shawn Willden61902362014-12-18 10:33:24 -0700328}
329
Shawn Willden6bfbff02015-02-06 19:48:24 -0700330keymaster_error_t RsaVerifyOperation::Finish(const AuthorizationSet& /* additional_params */,
331 const Buffer& signature, Buffer* /* output */) {
Shawn Willdenf90f2352014-12-18 23:01:15 -0700332 if (digest_ == KM_DIGEST_NONE)
333 return VerifyUndigested(signature);
334 else
335 return VerifyDigested(signature);
Shawn Willden61902362014-12-18 10:33:24 -0700336}
337
Shawn Willdenf90f2352014-12-18 23:01:15 -0700338keymaster_error_t RsaVerifyOperation::VerifyUndigested(const Buffer& signature) {
339 return DecryptAndMatch(signature, data_.peek_read(), data_.available_read());
Shawn Willden61902362014-12-18 10:33:24 -0700340}
341
Shawn Willdenf90f2352014-12-18 23:01:15 -0700342keymaster_error_t RsaVerifyOperation::VerifyDigested(const Buffer& signature) {
Shawn Willden61902362014-12-18 10:33:24 -0700343 unsigned digest_size = 0;
Shawn Willdenf90f2352014-12-18 23:01:15 -0700344 keymaster_error_t error = FinishDigest(&digest_size);
345 if (error != KM_ERROR_OK)
346 return error;
347 return DecryptAndMatch(signature, digest_buf_, digest_size);
348}
Shawn Willden61902362014-12-18 10:33:24 -0700349
Shawn Willdenf90f2352014-12-18 23:01:15 -0700350keymaster_error_t RsaVerifyOperation::DecryptAndMatch(const Buffer& signature,
351 const uint8_t* to_match, size_t len) {
352#ifdef OPENSSL_IS_BORINGSSL
353 size_t key_len = RSA_size(rsa_key_);
354#else
355 size_t key_len = (size_t)RSA_size(rsa_key_);
356#endif
357
358 int openssl_padding;
359 switch (padding_) {
360 case KM_PAD_NONE:
361 if (len != key_len)
362 return KM_ERROR_INVALID_INPUT_LENGTH;
363 if (len != signature.available_read())
364 return KM_ERROR_VERIFICATION_FAILED;
365 openssl_padding = RSA_NO_PADDING;
366 break;
367 case KM_PAD_RSA_PSS: // Do a raw decrypt for PSS
368 openssl_padding = RSA_NO_PADDING;
369 break;
370 case KM_PAD_RSA_PKCS1_1_5_SIGN:
371 openssl_padding = RSA_PKCS1_PADDING;
372 break;
373 default:
374 return KM_ERROR_UNSUPPORTED_PADDING_MODE;
375 }
376
377 UniquePtr<uint8_t[]> decrypted_data(new uint8_t[key_len]);
378 int bytes_decrypted = RSA_public_decrypt(signature.available_read(), signature.peek_read(),
379 decrypted_data.get(), rsa_key_, openssl_padding);
380 if (bytes_decrypted < 0)
381 return KM_ERROR_VERIFICATION_FAILED;
382
383 if (padding_ == KM_PAD_RSA_PSS &&
Adam Langleyadb0f332015-03-05 19:57:29 -0800384 RSA_verify_PKCS1_PSS_mgf1(rsa_key_, to_match, digest_algorithm_, NULL, decrypted_data.get(),
385 -2 /* salt length recovered from signature */))
Shawn Willdenf90f2352014-12-18 23:01:15 -0700386 return KM_ERROR_OK;
Shawn Willden197d9af2015-05-09 12:48:16 +0000387 else if (padding_ != KM_PAD_RSA_PSS && memcmp_s(decrypted_data.get(), to_match, len) == 0)
Shawn Willden61902362014-12-18 10:33:24 -0700388 return KM_ERROR_OK;
389
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600390 return KM_ERROR_VERIFICATION_FAILED;
391}
392
Shawn Willden7bae1322015-05-26 10:16:49 -0600393const int OAEP_PADDING_OVERHEAD = 42;
Shawn Willden4200f212014-12-02 07:01:21 -0700394const int PKCS1_PADDING_OVERHEAD = 11;
395
Shawn Willden6bfbff02015-02-06 19:48:24 -0700396keymaster_error_t RsaEncryptOperation::Finish(const AuthorizationSet& /* additional_params */,
397 const Buffer& /* signature */, Buffer* output) {
Shawn Willdenb7361132014-12-08 08:15:14 -0700398 assert(output);
Shawn Willden4200f212014-12-02 07:01:21 -0700399 int openssl_padding;
400
401#if defined(OPENSSL_IS_BORINGSSL)
Shawn Willdenf90f2352014-12-18 23:01:15 -0700402 size_t key_len = RSA_size(rsa_key_);
Shawn Willden4200f212014-12-02 07:01:21 -0700403#else
Shawn Willdenf90f2352014-12-18 23:01:15 -0700404 size_t key_len = (size_t)RSA_size(rsa_key_);
Shawn Willden4200f212014-12-02 07:01:21 -0700405#endif
406
Shawn Willdenf90f2352014-12-18 23:01:15 -0700407 size_t message_size = data_.available_read();
Shawn Willden4200f212014-12-02 07:01:21 -0700408 switch (padding_) {
409 case KM_PAD_RSA_OAEP:
410 openssl_padding = RSA_PKCS1_OAEP_PADDING;
Shawn Willden7bae1322015-05-26 10:16:49 -0600411 if (message_size + OAEP_PADDING_OVERHEAD > key_len) {
Shawn Willden567a4a02014-12-31 12:14:46 -0700412 LOG_E("Cannot encrypt %d bytes with %d-byte key and OAEP padding",
Shawn Willdenf90f2352014-12-18 23:01:15 -0700413 data_.available_read(), key_len);
Shawn Willden4200f212014-12-02 07:01:21 -0700414 return KM_ERROR_INVALID_INPUT_LENGTH;
415 }
416 break;
417 case KM_PAD_RSA_PKCS1_1_5_ENCRYPT:
418 openssl_padding = RSA_PKCS1_PADDING;
Shawn Willden7bae1322015-05-26 10:16:49 -0600419 if (message_size + PKCS1_PADDING_OVERHEAD > key_len) {
Shawn Willden567a4a02014-12-31 12:14:46 -0700420 LOG_E("Cannot encrypt %d bytes with %d-byte key and PKCS1 padding",
Shawn Willdenf90f2352014-12-18 23:01:15 -0700421 data_.available_read(), key_len);
Shawn Willden4200f212014-12-02 07:01:21 -0700422 return KM_ERROR_INVALID_INPUT_LENGTH;
423 }
424 break;
425 default:
Shawn Willden567a4a02014-12-31 12:14:46 -0700426 LOG_E("Padding mode %d not supported", padding_);
Shawn Willden4200f212014-12-02 07:01:21 -0700427 return KM_ERROR_UNSUPPORTED_PADDING_MODE;
428 }
429
430 output->Reinitialize(RSA_size(rsa_key_));
431 int bytes_encrypted = RSA_public_encrypt(data_.available_read(), data_.peek_read(),
432 output->peek_write(), rsa_key_, openssl_padding);
433
434 if (bytes_encrypted < 0) {
Shawn Willden567a4a02014-12-31 12:14:46 -0700435 LOG_E("Error %d encrypting data with RSA", ERR_get_error());
Shawn Willden4200f212014-12-02 07:01:21 -0700436 return KM_ERROR_UNKNOWN_ERROR;
437 }
Shawn Willden67380a92015-05-13 12:07:50 -0600438 assert(bytes_encrypted == (int)RSA_size(rsa_key_));
Shawn Willden4200f212014-12-02 07:01:21 -0700439 output->advance_write(bytes_encrypted);
440
441 return KM_ERROR_OK;
442}
443
Shawn Willden6bfbff02015-02-06 19:48:24 -0700444keymaster_error_t RsaDecryptOperation::Finish(const AuthorizationSet& /* additional_params */,
445 const Buffer& /* signature */, Buffer* output) {
Shawn Willdenb7361132014-12-08 08:15:14 -0700446 assert(output);
Shawn Willden4200f212014-12-02 07:01:21 -0700447 int openssl_padding;
448 switch (padding_) {
449 case KM_PAD_RSA_OAEP:
450 openssl_padding = RSA_PKCS1_OAEP_PADDING;
451 break;
452 case KM_PAD_RSA_PKCS1_1_5_ENCRYPT:
453 openssl_padding = RSA_PKCS1_PADDING;
454 break;
455 default:
Shawn Willden567a4a02014-12-31 12:14:46 -0700456 LOG_E("Padding mode %d not supported", padding_);
Shawn Willden4200f212014-12-02 07:01:21 -0700457 return KM_ERROR_UNSUPPORTED_PADDING_MODE;
458 }
459
460 output->Reinitialize(RSA_size(rsa_key_));
461 int bytes_decrypted = RSA_private_decrypt(data_.available_read(), data_.peek_read(),
462 output->peek_write(), rsa_key_, openssl_padding);
463
464 if (bytes_decrypted < 0) {
Shawn Willden567a4a02014-12-31 12:14:46 -0700465 LOG_E("Error %d decrypting data with RSA", ERR_get_error());
Shawn Willden4200f212014-12-02 07:01:21 -0700466 return KM_ERROR_UNKNOWN_ERROR;
467 }
468 output->advance_write(bytes_decrypted);
469
470 return KM_ERROR_OK;
471}
472
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600473} // namespace keymaster