blob: 73549a8013ce72872a1decb8255e0c55b1ead958 [file] [log] [blame]
Shawn Willden907c3012014-12-08 15:51:55 -07001/*
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 Willden6dde87c2014-12-11 14:08:48 -070017#include <stdio.h>
18
Shawn Willden06298102015-05-25 23:12:48 -060019#include <UniquePtr.h>
20
Shawn Willden907c3012014-12-08 15:51:55 -070021#include <openssl/aes.h>
Shawn Willdenf0f68b92014-12-30 16:03:28 -070022#include <openssl/err.h>
Shawn Willden907c3012014-12-08 15:51:55 -070023#include <openssl/rand.h>
24
Shawn Willden567a4a02014-12-31 12:14:46 -070025#include <keymaster/logger.h>
26
Shawn Willden63ac0432014-12-29 14:07:08 -070027#include "aes_key.h"
Shawn Willden907c3012014-12-08 15:51:55 -070028#include "aes_operation.h"
Shawn Willdenf0f68b92014-12-30 16:03:28 -070029#include "openssl_err.h"
Shawn Willden907c3012014-12-08 15:51:55 -070030
31namespace keymaster {
32
Shawn Willden3ed6d062015-04-15 13:39:38 -060033Operation* AesOperationFactory::CreateOperation(const Key& key,
Shawn Willden31e063f2015-05-08 14:31:22 -060034 const AuthorizationSet& begin_params,
Shawn Willden3ed6d062015-04-15 13:39:38 -060035 keymaster_error_t* error) {
Shawn Willden63ac0432014-12-29 14:07:08 -070036 *error = KM_ERROR_OK;
Shawn Willdenf0f68b92014-12-30 16:03:28 -070037 const SymmetricKey* symmetric_key = static_cast<const SymmetricKey*>(&key);
Shawn Willdenf0f68b92014-12-30 16:03:28 -070038
39 switch (symmetric_key->key_data_size()) {
40 case 16:
41 case 24:
42 case 32:
43 break;
44 default:
45 *error = KM_ERROR_UNSUPPORTED_KEY_SIZE;
Shawn Willden3ad5f052015-05-08 14:05:13 -060046 return nullptr;
Shawn Willdenf0f68b92014-12-30 16:03:28 -070047 }
48
Shawn Willden63ac0432014-12-29 14:07:08 -070049 keymaster_block_mode_t block_mode;
Shawn Willden31e063f2015-05-08 14:31:22 -060050 if (!begin_params.GetTagValue(TAG_BLOCK_MODE, &block_mode)) {
51 LOG_E("%d block modes specified in begin params", begin_params.GetTagCount(TAG_BLOCK_MODE));
Shawn Willdenf0f68b92014-12-30 16:03:28 -070052 *error = KM_ERROR_UNSUPPORTED_BLOCK_MODE;
Shawn Willden31e063f2015-05-08 14:31:22 -060053 return nullptr;
54 } else if (!supported(block_mode)) {
55 LOG_E("Block mode %d not supported", block_mode);
56 *error = KM_ERROR_UNSUPPORTED_BLOCK_MODE;
57 return nullptr;
58 } else if (!key.authorizations().Contains(TAG_BLOCK_MODE, block_mode)) {
59 LOG_E("Block mode %d was specified, but not authorized by key", block_mode);
60 *error = KM_ERROR_INCOMPATIBLE_BLOCK_MODE;
61 return nullptr;
62 }
Shawn Willdenf0f68b92014-12-30 16:03:28 -070063
Shawn Willdenc4424672015-05-11 11:56:02 -060064 keymaster_padding_t padding;
65 if (!begin_params.GetTagValue(TAG_PADDING, &padding)) {
Shawn Willdended8e7d2015-06-01 15:29:12 -060066 LOG_E("%d padding modes specified in begin params", begin_params.GetTagCount(TAG_PADDING));
Shawn Willdenc4424672015-05-11 11:56:02 -060067 *error = KM_ERROR_UNSUPPORTED_PADDING_MODE;
68 return nullptr;
69 } else if (!supported(padding)) {
70 LOG_E("Padding mode %d not supported", padding);
71 *error = KM_ERROR_UNSUPPORTED_PADDING_MODE;
72 return nullptr;
73 } else if (!key.authorizations().Contains(TAG_PADDING, padding)) {
Shawn Willden3ad5f052015-05-08 14:05:13 -060074 LOG_E("Padding mode %d was specified, but not authorized by key", padding);
75 *error = KM_ERROR_INCOMPATIBLE_PADDING_MODE;
Shawn Willdenc4424672015-05-11 11:56:02 -060076 return nullptr;
Shawn Willden3ad5f052015-05-08 14:05:13 -060077 }
Shawn Willdenf0f68b92014-12-30 16:03:28 -070078
Shawn Willden7a62f5e2015-03-10 12:59:20 -060079 bool caller_nonce = key.authorizations().GetTagValue(TAG_CALLER_NONCE);
80
Shawn Willdenf0f68b92014-12-30 16:03:28 -070081 if (*error != KM_ERROR_OK)
Shawn Willden3ad5f052015-05-08 14:05:13 -060082 return nullptr;
Shawn Willdenf0f68b92014-12-30 16:03:28 -070083
84 switch (block_mode) {
Shawn Willdenf0f68b92014-12-30 16:03:28 -070085 case KM_MODE_ECB:
86 case KM_MODE_CBC:
Shawn Willden7a62f5e2015-03-10 12:59:20 -060087 return CreateEvpOperation(*symmetric_key, block_mode, padding, caller_nonce, error);
Thai Duong20d725d2015-03-24 17:49:58 -070088 case KM_MODE_CTR:
89 if (padding != KM_PAD_NONE) {
Shawn Willden3ad5f052015-05-08 14:05:13 -060090 *error = KM_ERROR_INCOMPATIBLE_PADDING_MODE;
91 return nullptr;
Thai Duong20d725d2015-03-24 17:49:58 -070092 }
93 return CreateEvpOperation(*symmetric_key, block_mode, padding, caller_nonce, error);
Shawn Willdenf0f68b92014-12-30 16:03:28 -070094 default:
Shawn Willden63ac0432014-12-29 14:07:08 -070095 *error = KM_ERROR_UNSUPPORTED_BLOCK_MODE;
Shawn Willden3ad5f052015-05-08 14:05:13 -060096 return nullptr;
Shawn Willden63ac0432014-12-29 14:07:08 -070097 }
Shawn Willdenf0f68b92014-12-30 16:03:28 -070098}
99
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700100Operation* AesOperationFactory::CreateEvpOperation(const SymmetricKey& key,
101 keymaster_block_mode_t block_mode,
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600102 keymaster_padding_t padding, bool caller_iv,
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700103 keymaster_error_t* error) {
104 Operation* op = NULL;
105 switch (purpose()) {
106 case KM_PURPOSE_ENCRYPT:
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600107 op = new AesEvpEncryptOperation(block_mode, padding, caller_iv, key.key_data(),
108 key.key_data_size());
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700109 break;
110 case KM_PURPOSE_DECRYPT:
111 op = new AesEvpDecryptOperation(block_mode, padding, key.key_data(), key.key_data_size());
112 break;
113 default:
114 *error = KM_ERROR_UNSUPPORTED_PURPOSE;
115 return NULL;
116 }
117
118 if (!op)
119 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
120 return op;
121}
122
Shawn Willdenc47c88f2015-04-07 17:23:27 -0600123static const keymaster_block_mode_t supported_block_modes[] = {KM_MODE_ECB, KM_MODE_CBC,
124 KM_MODE_CTR};
Shawn Willden63ac0432014-12-29 14:07:08 -0700125
126const keymaster_block_mode_t*
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700127AesOperationFactory::SupportedBlockModes(size_t* block_mode_count) const {
Shawn Willden63ac0432014-12-29 14:07:08 -0700128 *block_mode_count = array_length(supported_block_modes);
129 return supported_block_modes;
130}
131
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700132static const keymaster_padding_t supported_padding_modes[] = {KM_PAD_NONE, KM_PAD_PKCS7};
133const keymaster_padding_t*
134AesOperationFactory::SupportedPaddingModes(size_t* padding_mode_count) const {
135 *padding_mode_count = array_length(supported_padding_modes);
136 return supported_padding_modes;
137}
Shawn Willden63ac0432014-12-29 14:07:08 -0700138
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700139AesEvpOperation::AesEvpOperation(keymaster_purpose_t purpose, keymaster_block_mode_t block_mode,
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600140 keymaster_padding_t padding, bool caller_iv, const uint8_t* key,
141 size_t key_size)
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700142 : Operation(purpose), key_size_(key_size), block_mode_(block_mode), padding_(padding),
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600143 caller_iv_(caller_iv) {
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700144 memcpy(key_, key, key_size_);
145 EVP_CIPHER_CTX_init(&ctx_);
146}
147
148AesEvpOperation::~AesEvpOperation() {
149 EVP_CIPHER_CTX_cleanup(&ctx_);
150}
151
152keymaster_error_t AesEvpOperation::InitializeCipher() {
153 const EVP_CIPHER* cipher;
154 switch (block_mode_) {
155 case KM_MODE_ECB:
156 switch (key_size_) {
157 case 16:
158 cipher = EVP_aes_128_ecb();
159 break;
160 case 24:
161 cipher = EVP_aes_192_ecb();
162 break;
163 case 32:
164 cipher = EVP_aes_256_ecb();
165 break;
166 default:
167 return KM_ERROR_UNSUPPORTED_KEY_SIZE;
168 }
169 break;
170 case KM_MODE_CBC:
171 switch (key_size_) {
172 case 16:
173 cipher = EVP_aes_128_cbc();
174 break;
175 case 24:
176 cipher = EVP_aes_192_cbc();
177 break;
178 case 32:
179 cipher = EVP_aes_256_cbc();
180 break;
181 default:
182 return KM_ERROR_UNSUPPORTED_KEY_SIZE;
183 }
184 break;
Thai Duong20d725d2015-03-24 17:49:58 -0700185 case KM_MODE_CTR:
186 switch (key_size_) {
187 case 16:
188 cipher = EVP_aes_128_ctr();
189 break;
190 case 24:
191 cipher = EVP_aes_192_ctr();
192 break;
193 case 32:
194 cipher = EVP_aes_256_ctr();
195 break;
196 default:
197 return KM_ERROR_UNSUPPORTED_KEY_SIZE;
198 }
199 break;
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700200 default:
201 return KM_ERROR_UNSUPPORTED_BLOCK_MODE;
202 }
203
204 int init_result =
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600205 EVP_CipherInit_ex(&ctx_, cipher, NULL /* engine */, key_, iv_.get(), evp_encrypt_mode());
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700206
207 if (!init_result)
Shawn Willdenf01329d2015-03-11 21:51:38 -0600208 return TranslateLastOpenSslError();
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700209
210 switch (padding_) {
211 case KM_PAD_NONE:
212 EVP_CIPHER_CTX_set_padding(&ctx_, 0 /* disable padding */);
213 break;
214 case KM_PAD_PKCS7:
215 // This is the default for OpenSSL EVP cipher operations.
216 break;
217 default:
218 return KM_ERROR_UNSUPPORTED_PADDING_MODE;
219 }
220
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700221 return KM_ERROR_OK;
222}
223
224bool AesEvpOperation::need_iv() const {
225 switch (block_mode_) {
226 case KM_MODE_CBC:
Thai Duong20d725d2015-03-24 17:49:58 -0700227 case KM_MODE_CTR:
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700228 return true;
229 case KM_MODE_ECB:
230 return false;
231 default:
232 // Shouldn't get here.
233 assert(false);
234 return false;
235 }
236}
237
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600238keymaster_error_t AesEvpOperation::Begin(const AuthorizationSet& input_params,
239 AuthorizationSet* output_params) {
240 if (!output_params)
241 return KM_ERROR_OUTPUT_PARAMETER_NULL;
242
243 keymaster_error_t error = KM_ERROR_OK;
244 if (need_iv()) {
245 switch (purpose()) {
246 case KM_PURPOSE_ENCRYPT:
Shawn Willden67706352015-04-28 00:43:19 -0600247 if (input_params.find(TAG_NONCE) == -1)
248 error = GenerateIv();
249 else if (caller_iv_)
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600250 error = GetIv(input_params);
Shawn Willden67706352015-04-28 00:43:19 -0600251 else
252 error = KM_ERROR_CALLER_NONCE_PROHIBITED;
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600253
254 if (error == KM_ERROR_OK)
255 output_params->push_back(TAG_NONCE, iv_.get(), AES_BLOCK_SIZE);
256 break;
257
258 case KM_PURPOSE_DECRYPT:
259 error = GetIv(input_params);
260 break;
261 default:
262 return KM_ERROR_UNSUPPORTED_PURPOSE;
263 }
264 }
265
266 if (error == KM_ERROR_OK)
267 error = InitializeCipher();
268
269 return error;
270}
271
272keymaster_error_t AesEvpOperation::GetIv(const AuthorizationSet& input_params) {
273 keymaster_blob_t iv_blob;
274 if (!input_params.GetTagValue(TAG_NONCE, &iv_blob)) {
275 LOG_E("No IV provided", 0);
276 return KM_ERROR_INVALID_ARGUMENT;
277 }
278 if (iv_blob.data_length != AES_BLOCK_SIZE) {
279 LOG_E("Expected %d-byte IV for AES operation, but got %d bytes", AES_BLOCK_SIZE,
280 iv_blob.data_length);
Thai Duong20d725d2015-03-24 17:49:58 -0700281 return KM_ERROR_INVALID_NONCE;
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600282 }
283 iv_.reset(dup_array(iv_blob.data, iv_blob.data_length));
Shawn Willden92b69a32015-03-14 11:07:36 -0600284 if (!iv_.get())
285 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700286 return KM_ERROR_OK;
287}
288
Shawn Willden67706352015-04-28 00:43:19 -0600289keymaster_error_t AesEvpOperation::GenerateIv() {
290 iv_.reset(new uint8_t[AES_BLOCK_SIZE]);
291 if (!iv_.get())
292 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willden34454982015-04-29 23:22:37 -0600293 if (RAND_bytes(iv_.get(), AES_BLOCK_SIZE) != 1)
Shawn Willden67706352015-04-28 00:43:19 -0600294 return TranslateLastOpenSslError();
295 return KM_ERROR_OK;
296}
297
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700298inline size_t min(size_t a, size_t b) {
299 if (a < b)
300 return a;
301 return b;
302}
303
304keymaster_error_t AesEvpOperation::Update(const AuthorizationSet& /* additional_params */,
Shawn Willdended8e7d2015-06-01 15:29:12 -0600305 const Buffer& input,
306 AuthorizationSet* /* output_params */, Buffer* output,
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700307 size_t* input_consumed) {
308 output->reserve(input.available_read() + AES_BLOCK_SIZE);
309
310 const uint8_t* input_pos = input.peek_read();
311 const uint8_t* input_end = input_pos + input.available_read();
312
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700313 int output_written = -1;
314 if (!EVP_CipherUpdate(&ctx_, output->peek_write(), &output_written, input_pos,
315 input_end - input_pos))
316 return TranslateLastOpenSslError();
317
318 assert(output_written >= 0);
319 assert(output_written <= (int)output->available_write());
320 output->advance_write(output_written);
321 *input_consumed = input.available_read();
322 return KM_ERROR_OK;
323}
324
325keymaster_error_t AesEvpOperation::Finish(const AuthorizationSet& /* additional_params */,
Shawn Willdended8e7d2015-06-01 15:29:12 -0600326 const Buffer& /* signature */,
327 AuthorizationSet* /* output_params */, Buffer* output) {
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700328 output->reserve(AES_BLOCK_SIZE);
329
330 int output_written = -1;
331 if (!EVP_CipherFinal_ex(&ctx_, output->peek_write(), &output_written)) {
332 LOG_E("Error encrypting final block: %s", ERR_error_string(ERR_peek_last_error(), NULL));
333 return TranslateLastOpenSslError();
334 }
335
336 assert(output_written <= AES_BLOCK_SIZE);
337 output->advance_write(output_written);
338 return KM_ERROR_OK;
339}
340
341keymaster_error_t AesEvpOperation::Abort() {
342 return KM_ERROR_OK;
343}
344
Shawn Willden907c3012014-12-08 15:51:55 -0700345} // namespace keymaster