blob: face408696697ec51d3081a4cb75fd8ee4fc8a4b [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 Willden3ed6d062015-04-15 13:39:38 -060053Operation* AesOperationFactory::CreateOperation(const Key& key,
Shawn Willden31e063f2015-05-08 14:31:22 -060054 const AuthorizationSet& begin_params,
Shawn Willden3ed6d062015-04-15 13:39:38 -060055 keymaster_error_t* error) {
Shawn Willden63ac0432014-12-29 14:07:08 -070056 *error = KM_ERROR_OK;
Shawn Willdenf0f68b92014-12-30 16:03:28 -070057 const SymmetricKey* symmetric_key = static_cast<const SymmetricKey*>(&key);
Shawn Willdenf0f68b92014-12-30 16:03:28 -070058
59 switch (symmetric_key->key_data_size()) {
60 case 16:
61 case 24:
62 case 32:
63 break;
64 default:
65 *error = KM_ERROR_UNSUPPORTED_KEY_SIZE;
Shawn Willden3ad5f052015-05-08 14:05:13 -060066 return nullptr;
Shawn Willdenf0f68b92014-12-30 16:03:28 -070067 }
68
Shawn Willden63ac0432014-12-29 14:07:08 -070069 keymaster_block_mode_t block_mode;
Shawn Willden31e063f2015-05-08 14:31:22 -060070 if (!begin_params.GetTagValue(TAG_BLOCK_MODE, &block_mode)) {
71 LOG_E("%d block modes specified in begin params", begin_params.GetTagCount(TAG_BLOCK_MODE));
Shawn Willdenf0f68b92014-12-30 16:03:28 -070072 *error = KM_ERROR_UNSUPPORTED_BLOCK_MODE;
Shawn Willden31e063f2015-05-08 14:31:22 -060073 } else if (!supported(block_mode)) {
74 LOG_E("Block mode %d not supported", block_mode);
75 *error = KM_ERROR_UNSUPPORTED_BLOCK_MODE;
Shawn Willden31e063f2015-05-08 14:31:22 -060076 } else if (!key.authorizations().Contains(TAG_BLOCK_MODE, block_mode)) {
77 LOG_E("Block mode %d was specified, but not authorized by key", block_mode);
78 *error = KM_ERROR_INCOMPATIBLE_BLOCK_MODE;
Shawn Willden0f392562015-06-02 09:00:52 -060079 }
80
81 size_t tag_length = 0;
Shawn Willden34419132015-06-08 23:10:44 -060082 if (block_mode == KM_MODE_GCM) {
Shawn Willden0f392562015-06-02 09:00:52 -060083 uint32_t tag_length_bits;
84 if (!begin_params.GetTagValue(TAG_MAC_LENGTH, &tag_length_bits))
85 *error = KM_ERROR_MISSING_MAC_LENGTH;
86 tag_length = tag_length_bits / 8;
87 if (tag_length_bits % 8 != 0 || tag_length > GCM_MAX_TAG_LENGTH ||
88 tag_length < GCM_MIN_TAG_LENGTH)
89 *error = KM_ERROR_UNSUPPORTED_MAC_LENGTH;
Shawn Willden31e063f2015-05-08 14:31:22 -060090 }
Shawn Willdenf0f68b92014-12-30 16:03:28 -070091
Shawn Willdenc4424672015-05-11 11:56:02 -060092 keymaster_padding_t padding;
Shawn Willden5532a082015-07-01 12:58:08 -060093 if (!GetAndValidatePadding(begin_params, key, &padding, error))
94 return nullptr;
95 if (!allows_padding(block_mode) && padding != KM_PAD_NONE) {
Shawn Willden0f392562015-06-02 09:00:52 -060096 LOG_E("Mode does not support padding", 0);
97 *error = KM_ERROR_INCOMPATIBLE_PADDING_MODE;
Shawn Willden3ad5f052015-05-08 14:05:13 -060098 }
Shawn Willdenf0f68b92014-12-30 16:03:28 -070099
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600100 bool caller_nonce = key.authorizations().GetTagValue(TAG_CALLER_NONCE);
101
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700102 if (*error != KM_ERROR_OK)
Shawn Willden3ad5f052015-05-08 14:05:13 -0600103 return nullptr;
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700104
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700105 Operation* op = NULL;
106 switch (purpose()) {
107 case KM_PURPOSE_ENCRYPT:
Shawn Willden0f906ec2015-06-20 09:16:30 -0600108 op = new (std::nothrow)
109 AesEvpEncryptOperation(block_mode, padding, caller_nonce, tag_length,
110 symmetric_key->key_data(), symmetric_key->key_data_size());
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700111 break;
112 case KM_PURPOSE_DECRYPT:
Shawn Willden0f906ec2015-06-20 09:16:30 -0600113 op = new (std::nothrow)
114 AesEvpDecryptOperation(block_mode, padding, tag_length, symmetric_key->key_data(),
115 symmetric_key->key_data_size());
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700116 break;
117 default:
118 *error = KM_ERROR_UNSUPPORTED_PURPOSE;
119 return NULL;
120 }
121
122 if (!op)
123 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
124 return op;
125}
126
Shawn Willdenc47c88f2015-04-07 17:23:27 -0600127static const keymaster_block_mode_t supported_block_modes[] = {KM_MODE_ECB, KM_MODE_CBC,
Shawn Willden0f392562015-06-02 09:00:52 -0600128 KM_MODE_CTR, KM_MODE_GCM};
Shawn Willden63ac0432014-12-29 14:07:08 -0700129
130const keymaster_block_mode_t*
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700131AesOperationFactory::SupportedBlockModes(size_t* block_mode_count) const {
Shawn Willden63ac0432014-12-29 14:07:08 -0700132 *block_mode_count = array_length(supported_block_modes);
133 return supported_block_modes;
134}
135
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700136static const keymaster_padding_t supported_padding_modes[] = {KM_PAD_NONE, KM_PAD_PKCS7};
137const keymaster_padding_t*
138AesOperationFactory::SupportedPaddingModes(size_t* padding_mode_count) const {
139 *padding_mode_count = array_length(supported_padding_modes);
140 return supported_padding_modes;
141}
Shawn Willden63ac0432014-12-29 14:07:08 -0700142
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700143AesEvpOperation::AesEvpOperation(keymaster_purpose_t purpose, keymaster_block_mode_t block_mode,
Shawn Willden34419132015-06-08 23:10:44 -0600144 keymaster_padding_t padding, bool caller_iv, size_t tag_length,
145 const uint8_t* key, size_t key_size)
146 : Operation(purpose), block_mode_(block_mode), caller_iv_(caller_iv), tag_length_(tag_length),
147 data_started_(false), key_size_(key_size), padding_(padding) {
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700148 memcpy(key_, key, key_size_);
149 EVP_CIPHER_CTX_init(&ctx_);
150}
151
152AesEvpOperation::~AesEvpOperation() {
153 EVP_CIPHER_CTX_cleanup(&ctx_);
Shawn Willden34419132015-06-08 23:10:44 -0600154 memset_s(aad_block_buf_.get(), AES_BLOCK_SIZE, 0);
155}
156
157keymaster_error_t AesEvpOperation::Begin(const AuthorizationSet& /* input_params */,
158 AuthorizationSet* /* output_params */) {
159 if (block_mode_ == KM_MODE_GCM) {
160 aad_block_buf_length_ = 0;
Shawn Willden0f906ec2015-06-20 09:16:30 -0600161 aad_block_buf_.reset(new (std::nothrow) uint8_t[AES_BLOCK_SIZE]);
Shawn Willden34419132015-06-08 23:10:44 -0600162 if (!aad_block_buf_.get())
163 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
164 }
165
166 return InitializeCipher();
167}
168
169keymaster_error_t AesEvpOperation::Update(const AuthorizationSet& additional_params,
170 const Buffer& input,
171 AuthorizationSet* /* output_params */, Buffer* output,
172 size_t* input_consumed) {
173 keymaster_error_t error;
174 if (block_mode_ == KM_MODE_GCM)
175 if (!HandleAad(additional_params, input, &error))
176 return error;
177
178 if (!InternalUpdate(input.peek_read(), input.available_read(), output, &error))
179 return error;
180 *input_consumed = input.available_read();
181
182 return KM_ERROR_OK;
183}
184
185inline bool is_bad_decrypt(unsigned long error) {
186 return (ERR_GET_LIB(error) == ERR_LIB_CIPHER && //
187 ERR_GET_REASON(error) == CIPHER_R_BAD_DECRYPT);
188}
189
190keymaster_error_t AesEvpOperation::Finish(const AuthorizationSet& /* additional_params */,
191 const Buffer& /* signature */,
192 AuthorizationSet* /* output_params */, Buffer* output) {
193 if (!output->reserve(AES_BLOCK_SIZE))
194 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
195
196 keymaster_error_t error;
197 if (block_mode_ == KM_MODE_GCM && aad_block_buf_length_ > 0 &&
198 !ProcessBufferedAadBlock(&error)) {
199 return error;
200 }
201
202 int output_written = -1;
203 if (!EVP_CipherFinal_ex(&ctx_, output->peek_write(), &output_written)) {
204 if (tag_length_ > 0)
205 return KM_ERROR_VERIFICATION_FAILED;
206 LOG_E("Error encrypting final block: %s", ERR_error_string(ERR_peek_last_error(), NULL));
207 return TranslateLastOpenSslError();
208 }
209
210 assert(output_written <= AES_BLOCK_SIZE);
Shawn Willden0f906ec2015-06-20 09:16:30 -0600211 if (!output->advance_write(output_written))
212 return KM_ERROR_UNKNOWN_ERROR;
Shawn Willden34419132015-06-08 23:10:44 -0600213 return KM_ERROR_OK;
214}
215
216bool AesEvpOperation::need_iv() const {
217 switch (block_mode_) {
218 case KM_MODE_CBC:
219 case KM_MODE_CTR:
220 case KM_MODE_GCM:
221 return true;
222 case KM_MODE_ECB:
223 return false;
224 default:
225 // Shouldn't get here.
226 assert(false);
227 return false;
228 }
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700229}
230
231keymaster_error_t AesEvpOperation::InitializeCipher() {
232 const EVP_CIPHER* cipher;
233 switch (block_mode_) {
234 case KM_MODE_ECB:
235 switch (key_size_) {
236 case 16:
237 cipher = EVP_aes_128_ecb();
238 break;
239 case 24:
240 cipher = EVP_aes_192_ecb();
241 break;
242 case 32:
243 cipher = EVP_aes_256_ecb();
244 break;
245 default:
246 return KM_ERROR_UNSUPPORTED_KEY_SIZE;
247 }
248 break;
249 case KM_MODE_CBC:
250 switch (key_size_) {
251 case 16:
252 cipher = EVP_aes_128_cbc();
253 break;
254 case 24:
255 cipher = EVP_aes_192_cbc();
256 break;
257 case 32:
258 cipher = EVP_aes_256_cbc();
259 break;
260 default:
261 return KM_ERROR_UNSUPPORTED_KEY_SIZE;
262 }
263 break;
Thai Duong20d725d2015-03-24 17:49:58 -0700264 case KM_MODE_CTR:
265 switch (key_size_) {
266 case 16:
267 cipher = EVP_aes_128_ctr();
268 break;
269 case 24:
270 cipher = EVP_aes_192_ctr();
271 break;
272 case 32:
273 cipher = EVP_aes_256_ctr();
274 break;
275 default:
276 return KM_ERROR_UNSUPPORTED_KEY_SIZE;
277 }
278 break;
Shawn Willden0f392562015-06-02 09:00:52 -0600279 case KM_MODE_GCM:
280 switch (key_size_) {
281 case 16:
282 cipher = EVP_aes_128_gcm();
283 break;
284 case 24:
285 cipher = EVP_aes_192_gcm();
286 break;
287 case 32:
288 cipher = EVP_aes_256_gcm();
289 break;
290 default:
291 return KM_ERROR_UNSUPPORTED_KEY_SIZE;
292 }
293 break;
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700294 default:
295 return KM_ERROR_UNSUPPORTED_BLOCK_MODE;
296 }
297
Shawn Willden0f392562015-06-02 09:00:52 -0600298 if (!EVP_CipherInit_ex(&ctx_, cipher, NULL /* engine */, key_, iv_.get(), evp_encrypt_mode()))
Shawn Willdenf01329d2015-03-11 21:51:38 -0600299 return TranslateLastOpenSslError();
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700300
301 switch (padding_) {
302 case KM_PAD_NONE:
303 EVP_CIPHER_CTX_set_padding(&ctx_, 0 /* disable padding */);
304 break;
305 case KM_PAD_PKCS7:
306 // This is the default for OpenSSL EVP cipher operations.
307 break;
308 default:
309 return KM_ERROR_UNSUPPORTED_PADDING_MODE;
310 }
311
Shawn Willden34419132015-06-08 23:10:44 -0600312 if (block_mode_ == KM_MODE_GCM) {
313 aad_block_buf_length_ = 0;
Shawn Willden0f906ec2015-06-20 09:16:30 -0600314 aad_block_buf_.reset(new (std::nothrow) uint8_t[AES_BLOCK_SIZE]);
Shawn Willden34419132015-06-08 23:10:44 -0600315 if (!aad_block_buf_.get())
316 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
317 }
318
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700319 return KM_ERROR_OK;
320}
321
Shawn Willden34419132015-06-08 23:10:44 -0600322keymaster_error_t AesEvpOperation::GetIv(const AuthorizationSet& input_params) {
323 keymaster_blob_t iv_blob;
324 if (!input_params.GetTagValue(TAG_NONCE, &iv_blob)) {
325 LOG_E("No IV provided", 0);
326 return KM_ERROR_INVALID_ARGUMENT;
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700327 }
Shawn Willden34419132015-06-08 23:10:44 -0600328 if (block_mode_ != KM_MODE_GCM && iv_blob.data_length != AES_BLOCK_SIZE) {
329 LOG_E("Expected %d-byte IV for AES operation, but got %d bytes", AES_BLOCK_SIZE,
330 iv_blob.data_length);
331 return KM_ERROR_INVALID_NONCE;
332 }
Shawn Willdenc4bfa862015-06-17 09:46:50 -0600333 if (block_mode_ == KM_MODE_GCM && iv_blob.data_length != GCM_NONCE_SIZE) {
334 LOG_E("Expected %d-byte nonce for AES-GCM operation, but got %d bytes", GCM_NONCE_SIZE,
335 iv_blob.data_length);
336 return KM_ERROR_INVALID_NONCE;
337 }
Shawn Willden34419132015-06-08 23:10:44 -0600338 iv_.reset(dup_array(iv_blob.data, iv_blob.data_length));
339 if (!iv_.get())
340 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
341 iv_length_ = iv_blob.data_length;
342 return KM_ERROR_OK;
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700343}
344
Shawn Willden34419132015-06-08 23:10:44 -0600345/*
346 * Process Incoming Associated Authentication Data.
347 *
348 * This method is more complex than might be expected, because the underlying library silently does
349 * the wrong thing when given partial AAD blocks, so we have to take care to process AAD in
350 * AES_BLOCK_SIZE increments, buffering (in aad_block_buf_) when given smaller amounts of data.
351 */
352bool AesEvpOperation::HandleAad(const AuthorizationSet& input_params, const Buffer& input,
353 keymaster_error_t* error) {
354 assert(tag_length_ > 0);
355 assert(error);
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600356
Shawn Willden34419132015-06-08 23:10:44 -0600357 keymaster_blob_t aad;
358 if (input_params.GetTagValue(TAG_ASSOCIATED_DATA, &aad)) {
359 if (data_started_) {
360 *error = KM_ERROR_INVALID_TAG;
361 return false;
362 }
363
364 if (aad_block_buf_length_ > 0) {
365 FillBufferedAadBlock(&aad);
366 if (aad_block_buf_length_ == AES_BLOCK_SIZE && !ProcessBufferedAadBlock(error))
367 return false;
368 }
369
370 size_t blocks_to_process = aad.data_length / AES_BLOCK_SIZE;
371 if (blocks_to_process && !ProcessAadBlocks(aad.data, blocks_to_process, error))
372 return false;
373 aad.data += blocks_to_process * AES_BLOCK_SIZE;
374 aad.data_length -= blocks_to_process * AES_BLOCK_SIZE;
375
376 FillBufferedAadBlock(&aad);
377 assert(aad.data_length == 0);
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600378 }
379
Shawn Willden34419132015-06-08 23:10:44 -0600380 if (input.available_read()) {
381 data_started_ = true;
382 // Data has begun, no more AAD is allowed. Process any buffered AAD.
383 if (aad_block_buf_length_ > 0 && !ProcessBufferedAadBlock(error))
384 return false;
385 }
386
387 return true;
388}
389
390bool AesEvpOperation::ProcessBufferedAadBlock(keymaster_error_t* error) {
391 int output_written;
392 if (EVP_CipherUpdate(&ctx_, nullptr /* out */, &output_written, aad_block_buf_.get(),
393 aad_block_buf_length_)) {
394 aad_block_buf_length_ = 0;
395 return true;
396 }
397 *error = TranslateLastOpenSslError();
398 return false;
399}
400
401bool AesEvpOperation::ProcessAadBlocks(const uint8_t* data, size_t blocks,
402 keymaster_error_t* error) {
403 int output_written;
404 if (EVP_CipherUpdate(&ctx_, nullptr /* out */, &output_written, data, blocks * AES_BLOCK_SIZE))
405 return true;
406 *error = TranslateLastOpenSslError();
407 return false;
408}
409
410inline size_t min(size_t a, size_t b) {
411 return (a < b) ? a : b;
412}
413
414void AesEvpOperation::FillBufferedAadBlock(keymaster_blob_t* aad) {
415 size_t to_buffer = min(AES_BLOCK_SIZE - aad_block_buf_length_, aad->data_length);
416 memcpy(aad_block_buf_.get() + aad_block_buf_length_, aad->data, to_buffer);
417 aad->data += to_buffer;
418 aad->data_length -= to_buffer;
419 aad_block_buf_length_ += to_buffer;
420}
421
422bool AesEvpOperation::InternalUpdate(const uint8_t* input, size_t input_length, Buffer* output,
423 keymaster_error_t* error) {
424 assert(output);
425 assert(error);
426
Shawn Willden294a2db2015-06-17 11:20:56 -0600427 if (!input_length)
428 return true;
429
Shawn Willden34419132015-06-08 23:10:44 -0600430 if (!output->reserve(input_length + AES_BLOCK_SIZE)) {
431 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
432 return false;
433 }
434
435 int output_written = -1;
436 if (!EVP_CipherUpdate(&ctx_, output->peek_write(), &output_written, input, input_length)) {
437 *error = TranslateLastOpenSslError();
438 return false;
439 }
Shawn Willden0f906ec2015-06-20 09:16:30 -0600440 return output->advance_write(output_written);
Shawn Willden0f392562015-06-02 09:00:52 -0600441}
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600442
Shawn Willden0f392562015-06-02 09:00:52 -0600443keymaster_error_t AesEvpEncryptOperation::Begin(const AuthorizationSet& input_params,
444 AuthorizationSet* output_params) {
445 if (!output_params)
446 return KM_ERROR_OUTPUT_PARAMETER_NULL;
447
448 if (need_iv()) {
449 keymaster_error_t error = KM_ERROR_OK;
450 if (input_params.find(TAG_NONCE) == -1)
451 error = GenerateIv();
452 else if (caller_iv_)
453 error = GetIv(input_params);
454 else
455 error = KM_ERROR_CALLER_NONCE_PROHIBITED;
456
457 if (error == KM_ERROR_OK)
458 output_params->push_back(TAG_NONCE, iv_.get(), iv_length_);
459 else
460 return error;
461 }
462
Shawn Willden34419132015-06-08 23:10:44 -0600463 return AesEvpOperation::Begin(input_params, output_params);
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600464}
465
Shawn Willden34419132015-06-08 23:10:44 -0600466keymaster_error_t AesEvpEncryptOperation::Finish(const AuthorizationSet& additional_params,
467 const Buffer& signature,
468 AuthorizationSet* output_params, Buffer* output) {
469 if (!output->reserve(AES_BLOCK_SIZE + tag_length_))
Shawn Willden92b69a32015-03-14 11:07:36 -0600470 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willden34419132015-06-08 23:10:44 -0600471
472 keymaster_error_t error =
473 AesEvpOperation::Finish(additional_params, signature, output_params, output);
474 if (error != KM_ERROR_OK)
475 return error;
476
477 if (tag_length_ > 0) {
478 if (!output->reserve(output->available_read() + tag_length_))
479 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
480
481 if (!EVP_CIPHER_CTX_ctrl(&ctx_, EVP_CTRL_GCM_GET_TAG, tag_length_, output->peek_write()))
482 return TranslateLastOpenSslError();
Shawn Willden0f906ec2015-06-20 09:16:30 -0600483 if (!output->advance_write(tag_length_))
484 return KM_ERROR_UNKNOWN_ERROR;
Shawn Willden34419132015-06-08 23:10:44 -0600485 }
486
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700487 return KM_ERROR_OK;
488}
489
Shawn Willden0f392562015-06-02 09:00:52 -0600490keymaster_error_t AesEvpEncryptOperation::GenerateIv() {
Shawn Willdenc4bfa862015-06-17 09:46:50 -0600491 iv_length_ = (block_mode_ == KM_MODE_GCM) ? GCM_NONCE_SIZE : AES_BLOCK_SIZE;
Shawn Willden0f906ec2015-06-20 09:16:30 -0600492 iv_.reset(new (std::nothrow) uint8_t[iv_length_]);
Shawn Willden67706352015-04-28 00:43:19 -0600493 if (!iv_.get())
494 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willden0f392562015-06-02 09:00:52 -0600495 if (RAND_bytes(iv_.get(), iv_length_) != 1)
Shawn Willden67706352015-04-28 00:43:19 -0600496 return TranslateLastOpenSslError();
497 return KM_ERROR_OK;
498}
499
Shawn Willden34419132015-06-08 23:10:44 -0600500keymaster_error_t AesEvpDecryptOperation::Begin(const AuthorizationSet& input_params,
501 AuthorizationSet* output_params) {
502 if (need_iv()) {
503 keymaster_error_t error = GetIv(input_params);
504 if (error != KM_ERROR_OK)
505 return error;
Shawn Willden0f392562015-06-02 09:00:52 -0600506 }
507
Shawn Willden34419132015-06-08 23:10:44 -0600508 if (tag_length_ > 0) {
509 tag_buf_length_ = 0;
Shawn Willden0f906ec2015-06-20 09:16:30 -0600510 tag_buf_.reset(new (std::nothrow) uint8_t[tag_length_]);
Shawn Willden34419132015-06-08 23:10:44 -0600511 if (!tag_buf_.get())
512 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
513 }
Shawn Willden0f392562015-06-02 09:00:52 -0600514
Shawn Willden34419132015-06-08 23:10:44 -0600515 return AesEvpOperation::Begin(input_params, output_params);
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700516}
517
Shawn Willden0f392562015-06-02 09:00:52 -0600518keymaster_error_t AesEvpDecryptOperation::Update(const AuthorizationSet& additional_params,
519 const Buffer& input,
Shawn Willden34419132015-06-08 23:10:44 -0600520 AuthorizationSet* /* output_params */,
521 Buffer* output, size_t* input_consumed) {
522 if (!output || !input_consumed)
523 return KM_ERROR_OUTPUT_PARAMETER_NULL;
Shawn Willden0f392562015-06-02 09:00:52 -0600524
Shawn Willden34419132015-06-08 23:10:44 -0600525 // Barring error, we'll consume it all.
526 *input_consumed = input.available_read();
527
528 keymaster_error_t error;
529 if (block_mode_ == KM_MODE_GCM) {
530 if (!HandleAad(additional_params, input, &error))
531 return error;
532 return ProcessAllButTagLengthBytes(input, output);
Shawn Willden0f392562015-06-02 09:00:52 -0600533 }
534
Shawn Willden34419132015-06-08 23:10:44 -0600535 if (!InternalUpdate(input.peek_read(), input.available_read(), output, &error))
536 return error;
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700537 return KM_ERROR_OK;
538}
539
Shawn Willden34419132015-06-08 23:10:44 -0600540keymaster_error_t AesEvpDecryptOperation::ProcessAllButTagLengthBytes(const Buffer& input,
541 Buffer* output) {
542 if (input.available_read() <= tag_buf_unused()) {
543 BufferCandidateTagData(input.peek_read(), input.available_read());
544 return KM_ERROR_OK;
545 }
546
547 const size_t data_available = tag_buf_length_ + input.available_read();
548
549 const size_t to_process = data_available - tag_length_;
550 const size_t to_process_from_tag_buf = min(to_process, tag_buf_length_);
551 const size_t to_process_from_input = to_process - to_process_from_tag_buf;
552
553 if (!output->reserve(to_process + AES_BLOCK_SIZE))
554 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
555
556 keymaster_error_t error;
557 if (!ProcessTagBufContentsAsData(to_process_from_tag_buf, output, &error))
Shawn Willden0f392562015-06-02 09:00:52 -0600558 return error;
559
Shawn Willden34419132015-06-08 23:10:44 -0600560 if (!InternalUpdate(input.peek_read(), to_process_from_input, output, &error))
561 return error;
562
563 BufferCandidateTagData(input.peek_read() + to_process_from_input,
564 input.available_read() - to_process_from_input);
565 assert(tag_buf_unused() == 0);
Shawn Willden0f392562015-06-02 09:00:52 -0600566
567 return KM_ERROR_OK;
568}
Shawn Willden34419132015-06-08 23:10:44 -0600569
570bool AesEvpDecryptOperation::ProcessTagBufContentsAsData(size_t to_process, Buffer* output,
571 keymaster_error_t* error) {
572 assert(to_process <= tag_buf_length_);
573 if (!InternalUpdate(tag_buf_.get(), to_process, output, error))
574 return false;
575 if (to_process < tag_buf_length_)
576 memmove(tag_buf_.get(), tag_buf_.get() + to_process, tag_buf_length_ - to_process);
577 tag_buf_length_ -= to_process;
578 return true;
579}
580
581void AesEvpDecryptOperation::BufferCandidateTagData(const uint8_t* data, size_t data_length) {
582 assert(data_length <= tag_length_ - tag_buf_length_);
583 memcpy(tag_buf_.get() + tag_buf_length_, data, data_length);
584 tag_buf_length_ += data_length;
585}
586
587keymaster_error_t AesEvpDecryptOperation::Finish(const AuthorizationSet& additional_params,
588 const Buffer& signature,
589 AuthorizationSet* output_params, Buffer* output) {
590 if (tag_buf_length_ < tag_length_)
591 return KM_ERROR_INVALID_INPUT_LENGTH;
592 else if (tag_length_ > 0 &&
593 !EVP_CIPHER_CTX_ctrl(&ctx_, EVP_CTRL_GCM_SET_TAG, tag_length_, tag_buf_.get()))
594 return TranslateLastOpenSslError();
595
596 return AesEvpOperation::Finish(additional_params, signature, output_params, output);
597}
598
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700599keymaster_error_t AesEvpOperation::Abort() {
600 return KM_ERROR_OK;
601}
602
Shawn Willden907c3012014-12-08 15:51:55 -0700603} // namespace keymaster