blob: 3e33e127bd9bb1dab39a5b3c1a67d6efe2677bfb [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)) {
66 LOG_E("%d padding modes specified in begin params",
67 begin_params.GetTagCount(TAG_PADDING));
68 *error = KM_ERROR_UNSUPPORTED_PADDING_MODE;
69 return nullptr;
70 } else if (!supported(padding)) {
71 LOG_E("Padding mode %d not supported", padding);
72 *error = KM_ERROR_UNSUPPORTED_PADDING_MODE;
73 return nullptr;
74 } else if (!key.authorizations().Contains(TAG_PADDING, padding)) {
Shawn Willden3ad5f052015-05-08 14:05:13 -060075 LOG_E("Padding mode %d was specified, but not authorized by key", padding);
76 *error = KM_ERROR_INCOMPATIBLE_PADDING_MODE;
Shawn Willdenc4424672015-05-11 11:56:02 -060077 return nullptr;
Shawn Willden3ad5f052015-05-08 14:05:13 -060078 }
Shawn Willdenf0f68b92014-12-30 16:03:28 -070079
Shawn Willden7a62f5e2015-03-10 12:59:20 -060080 bool caller_nonce = key.authorizations().GetTagValue(TAG_CALLER_NONCE);
81
Shawn Willdenf0f68b92014-12-30 16:03:28 -070082 if (*error != KM_ERROR_OK)
Shawn Willden3ad5f052015-05-08 14:05:13 -060083 return nullptr;
Shawn Willdenf0f68b92014-12-30 16:03:28 -070084
85 switch (block_mode) {
Shawn Willdenf0f68b92014-12-30 16:03:28 -070086 case KM_MODE_ECB:
87 case KM_MODE_CBC:
Shawn Willden7a62f5e2015-03-10 12:59:20 -060088 return CreateEvpOperation(*symmetric_key, block_mode, padding, caller_nonce, error);
Thai Duong20d725d2015-03-24 17:49:58 -070089 case KM_MODE_CTR:
90 if (padding != KM_PAD_NONE) {
Shawn Willden3ad5f052015-05-08 14:05:13 -060091 *error = KM_ERROR_INCOMPATIBLE_PADDING_MODE;
92 return nullptr;
Thai Duong20d725d2015-03-24 17:49:58 -070093 }
94 return CreateEvpOperation(*symmetric_key, block_mode, padding, caller_nonce, error);
Shawn Willdenf0f68b92014-12-30 16:03:28 -070095 default:
Shawn Willden63ac0432014-12-29 14:07:08 -070096 *error = KM_ERROR_UNSUPPORTED_BLOCK_MODE;
Shawn Willden3ad5f052015-05-08 14:05:13 -060097 return nullptr;
Shawn Willden63ac0432014-12-29 14:07:08 -070098 }
Shawn Willdenf0f68b92014-12-30 16:03:28 -070099}
100
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700101Operation* AesOperationFactory::CreateEvpOperation(const SymmetricKey& key,
102 keymaster_block_mode_t block_mode,
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600103 keymaster_padding_t padding, bool caller_iv,
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700104 keymaster_error_t* error) {
105 Operation* op = NULL;
106 switch (purpose()) {
107 case KM_PURPOSE_ENCRYPT:
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600108 op = new AesEvpEncryptOperation(block_mode, padding, caller_iv, key.key_data(),
109 key.key_data_size());
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700110 break;
111 case KM_PURPOSE_DECRYPT:
112 op = new AesEvpDecryptOperation(block_mode, padding, key.key_data(), key.key_data_size());
113 break;
114 default:
115 *error = KM_ERROR_UNSUPPORTED_PURPOSE;
116 return NULL;
117 }
118
119 if (!op)
120 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
121 return op;
122}
123
Shawn Willdenc47c88f2015-04-07 17:23:27 -0600124static const keymaster_block_mode_t supported_block_modes[] = {KM_MODE_ECB, KM_MODE_CBC,
125 KM_MODE_CTR};
Shawn Willden63ac0432014-12-29 14:07:08 -0700126
127const keymaster_block_mode_t*
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700128AesOperationFactory::SupportedBlockModes(size_t* block_mode_count) const {
Shawn Willden63ac0432014-12-29 14:07:08 -0700129 *block_mode_count = array_length(supported_block_modes);
130 return supported_block_modes;
131}
132
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700133static const keymaster_padding_t supported_padding_modes[] = {KM_PAD_NONE, KM_PAD_PKCS7};
134const keymaster_padding_t*
135AesOperationFactory::SupportedPaddingModes(size_t* padding_mode_count) const {
136 *padding_mode_count = array_length(supported_padding_modes);
137 return supported_padding_modes;
138}
Shawn Willden63ac0432014-12-29 14:07:08 -0700139
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700140AesEvpOperation::AesEvpOperation(keymaster_purpose_t purpose, keymaster_block_mode_t block_mode,
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600141 keymaster_padding_t padding, bool caller_iv, const uint8_t* key,
142 size_t key_size)
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700143 : Operation(purpose), key_size_(key_size), block_mode_(block_mode), padding_(padding),
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600144 caller_iv_(caller_iv) {
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700145 memcpy(key_, key, key_size_);
146 EVP_CIPHER_CTX_init(&ctx_);
147}
148
149AesEvpOperation::~AesEvpOperation() {
150 EVP_CIPHER_CTX_cleanup(&ctx_);
151}
152
153keymaster_error_t AesEvpOperation::InitializeCipher() {
154 const EVP_CIPHER* cipher;
155 switch (block_mode_) {
156 case KM_MODE_ECB:
157 switch (key_size_) {
158 case 16:
159 cipher = EVP_aes_128_ecb();
160 break;
161 case 24:
162 cipher = EVP_aes_192_ecb();
163 break;
164 case 32:
165 cipher = EVP_aes_256_ecb();
166 break;
167 default:
168 return KM_ERROR_UNSUPPORTED_KEY_SIZE;
169 }
170 break;
171 case KM_MODE_CBC:
172 switch (key_size_) {
173 case 16:
174 cipher = EVP_aes_128_cbc();
175 break;
176 case 24:
177 cipher = EVP_aes_192_cbc();
178 break;
179 case 32:
180 cipher = EVP_aes_256_cbc();
181 break;
182 default:
183 return KM_ERROR_UNSUPPORTED_KEY_SIZE;
184 }
185 break;
Thai Duong20d725d2015-03-24 17:49:58 -0700186 case KM_MODE_CTR:
187 switch (key_size_) {
188 case 16:
189 cipher = EVP_aes_128_ctr();
190 break;
191 case 24:
192 cipher = EVP_aes_192_ctr();
193 break;
194 case 32:
195 cipher = EVP_aes_256_ctr();
196 break;
197 default:
198 return KM_ERROR_UNSUPPORTED_KEY_SIZE;
199 }
200 break;
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700201 default:
202 return KM_ERROR_UNSUPPORTED_BLOCK_MODE;
203 }
204
205 int init_result =
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600206 EVP_CipherInit_ex(&ctx_, cipher, NULL /* engine */, key_, iv_.get(), evp_encrypt_mode());
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700207
208 if (!init_result)
Shawn Willdenf01329d2015-03-11 21:51:38 -0600209 return TranslateLastOpenSslError();
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700210
211 switch (padding_) {
212 case KM_PAD_NONE:
213 EVP_CIPHER_CTX_set_padding(&ctx_, 0 /* disable padding */);
214 break;
215 case KM_PAD_PKCS7:
216 // This is the default for OpenSSL EVP cipher operations.
217 break;
218 default:
219 return KM_ERROR_UNSUPPORTED_PADDING_MODE;
220 }
221
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700222 return KM_ERROR_OK;
223}
224
225bool AesEvpOperation::need_iv() const {
226 switch (block_mode_) {
227 case KM_MODE_CBC:
Thai Duong20d725d2015-03-24 17:49:58 -0700228 case KM_MODE_CTR:
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700229 return true;
230 case KM_MODE_ECB:
231 return false;
232 default:
233 // Shouldn't get here.
234 assert(false);
235 return false;
236 }
237}
238
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600239keymaster_error_t AesEvpOperation::Begin(const AuthorizationSet& input_params,
240 AuthorizationSet* output_params) {
241 if (!output_params)
242 return KM_ERROR_OUTPUT_PARAMETER_NULL;
243
244 keymaster_error_t error = KM_ERROR_OK;
245 if (need_iv()) {
246 switch (purpose()) {
247 case KM_PURPOSE_ENCRYPT:
Shawn Willden67706352015-04-28 00:43:19 -0600248 if (input_params.find(TAG_NONCE) == -1)
249 error = GenerateIv();
250 else if (caller_iv_)
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600251 error = GetIv(input_params);
Shawn Willden67706352015-04-28 00:43:19 -0600252 else
253 error = KM_ERROR_CALLER_NONCE_PROHIBITED;
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600254
255 if (error == KM_ERROR_OK)
256 output_params->push_back(TAG_NONCE, iv_.get(), AES_BLOCK_SIZE);
257 break;
258
259 case KM_PURPOSE_DECRYPT:
260 error = GetIv(input_params);
261 break;
262 default:
263 return KM_ERROR_UNSUPPORTED_PURPOSE;
264 }
265 }
266
267 if (error == KM_ERROR_OK)
268 error = InitializeCipher();
269
270 return error;
271}
272
273keymaster_error_t AesEvpOperation::GetIv(const AuthorizationSet& input_params) {
274 keymaster_blob_t iv_blob;
275 if (!input_params.GetTagValue(TAG_NONCE, &iv_blob)) {
276 LOG_E("No IV provided", 0);
277 return KM_ERROR_INVALID_ARGUMENT;
278 }
279 if (iv_blob.data_length != AES_BLOCK_SIZE) {
280 LOG_E("Expected %d-byte IV for AES operation, but got %d bytes", AES_BLOCK_SIZE,
281 iv_blob.data_length);
Thai Duong20d725d2015-03-24 17:49:58 -0700282 return KM_ERROR_INVALID_NONCE;
Shawn Willden7a62f5e2015-03-10 12:59:20 -0600283 }
284 iv_.reset(dup_array(iv_blob.data, iv_blob.data_length));
Shawn Willden92b69a32015-03-14 11:07:36 -0600285 if (!iv_.get())
286 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700287 return KM_ERROR_OK;
288}
289
Shawn Willden67706352015-04-28 00:43:19 -0600290keymaster_error_t AesEvpOperation::GenerateIv() {
291 iv_.reset(new uint8_t[AES_BLOCK_SIZE]);
292 if (!iv_.get())
293 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willden34454982015-04-29 23:22:37 -0600294 if (RAND_bytes(iv_.get(), AES_BLOCK_SIZE) != 1)
Shawn Willden67706352015-04-28 00:43:19 -0600295 return TranslateLastOpenSslError();
296 return KM_ERROR_OK;
297}
298
Shawn Willdenf0f68b92014-12-30 16:03:28 -0700299inline size_t min(size_t a, size_t b) {
300 if (a < b)
301 return a;
302 return b;
303}
304
305keymaster_error_t AesEvpOperation::Update(const AuthorizationSet& /* additional_params */,
306 const Buffer& input, Buffer* output,
307 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 */,
326 const Buffer& /* signature */, Buffer* output) {
327 output->reserve(AES_BLOCK_SIZE);
328
329 int output_written = -1;
330 if (!EVP_CipherFinal_ex(&ctx_, output->peek_write(), &output_written)) {
331 LOG_E("Error encrypting final block: %s", ERR_error_string(ERR_peek_last_error(), NULL));
332 return TranslateLastOpenSslError();
333 }
334
335 assert(output_written <= AES_BLOCK_SIZE);
336 output->advance_write(output_written);
337 return KM_ERROR_OK;
338}
339
340keymaster_error_t AesEvpOperation::Abort() {
341 return KM_ERROR_OK;
342}
343
Shawn Willden907c3012014-12-08 15:51:55 -0700344} // namespace keymaster