blob: 2046a64143caa5b23e3ba389e0a84c602bae8144 [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
Shawn Willden0f906ec2015-06-20 09:16:30 -060021#include <new>
22
Shawn Willden4200f212014-12-02 07:01:21 -070023#include <openssl/err.h>
Shawn Willden0a4df7e2014-08-28 16:09:05 -060024
Shawn Willden567a4a02014-12-31 12:14:46 -070025#include <keymaster/logger.h>
26
27#include "openssl_err.h"
Shawn Willden0a4df7e2014-08-28 16:09:05 -060028#include "openssl_utils.h"
Shawn Willden63ac0432014-12-29 14:07:08 -070029#include "rsa_key.h"
Shawn Willden0a4df7e2014-08-28 16:09:05 -060030
31namespace keymaster {
32
Shawn Willdend5303052015-06-22 05:25:59 -060033const size_t kPssOverhead = 2;
Shawn Willden53488c62015-07-16 18:15:45 -060034const size_t kMinPssSaltSize = 20;
Shawn Willdend5303052015-06-22 05:25:59 -060035
36// Overhead for PKCS#1 v1.5 signature padding of undigested messages. Digested messages have
37// additional overhead, for the digest algorithmIdentifier required by PKCS#1.
38const size_t kPkcs1UndigestedSignaturePaddingOverhead = 11;
39
Shawn Willden63ac0432014-12-29 14:07:08 -070040/* static */
Shawn Willden2bf4ad32015-06-01 07:33:51 -060041EVP_PKEY* RsaOperationFactory::GetRsaKey(const Key& key, keymaster_error_t* error) {
Shawn Willden63ac0432014-12-29 14:07:08 -070042 const RsaKey* rsa_key = static_cast<const RsaKey*>(&key);
43 assert(rsa_key);
44 if (!rsa_key || !rsa_key->key()) {
45 *error = KM_ERROR_UNKNOWN_ERROR;
Shawn Willden2bf4ad32015-06-01 07:33:51 -060046 return nullptr;
Shawn Willden63ac0432014-12-29 14:07:08 -070047 }
Shawn Willden2bf4ad32015-06-01 07:33:51 -060048
49 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKEY_new());
50 if (!rsa_key->InternalToEvp(pkey.get())) {
51 *error = KM_ERROR_UNKNOWN_ERROR;
52 return nullptr;
53 }
54 return pkey.release();
Shawn Willden63ac0432014-12-29 14:07:08 -070055}
56
Shawn Willden2bf4ad32015-06-01 07:33:51 -060057static const keymaster_digest_t supported_digests[] = {
58 KM_DIGEST_NONE, KM_DIGEST_MD5, KM_DIGEST_SHA1, KM_DIGEST_SHA_2_224,
59 KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512};
Shawn Willden63ac0432014-12-29 14:07:08 -070060
Shawn Willden0afa3c82015-06-22 10:39:21 -060061const keymaster_digest_t* RsaOperationFactory::SupportedDigests(size_t* digest_count) const {
Shawn Willden06298102015-05-25 23:12:48 -060062 *digest_count = array_length(supported_digests);
63 return supported_digests;
64}
Shawn Willden63ac0432014-12-29 14:07:08 -070065
Shawn Willden0afa3c82015-06-22 10:39:21 -060066RsaOperation* RsaOperationFactory::CreateRsaOperation(const Key& key,
67 const AuthorizationSet& begin_params,
68 keymaster_error_t* error) {
69 keymaster_padding_t padding;
Shawn Willden0afa3c82015-06-22 10:39:21 -060070 if (!GetAndValidatePadding(begin_params, key, &padding, error))
71 return nullptr;
72
73 bool require_digest = (purpose() == KM_PURPOSE_SIGN || purpose() == KM_PURPOSE_VERIFY ||
74 padding == KM_PAD_RSA_OAEP);
75
Shawn Willden7d05d882015-07-10 14:03:14 -060076 keymaster_digest_t digest = KM_DIGEST_NONE;
Shawn Willden0afa3c82015-06-22 10:39:21 -060077 if (require_digest && !GetAndValidateDigest(begin_params, key, &digest, error))
78 return nullptr;
Shawn Willden0afa3c82015-06-22 10:39:21 -060079
80 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> rsa(GetRsaKey(key, error));
81 if (!rsa.get())
82 return nullptr;
83
84 RsaOperation* op = InstantiateOperation(digest, padding, rsa.release());
85 if (!op)
86 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
87 return op;
88}
89
90static const keymaster_padding_t supported_sig_padding[] = {KM_PAD_NONE, KM_PAD_RSA_PKCS1_1_5_SIGN,
91 KM_PAD_RSA_PSS};
Shawn Willden06298102015-05-25 23:12:48 -060092const keymaster_padding_t*
93RsaDigestingOperationFactory::SupportedPaddingModes(size_t* padding_mode_count) const {
94 *padding_mode_count = array_length(supported_sig_padding);
95 return supported_sig_padding;
96}
Shawn Willden63ac0432014-12-29 14:07:08 -070097
Shawn Willden0afa3c82015-06-22 10:39:21 -060098RsaOperation* RsaCryptingOperationFactory::CreateRsaOperation(const Key& key,
99 const AuthorizationSet& begin_params,
100 keymaster_error_t* error) {
101 UniquePtr<RsaOperation> op(RsaOperationFactory::CreateRsaOperation(key, begin_params, error));
102 if (op.get()) {
103 switch (op->padding()) {
104 case KM_PAD_NONE:
105 case KM_PAD_RSA_PKCS1_1_5_ENCRYPT:
106 if (op->digest() != KM_DIGEST_NONE) {
107 *error = KM_ERROR_INCOMPATIBLE_DIGEST;
108 return nullptr;
109 }
110 break;
Shawn Willden63ac0432014-12-29 14:07:08 -0700111
Shawn Willden0afa3c82015-06-22 10:39:21 -0600112 case KM_PAD_RSA_OAEP:
113 if (op->digest() == KM_DIGEST_NONE) {
114 *error = KM_ERROR_INCOMPATIBLE_DIGEST;
115 return nullptr;
116 }
117 break;
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600118
Shawn Willden0afa3c82015-06-22 10:39:21 -0600119 default:
120 *error = KM_ERROR_UNSUPPORTED_PADDING_MODE;
121 return nullptr;
122 }
123 }
124 return op.release();
Shawn Willden63ac0432014-12-29 14:07:08 -0700125}
126
Shawn Willden30160842015-06-01 08:31:00 -0600127static const keymaster_padding_t supported_crypt_padding[] = {KM_PAD_NONE, KM_PAD_RSA_OAEP,
Shawn Willden63ac0432014-12-29 14:07:08 -0700128 KM_PAD_RSA_PKCS1_1_5_ENCRYPT};
Shawn Willden06298102015-05-25 23:12:48 -0600129const keymaster_padding_t*
130RsaCryptingOperationFactory::SupportedPaddingModes(size_t* padding_mode_count) const {
131 *padding_mode_count = array_length(supported_crypt_padding);
132 return supported_crypt_padding;
133}
Shawn Willden63ac0432014-12-29 14:07:08 -0700134
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600135RsaOperation::~RsaOperation() {
136 if (rsa_key_ != NULL)
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600137 EVP_PKEY_free(rsa_key_);
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600138}
139
Shawn Willden7d05d882015-07-10 14:03:14 -0600140keymaster_error_t RsaOperation::Begin(const AuthorizationSet& /* input_params */,
141 AuthorizationSet* /* output_params */) {
142 return InitDigest();
143}
144
Shawn Willden6bfbff02015-02-06 19:48:24 -0700145keymaster_error_t RsaOperation::Update(const AuthorizationSet& /* additional_params */,
Shawn Willdended8e7d2015-06-01 15:29:12 -0600146 const Buffer& input, AuthorizationSet* /* output_params */,
147 Buffer* /* output */, size_t* input_consumed) {
Shawn Willdenb7361132014-12-08 08:15:14 -0700148 assert(input_consumed);
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600149 switch (purpose()) {
150 default:
151 return KM_ERROR_UNIMPLEMENTED;
152 case KM_PURPOSE_SIGN:
153 case KM_PURPOSE_VERIFY:
Shawn Willden4200f212014-12-02 07:01:21 -0700154 case KM_PURPOSE_ENCRYPT:
155 case KM_PURPOSE_DECRYPT:
Shawn Willdenb7361132014-12-08 08:15:14 -0700156 return StoreData(input, input_consumed);
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600157 }
158}
159
Shawn Willdenb7361132014-12-08 08:15:14 -0700160keymaster_error_t RsaOperation::StoreData(const Buffer& input, size_t* input_consumed) {
161 assert(input_consumed);
Shawn Willdend5303052015-06-22 05:25:59 -0600162
163 if (!data_.reserve(EVP_PKEY_size(rsa_key_)))
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600164 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willdend5303052015-06-22 05:25:59 -0600165 // If the write fails, it's because input length exceeds key size.
166 if (!data_.write(input.peek_read(), input.available_read())) {
Shawn Willden2101e9e2015-06-24 12:22:02 -0700167 LOG_E("Input too long: cannot operate on %u bytes of data with %u-byte RSA key",
168 input.available_read() + data_.available_read(), EVP_PKEY_size(rsa_key_));
Shawn Willdend5303052015-06-22 05:25:59 -0600169 return KM_ERROR_INVALID_INPUT_LENGTH;
170 }
171
Shawn Willdenb7361132014-12-08 08:15:14 -0700172 *input_consumed = input.available_read();
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600173 return KM_ERROR_OK;
174}
175
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600176keymaster_error_t RsaOperation::SetRsaPaddingInEvpContext(EVP_PKEY_CTX* pkey_ctx) {
177 keymaster_error_t error;
178 int openssl_padding = GetOpensslPadding(&error);
179 if (error != KM_ERROR_OK)
180 return error;
181
182 if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, openssl_padding) <= 0)
183 return TranslateLastOpenSslError();
184 return KM_ERROR_OK;
185}
186
Shawn Willden0afa3c82015-06-22 10:39:21 -0600187keymaster_error_t RsaOperation::InitDigest() {
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600188 if (digest_ == KM_DIGEST_NONE) {
189 if (require_digest())
190 return KM_ERROR_INCOMPATIBLE_DIGEST;
191 return KM_ERROR_OK;
192 }
193
Shawn Willden61902362014-12-18 10:33:24 -0700194 switch (digest_) {
Shawn Willdenf90f2352014-12-18 23:01:15 -0700195 case KM_DIGEST_NONE:
196 return KM_ERROR_OK;
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600197 case KM_DIGEST_MD5:
198 digest_algorithm_ = EVP_md5();
199 return KM_ERROR_OK;
200 case KM_DIGEST_SHA1:
201 digest_algorithm_ = EVP_sha1();
202 return KM_ERROR_OK;
203 case KM_DIGEST_SHA_2_224:
204 digest_algorithm_ = EVP_sha224();
205 return KM_ERROR_OK;
Shawn Willden61902362014-12-18 10:33:24 -0700206 case KM_DIGEST_SHA_2_256:
207 digest_algorithm_ = EVP_sha256();
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600208 return KM_ERROR_OK;
209 case KM_DIGEST_SHA_2_384:
210 digest_algorithm_ = EVP_sha384();
211 return KM_ERROR_OK;
212 case KM_DIGEST_SHA_2_512:
213 digest_algorithm_ = EVP_sha512();
214 return KM_ERROR_OK;
Shawn Willden61902362014-12-18 10:33:24 -0700215 default:
216 return KM_ERROR_UNSUPPORTED_DIGEST;
217 }
Shawn Willden61902362014-12-18 10:33:24 -0700218}
219
Shawn Willden0afa3c82015-06-22 10:39:21 -0600220RsaDigestingOperation::RsaDigestingOperation(keymaster_purpose_t purpose, keymaster_digest_t digest,
221 keymaster_padding_t padding, EVP_PKEY* key)
222 : RsaOperation(purpose, digest, padding, key) {
223 EVP_MD_CTX_init(&digest_ctx_);
224}
225RsaDigestingOperation::~RsaDigestingOperation() {
226 EVP_MD_CTX_cleanup(&digest_ctx_);
227}
228
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600229int RsaDigestingOperation::GetOpensslPadding(keymaster_error_t* error) {
230 *error = KM_ERROR_OK;
231 switch (padding_) {
232 case KM_PAD_NONE:
233 return RSA_NO_PADDING;
234 case KM_PAD_RSA_PKCS1_1_5_SIGN:
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600235 return RSA_PKCS1_PADDING;
236 case KM_PAD_RSA_PSS:
237 if (digest_ == KM_DIGEST_NONE) {
238 *error = KM_ERROR_INCOMPATIBLE_PADDING_MODE;
239 return -1;
240 }
Shawn Willdend5303052015-06-22 05:25:59 -0600241 if (EVP_MD_size(digest_algorithm_) + kPssOverhead + kMinPssSaltSize >
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600242 (size_t)EVP_PKEY_size(rsa_key_)) {
Shawn Willdend5303052015-06-22 05:25:59 -0600243 LOG_E("Input too long: %d-byte digest cannot be used with %d-byte RSA key in PSS "
244 "padding mode",
Shawn Willdenbfd9ed72015-06-11 10:51:12 -0600245 EVP_MD_size(digest_algorithm_), EVP_PKEY_size(rsa_key_));
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600246 *error = KM_ERROR_INCOMPATIBLE_DIGEST;
247 return -1;
248 }
249 return RSA_PKCS1_PSS_PADDING;
250 default:
251 return -1;
Shawn Willden61902362014-12-18 10:33:24 -0700252 }
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600253}
254
Shawn Willden7d05d882015-07-10 14:03:14 -0600255keymaster_error_t RsaSignOperation::Begin(const AuthorizationSet& input_params,
256 AuthorizationSet* output_params) {
257 keymaster_error_t error = RsaDigestingOperation::Begin(input_params, output_params);
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600258 if (error != KM_ERROR_OK)
259 return error;
260
261 if (digest_ == KM_DIGEST_NONE)
262 return KM_ERROR_OK;
263
264 EVP_PKEY_CTX* pkey_ctx;
265 if (EVP_DigestSignInit(&digest_ctx_, &pkey_ctx, digest_algorithm_, nullptr /* engine */,
266 rsa_key_) != 1)
267 return TranslateLastOpenSslError();
268 return SetRsaPaddingInEvpContext(pkey_ctx);
269}
270
271keymaster_error_t RsaSignOperation::Update(const AuthorizationSet& additional_params,
Shawn Willdended8e7d2015-06-01 15:29:12 -0600272 const Buffer& input, AuthorizationSet* output_params,
273 Buffer* output, size_t* input_consumed) {
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600274 if (digest_ == KM_DIGEST_NONE)
275 // Just buffer the data.
Shawn Willdended8e7d2015-06-01 15:29:12 -0600276 return RsaOperation::Update(additional_params, input, output_params, output,
277 input_consumed);
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600278
279 if (EVP_DigestSignUpdate(&digest_ctx_, input.peek_read(), input.available_read()) != 1)
280 return TranslateLastOpenSslError();
Shawn Willden61902362014-12-18 10:33:24 -0700281 *input_consumed = input.available_read();
282 return KM_ERROR_OK;
283}
284
Shawn Willdencb647fe2016-01-27 12:59:13 -0700285keymaster_error_t RsaSignOperation::Finish(const AuthorizationSet& additional_params,
286 const Buffer& input, const Buffer& /* signature */,
Shawn Willdended8e7d2015-06-01 15:29:12 -0600287 AuthorizationSet* /* output_params */, Buffer* output) {
Shawn Willdenb7361132014-12-08 08:15:14 -0700288 assert(output);
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600289
Shawn Willdencb647fe2016-01-27 12:59:13 -0700290 keymaster_error_t error = UpdateForFinish(additional_params, input);
291 if (error != KM_ERROR_OK)
292 return error;
293
Shawn Willdenf90f2352014-12-18 23:01:15 -0700294 if (digest_ == KM_DIGEST_NONE)
295 return SignUndigested(output);
296 else
297 return SignDigested(output);
298}
Shawn Willden61902362014-12-18 10:33:24 -0700299
Shawn Willdenc0a63802015-07-29 16:43:17 -0600300static keymaster_error_t zero_pad_left(UniquePtr<uint8_t[]>* dest, size_t padded_len, Buffer& src) {
301 assert(padded_len > src.available_read());
302
303 dest->reset(new uint8_t[padded_len]);
304 if (!dest->get())
305 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
306
307 size_t padding_len = padded_len - src.available_read();
308 memset(dest->get(), 0, padding_len);
309 if (!src.read(dest->get() + padding_len, src.available_read()))
310 return KM_ERROR_UNKNOWN_ERROR;
311
312 return KM_ERROR_OK;
313}
314
Shawn Willdenf90f2352014-12-18 23:01:15 -0700315keymaster_error_t RsaSignOperation::SignUndigested(Buffer* output) {
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600316 UniquePtr<RSA, RSA_Delete> rsa(EVP_PKEY_get1_RSA(const_cast<EVP_PKEY*>(rsa_key_)));
317 if (!rsa.get())
318 return TranslateLastOpenSslError();
319
320 if (!output->Reinitialize(RSA_size(rsa.get())))
321 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
322
Shawn Willdenc0a63802015-07-29 16:43:17 -0600323 size_t key_len = EVP_PKEY_size(rsa_key_);
Shawn Willdenf90f2352014-12-18 23:01:15 -0700324 int bytes_encrypted;
325 switch (padding_) {
Shawn Willdenc0a63802015-07-29 16:43:17 -0600326 case KM_PAD_NONE: {
327 const uint8_t* to_encrypt = data_.peek_read();
328 UniquePtr<uint8_t[]> zero_padded;
329 if (data_.available_read() > key_len) {
330 return KM_ERROR_INVALID_INPUT_LENGTH;
331 } else if (data_.available_read() < key_len) {
332 keymaster_error_t error = zero_pad_left(&zero_padded, key_len, data_);
333 if (error != KM_ERROR_OK)
334 return error;
335 to_encrypt = zero_padded.get();
336 }
337 bytes_encrypted = RSA_private_encrypt(key_len, to_encrypt, output->peek_write(), rsa.get(),
338 RSA_NO_PADDING);
Shawn Willdenf90f2352014-12-18 23:01:15 -0700339 break;
Shawn Willdenc0a63802015-07-29 16:43:17 -0600340 }
Shawn Willdenf90f2352014-12-18 23:01:15 -0700341 case KM_PAD_RSA_PKCS1_1_5_SIGN:
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600342 // Does PKCS1 padding without digesting even make sense? Dunno. We'll support it.
Shawn Willdenc0a63802015-07-29 16:43:17 -0600343 if (data_.available_read() + kPkcs1UndigestedSignaturePaddingOverhead > key_len) {
Shawn Willdend5303052015-06-22 05:25:59 -0600344 LOG_E("Input too long: cannot sign %u-byte message with PKCS1 padding with %u-bit key",
345 data_.available_read(), EVP_PKEY_size(rsa_key_) * 8);
346 return KM_ERROR_INVALID_INPUT_LENGTH;
347 }
Shawn Willdenf90f2352014-12-18 23:01:15 -0700348 bytes_encrypted = RSA_private_encrypt(data_.available_read(), data_.peek_read(),
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600349 output->peek_write(), rsa.get(), RSA_PKCS1_PADDING);
Shawn Willdenf90f2352014-12-18 23:01:15 -0700350 break;
Shawn Willdenc0a63802015-07-29 16:43:17 -0600351
Shawn Willdenf90f2352014-12-18 23:01:15 -0700352 default:
353 return KM_ERROR_UNSUPPORTED_PADDING_MODE;
354 }
Shawn Willden61902362014-12-18 10:33:24 -0700355
Shawn Willdenf90f2352014-12-18 23:01:15 -0700356 if (bytes_encrypted <= 0)
Shawn Willden0f906ec2015-06-20 09:16:30 -0600357 return TranslateLastOpenSslError();
358 if (!output->advance_write(bytes_encrypted))
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600359 return KM_ERROR_UNKNOWN_ERROR;
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600360 return KM_ERROR_OK;
361}
362
Shawn Willdenf90f2352014-12-18 23:01:15 -0700363keymaster_error_t RsaSignOperation::SignDigested(Buffer* output) {
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600364 size_t siglen;
365 if (EVP_DigestSignFinal(&digest_ctx_, nullptr /* signature */, &siglen) != 1)
366 return TranslateLastOpenSslError();
Shawn Willdenf90f2352014-12-18 23:01:15 -0700367
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600368 if (!output->Reinitialize(siglen))
Shawn Willdenf90f2352014-12-18 23:01:15 -0700369 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
370
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600371 if (EVP_DigestSignFinal(&digest_ctx_, output->peek_write(), &siglen) <= 0)
372 return TranslateLastOpenSslError();
Shawn Willden0f906ec2015-06-20 09:16:30 -0600373 if (!output->advance_write(siglen))
374 return KM_ERROR_UNKNOWN_ERROR;
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600375
Shawn Willdenf90f2352014-12-18 23:01:15 -0700376 return KM_ERROR_OK;
377}
378
Shawn Willden7d05d882015-07-10 14:03:14 -0600379keymaster_error_t RsaVerifyOperation::Begin(const AuthorizationSet& input_params,
380 AuthorizationSet* output_params) {
381 keymaster_error_t error = RsaDigestingOperation::Begin(input_params, output_params);
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600382 if (error != KM_ERROR_OK)
383 return error;
384
385 if (digest_ == KM_DIGEST_NONE)
386 return KM_ERROR_OK;
387
388 EVP_PKEY_CTX* pkey_ctx;
389 if (EVP_DigestVerifyInit(&digest_ctx_, &pkey_ctx, digest_algorithm_, NULL, rsa_key_) != 1)
390 return TranslateLastOpenSslError();
391 return SetRsaPaddingInEvpContext(pkey_ctx);
392}
393
394keymaster_error_t RsaVerifyOperation::Update(const AuthorizationSet& additional_params,
Shawn Willdended8e7d2015-06-01 15:29:12 -0600395 const Buffer& input, AuthorizationSet* output_params,
396 Buffer* output, size_t* input_consumed) {
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600397 if (digest_ == KM_DIGEST_NONE)
398 // Just buffer the data.
Shawn Willdended8e7d2015-06-01 15:29:12 -0600399 return RsaOperation::Update(additional_params, input, output_params, output,
400 input_consumed);
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600401
402 if (EVP_DigestVerifyUpdate(&digest_ctx_, input.peek_read(), input.available_read()) != 1)
403 return TranslateLastOpenSslError();
404 *input_consumed = input.available_read();
Shawn Willdenf90f2352014-12-18 23:01:15 -0700405 return KM_ERROR_OK;
Shawn Willden61902362014-12-18 10:33:24 -0700406}
407
Shawn Willdencb647fe2016-01-27 12:59:13 -0700408keymaster_error_t RsaVerifyOperation::Finish(const AuthorizationSet& additional_params,
409 const Buffer& input, const Buffer& signature,
Shawn Willdended8e7d2015-06-01 15:29:12 -0600410 AuthorizationSet* /* output_params */,
411 Buffer* /* output */) {
Shawn Willdencb647fe2016-01-27 12:59:13 -0700412 keymaster_error_t error = UpdateForFinish(additional_params, input);
413 if (error != KM_ERROR_OK)
414 return error;
415
Shawn Willdenf90f2352014-12-18 23:01:15 -0700416 if (digest_ == KM_DIGEST_NONE)
417 return VerifyUndigested(signature);
418 else
419 return VerifyDigested(signature);
Shawn Willden61902362014-12-18 10:33:24 -0700420}
421
Shawn Willdenf90f2352014-12-18 23:01:15 -0700422keymaster_error_t RsaVerifyOperation::VerifyUndigested(const Buffer& signature) {
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600423 UniquePtr<RSA, RSA_Delete> rsa(EVP_PKEY_get1_RSA(const_cast<EVP_PKEY*>(rsa_key_)));
424 if (!rsa.get())
425 return KM_ERROR_UNKNOWN_ERROR;
Shawn Willden61902362014-12-18 10:33:24 -0700426
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600427 size_t key_len = RSA_size(rsa.get());
Shawn Willdenf90f2352014-12-18 23:01:15 -0700428 int openssl_padding;
429 switch (padding_) {
430 case KM_PAD_NONE:
Shawn Willdenc0a63802015-07-29 16:43:17 -0600431 if (data_.available_read() > key_len)
Shawn Willdenf90f2352014-12-18 23:01:15 -0700432 return KM_ERROR_INVALID_INPUT_LENGTH;
Shawn Willdenc0a63802015-07-29 16:43:17 -0600433 if (key_len != signature.available_read())
Shawn Willdenf90f2352014-12-18 23:01:15 -0700434 return KM_ERROR_VERIFICATION_FAILED;
435 openssl_padding = RSA_NO_PADDING;
436 break;
Shawn Willdenf90f2352014-12-18 23:01:15 -0700437 case KM_PAD_RSA_PKCS1_1_5_SIGN:
Shawn Willdend5303052015-06-22 05:25:59 -0600438 if (data_.available_read() + kPkcs1UndigestedSignaturePaddingOverhead > key_len) {
439 LOG_E("Input too long: cannot verify %u-byte message with PKCS1 padding && %u-bit key",
440 data_.available_read(), key_len * 8);
441 return KM_ERROR_INVALID_INPUT_LENGTH;
442 }
Shawn Willdenf90f2352014-12-18 23:01:15 -0700443 openssl_padding = RSA_PKCS1_PADDING;
444 break;
445 default:
446 return KM_ERROR_UNSUPPORTED_PADDING_MODE;
447 }
448
Shawn Willden0f906ec2015-06-20 09:16:30 -0600449 UniquePtr<uint8_t[]> decrypted_data(new (std::nothrow) uint8_t[key_len]);
450 if (!decrypted_data.get())
451 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willdenf90f2352014-12-18 23:01:15 -0700452 int bytes_decrypted = RSA_public_decrypt(signature.available_read(), signature.peek_read(),
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600453 decrypted_data.get(), rsa.get(), openssl_padding);
Shawn Willdenf90f2352014-12-18 23:01:15 -0700454 if (bytes_decrypted < 0)
455 return KM_ERROR_VERIFICATION_FAILED;
456
Shawn Willdenc0a63802015-07-29 16:43:17 -0600457 const uint8_t* compare_pos = decrypted_data.get();
458 size_t bytes_to_compare = bytes_decrypted;
459 uint8_t zero_check_result = 0;
460 if (padding_ == KM_PAD_NONE && data_.available_read() < bytes_to_compare) {
461 // If the data is short, for "unpadded" signing we zero-pad to the left. So during
462 // verification we should have zeros on the left of the decrypted data. Do a constant-time
463 // check.
464 const uint8_t* zero_end = compare_pos + bytes_to_compare - data_.available_read();
465 while (compare_pos < zero_end)
466 zero_check_result |= *compare_pos++;
467 bytes_to_compare = data_.available_read();
468 }
469 if (memcmp_s(compare_pos, data_.peek_read(), bytes_to_compare) != 0 || zero_check_result != 0)
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600470 return KM_ERROR_VERIFICATION_FAILED;
471 return KM_ERROR_OK;
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600472}
473
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600474keymaster_error_t RsaVerifyOperation::VerifyDigested(const Buffer& signature) {
475 if (!EVP_DigestVerifyFinal(&digest_ctx_, signature.peek_read(), signature.available_read()))
476 return KM_ERROR_VERIFICATION_FAILED;
477 return KM_ERROR_OK;
478}
479
Shawn Willden7d05d882015-07-10 14:03:14 -0600480keymaster_error_t RsaCryptOperation::SetOaepDigestIfRequired(EVP_PKEY_CTX* pkey_ctx) {
481 if (padding() != KM_PAD_RSA_OAEP)
482 return KM_ERROR_OK;
483
484 assert(digest_algorithm_ != nullptr);
485 if (!EVP_PKEY_CTX_set_rsa_oaep_md(pkey_ctx, digest_algorithm_))
486 return TranslateLastOpenSslError();
487
488 // MGF1 MD is always SHA1.
489 if (!EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, EVP_sha1()))
490 return TranslateLastOpenSslError();
491
492 return KM_ERROR_OK;
493}
494
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600495int RsaCryptOperation::GetOpensslPadding(keymaster_error_t* error) {
496 *error = KM_ERROR_OK;
497 switch (padding_) {
Shawn Willden30160842015-06-01 08:31:00 -0600498 case KM_PAD_NONE:
499 return RSA_NO_PADDING;
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600500 case KM_PAD_RSA_PKCS1_1_5_ENCRYPT:
501 return RSA_PKCS1_PADDING;
502 case KM_PAD_RSA_OAEP:
503 return RSA_PKCS1_OAEP_PADDING;
504 default:
505 return -1;
506 }
507}
508
509struct EVP_PKEY_CTX_Delete {
510 void operator()(EVP_PKEY_CTX* p) { EVP_PKEY_CTX_free(p); }
511};
Shawn Willden4200f212014-12-02 07:01:21 -0700512
Shawn Willdencb647fe2016-01-27 12:59:13 -0700513keymaster_error_t RsaEncryptOperation::Finish(const AuthorizationSet& additional_params,
514 const Buffer& input, const Buffer& /* signature */,
Shawn Willdended8e7d2015-06-01 15:29:12 -0600515 AuthorizationSet* /* output_params */,
516 Buffer* output) {
Shawn Willdencb647fe2016-01-27 12:59:13 -0700517 if (!output)
518 return KM_ERROR_OUTPUT_PARAMETER_NULL;
519
520 keymaster_error_t error = UpdateForFinish(additional_params, input);
521 if (error != KM_ERROR_OK)
522 return error;
Shawn Willden4200f212014-12-02 07:01:21 -0700523
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600524 UniquePtr<EVP_PKEY_CTX, EVP_PKEY_CTX_Delete> ctx(
525 EVP_PKEY_CTX_new(rsa_key_, nullptr /* engine */));
526 if (!ctx.get())
527 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willden4200f212014-12-02 07:01:21 -0700528
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600529 if (EVP_PKEY_encrypt_init(ctx.get()) <= 0)
530 return TranslateLastOpenSslError();
Shawn Willden4200f212014-12-02 07:01:21 -0700531
Shawn Willdencb647fe2016-01-27 12:59:13 -0700532 error = SetRsaPaddingInEvpContext(ctx.get());
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600533 if (error != KM_ERROR_OK)
534 return error;
Shawn Willden7d05d882015-07-10 14:03:14 -0600535 error = SetOaepDigestIfRequired(ctx.get());
536 if (error != KM_ERROR_OK)
537 return error;
Shawn Willden4200f212014-12-02 07:01:21 -0700538
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600539 size_t outlen;
540 if (EVP_PKEY_encrypt(ctx.get(), nullptr /* out */, &outlen, data_.peek_read(),
541 data_.available_read()) <= 0)
542 return TranslateLastOpenSslError();
543
544 if (!output->Reinitialize(outlen))
545 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
546
Shawn Willdenc0a63802015-07-29 16:43:17 -0600547 const uint8_t* to_encrypt = data_.peek_read();
548 size_t to_encrypt_len = data_.available_read();
549 UniquePtr<uint8_t[]> zero_padded;
550 if (padding_ == KM_PAD_NONE && to_encrypt_len < outlen) {
551 keymaster_error_t error = zero_pad_left(&zero_padded, outlen, data_);
552 if (error != KM_ERROR_OK)
553 return error;
554 to_encrypt = zero_padded.get();
555 to_encrypt_len = outlen;
556 }
557
558 if (EVP_PKEY_encrypt(ctx.get(), output->peek_write(), &outlen, to_encrypt, to_encrypt_len) <= 0)
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600559 return TranslateLastOpenSslError();
Shawn Willden0f906ec2015-06-20 09:16:30 -0600560 if (!output->advance_write(outlen))
561 return KM_ERROR_UNKNOWN_ERROR;
Shawn Willden4200f212014-12-02 07:01:21 -0700562
563 return KM_ERROR_OK;
564}
565
Shawn Willdencb647fe2016-01-27 12:59:13 -0700566keymaster_error_t RsaDecryptOperation::Finish(const AuthorizationSet& additional_params,
567 const Buffer& input, const Buffer& /* signature */,
Shawn Willdended8e7d2015-06-01 15:29:12 -0600568 AuthorizationSet* /* output_params */,
569 Buffer* output) {
Shawn Willdencb647fe2016-01-27 12:59:13 -0700570 if (!output)
571 return KM_ERROR_OUTPUT_PARAMETER_NULL;
572
573 keymaster_error_t error = UpdateForFinish(additional_params, input);
574 if (error != KM_ERROR_OK)
575 return error;
Shawn Willden4200f212014-12-02 07:01:21 -0700576
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600577 UniquePtr<EVP_PKEY_CTX, EVP_PKEY_CTX_Delete> ctx(
578 EVP_PKEY_CTX_new(rsa_key_, nullptr /* engine */));
579 if (!ctx.get())
580 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willden4200f212014-12-02 07:01:21 -0700581
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600582 if (EVP_PKEY_decrypt_init(ctx.get()) <= 0)
583 return TranslateLastOpenSslError();
584
Shawn Willdencb647fe2016-01-27 12:59:13 -0700585 error = SetRsaPaddingInEvpContext(ctx.get());
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600586 if (error != KM_ERROR_OK)
587 return error;
Shawn Willden7d05d882015-07-10 14:03:14 -0600588 error = SetOaepDigestIfRequired(ctx.get());
589 if (error != KM_ERROR_OK)
590 return error;
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600591
592 size_t outlen;
593 if (EVP_PKEY_decrypt(ctx.get(), nullptr /* out */, &outlen, data_.peek_read(),
594 data_.available_read()) <= 0)
595 return TranslateLastOpenSslError();
596
597 if (!output->Reinitialize(outlen))
598 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
599
Shawn Willdenc0a63802015-07-29 16:43:17 -0600600 const uint8_t* to_decrypt = data_.peek_read();
601 size_t to_decrypt_len = data_.available_read();
602 UniquePtr<uint8_t[]> zero_padded;
603 if (padding_ == KM_PAD_NONE && to_decrypt_len < outlen) {
604 keymaster_error_t error = zero_pad_left(&zero_padded, outlen, data_);
605 if (error != KM_ERROR_OK)
606 return error;
607 to_decrypt = zero_padded.get();
608 to_decrypt_len = outlen;
609 }
610
611 if (EVP_PKEY_decrypt(ctx.get(), output->peek_write(), &outlen, to_decrypt, to_decrypt_len) <= 0)
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600612 return TranslateLastOpenSslError();
Shawn Willden0f906ec2015-06-20 09:16:30 -0600613 if (!output->advance_write(outlen))
614 return KM_ERROR_UNKNOWN_ERROR;
Shawn Willden4200f212014-12-02 07:01:21 -0700615
616 return KM_ERROR_OK;
617}
618
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600619} // namespace keymaster