blob: 22fbd0e9d8bcfd04b7a01044d7c23e305e2b1da7 [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 Willden907c3012014-12-08 15:51:55 -070019#include <openssl/aes.h>
Shawn Willdenf0f68b92014-12-30 16:03:28 -070020#include <openssl/err.h>
Shawn Willden907c3012014-12-08 15:51:55 -070021#include <openssl/rand.h>
22
Shawn Willden567a4a02014-12-31 12:14:46 -070023#include <keymaster/logger.h>
24
Shawn Willden63ac0432014-12-29 14:07:08 -070025#include "aes_key.h"
Shawn Willden907c3012014-12-08 15:51:55 -070026#include "aes_operation.h"
Shawn Willdenf0f68b92014-12-30 16:03:28 -070027#include "openssl_err.h"
Shawn Willden907c3012014-12-08 15:51:55 -070028
29namespace keymaster {
30
Shawn Willden63ac0432014-12-29 14:07:08 -070031/**
Shawn Willdenf0f68b92014-12-30 16:03:28 -070032 * Abstract base for AES operation factories. This class does all of the work to create
33 * AES operations.
Shawn Willden63ac0432014-12-29 14:07:08 -070034 */
Shawn Willdenf0f68b92014-12-30 16:03:28 -070035class AesOperationFactory : public OperationFactory {
Shawn Willden63ac0432014-12-29 14:07:08 -070036 public:
37 virtual KeyType registry_key() const { return KeyType(KM_ALGORITHM_AES, purpose()); }
38
Shawn Willden3ed6d062015-04-15 13:39:38 -060039 virtual Operation* CreateOperation(const Key& key, const AuthorizationSet& begin_params,
40 keymaster_error_t* error);
Shawn Willden63ac0432014-12-29 14:07:08 -070041 virtual const keymaster_block_mode_t* SupportedBlockModes(size_t* block_mode_count) const;
Shawn Willdenf0f68b92014-12-30 16:03:28 -070042 virtual const keymaster_padding_t* SupportedPaddingModes(size_t* padding_count) const;
Shawn Willden63ac0432014-12-29 14:07:08 -070043
44 virtual keymaster_purpose_t purpose() const = 0;
Shawn Willdenf0f68b92014-12-30 16:03:28 -070045
46 private:
Shawn Willdenf0f68b92014-12-30 16:03:28 -070047 virtual Operation* CreateEvpOperation(const SymmetricKey& key,
48 keymaster_block_mode_t block_mode,
Shawn Willden7a62f5e2015-03-10 12:59:20 -060049 keymaster_padding_t padding, bool caller_iv,
50 keymaster_error_t* error);
Shawn Willden63ac0432014-12-29 14:07:08 -070051};
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 return nullptr;
74 } else if (!supported(block_mode)) {
75 LOG_E("Block mode %d not supported", block_mode);
76 *error = KM_ERROR_UNSUPPORTED_BLOCK_MODE;
77 return nullptr;
78 } else if (!key.authorizations().Contains(TAG_BLOCK_MODE, block_mode)) {
79 LOG_E("Block mode %d was specified, but not authorized by key", block_mode);
80 *error = KM_ERROR_INCOMPATIBLE_BLOCK_MODE;
81 return nullptr;
82 }
Shawn Willdenf0f68b92014-12-30 16:03:28 -070083
Shawn Willdenc4424672015-05-11 11:56:02 -060084 keymaster_padding_t padding;
85 if (!begin_params.GetTagValue(TAG_PADDING, &padding)) {
86 LOG_E("%d padding modes specified in begin params",
87 begin_params.GetTagCount(TAG_PADDING));
88 *error = KM_ERROR_UNSUPPORTED_PADDING_MODE;
89 return nullptr;
90 } else if (!supported(padding)) {
91 LOG_E("Padding mode %d not supported", padding);
92 *error = KM_ERROR_UNSUPPORTED_PADDING_MODE;
93 return nullptr;
94 } else if (!key.authorizations().Contains(TAG_PADDING, padding)) {
Shawn Willden3ad5f052015-05-08 14:05:13 -060095 LOG_E("Padding mode %d was specified, but not authorized by key", padding);
96 *error = KM_ERROR_INCOMPATIBLE_PADDING_MODE;
Shawn Willdenc4424672015-05-11 11:56:02 -060097 return nullptr;
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
105 switch (block_mode) {
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700106 case KM_MODE_ECB:
107 case KM_MODE_CBC:
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600108 return CreateEvpOperation(*symmetric_key, block_mode, padding, caller_nonce, error);
Thai Duong20d725d2015-03-24 17:49:58 -0700109 case KM_MODE_CTR:
110 if (padding != KM_PAD_NONE) {
Shawn Willden3ad5f052015-05-08 14:05:13 -0600111 *error = KM_ERROR_INCOMPATIBLE_PADDING_MODE;
112 return nullptr;
Thai Duong20d725d2015-03-24 17:49:58 -0700113 }
114 return CreateEvpOperation(*symmetric_key, block_mode, padding, caller_nonce, error);
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700115 default:
Shawn Willden63ac0432014-12-29 14:07:08 -0700116 *error = KM_ERROR_UNSUPPORTED_BLOCK_MODE;
Shawn Willden3ad5f052015-05-08 14:05:13 -0600117 return nullptr;
Shawn Willden63ac0432014-12-29 14:07:08 -0700118 }
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700119}
120
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700121Operation* AesOperationFactory::CreateEvpOperation(const SymmetricKey& key,
122 keymaster_block_mode_t block_mode,
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600123 keymaster_padding_t padding, bool caller_iv,
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700124 keymaster_error_t* error) {
125 Operation* op = NULL;
126 switch (purpose()) {
127 case KM_PURPOSE_ENCRYPT:
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600128 op = new AesEvpEncryptOperation(block_mode, padding, caller_iv, key.key_data(),
129 key.key_data_size());
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700130 break;
131 case KM_PURPOSE_DECRYPT:
132 op = new AesEvpDecryptOperation(block_mode, padding, key.key_data(), key.key_data_size());
133 break;
134 default:
135 *error = KM_ERROR_UNSUPPORTED_PURPOSE;
136 return NULL;
137 }
138
139 if (!op)
140 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
141 return op;
142}
143
Shawn Willdenc47c88f2015-04-07 17:23:27 -0600144static const keymaster_block_mode_t supported_block_modes[] = {KM_MODE_ECB, KM_MODE_CBC,
145 KM_MODE_CTR};
Shawn Willden63ac0432014-12-29 14:07:08 -0700146
147const keymaster_block_mode_t*
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700148AesOperationFactory::SupportedBlockModes(size_t* block_mode_count) const {
Shawn Willden63ac0432014-12-29 14:07:08 -0700149 *block_mode_count = array_length(supported_block_modes);
150 return supported_block_modes;
151}
152
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700153static const keymaster_padding_t supported_padding_modes[] = {KM_PAD_NONE, KM_PAD_PKCS7};
154const keymaster_padding_t*
155AesOperationFactory::SupportedPaddingModes(size_t* padding_mode_count) const {
156 *padding_mode_count = array_length(supported_padding_modes);
157 return supported_padding_modes;
158}
Shawn Willden63ac0432014-12-29 14:07:08 -0700159
160/**
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700161 * Concrete factory for AES encryption operations.
Shawn Willden63ac0432014-12-29 14:07:08 -0700162 */
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700163class AesEncryptionOperationFactory : public AesOperationFactory {
164 keymaster_purpose_t purpose() const { return KM_PURPOSE_ENCRYPT; }
165};
166static OperationFactoryRegistry::Registration<AesEncryptionOperationFactory> encrypt_registration;
167
168/**
169 * Concrete factory for AES decryption operations.
170 */
171class AesDecryptionOperationFactory : public AesOperationFactory {
Shawn Willden63ac0432014-12-29 14:07:08 -0700172 keymaster_purpose_t purpose() const { return KM_PURPOSE_DECRYPT; }
173};
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700174static OperationFactoryRegistry::Registration<AesDecryptionOperationFactory> decrypt_registration;
Shawn Willden63ac0432014-12-29 14:07:08 -0700175
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700176AesEvpOperation::AesEvpOperation(keymaster_purpose_t purpose, keymaster_block_mode_t block_mode,
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600177 keymaster_padding_t padding, bool caller_iv, const uint8_t* key,
178 size_t key_size)
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700179 : Operation(purpose), key_size_(key_size), block_mode_(block_mode), padding_(padding),
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600180 caller_iv_(caller_iv) {
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700181 memcpy(key_, key, key_size_);
182 EVP_CIPHER_CTX_init(&ctx_);
183}
184
185AesEvpOperation::~AesEvpOperation() {
186 EVP_CIPHER_CTX_cleanup(&ctx_);
187}
188
189keymaster_error_t AesEvpOperation::InitializeCipher() {
190 const EVP_CIPHER* cipher;
191 switch (block_mode_) {
192 case KM_MODE_ECB:
193 switch (key_size_) {
194 case 16:
195 cipher = EVP_aes_128_ecb();
196 break;
197 case 24:
198 cipher = EVP_aes_192_ecb();
199 break;
200 case 32:
201 cipher = EVP_aes_256_ecb();
202 break;
203 default:
204 return KM_ERROR_UNSUPPORTED_KEY_SIZE;
205 }
206 break;
207 case KM_MODE_CBC:
208 switch (key_size_) {
209 case 16:
210 cipher = EVP_aes_128_cbc();
211 break;
212 case 24:
213 cipher = EVP_aes_192_cbc();
214 break;
215 case 32:
216 cipher = EVP_aes_256_cbc();
217 break;
218 default:
219 return KM_ERROR_UNSUPPORTED_KEY_SIZE;
220 }
221 break;
Thai Duong20d725d2015-03-24 17:49:58 -0700222 case KM_MODE_CTR:
223 switch (key_size_) {
224 case 16:
225 cipher = EVP_aes_128_ctr();
226 break;
227 case 24:
228 cipher = EVP_aes_192_ctr();
229 break;
230 case 32:
231 cipher = EVP_aes_256_ctr();
232 break;
233 default:
234 return KM_ERROR_UNSUPPORTED_KEY_SIZE;
235 }
236 break;
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700237 default:
238 return KM_ERROR_UNSUPPORTED_BLOCK_MODE;
239 }
240
241 int init_result =
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600242 EVP_CipherInit_ex(&ctx_, cipher, NULL /* engine */, key_, iv_.get(), evp_encrypt_mode());
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700243
244 if (!init_result)
Shawn Willdenf01329d2015-03-11 21:51:38 -0600245 return TranslateLastOpenSslError();
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700246
247 switch (padding_) {
248 case KM_PAD_NONE:
249 EVP_CIPHER_CTX_set_padding(&ctx_, 0 /* disable padding */);
250 break;
251 case KM_PAD_PKCS7:
252 // This is the default for OpenSSL EVP cipher operations.
253 break;
254 default:
255 return KM_ERROR_UNSUPPORTED_PADDING_MODE;
256 }
257
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700258 return KM_ERROR_OK;
259}
260
261bool AesEvpOperation::need_iv() const {
262 switch (block_mode_) {
263 case KM_MODE_CBC:
Thai Duong20d725d2015-03-24 17:49:58 -0700264 case KM_MODE_CTR:
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700265 return true;
266 case KM_MODE_ECB:
267 return false;
268 default:
269 // Shouldn't get here.
270 assert(false);
271 return false;
272 }
273}
274
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600275keymaster_error_t AesEvpOperation::Begin(const AuthorizationSet& input_params,
276 AuthorizationSet* output_params) {
277 if (!output_params)
278 return KM_ERROR_OUTPUT_PARAMETER_NULL;
279
280 keymaster_error_t error = KM_ERROR_OK;
281 if (need_iv()) {
282 switch (purpose()) {
283 case KM_PURPOSE_ENCRYPT:
Shawn Willden67706352015-04-28 00:43:19 -0600284 if (input_params.find(TAG_NONCE) == -1)
285 error = GenerateIv();
286 else if (caller_iv_)
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600287 error = GetIv(input_params);
Shawn Willden67706352015-04-28 00:43:19 -0600288 else
289 error = KM_ERROR_CALLER_NONCE_PROHIBITED;
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600290
291 if (error == KM_ERROR_OK)
292 output_params->push_back(TAG_NONCE, iv_.get(), AES_BLOCK_SIZE);
293 break;
294
295 case KM_PURPOSE_DECRYPT:
296 error = GetIv(input_params);
297 break;
298 default:
299 return KM_ERROR_UNSUPPORTED_PURPOSE;
300 }
301 }
302
303 if (error == KM_ERROR_OK)
304 error = InitializeCipher();
305
306 return error;
307}
308
309keymaster_error_t AesEvpOperation::GetIv(const AuthorizationSet& input_params) {
310 keymaster_blob_t iv_blob;
311 if (!input_params.GetTagValue(TAG_NONCE, &iv_blob)) {
312 LOG_E("No IV provided", 0);
313 return KM_ERROR_INVALID_ARGUMENT;
314 }
315 if (iv_blob.data_length != AES_BLOCK_SIZE) {
316 LOG_E("Expected %d-byte IV for AES operation, but got %d bytes", AES_BLOCK_SIZE,
317 iv_blob.data_length);
Thai Duong20d725d2015-03-24 17:49:58 -0700318 return KM_ERROR_INVALID_NONCE;
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600319 }
320 iv_.reset(dup_array(iv_blob.data, iv_blob.data_length));
Shawn Willden92b69a32015-03-14 11:07:36 -0600321 if (!iv_.get())
322 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700323 return KM_ERROR_OK;
324}
325
Shawn Willden67706352015-04-28 00:43:19 -0600326keymaster_error_t AesEvpOperation::GenerateIv() {
327 iv_.reset(new uint8_t[AES_BLOCK_SIZE]);
328 if (!iv_.get())
329 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willden34454982015-04-29 23:22:37 -0600330 if (RAND_bytes(iv_.get(), AES_BLOCK_SIZE) != 1)
Shawn Willden67706352015-04-28 00:43:19 -0600331 return TranslateLastOpenSslError();
332 return KM_ERROR_OK;
333}
334
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700335inline size_t min(size_t a, size_t b) {
336 if (a < b)
337 return a;
338 return b;
339}
340
341keymaster_error_t AesEvpOperation::Update(const AuthorizationSet& /* additional_params */,
342 const Buffer& input, Buffer* output,
343 size_t* input_consumed) {
344 output->reserve(input.available_read() + AES_BLOCK_SIZE);
345
346 const uint8_t* input_pos = input.peek_read();
347 const uint8_t* input_end = input_pos + input.available_read();
348
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700349 int output_written = -1;
350 if (!EVP_CipherUpdate(&ctx_, output->peek_write(), &output_written, input_pos,
351 input_end - input_pos))
352 return TranslateLastOpenSslError();
353
354 assert(output_written >= 0);
355 assert(output_written <= (int)output->available_write());
356 output->advance_write(output_written);
357 *input_consumed = input.available_read();
358 return KM_ERROR_OK;
359}
360
361keymaster_error_t AesEvpOperation::Finish(const AuthorizationSet& /* additional_params */,
362 const Buffer& /* signature */, Buffer* output) {
363 output->reserve(AES_BLOCK_SIZE);
364
365 int output_written = -1;
366 if (!EVP_CipherFinal_ex(&ctx_, output->peek_write(), &output_written)) {
367 LOG_E("Error encrypting final block: %s", ERR_error_string(ERR_peek_last_error(), NULL));
368 return TranslateLastOpenSslError();
369 }
370
371 assert(output_written <= AES_BLOCK_SIZE);
372 output->advance_write(output_written);
373 return KM_ERROR_OK;
374}
375
376keymaster_error_t AesEvpOperation::Abort() {
377 return KM_ERROR_OK;
378}
379
Shawn Willden907c3012014-12-08 15:51:55 -0700380} // namespace keymaster