blob: 7c80ec558d6a5fcffb3dfb192292e9ea8920d399 [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;
34const size_t kMinPssSaltSize = 8;
35
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 Willdenf90f2352014-12-18 23:01:15 -070060static const keymaster_padding_t supported_sig_padding[] = {KM_PAD_NONE, KM_PAD_RSA_PKCS1_1_5_SIGN,
61 KM_PAD_RSA_PSS};
Shawn Willden63ac0432014-12-29 14:07:08 -070062
Shawn Willden06298102015-05-25 23:12:48 -060063const keymaster_digest_t*
64RsaDigestingOperationFactory::SupportedDigests(size_t* digest_count) const {
65 *digest_count = array_length(supported_digests);
66 return supported_digests;
67}
Shawn Willden63ac0432014-12-29 14:07:08 -070068
Shawn Willden06298102015-05-25 23:12:48 -060069const keymaster_padding_t*
70RsaDigestingOperationFactory::SupportedPaddingModes(size_t* padding_mode_count) const {
71 *padding_mode_count = array_length(supported_sig_padding);
72 return supported_sig_padding;
73}
Shawn Willden63ac0432014-12-29 14:07:08 -070074
Shawn Willden3ed6d062015-04-15 13:39:38 -060075Operation* RsaDigestingOperationFactory::CreateOperation(const Key& key,
Shawn Willden226746b2015-05-08 11:36:56 -060076 const AuthorizationSet& begin_params,
Shawn Willden3ed6d062015-04-15 13:39:38 -060077 keymaster_error_t* error) {
Shawn Willden63ac0432014-12-29 14:07:08 -070078 keymaster_padding_t padding;
79 keymaster_digest_t digest;
Shawn Willden226746b2015-05-08 11:36:56 -060080 if (!GetAndValidateDigest(begin_params, key, &digest, error) ||
Shawn Willden2bf4ad32015-06-01 07:33:51 -060081 !GetAndValidatePadding(begin_params, key, &padding, error))
82 return nullptr;
Shawn Willden63ac0432014-12-29 14:07:08 -070083
Shawn Willden2bf4ad32015-06-01 07:33:51 -060084 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> rsa(GetRsaKey(key, error));
85 if (!rsa.get())
86 return nullptr;
87
88 Operation* op = InstantiateOperation(digest, padding, rsa.release());
Shawn Willden63ac0432014-12-29 14:07:08 -070089 if (!op)
90 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
91 return op;
92}
93
Shawn Willden30160842015-06-01 08:31:00 -060094static const keymaster_padding_t supported_crypt_padding[] = {KM_PAD_NONE, KM_PAD_RSA_OAEP,
Shawn Willden63ac0432014-12-29 14:07:08 -070095 KM_PAD_RSA_PKCS1_1_5_ENCRYPT};
96
Shawn Willden3ed6d062015-04-15 13:39:38 -060097Operation* RsaCryptingOperationFactory::CreateOperation(const Key& key,
Shawn Willden3ad5f052015-05-08 14:05:13 -060098 const AuthorizationSet& begin_params,
Shawn Willden3ed6d062015-04-15 13:39:38 -060099 keymaster_error_t* error) {
Shawn Willden63ac0432014-12-29 14:07:08 -0700100 keymaster_padding_t padding;
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600101 if (!GetAndValidatePadding(begin_params, key, &padding, error))
102 return nullptr;
Shawn Willden63ac0432014-12-29 14:07:08 -0700103
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600104 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> rsa(GetRsaKey(key, error));
105 if (!rsa.get())
106 return nullptr;
107
108 Operation* op = InstantiateOperation(padding, rsa.release());
Shawn Willden63ac0432014-12-29 14:07:08 -0700109 if (!op)
110 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
111 return op;
112}
113
Shawn Willden06298102015-05-25 23:12:48 -0600114const keymaster_padding_t*
115RsaCryptingOperationFactory::SupportedPaddingModes(size_t* padding_mode_count) const {
116 *padding_mode_count = array_length(supported_crypt_padding);
117 return supported_crypt_padding;
118}
Shawn Willden63ac0432014-12-29 14:07:08 -0700119
Shawn Willden06298102015-05-25 23:12:48 -0600120const keymaster_digest_t*
121RsaCryptingOperationFactory::SupportedDigests(size_t* digest_count) const {
122 *digest_count = 0;
123 return NULL;
124}
Shawn Willden63ac0432014-12-29 14:07:08 -0700125
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600126RsaOperation::~RsaOperation() {
127 if (rsa_key_ != NULL)
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600128 EVP_PKEY_free(rsa_key_);
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600129}
130
Shawn Willden6bfbff02015-02-06 19:48:24 -0700131keymaster_error_t RsaOperation::Update(const AuthorizationSet& /* additional_params */,
Shawn Willdended8e7d2015-06-01 15:29:12 -0600132 const Buffer& input, AuthorizationSet* /* output_params */,
133 Buffer* /* output */, size_t* input_consumed) {
Shawn Willdenb7361132014-12-08 08:15:14 -0700134 assert(input_consumed);
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600135 switch (purpose()) {
136 default:
137 return KM_ERROR_UNIMPLEMENTED;
138 case KM_PURPOSE_SIGN:
139 case KM_PURPOSE_VERIFY:
Shawn Willden4200f212014-12-02 07:01:21 -0700140 case KM_PURPOSE_ENCRYPT:
141 case KM_PURPOSE_DECRYPT:
Shawn Willdenb7361132014-12-08 08:15:14 -0700142 return StoreData(input, input_consumed);
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600143 }
144}
145
Shawn Willdenb7361132014-12-08 08:15:14 -0700146keymaster_error_t RsaOperation::StoreData(const Buffer& input, size_t* input_consumed) {
147 assert(input_consumed);
Shawn Willdend5303052015-06-22 05:25:59 -0600148
149 if (!data_.reserve(EVP_PKEY_size(rsa_key_)))
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600150 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willdend5303052015-06-22 05:25:59 -0600151 // If the write fails, it's because input length exceeds key size.
152 if (!data_.write(input.peek_read(), input.available_read())) {
153 LOG_E("Input too long: cannot operate on %u bytes of data with %u-bit RSA key",
154 input.available_read() + data_.available_read());
155 return KM_ERROR_INVALID_INPUT_LENGTH;
156 }
157
Shawn Willdenb7361132014-12-08 08:15:14 -0700158 *input_consumed = input.available_read();
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600159 return KM_ERROR_OK;
160}
161
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600162keymaster_error_t RsaOperation::SetRsaPaddingInEvpContext(EVP_PKEY_CTX* pkey_ctx) {
163 keymaster_error_t error;
164 int openssl_padding = GetOpensslPadding(&error);
165 if (error != KM_ERROR_OK)
166 return error;
167
168 if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, openssl_padding) <= 0)
169 return TranslateLastOpenSslError();
170 return KM_ERROR_OK;
171}
172
Shawn Willden61902362014-12-18 10:33:24 -0700173RsaDigestingOperation::RsaDigestingOperation(keymaster_purpose_t purpose, keymaster_digest_t digest,
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600174 keymaster_padding_t padding, EVP_PKEY* key)
Shawn Willden61902362014-12-18 10:33:24 -0700175 : RsaOperation(purpose, padding, key), digest_(digest), digest_algorithm_(NULL) {
176 EVP_MD_CTX_init(&digest_ctx_);
177}
178RsaDigestingOperation::~RsaDigestingOperation() {
179 EVP_MD_CTX_cleanup(&digest_ctx_);
Shawn Willdenf90f2352014-12-18 23:01:15 -0700180}
181
182keymaster_error_t RsaDigestingOperation::InitDigest() {
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600183 if (digest_ == KM_DIGEST_NONE) {
184 if (require_digest())
185 return KM_ERROR_INCOMPATIBLE_DIGEST;
186 return KM_ERROR_OK;
187 }
188
Shawn Willden61902362014-12-18 10:33:24 -0700189 switch (digest_) {
Shawn Willdenf90f2352014-12-18 23:01:15 -0700190 case KM_DIGEST_NONE:
191 return KM_ERROR_OK;
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600192 case KM_DIGEST_MD5:
193 digest_algorithm_ = EVP_md5();
194 return KM_ERROR_OK;
195 case KM_DIGEST_SHA1:
196 digest_algorithm_ = EVP_sha1();
197 return KM_ERROR_OK;
198 case KM_DIGEST_SHA_2_224:
199 digest_algorithm_ = EVP_sha224();
200 return KM_ERROR_OK;
Shawn Willden61902362014-12-18 10:33:24 -0700201 case KM_DIGEST_SHA_2_256:
202 digest_algorithm_ = EVP_sha256();
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600203 return KM_ERROR_OK;
204 case KM_DIGEST_SHA_2_384:
205 digest_algorithm_ = EVP_sha384();
206 return KM_ERROR_OK;
207 case KM_DIGEST_SHA_2_512:
208 digest_algorithm_ = EVP_sha512();
209 return KM_ERROR_OK;
Shawn Willden61902362014-12-18 10:33:24 -0700210 default:
211 return KM_ERROR_UNSUPPORTED_DIGEST;
212 }
Shawn Willden61902362014-12-18 10:33:24 -0700213}
214
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600215int RsaDigestingOperation::GetOpensslPadding(keymaster_error_t* error) {
216 *error = KM_ERROR_OK;
217 switch (padding_) {
218 case KM_PAD_NONE:
219 return RSA_NO_PADDING;
220 case KM_PAD_RSA_PKCS1_1_5_SIGN:
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600221 return RSA_PKCS1_PADDING;
222 case KM_PAD_RSA_PSS:
223 if (digest_ == KM_DIGEST_NONE) {
224 *error = KM_ERROR_INCOMPATIBLE_PADDING_MODE;
225 return -1;
226 }
Shawn Willdend5303052015-06-22 05:25:59 -0600227 if (EVP_MD_size(digest_algorithm_) + kPssOverhead + kMinPssSaltSize >
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600228 (size_t)EVP_PKEY_size(rsa_key_)) {
Shawn Willdend5303052015-06-22 05:25:59 -0600229 LOG_E("Input too long: %d-byte digest cannot be used with %d-byte RSA key in PSS "
230 "padding mode",
Shawn Willdenbfd9ed72015-06-11 10:51:12 -0600231 EVP_MD_size(digest_algorithm_), EVP_PKEY_size(rsa_key_));
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600232 *error = KM_ERROR_INCOMPATIBLE_DIGEST;
233 return -1;
234 }
235 return RSA_PKCS1_PSS_PADDING;
236 default:
237 return -1;
Shawn Willden61902362014-12-18 10:33:24 -0700238 }
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600239}
240
241keymaster_error_t RsaSignOperation::Begin(const AuthorizationSet& /* input_params */,
242 AuthorizationSet* /* output_params */) {
243 keymaster_error_t error = InitDigest();
244 if (error != KM_ERROR_OK)
245 return error;
246
247 if (digest_ == KM_DIGEST_NONE)
248 return KM_ERROR_OK;
249
250 EVP_PKEY_CTX* pkey_ctx;
251 if (EVP_DigestSignInit(&digest_ctx_, &pkey_ctx, digest_algorithm_, nullptr /* engine */,
252 rsa_key_) != 1)
253 return TranslateLastOpenSslError();
254 return SetRsaPaddingInEvpContext(pkey_ctx);
255}
256
257keymaster_error_t RsaSignOperation::Update(const AuthorizationSet& additional_params,
Shawn Willdended8e7d2015-06-01 15:29:12 -0600258 const Buffer& input, AuthorizationSet* output_params,
259 Buffer* output, size_t* input_consumed) {
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600260 if (digest_ == KM_DIGEST_NONE)
261 // Just buffer the data.
Shawn Willdended8e7d2015-06-01 15:29:12 -0600262 return RsaOperation::Update(additional_params, input, output_params, output,
263 input_consumed);
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600264
265 if (EVP_DigestSignUpdate(&digest_ctx_, input.peek_read(), input.available_read()) != 1)
266 return TranslateLastOpenSslError();
Shawn Willden61902362014-12-18 10:33:24 -0700267 *input_consumed = input.available_read();
268 return KM_ERROR_OK;
269}
270
Shawn Willden6bfbff02015-02-06 19:48:24 -0700271keymaster_error_t RsaSignOperation::Finish(const AuthorizationSet& /* additional_params */,
Shawn Willdended8e7d2015-06-01 15:29:12 -0600272 const Buffer& /* signature */,
273 AuthorizationSet* /* output_params */, Buffer* output) {
Shawn Willdenb7361132014-12-08 08:15:14 -0700274 assert(output);
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600275
Shawn Willdenf90f2352014-12-18 23:01:15 -0700276 if (digest_ == KM_DIGEST_NONE)
277 return SignUndigested(output);
278 else
279 return SignDigested(output);
280}
Shawn Willden61902362014-12-18 10:33:24 -0700281
Shawn Willdenf90f2352014-12-18 23:01:15 -0700282keymaster_error_t RsaSignOperation::SignUndigested(Buffer* output) {
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600283 UniquePtr<RSA, RSA_Delete> rsa(EVP_PKEY_get1_RSA(const_cast<EVP_PKEY*>(rsa_key_)));
284 if (!rsa.get())
285 return TranslateLastOpenSslError();
286
287 if (!output->Reinitialize(RSA_size(rsa.get())))
288 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
289
Shawn Willdenf90f2352014-12-18 23:01:15 -0700290 int bytes_encrypted;
291 switch (padding_) {
292 case KM_PAD_NONE:
293 bytes_encrypted = RSA_private_encrypt(data_.available_read(), data_.peek_read(),
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600294 output->peek_write(), rsa.get(), RSA_NO_PADDING);
Shawn Willdenf90f2352014-12-18 23:01:15 -0700295 break;
296 case KM_PAD_RSA_PKCS1_1_5_SIGN:
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600297 // Does PKCS1 padding without digesting even make sense? Dunno. We'll support it.
Shawn Willdend5303052015-06-22 05:25:59 -0600298 if (data_.available_read() + kPkcs1UndigestedSignaturePaddingOverhead >
299 static_cast<size_t>(EVP_PKEY_size(rsa_key_))) {
300 LOG_E("Input too long: cannot sign %u-byte message with PKCS1 padding with %u-bit key",
301 data_.available_read(), EVP_PKEY_size(rsa_key_) * 8);
302 return KM_ERROR_INVALID_INPUT_LENGTH;
303 }
Shawn Willdenf90f2352014-12-18 23:01:15 -0700304 bytes_encrypted = RSA_private_encrypt(data_.available_read(), data_.peek_read(),
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600305 output->peek_write(), rsa.get(), RSA_PKCS1_PADDING);
Shawn Willdenf90f2352014-12-18 23:01:15 -0700306 break;
307 default:
308 return KM_ERROR_UNSUPPORTED_PADDING_MODE;
309 }
Shawn Willden61902362014-12-18 10:33:24 -0700310
Shawn Willdenf90f2352014-12-18 23:01:15 -0700311 if (bytes_encrypted <= 0)
Shawn Willden0f906ec2015-06-20 09:16:30 -0600312 return TranslateLastOpenSslError();
313 if (!output->advance_write(bytes_encrypted))
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600314 return KM_ERROR_UNKNOWN_ERROR;
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600315 return KM_ERROR_OK;
316}
317
Shawn Willdenf90f2352014-12-18 23:01:15 -0700318keymaster_error_t RsaSignOperation::SignDigested(Buffer* output) {
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600319 size_t siglen;
320 if (EVP_DigestSignFinal(&digest_ctx_, nullptr /* signature */, &siglen) != 1)
321 return TranslateLastOpenSslError();
Shawn Willdenf90f2352014-12-18 23:01:15 -0700322
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600323 if (!output->Reinitialize(siglen))
Shawn Willdenf90f2352014-12-18 23:01:15 -0700324 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
325
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600326 if (EVP_DigestSignFinal(&digest_ctx_, output->peek_write(), &siglen) <= 0)
327 return TranslateLastOpenSslError();
Shawn Willden0f906ec2015-06-20 09:16:30 -0600328 if (!output->advance_write(siglen))
329 return KM_ERROR_UNKNOWN_ERROR;
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600330
Shawn Willdenf90f2352014-12-18 23:01:15 -0700331 return KM_ERROR_OK;
332}
333
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600334keymaster_error_t RsaVerifyOperation::Begin(const AuthorizationSet& /* input_params */,
335 AuthorizationSet* /* output_params */) {
336 keymaster_error_t error = InitDigest();
337 if (error != KM_ERROR_OK)
338 return error;
339
340 if (digest_ == KM_DIGEST_NONE)
341 return KM_ERROR_OK;
342
343 EVP_PKEY_CTX* pkey_ctx;
344 if (EVP_DigestVerifyInit(&digest_ctx_, &pkey_ctx, digest_algorithm_, NULL, rsa_key_) != 1)
345 return TranslateLastOpenSslError();
346 return SetRsaPaddingInEvpContext(pkey_ctx);
347}
348
349keymaster_error_t RsaVerifyOperation::Update(const AuthorizationSet& additional_params,
Shawn Willdended8e7d2015-06-01 15:29:12 -0600350 const Buffer& input, AuthorizationSet* output_params,
351 Buffer* output, size_t* input_consumed) {
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600352 if (digest_ == KM_DIGEST_NONE)
353 // Just buffer the data.
Shawn Willdended8e7d2015-06-01 15:29:12 -0600354 return RsaOperation::Update(additional_params, input, output_params, output,
355 input_consumed);
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600356
357 if (EVP_DigestVerifyUpdate(&digest_ctx_, input.peek_read(), input.available_read()) != 1)
358 return TranslateLastOpenSslError();
359 *input_consumed = input.available_read();
Shawn Willdenf90f2352014-12-18 23:01:15 -0700360 return KM_ERROR_OK;
Shawn Willden61902362014-12-18 10:33:24 -0700361}
362
Shawn Willden6bfbff02015-02-06 19:48:24 -0700363keymaster_error_t RsaVerifyOperation::Finish(const AuthorizationSet& /* additional_params */,
Shawn Willdended8e7d2015-06-01 15:29:12 -0600364 const Buffer& signature,
365 AuthorizationSet* /* output_params */,
366 Buffer* /* output */) {
Shawn Willdenf90f2352014-12-18 23:01:15 -0700367 if (digest_ == KM_DIGEST_NONE)
368 return VerifyUndigested(signature);
369 else
370 return VerifyDigested(signature);
Shawn Willden61902362014-12-18 10:33:24 -0700371}
372
Shawn Willdenf90f2352014-12-18 23:01:15 -0700373keymaster_error_t RsaVerifyOperation::VerifyUndigested(const Buffer& signature) {
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600374 UniquePtr<RSA, RSA_Delete> rsa(EVP_PKEY_get1_RSA(const_cast<EVP_PKEY*>(rsa_key_)));
375 if (!rsa.get())
376 return KM_ERROR_UNKNOWN_ERROR;
Shawn Willden61902362014-12-18 10:33:24 -0700377
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600378 size_t key_len = RSA_size(rsa.get());
Shawn Willdenf90f2352014-12-18 23:01:15 -0700379 int openssl_padding;
380 switch (padding_) {
381 case KM_PAD_NONE:
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600382 if (data_.available_read() != key_len)
Shawn Willdenf90f2352014-12-18 23:01:15 -0700383 return KM_ERROR_INVALID_INPUT_LENGTH;
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600384 if (data_.available_read() != signature.available_read())
Shawn Willdenf90f2352014-12-18 23:01:15 -0700385 return KM_ERROR_VERIFICATION_FAILED;
386 openssl_padding = RSA_NO_PADDING;
387 break;
Shawn Willdenf90f2352014-12-18 23:01:15 -0700388 case KM_PAD_RSA_PKCS1_1_5_SIGN:
Shawn Willdend5303052015-06-22 05:25:59 -0600389 if (data_.available_read() + kPkcs1UndigestedSignaturePaddingOverhead > key_len) {
390 LOG_E("Input too long: cannot verify %u-byte message with PKCS1 padding && %u-bit key",
391 data_.available_read(), key_len * 8);
392 return KM_ERROR_INVALID_INPUT_LENGTH;
393 }
Shawn Willdenf90f2352014-12-18 23:01:15 -0700394 openssl_padding = RSA_PKCS1_PADDING;
395 break;
396 default:
397 return KM_ERROR_UNSUPPORTED_PADDING_MODE;
398 }
399
Shawn Willden0f906ec2015-06-20 09:16:30 -0600400 UniquePtr<uint8_t[]> decrypted_data(new (std::nothrow) uint8_t[key_len]);
401 if (!decrypted_data.get())
402 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willdenf90f2352014-12-18 23:01:15 -0700403 int bytes_decrypted = RSA_public_decrypt(signature.available_read(), signature.peek_read(),
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600404 decrypted_data.get(), rsa.get(), openssl_padding);
Shawn Willdenf90f2352014-12-18 23:01:15 -0700405 if (bytes_decrypted < 0)
406 return KM_ERROR_VERIFICATION_FAILED;
407
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600408 if (memcmp_s(decrypted_data.get(), data_.peek_read(), data_.available_read()) != 0)
409 return KM_ERROR_VERIFICATION_FAILED;
410 return KM_ERROR_OK;
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600411}
412
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600413keymaster_error_t RsaVerifyOperation::VerifyDigested(const Buffer& signature) {
414 if (!EVP_DigestVerifyFinal(&digest_ctx_, signature.peek_read(), signature.available_read()))
415 return KM_ERROR_VERIFICATION_FAILED;
416 return KM_ERROR_OK;
417}
418
419int RsaCryptOperation::GetOpensslPadding(keymaster_error_t* error) {
420 *error = KM_ERROR_OK;
421 switch (padding_) {
Shawn Willden30160842015-06-01 08:31:00 -0600422 case KM_PAD_NONE:
423 return RSA_NO_PADDING;
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600424 case KM_PAD_RSA_PKCS1_1_5_ENCRYPT:
425 return RSA_PKCS1_PADDING;
426 case KM_PAD_RSA_OAEP:
427 return RSA_PKCS1_OAEP_PADDING;
428 default:
429 return -1;
430 }
431}
432
433struct EVP_PKEY_CTX_Delete {
434 void operator()(EVP_PKEY_CTX* p) { EVP_PKEY_CTX_free(p); }
435};
Shawn Willden4200f212014-12-02 07:01:21 -0700436
Shawn Willden6bfbff02015-02-06 19:48:24 -0700437keymaster_error_t RsaEncryptOperation::Finish(const AuthorizationSet& /* additional_params */,
Shawn Willdended8e7d2015-06-01 15:29:12 -0600438 const Buffer& /* signature */,
439 AuthorizationSet* /* output_params */,
440 Buffer* output) {
Shawn Willdenb7361132014-12-08 08:15:14 -0700441 assert(output);
Shawn Willden4200f212014-12-02 07:01:21 -0700442
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600443 UniquePtr<EVP_PKEY_CTX, EVP_PKEY_CTX_Delete> ctx(
444 EVP_PKEY_CTX_new(rsa_key_, nullptr /* engine */));
445 if (!ctx.get())
446 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willden4200f212014-12-02 07:01:21 -0700447
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600448 if (EVP_PKEY_encrypt_init(ctx.get()) <= 0)
449 return TranslateLastOpenSslError();
Shawn Willden4200f212014-12-02 07:01:21 -0700450
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600451 keymaster_error_t error = SetRsaPaddingInEvpContext(ctx.get());
452 if (error != KM_ERROR_OK)
453 return error;
Shawn Willden4200f212014-12-02 07:01:21 -0700454
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600455 size_t outlen;
456 if (EVP_PKEY_encrypt(ctx.get(), nullptr /* out */, &outlen, data_.peek_read(),
457 data_.available_read()) <= 0)
458 return TranslateLastOpenSslError();
459
460 if (!output->Reinitialize(outlen))
461 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
462
463 if (EVP_PKEY_encrypt(ctx.get(), output->peek_write(), &outlen, data_.peek_read(),
464 data_.available_read()) <= 0)
465 return TranslateLastOpenSslError();
Shawn Willden0f906ec2015-06-20 09:16:30 -0600466 if (!output->advance_write(outlen))
467 return KM_ERROR_UNKNOWN_ERROR;
Shawn Willden4200f212014-12-02 07:01:21 -0700468
469 return KM_ERROR_OK;
470}
471
Shawn Willden6bfbff02015-02-06 19:48:24 -0700472keymaster_error_t RsaDecryptOperation::Finish(const AuthorizationSet& /* additional_params */,
Shawn Willdended8e7d2015-06-01 15:29:12 -0600473 const Buffer& /* signature */,
474 AuthorizationSet* /* output_params */,
475 Buffer* output) {
Shawn Willdenb7361132014-12-08 08:15:14 -0700476 assert(output);
Shawn Willden4200f212014-12-02 07:01:21 -0700477
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600478 UniquePtr<EVP_PKEY_CTX, EVP_PKEY_CTX_Delete> ctx(
479 EVP_PKEY_CTX_new(rsa_key_, nullptr /* engine */));
480 if (!ctx.get())
481 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willden4200f212014-12-02 07:01:21 -0700482
Shawn Willden2bf4ad32015-06-01 07:33:51 -0600483 if (EVP_PKEY_decrypt_init(ctx.get()) <= 0)
484 return TranslateLastOpenSslError();
485
486 keymaster_error_t error = SetRsaPaddingInEvpContext(ctx.get());
487 if (error != KM_ERROR_OK)
488 return error;
489
490 size_t outlen;
491 if (EVP_PKEY_decrypt(ctx.get(), nullptr /* out */, &outlen, data_.peek_read(),
492 data_.available_read()) <= 0)
493 return TranslateLastOpenSslError();
494
495 if (!output->Reinitialize(outlen))
496 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
497
498 if (EVP_PKEY_decrypt(ctx.get(), output->peek_write(), &outlen, data_.peek_read(),
499 data_.available_read()) <= 0)
500 return TranslateLastOpenSslError();
Shawn Willden0f906ec2015-06-20 09:16:30 -0600501 if (!output->advance_write(outlen))
502 return KM_ERROR_UNKNOWN_ERROR;
Shawn Willden4200f212014-12-02 07:01:21 -0700503
504 return KM_ERROR_OK;
505}
506
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600507} // namespace keymaster