blob: 05d828553b2692e52e016bfc3937529e9e86556e [file] [log] [blame]
Antonio de Angelis8908f472018-08-31 15:44:25 +01001/*
Antonio de Angelis377a1552018-11-22 17:02:40 +00002 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
Antonio de Angelis8908f472018-08-31 15:44:25 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
Antonio de Angelis8908f472018-08-31 15:44:25 +01008#include "tfm_crypto_api.h"
Antonio de Angelisab85ccd2019-03-25 15:14:29 +00009#include "crypto_engine.h"
10#include "tfm_crypto_struct.h"
Antonio de Angelis8908f472018-08-31 15:44:25 +010011
Jamie Fox82b87ca2018-12-11 16:41:11 +000012/**
13 * \def CRYPTO_CIPHER_MAX_KEY_LENGTH
14 *
15 * \brief Specifies the maximum key length supported by the
16 * Cipher operations in this implementation
17 */
18#ifndef CRYPTO_CIPHER_MAX_KEY_LENGTH
19#define CRYPTO_CIPHER_MAX_KEY_LENGTH (32)
20#endif
21
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000022static psa_status_t _psa_get_key_information(psa_key_slot_t key,
23 psa_key_type_t *type,
24 size_t *bits)
25{
26 psa_invec in_vec[] = {
27 {.base = &key, .len = sizeof(psa_key_slot_t)},
28 };
29 psa_outvec out_vec[] = {
30 {.base = type, .len = sizeof(psa_key_type_t)},
31 {.base = bits, .len = sizeof(size_t)}
32 };
33
34 return tfm_crypto_get_key_information(
35 in_vec, sizeof(in_vec)/sizeof(in_vec[0]),
36 out_vec, sizeof(out_vec)/sizeof(out_vec[0]));
37}
38
Jamie Fox0ff04ba2019-02-05 14:19:07 +000039/**
40 * \brief Release all resources associated with a cipher operation.
41 *
42 * \param[in] operation Frontend cipher operation context
43 * \param[in] ctx Backend cipher operation context
44 *
45 * \return Return values as described in \ref tfm_crypto_err_t
46 */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000047static psa_status_t tfm_crypto_cipher_release(
Jamie Fox0ff04ba2019-02-05 14:19:07 +000048 psa_cipher_operation_t *operation,
49 struct tfm_cipher_operation_s *ctx)
50{
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000051 psa_status_t status = PSA_SUCCESS;
Jamie Fox0ff04ba2019-02-05 14:19:07 +000052
53 /* Release resources in the engine */
54 status = tfm_crypto_engine_cipher_release(&(ctx->engine_ctx));
55 if (status != PSA_SUCCESS) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000056 return status;
Jamie Fox0ff04ba2019-02-05 14:19:07 +000057 }
58
59 /* Release the operation context */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000060 return tfm_crypto_operation_release(TFM_CRYPTO_CIPHER_OPERATION, operation);
Jamie Fox0ff04ba2019-02-05 14:19:07 +000061}
62
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000063static psa_status_t tfm_crypto_cipher_setup(psa_cipher_operation_t *operation,
64 psa_key_slot_t key,
65 psa_algorithm_t alg,
66 enum engine_cipher_mode_t c_mode)
Antonio de Angelis8908f472018-08-31 15:44:25 +010067{
Jamie Fox82b87ca2018-12-11 16:41:11 +000068 uint8_t key_data[CRYPTO_CIPHER_MAX_KEY_LENGTH];
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010069 size_t key_size;
70 psa_key_type_t key_type = PSA_KEY_TYPE_NONE;
71 psa_status_t status = PSA_SUCCESS;
Antonio de Angelis377a1552018-11-22 17:02:40 +000072 struct tfm_cipher_operation_s *ctx = NULL;
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010073 struct cipher_engine_info engine_info;
Jamie Foxefd82732018-11-26 10:34:32 +000074 psa_key_usage_t usage;
Antonio de Angelis8908f472018-08-31 15:44:25 +010075
Antonio de Angelis8908f472018-08-31 15:44:25 +010076 if (!PSA_ALG_IS_CIPHER(alg)) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000077 return PSA_ERROR_INVALID_ARGUMENT;
Antonio de Angelis8908f472018-08-31 15:44:25 +010078 }
79
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010080 /* Access the key module to retrieve key related information */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000081 status = _psa_get_key_information(key, &key_type, &key_size);
82 if (status != PSA_SUCCESS) {
83 return status;
Jamie Fox82b87ca2018-12-11 16:41:11 +000084 }
85
86 /* Check if it's a raw data key type */
87 if (key_type == PSA_KEY_TYPE_RAW_DATA) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000088 return PSA_ERROR_NOT_PERMITTED;
Jamie Fox82b87ca2018-12-11 16:41:11 +000089 }
90
91 /* Check compatibility between key and algorithm */
92 if ((key_type == PSA_KEY_TYPE_ARC4) && (alg != PSA_ALG_ARC4)) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000093 return PSA_ERROR_INVALID_ARGUMENT;
Antonio de Angelis8908f472018-08-31 15:44:25 +010094 }
95
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010096 /* Setup the algorithm on the crypto engine */
97 status = tfm_crypto_engine_cipher_setup(alg,
98 (const psa_key_type_t)key_type,
99 (const uint32_t)key_size,
100 c_mode,
101 &engine_info);
102 if (status != PSA_SUCCESS) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000103 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100104 }
105
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100106 /* Allocate the operation context in the secure world */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000107 status = tfm_crypto_operation_alloc(TFM_CRYPTO_CIPHER_OPERATION,
108 operation,
109 (void **)&ctx);
110 if (status != PSA_SUCCESS) {
111 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100112 }
113
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100114 /* Set the proper cipher mode (encrypt/decrypt) in the operation context */
115 ctx->cipher_mode = (uint8_t) c_mode;
116
Antonio de Angelis8908f472018-08-31 15:44:25 +0100117 /* Bind the algorithm to the cipher operation */
Antonio de Angelis377a1552018-11-22 17:02:40 +0000118 ctx->alg = alg;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100119
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100120 /* Start the crypto engine */
121 status = tfm_crypto_engine_cipher_start(&(ctx->engine_ctx), &engine_info);
122 if (status != PSA_SUCCESS) {
Hugues de Valon8b442442019-02-19 14:30:52 +0000123 /* Release the operation context, ignore if this operation fails. */
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000124 (void)tfm_crypto_cipher_release(operation, ctx);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000125 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100126 }
127
Jamie Foxefd82732018-11-26 10:34:32 +0000128 /* Set the key usage based on the cipher mode */
129 usage = (c_mode == ENGINE_CIPHER_MODE_DECRYPT) ? PSA_KEY_USAGE_DECRYPT
130 : PSA_KEY_USAGE_ENCRYPT;
131
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100132 /* Access the crypto service key module to retrieve key data */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000133 status = tfm_crypto_get_key(key,
134 usage,
135 alg,
136 key_data,
137 CRYPTO_CIPHER_MAX_KEY_LENGTH,
138 &key_size);
139 if (status != PSA_SUCCESS) {
Hugues de Valon8b442442019-02-19 14:30:52 +0000140 /* Release the operation context, ignore if this operation fails. */
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000141 (void)tfm_crypto_cipher_release(operation, ctx);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000142 return status;
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100143 }
144
145 /* Set the key on the engine */
146 status = tfm_crypto_engine_cipher_set_key(&(ctx->engine_ctx),
147 key_data,
148 key_size,
149 &engine_info);
150 if (status != PSA_SUCCESS) {
Hugues de Valon8b442442019-02-19 14:30:52 +0000151 /* Release the operation context, ignore if this operation fails. */
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000152 (void)tfm_crypto_cipher_release(operation, ctx);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000153 return status;
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100154 }
Antonio de Angelis8908f472018-08-31 15:44:25 +0100155
156 /* Bind the key to the cipher operation */
Antonio de Angelis377a1552018-11-22 17:02:40 +0000157 ctx->key = key;
158 ctx->key_set = 1;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100159
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100160 /* Set padding mode on engine in case of CBC */
Antonio de Angelis8908f472018-08-31 15:44:25 +0100161 if ((alg & ~PSA_ALG_BLOCK_CIPHER_PADDING_MASK) == PSA_ALG_CBC_BASE) {
162
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100163 status = tfm_crypto_engine_cipher_set_padding_mode(&(ctx->engine_ctx),
164 &engine_info);
165 if (status != PSA_SUCCESS) {
Hugues de Valon8b442442019-02-19 14:30:52 +0000166 /* Release the operation context, ignore if this operation fails. */
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000167 (void)tfm_crypto_cipher_release(operation, ctx);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000168 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100169 }
170 }
171
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100172 /* FIXME: Check based on the algorithm, if we need to have an IV */
173 ctx->iv_required = 1;
174 ctx->block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE(key_type);
175
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000176 return PSA_SUCCESS;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100177}
178
179/*!
180 * \defgroup public_psa Public functions, PSA
181 *
182 */
183
184/*!@{*/
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000185psa_status_t tfm_crypto_cipher_set_iv(psa_invec in_vec[],
186 size_t in_len,
187 psa_outvec out_vec[],
188 size_t out_len)
Antonio de Angelis8908f472018-08-31 15:44:25 +0100189{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100190 psa_status_t status = PSA_SUCCESS;
Antonio de Angelis377a1552018-11-22 17:02:40 +0000191 struct tfm_cipher_operation_s *ctx = NULL;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100192
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000193 if ((in_len != 1) || (out_len != 1)) {
194 return PSA_CONNECTION_REFUSED;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100195 }
196
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000197 if (out_vec[0].len != sizeof(psa_cipher_operation_t)) {
198 return PSA_CONNECTION_REFUSED;
199 }
200
201 psa_cipher_operation_t *operation = out_vec[0].base;
202 const unsigned char *iv = in_vec[0].base;
203 size_t iv_length = in_vec[0].len;
204
Antonio de Angelis8908f472018-08-31 15:44:25 +0100205 /* Look up the corresponding operation context */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000206 status = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
207 operation,
208 (void **)&ctx);
209 if (status != PSA_SUCCESS) {
210 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100211 }
212
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100213 if ((iv_length != ctx->block_size) || (iv_length > TFM_CIPHER_IV_MAX_SIZE)){
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000214 (void)tfm_crypto_cipher_release(operation, ctx);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000215 return PSA_ERROR_INVALID_ARGUMENT;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100216 }
217
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100218 if ((ctx->iv_set == 1) || (ctx->iv_required == 0)) {
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000219 (void)tfm_crypto_cipher_release(operation, ctx);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000220 return PSA_ERROR_BAD_STATE;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100221 }
222
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100223 /* Set the IV on the crypto engine */
224 status = tfm_crypto_engine_cipher_set_iv(&(ctx->engine_ctx),
225 iv,
226 iv_length);
227 if (status != PSA_SUCCESS) {
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000228 (void)tfm_crypto_cipher_release(operation, ctx);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000229 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100230 }
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100231
Antonio de Angelis377a1552018-11-22 17:02:40 +0000232 ctx->iv_set = 1;
233 ctx->iv_size = iv_length;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100234
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000235 return PSA_SUCCESS;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100236}
237
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000238static psa_status_t _psa_cipher_set_iv(psa_cipher_operation_t *operation,
239 const unsigned char *iv,
240 size_t iv_length)
Antonio de Angelis8908f472018-08-31 15:44:25 +0100241{
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000242 psa_status_t status;
243 psa_invec in_vec[] = {
244 {.base = iv, .len = iv_length},
245 };
246 psa_outvec out_vec[] = {
247 {.base = operation, .len = sizeof(psa_cipher_operation_t)},
248 };
249
250 status = tfm_crypto_cipher_set_iv(in_vec, sizeof(in_vec)/sizeof(in_vec[0]),
251 out_vec, sizeof(out_vec)/sizeof(out_vec[0]));
252 return status;
253}
254psa_status_t tfm_crypto_cipher_encrypt_setup(psa_invec in_vec[],
255 size_t in_len,
256 psa_outvec out_vec[],
257 size_t out_len)
258{
259 if ((in_len != 2) || (out_len != 1)) {
260 return PSA_CONNECTION_REFUSED;
261 }
262
263 if ((out_vec[0].len != sizeof(psa_cipher_operation_t)) ||
264 (in_vec[0].len != sizeof(psa_key_slot_t)) ||
265 (in_vec[1].len != sizeof(psa_algorithm_t))) {
266 return PSA_CONNECTION_REFUSED;
267 }
268
269 psa_cipher_operation_t *operation = out_vec[0].base;
270 psa_key_slot_t key = *((psa_key_slot_t *)in_vec[0].base);
271 psa_algorithm_t alg = *((psa_algorithm_t *)in_vec[1].base);
272
Antonio de Angelis377a1552018-11-22 17:02:40 +0000273 return tfm_crypto_cipher_setup(operation,
Antonio de Angelis8908f472018-08-31 15:44:25 +0100274 key,
275 alg,
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100276 ENGINE_CIPHER_MODE_ENCRYPT);
Antonio de Angelis8908f472018-08-31 15:44:25 +0100277}
278
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000279psa_status_t tfm_crypto_cipher_decrypt_setup(psa_invec in_vec[],
280 size_t in_len,
281 psa_outvec out_vec[],
282 size_t out_len)
Antonio de Angelis8908f472018-08-31 15:44:25 +0100283{
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000284 if ((in_len != 2) || (out_len != 1)) {
285 return PSA_CONNECTION_REFUSED;
286 }
287
288 if ((out_vec[0].len != sizeof(psa_cipher_operation_t)) ||
289 (in_vec[0].len != sizeof(psa_key_slot_t)) ||
290 (in_vec[1].len != sizeof(psa_algorithm_t))) {
291 return PSA_CONNECTION_REFUSED;
292 }
293
294 psa_cipher_operation_t *operation = out_vec[0].base;
295 psa_key_slot_t key = *((psa_key_slot_t *)in_vec[0].base);
296 psa_algorithm_t alg = *((psa_algorithm_t *)in_vec[1].base);
297
Antonio de Angelis377a1552018-11-22 17:02:40 +0000298 return tfm_crypto_cipher_setup(operation,
Antonio de Angelis8908f472018-08-31 15:44:25 +0100299 key,
300 alg,
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100301 ENGINE_CIPHER_MODE_DECRYPT);
Antonio de Angelis8908f472018-08-31 15:44:25 +0100302}
303
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000304psa_status_t tfm_crypto_cipher_update(psa_invec in_vec[],
305 size_t in_len,
306 psa_outvec out_vec[],
307 size_t out_len)
Antonio de Angelis8908f472018-08-31 15:44:25 +0100308{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100309 psa_status_t status = PSA_SUCCESS;
Antonio de Angelis377a1552018-11-22 17:02:40 +0000310 struct tfm_cipher_operation_s *ctx = NULL;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100311
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000312 if ((in_len != 1) || (out_len != 2)) {
313 return PSA_CONNECTION_REFUSED;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100314 }
315
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000316 if ((out_vec[0].len != sizeof(psa_cipher_operation_t))) {
317 return PSA_CONNECTION_REFUSED;
318 }
319
320 psa_cipher_operation_t *operation = out_vec[0].base;
321 const uint8_t *input = in_vec[0].base;
322 size_t input_length = in_vec[0].len;
323 unsigned char *output = out_vec[1].base;
324 size_t output_size = out_vec[1].len;
325
326 /* Initialise the output_length to zero */
327 out_vec[1].len = 0;
Jamie Fox82b87ca2018-12-11 16:41:11 +0000328
Antonio de Angelis8908f472018-08-31 15:44:25 +0100329 /* Look up the corresponding operation context */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000330 status = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
331 operation,
332 (void **)&ctx);
333 if (status != PSA_SUCCESS) {
334 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100335 }
336
337 /* If the IV is required and it's not been set yet */
Antonio de Angelis377a1552018-11-22 17:02:40 +0000338 if ((ctx->iv_required == 1) && (ctx->iv_set == 0)) {
Antonio de Angelis8908f472018-08-31 15:44:25 +0100339
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100340 if (ctx->cipher_mode != ENGINE_CIPHER_MODE_DECRYPT) {
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000341 (void)tfm_crypto_cipher_release(operation, ctx);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000342 return PSA_ERROR_BAD_STATE;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100343 }
344
345 /* This call is used to set the IV on the object */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000346 return _psa_cipher_set_iv(operation, input, input_length);
Antonio de Angelis8908f472018-08-31 15:44:25 +0100347 }
348
349 /* If the key is not set, setup phase has not been completed */
Antonio de Angelis377a1552018-11-22 17:02:40 +0000350 if (ctx->key_set == 0) {
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000351 (void)tfm_crypto_cipher_release(operation, ctx);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000352 return PSA_ERROR_BAD_STATE;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100353 }
354
Jamie Fox82b87ca2018-12-11 16:41:11 +0000355 /* FIXME: The implementation currently expects to work only on blocks
356 * of input data whose length is equal to the block size
357 */
358 if (input_length > output_size) {
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000359 (void)tfm_crypto_cipher_release(operation, ctx);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000360 return PSA_ERROR_BUFFER_TOO_SMALL;
Jamie Fox82b87ca2018-12-11 16:41:11 +0000361 }
362
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100363 /* Update the cipher output with the input chunk on the engine */
364 status = tfm_crypto_engine_cipher_update(&(ctx->engine_ctx),
365 input,
366 input_length,
367 output,
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000368 (uint32_t *)&(out_vec[1].len));
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100369 if (status != PSA_SUCCESS) {
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000370 (void)tfm_crypto_cipher_release(operation, ctx);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000371 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100372 }
373
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000374 return PSA_SUCCESS;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100375}
376
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000377psa_status_t tfm_crypto_cipher_finish(psa_invec in_vec[],
378 size_t in_len,
379 psa_outvec out_vec[],
380 size_t out_len)
Antonio de Angelis8908f472018-08-31 15:44:25 +0100381{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100382 psa_status_t status = PSA_SUCCESS;
Antonio de Angelis377a1552018-11-22 17:02:40 +0000383 struct tfm_cipher_operation_s *ctx = NULL;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100384
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000385 if ((in_len != 0) || (out_len != 2)) {
386 return PSA_CONNECTION_REFUSED;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100387 }
388
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000389 if ((out_vec[0].len != sizeof(psa_cipher_operation_t))) {
390 return PSA_CONNECTION_REFUSED;
391 }
392
393 psa_cipher_operation_t *operation = out_vec[0].base;
394 unsigned char *output = out_vec[1].base;
395 size_t output_size = out_vec[1].len;
396
397 /* Initialise the output_length to zero */
398 out_vec[1].len = 0;
399
Antonio de Angelis8908f472018-08-31 15:44:25 +0100400 /* Look up the corresponding operation context */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000401 status = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
402 operation,
403 (void **)&ctx);
404 if (status != PSA_SUCCESS) {
405 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100406 }
407
Jamie Fox82b87ca2018-12-11 16:41:11 +0000408 /* Check that the output buffer is large enough for up to one block size of
409 * output data.
410 */
411 if (output_size < ctx->block_size) {
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000412 (void)tfm_crypto_cipher_release(operation, ctx);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000413 return PSA_ERROR_BUFFER_TOO_SMALL;
Jamie Fox82b87ca2018-12-11 16:41:11 +0000414 }
415
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100416 /* Finalise the operation on the crypto engine */
417 status = tfm_crypto_engine_cipher_finish(&(ctx->engine_ctx),
418 output,
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000419 (uint32_t *)&(out_vec[1].len));
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100420 if (status != PSA_SUCCESS) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000421 out_vec[1].len = 0;
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000422 (void)tfm_crypto_cipher_release(operation, ctx);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000423 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100424 }
425
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000426 return tfm_crypto_cipher_release(operation, ctx);
Antonio de Angelis8908f472018-08-31 15:44:25 +0100427}
428
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000429psa_status_t tfm_crypto_cipher_abort(psa_invec in_vec[],
430 size_t in_len,
431 psa_outvec out_vec[],
432 size_t out_len)
Antonio de Angelis8908f472018-08-31 15:44:25 +0100433{
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000434 psa_status_t status = PSA_SUCCESS;
Antonio de Angelis377a1552018-11-22 17:02:40 +0000435 struct tfm_cipher_operation_s *ctx = NULL;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100436
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000437 if ((in_len != 0) || (out_len != 1)) {
438 return PSA_CONNECTION_REFUSED;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100439 }
440
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000441 if ((out_vec[0].len != sizeof(psa_cipher_operation_t))) {
442 return PSA_CONNECTION_REFUSED;
443 }
444
445 psa_cipher_operation_t *operation = out_vec[0].base;
446
Antonio de Angelis8908f472018-08-31 15:44:25 +0100447 /* Look up the corresponding operation context */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000448 status = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
449 operation,
450 (void **)&ctx);
451 if (status != PSA_SUCCESS) {
452 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100453 }
454
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000455 return tfm_crypto_cipher_release(operation, ctx);
Antonio de Angelis8908f472018-08-31 15:44:25 +0100456}
457/*!@}*/