blob: 4ca7812d1b327cd260b2d62137977b9ceaba0d3e [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 Willden4200f212014-12-02 07:01:21 -070017#include <limits.h>
18
19#include <openssl/err.h>
Shawn Willden5f42dba2015-01-20 11:45:19 -070020#include <openssl/evp.h>
Shawn Willden4200f212014-12-02 07:01:21 -070021#include <openssl/rsa.h>
Shawn Willden0a4df7e2014-08-28 16:09:05 -060022
23#include "rsa_operation.h"
24#include "openssl_utils.h"
25
26namespace keymaster {
27
28struct RSA_Delete {
29 void operator()(RSA* p) const { RSA_free(p); }
30};
31
32RsaOperation::~RsaOperation() {
33 if (rsa_key_ != NULL)
34 RSA_free(rsa_key_);
35}
36
Shawn Willden6bfbff02015-02-06 19:48:24 -070037keymaster_error_t RsaOperation::Update(const AuthorizationSet& /* additional_params */,
38 const Buffer& input, Buffer* /* output */,
Shawn Willdenb7361132014-12-08 08:15:14 -070039 size_t* input_consumed) {
40 assert(input_consumed);
Shawn Willden0a4df7e2014-08-28 16:09:05 -060041 switch (purpose()) {
42 default:
43 return KM_ERROR_UNIMPLEMENTED;
44 case KM_PURPOSE_SIGN:
45 case KM_PURPOSE_VERIFY:
Shawn Willden4200f212014-12-02 07:01:21 -070046 case KM_PURPOSE_ENCRYPT:
47 case KM_PURPOSE_DECRYPT:
Shawn Willdenb7361132014-12-08 08:15:14 -070048 return StoreData(input, input_consumed);
Shawn Willden0a4df7e2014-08-28 16:09:05 -060049 }
50}
51
Shawn Willdenb7361132014-12-08 08:15:14 -070052keymaster_error_t RsaOperation::StoreData(const Buffer& input, size_t* input_consumed) {
53 assert(input_consumed);
Shawn Willden0a4df7e2014-08-28 16:09:05 -060054 if (!data_.reserve(data_.available_read() + input.available_read()) ||
55 !data_.write(input.peek_read(), input.available_read()))
56 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willdenb7361132014-12-08 08:15:14 -070057 *input_consumed = input.available_read();
Shawn Willden0a4df7e2014-08-28 16:09:05 -060058 return KM_ERROR_OK;
59}
60
Shawn Willden6bfbff02015-02-06 19:48:24 -070061keymaster_error_t RsaSignOperation::Finish(const AuthorizationSet& /* additional_params */,
62 const Buffer& /* signature */, Buffer* output) {
Shawn Willdenb7361132014-12-08 08:15:14 -070063 assert(output);
Shawn Willden0a4df7e2014-08-28 16:09:05 -060064 output->Reinitialize(RSA_size(rsa_key_));
Shawn Willden0a4df7e2014-08-28 16:09:05 -060065 int bytes_encrypted = RSA_private_encrypt(data_.available_read(), data_.peek_read(),
66 output->peek_write(), rsa_key_, RSA_NO_PADDING);
67 if (bytes_encrypted < 0)
68 return KM_ERROR_UNKNOWN_ERROR;
69 assert(bytes_encrypted == RSA_size(rsa_key_));
70 output->advance_write(bytes_encrypted);
71 return KM_ERROR_OK;
72}
73
Shawn Willden6bfbff02015-02-06 19:48:24 -070074keymaster_error_t RsaVerifyOperation::Finish(const AuthorizationSet& /* additional_params */,
75 const Buffer& signature, Buffer* /* output */) {
Adam Langleyf2aefdf2014-09-26 11:16:10 -070076#if defined(OPENSSL_IS_BORINGSSL)
Shawn Willden4200f212014-12-02 07:01:21 -070077 size_t message_size = data_.available_read();
Adam Langleyf2aefdf2014-09-26 11:16:10 -070078#else
Shawn Willden4200f212014-12-02 07:01:21 -070079 if (data_.available_read() > INT_MAX)
Shawn Willden0a4df7e2014-08-28 16:09:05 -060080 return KM_ERROR_INVALID_INPUT_LENGTH;
Shawn Willden4200f212014-12-02 07:01:21 -070081 int message_size = (int)data_.available_read();
Adam Langleyf2aefdf2014-09-26 11:16:10 -070082#endif
83
Shawn Willden4200f212014-12-02 07:01:21 -070084 if (message_size != RSA_size(rsa_key_))
85 return KM_ERROR_INVALID_INPUT_LENGTH;
86
Shawn Willden0a4df7e2014-08-28 16:09:05 -060087 if (data_.available_read() != signature.available_read())
88 return KM_ERROR_VERIFICATION_FAILED;
89
90 UniquePtr<uint8_t[]> decrypted_data(new uint8_t[RSA_size(rsa_key_)]);
91 int bytes_decrypted = RSA_public_decrypt(signature.available_read(), signature.peek_read(),
92 decrypted_data.get(), rsa_key_, RSA_NO_PADDING);
93 if (bytes_decrypted < 0)
94 return KM_ERROR_UNKNOWN_ERROR;
95 assert(bytes_decrypted == RSA_size(rsa_key_));
96
97 if (memcmp_s(decrypted_data.get(), data_.peek_read(), data_.available_read()) == 0)
98 return KM_ERROR_OK;
99 return KM_ERROR_VERIFICATION_FAILED;
100}
101
Shawn Willden4200f212014-12-02 07:01:21 -0700102const int OAEP_PADDING_OVERHEAD = 41;
103const int PKCS1_PADDING_OVERHEAD = 11;
104
Shawn Willden6bfbff02015-02-06 19:48:24 -0700105keymaster_error_t RsaEncryptOperation::Finish(const AuthorizationSet& /* additional_params */,
106 const Buffer& /* signature */, Buffer* output) {
Shawn Willdenb7361132014-12-08 08:15:14 -0700107 assert(output);
Shawn Willden4200f212014-12-02 07:01:21 -0700108 int openssl_padding;
109
110#if defined(OPENSSL_IS_BORINGSSL)
111 size_t message_size = data_.available_read();
112#else
113 if (data_.available_read() > INT_MAX)
114 return KM_ERROR_INVALID_INPUT_LENGTH;
115 int message_size = (int)data_.available_read();
116#endif
117
118 switch (padding_) {
119 case KM_PAD_RSA_OAEP:
120 openssl_padding = RSA_PKCS1_OAEP_PADDING;
121 if (message_size >= RSA_size(rsa_key_) - OAEP_PADDING_OVERHEAD) {
122 logger().error("Cannot encrypt %d bytes with %d-byte key and OAEP padding",
123 data_.available_read(), RSA_size(rsa_key_));
124 return KM_ERROR_INVALID_INPUT_LENGTH;
125 }
126 break;
127 case KM_PAD_RSA_PKCS1_1_5_ENCRYPT:
128 openssl_padding = RSA_PKCS1_PADDING;
129 if (message_size >= RSA_size(rsa_key_) - PKCS1_PADDING_OVERHEAD) {
130 logger().error("Cannot encrypt %d bytes with %d-byte key and PKCS1 padding",
131 data_.available_read(), RSA_size(rsa_key_));
132 return KM_ERROR_INVALID_INPUT_LENGTH;
133 }
134 break;
135 default:
136 logger().error("Padding mode %d not supported", padding_);
137 return KM_ERROR_UNSUPPORTED_PADDING_MODE;
138 }
139
140 output->Reinitialize(RSA_size(rsa_key_));
141 int bytes_encrypted = RSA_public_encrypt(data_.available_read(), data_.peek_read(),
142 output->peek_write(), rsa_key_, openssl_padding);
143
144 if (bytes_encrypted < 0) {
145 logger().error("Error %d encrypting data with RSA", ERR_get_error());
146 return KM_ERROR_UNKNOWN_ERROR;
147 }
148 assert(bytes_encrypted == RSA_size(rsa_key_));
149 output->advance_write(bytes_encrypted);
150
151 return KM_ERROR_OK;
152}
153
Shawn Willden6bfbff02015-02-06 19:48:24 -0700154keymaster_error_t RsaDecryptOperation::Finish(const AuthorizationSet& /* additional_params */,
155 const Buffer& /* signature */, Buffer* output) {
Shawn Willdenb7361132014-12-08 08:15:14 -0700156 assert(output);
Shawn Willden4200f212014-12-02 07:01:21 -0700157 int openssl_padding;
158 switch (padding_) {
159 case KM_PAD_RSA_OAEP:
160 openssl_padding = RSA_PKCS1_OAEP_PADDING;
161 break;
162 case KM_PAD_RSA_PKCS1_1_5_ENCRYPT:
163 openssl_padding = RSA_PKCS1_PADDING;
164 break;
165 default:
166 logger().error("Padding mode %d not supported", padding_);
167 return KM_ERROR_UNSUPPORTED_PADDING_MODE;
168 }
169
170 output->Reinitialize(RSA_size(rsa_key_));
171 int bytes_decrypted = RSA_private_decrypt(data_.available_read(), data_.peek_read(),
172 output->peek_write(), rsa_key_, openssl_padding);
173
174 if (bytes_decrypted < 0) {
175 logger().error("Error %d decrypting data with RSA", ERR_get_error());
176 return KM_ERROR_UNKNOWN_ERROR;
177 }
178 output->advance_write(bytes_decrypted);
179
180 return KM_ERROR_OK;
181}
182
Shawn Willden0a4df7e2014-08-28 16:09:05 -0600183} // namespace keymaster