blob: c3bc6623952794ab395178eb8ba1f67080ac3e57 [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 Willden0f906ec2015-06-20 09:16:30 -060017#include "aes_operation.h"
18
Shawn Willden6dde87c2014-12-11 14:08:48 -070019#include <stdio.h>
20
Shawn Willden0f906ec2015-06-20 09:16:30 -060021#include <new>
22
Shawn Willden06298102015-05-25 23:12:48 -060023#include <UniquePtr.h>
24
Shawn Willden907c3012014-12-08 15:51:55 -070025#include <openssl/aes.h>
Shawn Willdenf0f68b92014-12-30 16:03:28 -070026#include <openssl/err.h>
Shawn Willden907c3012014-12-08 15:51:55 -070027#include <openssl/rand.h>
28
Shawn Willden567a4a02014-12-31 12:14:46 -070029#include <keymaster/logger.h>
30
Shawn Willden63ac0432014-12-29 14:07:08 -070031#include "aes_key.h"
Shawn Willdenf0f68b92014-12-30 16:03:28 -070032#include "openssl_err.h"
Shawn Willden907c3012014-12-08 15:51:55 -070033
34namespace keymaster {
35
Shawn Willdenc4bfa862015-06-17 09:46:50 -060036static const size_t GCM_NONCE_SIZE = 12;
Shawn Willden0f392562015-06-02 09:00:52 -060037static const size_t GCM_MAX_TAG_LENGTH = 16;
38static const size_t GCM_MIN_TAG_LENGTH = 12;
39
40inline bool allows_padding(keymaster_block_mode_t block_mode) {
Shawn Willden5532a082015-07-01 12:58:08 -060041 switch (block_mode) {
42 case KM_MODE_CTR:
43 case KM_MODE_GCM:
44 return false;
45 case KM_MODE_ECB:
46 case KM_MODE_CBC:
47 return true;
48 }
49 assert(false /* Can't get here */);
50 return false;
Shawn Willden0f392562015-06-02 09:00:52 -060051}
52
Shawn Willden33ab0382015-07-08 08:47:25 -060053static keymaster_error_t GetAndValidateGcmTagLength(const AuthorizationSet& begin_params,
54 const AuthorizationSet& key_params,
55 size_t* tag_length) {
56 uint32_t tag_length_bits;
57 if (!begin_params.GetTagValue(TAG_MAC_LENGTH, &tag_length_bits)) {
58 return KM_ERROR_MISSING_MAC_LENGTH;
59 }
60
61 uint32_t min_tag_length_bits;
62 if (!key_params.GetTagValue(TAG_MIN_MAC_LENGTH, &min_tag_length_bits)) {
63 LOG_E("AES GCM key must have KM_TAG_MIN_MAC_LENGTH", 0);
64 return KM_ERROR_INVALID_KEY_BLOB;
65 }
66
67 if (tag_length_bits % 8 != 0 || tag_length_bits > kMaxGcmTagLength ||
68 tag_length_bits < kMinGcmTagLength) {
69 return KM_ERROR_UNSUPPORTED_MAC_LENGTH;
70 }
71
72 if (tag_length_bits < min_tag_length_bits) {
73 return KM_ERROR_INVALID_MAC_LENGTH;
74 }
75
76 *tag_length = tag_length_bits / 8;
77 return KM_ERROR_OK;
78}
79
Shawn Willden3ed6d062015-04-15 13:39:38 -060080Operation* AesOperationFactory::CreateOperation(const Key& key,
Shawn Willden31e063f2015-05-08 14:31:22 -060081 const AuthorizationSet& begin_params,
Shawn Willden3ed6d062015-04-15 13:39:38 -060082 keymaster_error_t* error) {
Shawn Willden63ac0432014-12-29 14:07:08 -070083 *error = KM_ERROR_OK;
Shawn Willdenf0f68b92014-12-30 16:03:28 -070084 const SymmetricKey* symmetric_key = static_cast<const SymmetricKey*>(&key);
Shawn Willdenf0f68b92014-12-30 16:03:28 -070085
86 switch (symmetric_key->key_data_size()) {
87 case 16:
88 case 24:
89 case 32:
90 break;
91 default:
92 *error = KM_ERROR_UNSUPPORTED_KEY_SIZE;
Shawn Willden3ad5f052015-05-08 14:05:13 -060093 return nullptr;
Shawn Willdenf0f68b92014-12-30 16:03:28 -070094 }
95
Shawn Willden63ac0432014-12-29 14:07:08 -070096 keymaster_block_mode_t block_mode;
Shawn Willden31e063f2015-05-08 14:31:22 -060097 if (!begin_params.GetTagValue(TAG_BLOCK_MODE, &block_mode)) {
98 LOG_E("%d block modes specified in begin params", begin_params.GetTagCount(TAG_BLOCK_MODE));
Shawn Willdenf0f68b92014-12-30 16:03:28 -070099 *error = KM_ERROR_UNSUPPORTED_BLOCK_MODE;
Shawn Willdene23a2c92015-07-06 15:52:45 -0600100 return nullptr;
Shawn Willden31e063f2015-05-08 14:31:22 -0600101 } else if (!supported(block_mode)) {
102 LOG_E("Block mode %d not supported", block_mode);
103 *error = KM_ERROR_UNSUPPORTED_BLOCK_MODE;
Shawn Willdene23a2c92015-07-06 15:52:45 -0600104 return nullptr;
Shawn Willden31e063f2015-05-08 14:31:22 -0600105 } else if (!key.authorizations().Contains(TAG_BLOCK_MODE, block_mode)) {
106 LOG_E("Block mode %d was specified, but not authorized by key", block_mode);
107 *error = KM_ERROR_INCOMPATIBLE_BLOCK_MODE;
Shawn Willdene23a2c92015-07-06 15:52:45 -0600108 return nullptr;
Shawn Willden0f392562015-06-02 09:00:52 -0600109 }
110
111 size_t tag_length = 0;
Shawn Willden34419132015-06-08 23:10:44 -0600112 if (block_mode == KM_MODE_GCM) {
Shawn Willden33ab0382015-07-08 08:47:25 -0600113 *error = GetAndValidateGcmTagLength(begin_params, key.authorizations(), &tag_length);
114 if (*error != KM_ERROR_OK) {
Shawn Willdene23a2c92015-07-06 15:52:45 -0600115 return nullptr;
116 }
Shawn Willden31e063f2015-05-08 14:31:22 -0600117 }
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700118
Shawn Willdenc4424672015-05-11 11:56:02 -0600119 keymaster_padding_t padding;
Shawn Willden33ab0382015-07-08 08:47:25 -0600120 if (!GetAndValidatePadding(begin_params, key, &padding, error)) {
Shawn Willden5532a082015-07-01 12:58:08 -0600121 return nullptr;
Shawn Willden33ab0382015-07-08 08:47:25 -0600122 }
Shawn Willden5532a082015-07-01 12:58:08 -0600123 if (!allows_padding(block_mode) && padding != KM_PAD_NONE) {
Shawn Willden0f392562015-06-02 09:00:52 -0600124 LOG_E("Mode does not support padding", 0);
125 *error = KM_ERROR_INCOMPATIBLE_PADDING_MODE;
Shawn Willdene23a2c92015-07-06 15:52:45 -0600126 return nullptr;
Shawn Willden3ad5f052015-05-08 14:05:13 -0600127 }
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700128
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600129 bool caller_nonce = key.authorizations().GetTagValue(TAG_CALLER_NONCE);
130
Shawn Willdene23a2c92015-07-06 15:52:45 -0600131 Operation* op = nullptr;
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700132 switch (purpose()) {
133 case KM_PURPOSE_ENCRYPT:
Shawn Willden0f906ec2015-06-20 09:16:30 -0600134 op = new (std::nothrow)
135 AesEvpEncryptOperation(block_mode, padding, caller_nonce, tag_length,
136 symmetric_key->key_data(), symmetric_key->key_data_size());
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700137 break;
138 case KM_PURPOSE_DECRYPT:
Shawn Willden0f906ec2015-06-20 09:16:30 -0600139 op = new (std::nothrow)
140 AesEvpDecryptOperation(block_mode, padding, tag_length, symmetric_key->key_data(),
141 symmetric_key->key_data_size());
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700142 break;
143 default:
144 *error = KM_ERROR_UNSUPPORTED_PURPOSE;
Shawn Willdene23a2c92015-07-06 15:52:45 -0600145 return nullptr;
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700146 }
147
148 if (!op)
149 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
150 return op;
151}
152
Shawn Willdenc47c88f2015-04-07 17:23:27 -0600153static const keymaster_block_mode_t supported_block_modes[] = {KM_MODE_ECB, KM_MODE_CBC,
Shawn Willden0f392562015-06-02 09:00:52 -0600154 KM_MODE_CTR, KM_MODE_GCM};
Shawn Willden63ac0432014-12-29 14:07:08 -0700155
156const keymaster_block_mode_t*
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700157AesOperationFactory::SupportedBlockModes(size_t* block_mode_count) const {
Shawn Willden63ac0432014-12-29 14:07:08 -0700158 *block_mode_count = array_length(supported_block_modes);
159 return supported_block_modes;
160}
161
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700162static const keymaster_padding_t supported_padding_modes[] = {KM_PAD_NONE, KM_PAD_PKCS7};
163const keymaster_padding_t*
164AesOperationFactory::SupportedPaddingModes(size_t* padding_mode_count) const {
165 *padding_mode_count = array_length(supported_padding_modes);
166 return supported_padding_modes;
167}
Shawn Willden63ac0432014-12-29 14:07:08 -0700168
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700169AesEvpOperation::AesEvpOperation(keymaster_purpose_t purpose, keymaster_block_mode_t block_mode,
Shawn Willden34419132015-06-08 23:10:44 -0600170 keymaster_padding_t padding, bool caller_iv, size_t tag_length,
171 const uint8_t* key, size_t key_size)
172 : Operation(purpose), block_mode_(block_mode), caller_iv_(caller_iv), tag_length_(tag_length),
173 data_started_(false), key_size_(key_size), padding_(padding) {
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700174 memcpy(key_, key, key_size_);
175 EVP_CIPHER_CTX_init(&ctx_);
176}
177
178AesEvpOperation::~AesEvpOperation() {
179 EVP_CIPHER_CTX_cleanup(&ctx_);
Shawn Willden34419132015-06-08 23:10:44 -0600180 memset_s(aad_block_buf_.get(), AES_BLOCK_SIZE, 0);
181}
182
183keymaster_error_t AesEvpOperation::Begin(const AuthorizationSet& /* input_params */,
184 AuthorizationSet* /* output_params */) {
185 if (block_mode_ == KM_MODE_GCM) {
186 aad_block_buf_length_ = 0;
Shawn Willden0f906ec2015-06-20 09:16:30 -0600187 aad_block_buf_.reset(new (std::nothrow) uint8_t[AES_BLOCK_SIZE]);
Shawn Willden34419132015-06-08 23:10:44 -0600188 if (!aad_block_buf_.get())
189 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
190 }
191
192 return InitializeCipher();
193}
194
195keymaster_error_t AesEvpOperation::Update(const AuthorizationSet& additional_params,
196 const Buffer& input,
197 AuthorizationSet* /* output_params */, Buffer* output,
198 size_t* input_consumed) {
199 keymaster_error_t error;
200 if (block_mode_ == KM_MODE_GCM)
201 if (!HandleAad(additional_params, input, &error))
202 return error;
203
204 if (!InternalUpdate(input.peek_read(), input.available_read(), output, &error))
205 return error;
206 *input_consumed = input.available_read();
207
208 return KM_ERROR_OK;
209}
210
211inline bool is_bad_decrypt(unsigned long error) {
212 return (ERR_GET_LIB(error) == ERR_LIB_CIPHER && //
213 ERR_GET_REASON(error) == CIPHER_R_BAD_DECRYPT);
214}
215
216keymaster_error_t AesEvpOperation::Finish(const AuthorizationSet& /* additional_params */,
217 const Buffer& /* signature */,
218 AuthorizationSet* /* output_params */, Buffer* output) {
219 if (!output->reserve(AES_BLOCK_SIZE))
220 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
221
222 keymaster_error_t error;
223 if (block_mode_ == KM_MODE_GCM && aad_block_buf_length_ > 0 &&
224 !ProcessBufferedAadBlock(&error)) {
225 return error;
226 }
227
228 int output_written = -1;
229 if (!EVP_CipherFinal_ex(&ctx_, output->peek_write(), &output_written)) {
230 if (tag_length_ > 0)
231 return KM_ERROR_VERIFICATION_FAILED;
232 LOG_E("Error encrypting final block: %s", ERR_error_string(ERR_peek_last_error(), NULL));
233 return TranslateLastOpenSslError();
234 }
235
236 assert(output_written <= AES_BLOCK_SIZE);
Shawn Willden0f906ec2015-06-20 09:16:30 -0600237 if (!output->advance_write(output_written))
238 return KM_ERROR_UNKNOWN_ERROR;
Shawn Willden34419132015-06-08 23:10:44 -0600239 return KM_ERROR_OK;
240}
241
242bool AesEvpOperation::need_iv() const {
243 switch (block_mode_) {
244 case KM_MODE_CBC:
245 case KM_MODE_CTR:
246 case KM_MODE_GCM:
247 return true;
248 case KM_MODE_ECB:
249 return false;
250 default:
251 // Shouldn't get here.
252 assert(false);
253 return false;
254 }
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700255}
256
257keymaster_error_t AesEvpOperation::InitializeCipher() {
258 const EVP_CIPHER* cipher;
259 switch (block_mode_) {
260 case KM_MODE_ECB:
261 switch (key_size_) {
262 case 16:
263 cipher = EVP_aes_128_ecb();
264 break;
265 case 24:
266 cipher = EVP_aes_192_ecb();
267 break;
268 case 32:
269 cipher = EVP_aes_256_ecb();
270 break;
271 default:
272 return KM_ERROR_UNSUPPORTED_KEY_SIZE;
273 }
274 break;
275 case KM_MODE_CBC:
276 switch (key_size_) {
277 case 16:
278 cipher = EVP_aes_128_cbc();
279 break;
280 case 24:
281 cipher = EVP_aes_192_cbc();
282 break;
283 case 32:
284 cipher = EVP_aes_256_cbc();
285 break;
286 default:
287 return KM_ERROR_UNSUPPORTED_KEY_SIZE;
288 }
289 break;
Thai Duong20d725d2015-03-24 17:49:58 -0700290 case KM_MODE_CTR:
291 switch (key_size_) {
292 case 16:
293 cipher = EVP_aes_128_ctr();
294 break;
295 case 24:
296 cipher = EVP_aes_192_ctr();
297 break;
298 case 32:
299 cipher = EVP_aes_256_ctr();
300 break;
301 default:
302 return KM_ERROR_UNSUPPORTED_KEY_SIZE;
303 }
304 break;
Shawn Willden0f392562015-06-02 09:00:52 -0600305 case KM_MODE_GCM:
306 switch (key_size_) {
307 case 16:
308 cipher = EVP_aes_128_gcm();
309 break;
310 case 24:
311 cipher = EVP_aes_192_gcm();
312 break;
313 case 32:
314 cipher = EVP_aes_256_gcm();
315 break;
316 default:
317 return KM_ERROR_UNSUPPORTED_KEY_SIZE;
318 }
319 break;
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700320 default:
321 return KM_ERROR_UNSUPPORTED_BLOCK_MODE;
322 }
323
Shawn Willden0f392562015-06-02 09:00:52 -0600324 if (!EVP_CipherInit_ex(&ctx_, cipher, NULL /* engine */, key_, iv_.get(), evp_encrypt_mode()))
Shawn Willdenf01329d2015-03-11 21:51:38 -0600325 return TranslateLastOpenSslError();
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700326
327 switch (padding_) {
328 case KM_PAD_NONE:
329 EVP_CIPHER_CTX_set_padding(&ctx_, 0 /* disable padding */);
330 break;
331 case KM_PAD_PKCS7:
332 // This is the default for OpenSSL EVP cipher operations.
333 break;
334 default:
335 return KM_ERROR_UNSUPPORTED_PADDING_MODE;
336 }
337
Shawn Willden34419132015-06-08 23:10:44 -0600338 if (block_mode_ == KM_MODE_GCM) {
339 aad_block_buf_length_ = 0;
Shawn Willden0f906ec2015-06-20 09:16:30 -0600340 aad_block_buf_.reset(new (std::nothrow) uint8_t[AES_BLOCK_SIZE]);
Shawn Willden34419132015-06-08 23:10:44 -0600341 if (!aad_block_buf_.get())
342 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
343 }
344
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700345 return KM_ERROR_OK;
346}
347
Shawn Willden34419132015-06-08 23:10:44 -0600348keymaster_error_t AesEvpOperation::GetIv(const AuthorizationSet& input_params) {
349 keymaster_blob_t iv_blob;
350 if (!input_params.GetTagValue(TAG_NONCE, &iv_blob)) {
351 LOG_E("No IV provided", 0);
352 return KM_ERROR_INVALID_ARGUMENT;
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700353 }
Shawn Willden34419132015-06-08 23:10:44 -0600354 if (block_mode_ != KM_MODE_GCM && iv_blob.data_length != AES_BLOCK_SIZE) {
355 LOG_E("Expected %d-byte IV for AES operation, but got %d bytes", AES_BLOCK_SIZE,
356 iv_blob.data_length);
357 return KM_ERROR_INVALID_NONCE;
358 }
Shawn Willdenc4bfa862015-06-17 09:46:50 -0600359 if (block_mode_ == KM_MODE_GCM && iv_blob.data_length != GCM_NONCE_SIZE) {
360 LOG_E("Expected %d-byte nonce for AES-GCM operation, but got %d bytes", GCM_NONCE_SIZE,
361 iv_blob.data_length);
362 return KM_ERROR_INVALID_NONCE;
363 }
Shawn Willden34419132015-06-08 23:10:44 -0600364 iv_.reset(dup_array(iv_blob.data, iv_blob.data_length));
365 if (!iv_.get())
366 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
367 iv_length_ = iv_blob.data_length;
368 return KM_ERROR_OK;
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700369}
370
Shawn Willden34419132015-06-08 23:10:44 -0600371/*
372 * Process Incoming Associated Authentication Data.
373 *
374 * This method is more complex than might be expected, because the underlying library silently does
375 * the wrong thing when given partial AAD blocks, so we have to take care to process AAD in
376 * AES_BLOCK_SIZE increments, buffering (in aad_block_buf_) when given smaller amounts of data.
377 */
378bool AesEvpOperation::HandleAad(const AuthorizationSet& input_params, const Buffer& input,
379 keymaster_error_t* error) {
380 assert(tag_length_ > 0);
381 assert(error);
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600382
Shawn Willden34419132015-06-08 23:10:44 -0600383 keymaster_blob_t aad;
384 if (input_params.GetTagValue(TAG_ASSOCIATED_DATA, &aad)) {
385 if (data_started_) {
386 *error = KM_ERROR_INVALID_TAG;
387 return false;
388 }
389
390 if (aad_block_buf_length_ > 0) {
391 FillBufferedAadBlock(&aad);
392 if (aad_block_buf_length_ == AES_BLOCK_SIZE && !ProcessBufferedAadBlock(error))
393 return false;
394 }
395
396 size_t blocks_to_process = aad.data_length / AES_BLOCK_SIZE;
397 if (blocks_to_process && !ProcessAadBlocks(aad.data, blocks_to_process, error))
398 return false;
399 aad.data += blocks_to_process * AES_BLOCK_SIZE;
400 aad.data_length -= blocks_to_process * AES_BLOCK_SIZE;
401
402 FillBufferedAadBlock(&aad);
403 assert(aad.data_length == 0);
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600404 }
405
Shawn Willden34419132015-06-08 23:10:44 -0600406 if (input.available_read()) {
407 data_started_ = true;
408 // Data has begun, no more AAD is allowed. Process any buffered AAD.
409 if (aad_block_buf_length_ > 0 && !ProcessBufferedAadBlock(error))
410 return false;
411 }
412
413 return true;
414}
415
416bool AesEvpOperation::ProcessBufferedAadBlock(keymaster_error_t* error) {
417 int output_written;
418 if (EVP_CipherUpdate(&ctx_, nullptr /* out */, &output_written, aad_block_buf_.get(),
419 aad_block_buf_length_)) {
420 aad_block_buf_length_ = 0;
421 return true;
422 }
423 *error = TranslateLastOpenSslError();
424 return false;
425}
426
427bool AesEvpOperation::ProcessAadBlocks(const uint8_t* data, size_t blocks,
428 keymaster_error_t* error) {
429 int output_written;
430 if (EVP_CipherUpdate(&ctx_, nullptr /* out */, &output_written, data, blocks * AES_BLOCK_SIZE))
431 return true;
432 *error = TranslateLastOpenSslError();
433 return false;
434}
435
436inline size_t min(size_t a, size_t b) {
437 return (a < b) ? a : b;
438}
439
440void AesEvpOperation::FillBufferedAadBlock(keymaster_blob_t* aad) {
441 size_t to_buffer = min(AES_BLOCK_SIZE - aad_block_buf_length_, aad->data_length);
442 memcpy(aad_block_buf_.get() + aad_block_buf_length_, aad->data, to_buffer);
443 aad->data += to_buffer;
444 aad->data_length -= to_buffer;
445 aad_block_buf_length_ += to_buffer;
446}
447
448bool AesEvpOperation::InternalUpdate(const uint8_t* input, size_t input_length, Buffer* output,
449 keymaster_error_t* error) {
450 assert(output);
451 assert(error);
452
Shawn Willden294a2db2015-06-17 11:20:56 -0600453 if (!input_length)
454 return true;
455
Shawn Willden34419132015-06-08 23:10:44 -0600456 if (!output->reserve(input_length + AES_BLOCK_SIZE)) {
457 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
458 return false;
459 }
460
461 int output_written = -1;
462 if (!EVP_CipherUpdate(&ctx_, output->peek_write(), &output_written, input, input_length)) {
463 *error = TranslateLastOpenSslError();
464 return false;
465 }
Shawn Willden0f906ec2015-06-20 09:16:30 -0600466 return output->advance_write(output_written);
Shawn Willden0f392562015-06-02 09:00:52 -0600467}
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600468
Shawn Willden0f392562015-06-02 09:00:52 -0600469keymaster_error_t AesEvpEncryptOperation::Begin(const AuthorizationSet& input_params,
470 AuthorizationSet* output_params) {
471 if (!output_params)
472 return KM_ERROR_OUTPUT_PARAMETER_NULL;
473
474 if (need_iv()) {
475 keymaster_error_t error = KM_ERROR_OK;
476 if (input_params.find(TAG_NONCE) == -1)
477 error = GenerateIv();
478 else if (caller_iv_)
479 error = GetIv(input_params);
480 else
481 error = KM_ERROR_CALLER_NONCE_PROHIBITED;
482
483 if (error == KM_ERROR_OK)
484 output_params->push_back(TAG_NONCE, iv_.get(), iv_length_);
485 else
486 return error;
487 }
488
Shawn Willden34419132015-06-08 23:10:44 -0600489 return AesEvpOperation::Begin(input_params, output_params);
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600490}
491
Shawn Willden34419132015-06-08 23:10:44 -0600492keymaster_error_t AesEvpEncryptOperation::Finish(const AuthorizationSet& additional_params,
493 const Buffer& signature,
494 AuthorizationSet* output_params, Buffer* output) {
495 if (!output->reserve(AES_BLOCK_SIZE + tag_length_))
Shawn Willden92b69a32015-03-14 11:07:36 -0600496 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willden34419132015-06-08 23:10:44 -0600497
498 keymaster_error_t error =
499 AesEvpOperation::Finish(additional_params, signature, output_params, output);
500 if (error != KM_ERROR_OK)
501 return error;
502
503 if (tag_length_ > 0) {
504 if (!output->reserve(output->available_read() + tag_length_))
505 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
506
507 if (!EVP_CIPHER_CTX_ctrl(&ctx_, EVP_CTRL_GCM_GET_TAG, tag_length_, output->peek_write()))
508 return TranslateLastOpenSslError();
Shawn Willden0f906ec2015-06-20 09:16:30 -0600509 if (!output->advance_write(tag_length_))
510 return KM_ERROR_UNKNOWN_ERROR;
Shawn Willden34419132015-06-08 23:10:44 -0600511 }
512
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700513 return KM_ERROR_OK;
514}
515
Shawn Willden0f392562015-06-02 09:00:52 -0600516keymaster_error_t AesEvpEncryptOperation::GenerateIv() {
Shawn Willdenc4bfa862015-06-17 09:46:50 -0600517 iv_length_ = (block_mode_ == KM_MODE_GCM) ? GCM_NONCE_SIZE : AES_BLOCK_SIZE;
Shawn Willden0f906ec2015-06-20 09:16:30 -0600518 iv_.reset(new (std::nothrow) uint8_t[iv_length_]);
Shawn Willden67706352015-04-28 00:43:19 -0600519 if (!iv_.get())
520 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willden0f392562015-06-02 09:00:52 -0600521 if (RAND_bytes(iv_.get(), iv_length_) != 1)
Shawn Willden67706352015-04-28 00:43:19 -0600522 return TranslateLastOpenSslError();
523 return KM_ERROR_OK;
524}
525
Shawn Willden34419132015-06-08 23:10:44 -0600526keymaster_error_t AesEvpDecryptOperation::Begin(const AuthorizationSet& input_params,
527 AuthorizationSet* output_params) {
528 if (need_iv()) {
529 keymaster_error_t error = GetIv(input_params);
530 if (error != KM_ERROR_OK)
531 return error;
Shawn Willden0f392562015-06-02 09:00:52 -0600532 }
533
Shawn Willden34419132015-06-08 23:10:44 -0600534 if (tag_length_ > 0) {
535 tag_buf_length_ = 0;
Shawn Willden0f906ec2015-06-20 09:16:30 -0600536 tag_buf_.reset(new (std::nothrow) uint8_t[tag_length_]);
Shawn Willden34419132015-06-08 23:10:44 -0600537 if (!tag_buf_.get())
538 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
539 }
Shawn Willden0f392562015-06-02 09:00:52 -0600540
Shawn Willden34419132015-06-08 23:10:44 -0600541 return AesEvpOperation::Begin(input_params, output_params);
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700542}
543
Shawn Willden0f392562015-06-02 09:00:52 -0600544keymaster_error_t AesEvpDecryptOperation::Update(const AuthorizationSet& additional_params,
545 const Buffer& input,
Shawn Willden34419132015-06-08 23:10:44 -0600546 AuthorizationSet* /* output_params */,
547 Buffer* output, size_t* input_consumed) {
548 if (!output || !input_consumed)
549 return KM_ERROR_OUTPUT_PARAMETER_NULL;
Shawn Willden0f392562015-06-02 09:00:52 -0600550
Shawn Willden34419132015-06-08 23:10:44 -0600551 // Barring error, we'll consume it all.
552 *input_consumed = input.available_read();
553
554 keymaster_error_t error;
555 if (block_mode_ == KM_MODE_GCM) {
556 if (!HandleAad(additional_params, input, &error))
557 return error;
558 return ProcessAllButTagLengthBytes(input, output);
Shawn Willden0f392562015-06-02 09:00:52 -0600559 }
560
Shawn Willden34419132015-06-08 23:10:44 -0600561 if (!InternalUpdate(input.peek_read(), input.available_read(), output, &error))
562 return error;
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700563 return KM_ERROR_OK;
564}
565
Shawn Willden34419132015-06-08 23:10:44 -0600566keymaster_error_t AesEvpDecryptOperation::ProcessAllButTagLengthBytes(const Buffer& input,
567 Buffer* output) {
568 if (input.available_read() <= tag_buf_unused()) {
569 BufferCandidateTagData(input.peek_read(), input.available_read());
570 return KM_ERROR_OK;
571 }
572
573 const size_t data_available = tag_buf_length_ + input.available_read();
574
575 const size_t to_process = data_available - tag_length_;
576 const size_t to_process_from_tag_buf = min(to_process, tag_buf_length_);
577 const size_t to_process_from_input = to_process - to_process_from_tag_buf;
578
579 if (!output->reserve(to_process + AES_BLOCK_SIZE))
580 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
581
582 keymaster_error_t error;
583 if (!ProcessTagBufContentsAsData(to_process_from_tag_buf, output, &error))
Shawn Willden0f392562015-06-02 09:00:52 -0600584 return error;
585
Shawn Willden34419132015-06-08 23:10:44 -0600586 if (!InternalUpdate(input.peek_read(), to_process_from_input, output, &error))
587 return error;
588
589 BufferCandidateTagData(input.peek_read() + to_process_from_input,
590 input.available_read() - to_process_from_input);
591 assert(tag_buf_unused() == 0);
Shawn Willden0f392562015-06-02 09:00:52 -0600592
593 return KM_ERROR_OK;
594}
Shawn Willden34419132015-06-08 23:10:44 -0600595
596bool AesEvpDecryptOperation::ProcessTagBufContentsAsData(size_t to_process, Buffer* output,
597 keymaster_error_t* error) {
598 assert(to_process <= tag_buf_length_);
599 if (!InternalUpdate(tag_buf_.get(), to_process, output, error))
600 return false;
601 if (to_process < tag_buf_length_)
602 memmove(tag_buf_.get(), tag_buf_.get() + to_process, tag_buf_length_ - to_process);
603 tag_buf_length_ -= to_process;
604 return true;
605}
606
607void AesEvpDecryptOperation::BufferCandidateTagData(const uint8_t* data, size_t data_length) {
608 assert(data_length <= tag_length_ - tag_buf_length_);
609 memcpy(tag_buf_.get() + tag_buf_length_, data, data_length);
610 tag_buf_length_ += data_length;
611}
612
613keymaster_error_t AesEvpDecryptOperation::Finish(const AuthorizationSet& additional_params,
614 const Buffer& signature,
615 AuthorizationSet* output_params, Buffer* output) {
616 if (tag_buf_length_ < tag_length_)
617 return KM_ERROR_INVALID_INPUT_LENGTH;
618 else if (tag_length_ > 0 &&
619 !EVP_CIPHER_CTX_ctrl(&ctx_, EVP_CTRL_GCM_SET_TAG, tag_length_, tag_buf_.get()))
620 return TranslateLastOpenSslError();
621
622 return AesEvpOperation::Finish(additional_params, signature, output_params, output);
623}
624
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700625keymaster_error_t AesEvpOperation::Abort() {
626 return KM_ERROR_OK;
627}
628
Shawn Willden907c3012014-12-08 15:51:55 -0700629} // namespace keymaster