blob: 1dcd3a6cc3ed675ca9b7181e2eb6268c74188921 [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 Willden0f392562015-06-02 09:00:52 -060033static const size_t GCM_DEFAULT_NONCE_SIZE = 12;
34static const size_t GCM_MAX_TAG_LENGTH = 16;
35static const size_t GCM_MIN_TAG_LENGTH = 12;
36
37inline bool allows_padding(keymaster_block_mode_t block_mode) {
38 return (block_mode == KM_MODE_CTR || block_mode == KM_MODE_GCM);
39}
40
Shawn Willden3ed6d062015-04-15 13:39:38 -060041Operation* AesOperationFactory::CreateOperation(const Key& key,
Shawn Willden31e063f2015-05-08 14:31:22 -060042 const AuthorizationSet& begin_params,
Shawn Willden3ed6d062015-04-15 13:39:38 -060043 keymaster_error_t* error) {
Shawn Willden63ac0432014-12-29 14:07:08 -070044 *error = KM_ERROR_OK;
Shawn Willdenf0f68b92014-12-30 16:03:28 -070045 const SymmetricKey* symmetric_key = static_cast<const SymmetricKey*>(&key);
Shawn Willdenf0f68b92014-12-30 16:03:28 -070046
47 switch (symmetric_key->key_data_size()) {
48 case 16:
49 case 24:
50 case 32:
51 break;
52 default:
53 *error = KM_ERROR_UNSUPPORTED_KEY_SIZE;
Shawn Willden3ad5f052015-05-08 14:05:13 -060054 return nullptr;
Shawn Willdenf0f68b92014-12-30 16:03:28 -070055 }
56
Shawn Willden63ac0432014-12-29 14:07:08 -070057 keymaster_block_mode_t block_mode;
Shawn Willden31e063f2015-05-08 14:31:22 -060058 if (!begin_params.GetTagValue(TAG_BLOCK_MODE, &block_mode)) {
59 LOG_E("%d block modes specified in begin params", begin_params.GetTagCount(TAG_BLOCK_MODE));
Shawn Willdenf0f68b92014-12-30 16:03:28 -070060 *error = KM_ERROR_UNSUPPORTED_BLOCK_MODE;
Shawn Willden31e063f2015-05-08 14:31:22 -060061 } else if (!supported(block_mode)) {
62 LOG_E("Block mode %d not supported", block_mode);
63 *error = KM_ERROR_UNSUPPORTED_BLOCK_MODE;
Shawn Willden31e063f2015-05-08 14:31:22 -060064 } else if (!key.authorizations().Contains(TAG_BLOCK_MODE, block_mode)) {
65 LOG_E("Block mode %d was specified, but not authorized by key", block_mode);
66 *error = KM_ERROR_INCOMPATIBLE_BLOCK_MODE;
Shawn Willden0f392562015-06-02 09:00:52 -060067 }
68
69 size_t tag_length = 0;
70 if (block_mode == KM_MODE_GCM && purpose() == KM_PURPOSE_ENCRYPT) {
71 uint32_t tag_length_bits;
72 if (!begin_params.GetTagValue(TAG_MAC_LENGTH, &tag_length_bits))
73 *error = KM_ERROR_MISSING_MAC_LENGTH;
74 tag_length = tag_length_bits / 8;
75 if (tag_length_bits % 8 != 0 || tag_length > GCM_MAX_TAG_LENGTH ||
76 tag_length < GCM_MIN_TAG_LENGTH)
77 *error = KM_ERROR_UNSUPPORTED_MAC_LENGTH;
Shawn Willden31e063f2015-05-08 14:31:22 -060078 }
Shawn Willdenf0f68b92014-12-30 16:03:28 -070079
Shawn Willdenc4424672015-05-11 11:56:02 -060080 keymaster_padding_t padding;
81 if (!begin_params.GetTagValue(TAG_PADDING, &padding)) {
Shawn Willdended8e7d2015-06-01 15:29:12 -060082 LOG_E("%d padding modes specified in begin params", begin_params.GetTagCount(TAG_PADDING));
Shawn Willdenc4424672015-05-11 11:56:02 -060083 *error = KM_ERROR_UNSUPPORTED_PADDING_MODE;
Shawn Willdenc4424672015-05-11 11:56:02 -060084 } else if (!supported(padding)) {
85 LOG_E("Padding mode %d not supported", padding);
86 *error = KM_ERROR_UNSUPPORTED_PADDING_MODE;
Shawn Willden0f392562015-06-02 09:00:52 -060087 } else if (allows_padding(block_mode) && padding != KM_PAD_NONE) {
88 LOG_E("Mode does not support padding", 0);
89 *error = KM_ERROR_INCOMPATIBLE_PADDING_MODE;
Shawn Willdenc4424672015-05-11 11:56:02 -060090 } else if (!key.authorizations().Contains(TAG_PADDING, padding)) {
Shawn Willden3ad5f052015-05-08 14:05:13 -060091 LOG_E("Padding mode %d was specified, but not authorized by key", padding);
92 *error = KM_ERROR_INCOMPATIBLE_PADDING_MODE;
93 }
Shawn Willdenf0f68b92014-12-30 16:03:28 -070094
Shawn Willden7a62f5e2015-03-10 12:59:20 -060095 bool caller_nonce = key.authorizations().GetTagValue(TAG_CALLER_NONCE);
96
Shawn Willdenf0f68b92014-12-30 16:03:28 -070097 if (*error != KM_ERROR_OK)
Shawn Willden3ad5f052015-05-08 14:05:13 -060098 return nullptr;
Shawn Willdenf0f68b92014-12-30 16:03:28 -070099
Shawn Willden0f392562015-06-02 09:00:52 -0600100 return CreateEvpOperation(*symmetric_key, block_mode, padding, caller_nonce, tag_length, error);
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700101}
102
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700103Operation* AesOperationFactory::CreateEvpOperation(const SymmetricKey& key,
104 keymaster_block_mode_t block_mode,
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600105 keymaster_padding_t padding, bool caller_iv,
Shawn Willden0f392562015-06-02 09:00:52 -0600106 size_t tag_length, keymaster_error_t* error) {
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700107 Operation* op = NULL;
108 switch (purpose()) {
109 case KM_PURPOSE_ENCRYPT:
Shawn Willden0f392562015-06-02 09:00:52 -0600110 op = new AesEvpEncryptOperation(block_mode, padding, caller_iv, tag_length, key.key_data(),
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600111 key.key_data_size());
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700112 break;
113 case KM_PURPOSE_DECRYPT:
114 op = new AesEvpDecryptOperation(block_mode, padding, key.key_data(), key.key_data_size());
115 break;
116 default:
117 *error = KM_ERROR_UNSUPPORTED_PURPOSE;
118 return NULL;
119 }
120
121 if (!op)
122 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
123 return op;
124}
125
Shawn Willdenc47c88f2015-04-07 17:23:27 -0600126static const keymaster_block_mode_t supported_block_modes[] = {KM_MODE_ECB, KM_MODE_CBC,
Shawn Willden0f392562015-06-02 09:00:52 -0600127 KM_MODE_CTR, KM_MODE_GCM};
Shawn Willden63ac0432014-12-29 14:07:08 -0700128
129const keymaster_block_mode_t*
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700130AesOperationFactory::SupportedBlockModes(size_t* block_mode_count) const {
Shawn Willden63ac0432014-12-29 14:07:08 -0700131 *block_mode_count = array_length(supported_block_modes);
132 return supported_block_modes;
133}
134
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700135static const keymaster_padding_t supported_padding_modes[] = {KM_PAD_NONE, KM_PAD_PKCS7};
136const keymaster_padding_t*
137AesOperationFactory::SupportedPaddingModes(size_t* padding_mode_count) const {
138 *padding_mode_count = array_length(supported_padding_modes);
139 return supported_padding_modes;
140}
Shawn Willden63ac0432014-12-29 14:07:08 -0700141
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700142AesEvpOperation::AesEvpOperation(keymaster_purpose_t purpose, keymaster_block_mode_t block_mode,
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600143 keymaster_padding_t padding, bool caller_iv, const uint8_t* key,
144 size_t key_size)
Shawn Willden0f392562015-06-02 09:00:52 -0600145 : Operation(purpose), block_mode_(block_mode), caller_iv_(caller_iv), data_started_(false),
146 key_size_(key_size), padding_(padding) {
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700147 memcpy(key_, key, key_size_);
148 EVP_CIPHER_CTX_init(&ctx_);
149}
150
151AesEvpOperation::~AesEvpOperation() {
152 EVP_CIPHER_CTX_cleanup(&ctx_);
153}
154
155keymaster_error_t AesEvpOperation::InitializeCipher() {
156 const EVP_CIPHER* cipher;
157 switch (block_mode_) {
158 case KM_MODE_ECB:
159 switch (key_size_) {
160 case 16:
161 cipher = EVP_aes_128_ecb();
162 break;
163 case 24:
164 cipher = EVP_aes_192_ecb();
165 break;
166 case 32:
167 cipher = EVP_aes_256_ecb();
168 break;
169 default:
170 return KM_ERROR_UNSUPPORTED_KEY_SIZE;
171 }
172 break;
173 case KM_MODE_CBC:
174 switch (key_size_) {
175 case 16:
176 cipher = EVP_aes_128_cbc();
177 break;
178 case 24:
179 cipher = EVP_aes_192_cbc();
180 break;
181 case 32:
182 cipher = EVP_aes_256_cbc();
183 break;
184 default:
185 return KM_ERROR_UNSUPPORTED_KEY_SIZE;
186 }
187 break;
Thai Duong20d725d2015-03-24 17:49:58 -0700188 case KM_MODE_CTR:
189 switch (key_size_) {
190 case 16:
191 cipher = EVP_aes_128_ctr();
192 break;
193 case 24:
194 cipher = EVP_aes_192_ctr();
195 break;
196 case 32:
197 cipher = EVP_aes_256_ctr();
198 break;
199 default:
200 return KM_ERROR_UNSUPPORTED_KEY_SIZE;
201 }
202 break;
Shawn Willden0f392562015-06-02 09:00:52 -0600203 case KM_MODE_GCM:
204 switch (key_size_) {
205 case 16:
206 cipher = EVP_aes_128_gcm();
207 break;
208 case 24:
209 cipher = EVP_aes_192_gcm();
210 break;
211 case 32:
212 cipher = EVP_aes_256_gcm();
213 break;
214 default:
215 return KM_ERROR_UNSUPPORTED_KEY_SIZE;
216 }
217 break;
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700218 default:
219 return KM_ERROR_UNSUPPORTED_BLOCK_MODE;
220 }
221
Shawn Willden0f392562015-06-02 09:00:52 -0600222 if (!EVP_CipherInit_ex(&ctx_, cipher, NULL /* engine */, key_, iv_.get(), evp_encrypt_mode()))
Shawn Willdenf01329d2015-03-11 21:51:38 -0600223 return TranslateLastOpenSslError();
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700224
225 switch (padding_) {
226 case KM_PAD_NONE:
227 EVP_CIPHER_CTX_set_padding(&ctx_, 0 /* disable padding */);
228 break;
229 case KM_PAD_PKCS7:
230 // This is the default for OpenSSL EVP cipher operations.
231 break;
232 default:
233 return KM_ERROR_UNSUPPORTED_PADDING_MODE;
234 }
235
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700236 return KM_ERROR_OK;
237}
238
239bool AesEvpOperation::need_iv() const {
240 switch (block_mode_) {
241 case KM_MODE_CBC:
Thai Duong20d725d2015-03-24 17:49:58 -0700242 case KM_MODE_CTR:
Shawn Willden0f392562015-06-02 09:00:52 -0600243 case KM_MODE_GCM:
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700244 return true;
245 case KM_MODE_ECB:
246 return false;
247 default:
248 // Shouldn't get here.
249 assert(false);
250 return false;
251 }
252}
253
Shawn Willden0f392562015-06-02 09:00:52 -0600254keymaster_error_t AesEvpDecryptOperation::Begin(const AuthorizationSet& input_params,
255 AuthorizationSet* output_params) {
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600256 if (!output_params)
257 return KM_ERROR_OUTPUT_PARAMETER_NULL;
258
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600259 if (need_iv()) {
Shawn Willden0f392562015-06-02 09:00:52 -0600260 keymaster_error_t error = GetIv(input_params);
261 if (error != KM_ERROR_OK)
262 return error;
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600263 }
264
Shawn Willden0f392562015-06-02 09:00:52 -0600265 return InitializeCipher();
266}
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600267
Shawn Willden0f392562015-06-02 09:00:52 -0600268keymaster_error_t AesEvpEncryptOperation::Begin(const AuthorizationSet& input_params,
269 AuthorizationSet* output_params) {
270 if (!output_params)
271 return KM_ERROR_OUTPUT_PARAMETER_NULL;
272
273 if (need_iv()) {
274 keymaster_error_t error = KM_ERROR_OK;
275 if (input_params.find(TAG_NONCE) == -1)
276 error = GenerateIv();
277 else if (caller_iv_)
278 error = GetIv(input_params);
279 else
280 error = KM_ERROR_CALLER_NONCE_PROHIBITED;
281
282 if (error == KM_ERROR_OK)
283 output_params->push_back(TAG_NONCE, iv_.get(), iv_length_);
284 else
285 return error;
286 }
287
288 return InitializeCipher();
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600289}
290
291keymaster_error_t AesEvpOperation::GetIv(const AuthorizationSet& input_params) {
292 keymaster_blob_t iv_blob;
293 if (!input_params.GetTagValue(TAG_NONCE, &iv_blob)) {
294 LOG_E("No IV provided", 0);
295 return KM_ERROR_INVALID_ARGUMENT;
296 }
Shawn Willden0f392562015-06-02 09:00:52 -0600297 if (block_mode_ != KM_MODE_GCM && iv_blob.data_length != AES_BLOCK_SIZE) {
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600298 LOG_E("Expected %d-byte IV for AES operation, but got %d bytes", AES_BLOCK_SIZE,
299 iv_blob.data_length);
Thai Duong20d725d2015-03-24 17:49:58 -0700300 return KM_ERROR_INVALID_NONCE;
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600301 }
302 iv_.reset(dup_array(iv_blob.data, iv_blob.data_length));
Shawn Willden92b69a32015-03-14 11:07:36 -0600303 if (!iv_.get())
304 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willden0f392562015-06-02 09:00:52 -0600305 iv_length_ = iv_blob.data_length;
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700306 return KM_ERROR_OK;
307}
308
Shawn Willden0f392562015-06-02 09:00:52 -0600309keymaster_error_t AesEvpEncryptOperation::GenerateIv() {
310 iv_length_ = (block_mode_ == KM_MODE_GCM) ? GCM_DEFAULT_NONCE_SIZE : AES_BLOCK_SIZE;
311 iv_.reset(new uint8_t[iv_length_]);
Shawn Willden67706352015-04-28 00:43:19 -0600312 if (!iv_.get())
313 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willden0f392562015-06-02 09:00:52 -0600314 if (RAND_bytes(iv_.get(), iv_length_) != 1)
Shawn Willden67706352015-04-28 00:43:19 -0600315 return TranslateLastOpenSslError();
316 return KM_ERROR_OK;
317}
318
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700319inline size_t min(size_t a, size_t b) {
320 if (a < b)
321 return a;
322 return b;
323}
324
Shawn Willden0f392562015-06-02 09:00:52 -0600325keymaster_error_t AesEvpOperation::Update(const AuthorizationSet& additional_params,
Shawn Willdended8e7d2015-06-01 15:29:12 -0600326 const Buffer& input,
327 AuthorizationSet* /* output_params */, Buffer* output,
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700328 size_t* input_consumed) {
Shawn Willden0f392562015-06-02 09:00:52 -0600329 keymaster_blob_t aad;
330 if (block_mode_ == KM_MODE_GCM && additional_params.GetTagValue(TAG_ASSOCIATED_DATA, &aad)) {
331 if (data_started_)
332 return KM_ERROR_INVALID_TAG;
333 // Incantation to add AAD is to call update with null output. Ugly.
334 int output_written;
335 if (!EVP_CipherUpdate(&ctx_, nullptr /* out */, &output_written, aad.data, aad.data_length))
336 return TranslateLastOpenSslError();
337 }
338
339 if (input.available_read() > 0)
340 data_started_ = true;
341
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700342 output->reserve(input.available_read() + AES_BLOCK_SIZE);
343
344 const uint8_t* input_pos = input.peek_read();
345 const uint8_t* input_end = input_pos + input.available_read();
346
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700347 int output_written = -1;
348 if (!EVP_CipherUpdate(&ctx_, output->peek_write(), &output_written, input_pos,
349 input_end - input_pos))
350 return TranslateLastOpenSslError();
351
352 assert(output_written >= 0);
353 assert(output_written <= (int)output->available_write());
354 output->advance_write(output_written);
355 *input_consumed = input.available_read();
356 return KM_ERROR_OK;
357}
358
Shawn Willden0f392562015-06-02 09:00:52 -0600359keymaster_error_t AesEvpDecryptOperation::Update(const AuthorizationSet& additional_params,
360 const Buffer& input,
361 AuthorizationSet* output_params, Buffer* output,
362 size_t* input_consumed) {
363 if (!tag_provided_ && block_mode_ == KM_MODE_GCM && purpose() == KM_PURPOSE_DECRYPT) {
364 keymaster_blob_t tag;
365 if (additional_params.GetTagValue(TAG_AEAD_TAG, &tag)) {
366 if (tag.data_length < GCM_MIN_TAG_LENGTH || tag.data_length > GCM_MAX_TAG_LENGTH)
367 return KM_ERROR_UNSUPPORTED_MAC_LENGTH;
368
369 if (!EVP_CIPHER_CTX_ctrl(&ctx_, EVP_CTRL_GCM_SET_TAG, tag.data_length,
370 const_cast<uint8_t*>(tag.data)))
371 return TranslateLastOpenSslError();
372 tag_provided_ = true;
373 }
374 if (!tag_provided_)
375 return KM_ERROR_INVALID_TAG;
376 }
377
378 return AesEvpOperation::Update(additional_params, input, output_params, output, input_consumed);
379}
380
381inline bool is_bad_decrypt(unsigned long error) {
382 return (ERR_GET_LIB(error) == ERR_LIB_CIPHER && //
383 ERR_GET_REASON(error) == CIPHER_R_BAD_DECRYPT);
384}
385
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700386keymaster_error_t AesEvpOperation::Finish(const AuthorizationSet& /* additional_params */,
Shawn Willdended8e7d2015-06-01 15:29:12 -0600387 const Buffer& /* signature */,
388 AuthorizationSet* /* output_params */, Buffer* output) {
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700389 output->reserve(AES_BLOCK_SIZE);
390
391 int output_written = -1;
392 if (!EVP_CipherFinal_ex(&ctx_, output->peek_write(), &output_written)) {
Shawn Willden0f392562015-06-02 09:00:52 -0600393 if (block_mode_ == KM_MODE_GCM && is_bad_decrypt(ERR_peek_last_error()))
394 return KM_ERROR_VERIFICATION_FAILED;
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700395 LOG_E("Error encrypting final block: %s", ERR_error_string(ERR_peek_last_error(), NULL));
396 return TranslateLastOpenSslError();
397 }
398
399 assert(output_written <= AES_BLOCK_SIZE);
400 output->advance_write(output_written);
401 return KM_ERROR_OK;
402}
403
Shawn Willden0f392562015-06-02 09:00:52 -0600404keymaster_error_t AesEvpEncryptOperation::Finish(const AuthorizationSet& additional_params,
405 const Buffer& signature,
406 AuthorizationSet* output_params, Buffer* output) {
407 keymaster_error_t error =
408 AesEvpOperation::Finish(additional_params, signature, output_params, output);
409 if (error != KM_ERROR_OK)
410 return error;
411
412 if (block_mode_ == KM_MODE_GCM && purpose() == KM_PURPOSE_ENCRYPT) {
413 uint8_t tag[tag_length_];
414 if (!EVP_CIPHER_CTX_ctrl(&ctx_, EVP_CTRL_GCM_GET_TAG, tag_length_, tag))
415 return TranslateLastOpenSslError();
416 output_params->push_back(TAG_AEAD_TAG, tag, tag_length_);
417 }
418
419 return KM_ERROR_OK;
420}
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700421keymaster_error_t AesEvpOperation::Abort() {
422 return KM_ERROR_OK;
423}
424
Shawn Willden907c3012014-12-08 15:51:55 -0700425} // namespace keymaster