blob: 757ccc02734bf91a8743fec798eb22f4548cb7f2 [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
Antonio de Angelis4743e672019-04-11 11:38:48 +010012/* FixMe: Use PSA_CONNECTION_REFUSED when performing parameter
13 * integrity checks but this will have to be revised
14 * when the full set of error codes mandated by PSA FF
15 * is available.
16 */
17
Jamie Fox82b87ca2018-12-11 16:41:11 +000018/**
19 * \def CRYPTO_CIPHER_MAX_KEY_LENGTH
20 *
21 * \brief Specifies the maximum key length supported by the
22 * Cipher operations in this implementation
23 */
24#ifndef CRYPTO_CIPHER_MAX_KEY_LENGTH
25#define CRYPTO_CIPHER_MAX_KEY_LENGTH (32)
26#endif
27
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000028static psa_status_t _psa_get_key_information(psa_key_slot_t key,
29 psa_key_type_t *type,
30 size_t *bits)
31{
Antonio de Angelis4743e672019-04-11 11:38:48 +010032 psa_status_t status;
33 struct tfm_crypto_pack_iovec iov = {
34 .sfn_id = TFM_CRYPTO_GET_KEY_INFORMATION_SFID,
35 .key = key,
36 };
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000037 psa_invec in_vec[] = {
Antonio de Angelis4743e672019-04-11 11:38:48 +010038 {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000039 };
40 psa_outvec out_vec[] = {
41 {.base = type, .len = sizeof(psa_key_type_t)},
42 {.base = bits, .len = sizeof(size_t)}
43 };
44
Antonio de Angelis4743e672019-04-11 11:38:48 +010045 status = tfm_crypto_get_key_information(
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000046 in_vec, sizeof(in_vec)/sizeof(in_vec[0]),
47 out_vec, sizeof(out_vec)/sizeof(out_vec[0]));
Antonio de Angelis4743e672019-04-11 11:38:48 +010048
49 return status;
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000050}
51
Jamie Fox0ff04ba2019-02-05 14:19:07 +000052/**
53 * \brief Release all resources associated with a cipher operation.
54 *
55 * \param[in] operation Frontend cipher operation context
56 * \param[in] ctx Backend cipher operation context
57 *
58 * \return Return values as described in \ref tfm_crypto_err_t
59 */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000060static psa_status_t tfm_crypto_cipher_release(
Antonio de Angelis4743e672019-04-11 11:38:48 +010061 uint32_t *handle,
Jamie Fox0ff04ba2019-02-05 14:19:07 +000062 struct tfm_cipher_operation_s *ctx)
63{
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000064 psa_status_t status = PSA_SUCCESS;
Jamie Fox0ff04ba2019-02-05 14:19:07 +000065
66 /* Release resources in the engine */
67 status = tfm_crypto_engine_cipher_release(&(ctx->engine_ctx));
68 if (status != PSA_SUCCESS) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000069 return status;
Jamie Fox0ff04ba2019-02-05 14:19:07 +000070 }
71
72 /* Release the operation context */
Antonio de Angelis4743e672019-04-11 11:38:48 +010073 return tfm_crypto_operation_release(handle);
Jamie Fox0ff04ba2019-02-05 14:19:07 +000074}
75
Antonio de Angelis4743e672019-04-11 11:38:48 +010076static psa_status_t tfm_crypto_cipher_setup(uint32_t *handle,
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000077 psa_key_slot_t key,
78 psa_algorithm_t alg,
79 enum engine_cipher_mode_t c_mode)
Antonio de Angelis8908f472018-08-31 15:44:25 +010080{
Jamie Fox82b87ca2018-12-11 16:41:11 +000081 uint8_t key_data[CRYPTO_CIPHER_MAX_KEY_LENGTH];
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010082 size_t key_size;
83 psa_key_type_t key_type = PSA_KEY_TYPE_NONE;
84 psa_status_t status = PSA_SUCCESS;
Antonio de Angelis377a1552018-11-22 17:02:40 +000085 struct tfm_cipher_operation_s *ctx = NULL;
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010086 struct cipher_engine_info engine_info;
Jamie Foxefd82732018-11-26 10:34:32 +000087 psa_key_usage_t usage;
Antonio de Angelis8908f472018-08-31 15:44:25 +010088
Antonio de Angelis8908f472018-08-31 15:44:25 +010089 if (!PSA_ALG_IS_CIPHER(alg)) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000090 return PSA_ERROR_INVALID_ARGUMENT;
Antonio de Angelis8908f472018-08-31 15:44:25 +010091 }
92
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010093 /* Access the key module to retrieve key related information */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000094 status = _psa_get_key_information(key, &key_type, &key_size);
95 if (status != PSA_SUCCESS) {
96 return status;
Jamie Fox82b87ca2018-12-11 16:41:11 +000097 }
98
99 /* Check if it's a raw data key type */
100 if (key_type == PSA_KEY_TYPE_RAW_DATA) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000101 return PSA_ERROR_NOT_PERMITTED;
Jamie Fox82b87ca2018-12-11 16:41:11 +0000102 }
103
104 /* Check compatibility between key and algorithm */
105 if ((key_type == PSA_KEY_TYPE_ARC4) && (alg != PSA_ALG_ARC4)) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000106 return PSA_ERROR_INVALID_ARGUMENT;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100107 }
108
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100109 /* Setup the algorithm on the crypto engine */
110 status = tfm_crypto_engine_cipher_setup(alg,
111 (const psa_key_type_t)key_type,
112 (const uint32_t)key_size,
113 c_mode,
114 &engine_info);
115 if (status != PSA_SUCCESS) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000116 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100117 }
118
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100119 /* Allocate the operation context in the secure world */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000120 status = tfm_crypto_operation_alloc(TFM_CRYPTO_CIPHER_OPERATION,
Antonio de Angelis4743e672019-04-11 11:38:48 +0100121 handle,
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000122 (void **)&ctx);
123 if (status != PSA_SUCCESS) {
124 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100125 }
126
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100127 /* Set the proper cipher mode (encrypt/decrypt) in the operation context */
128 ctx->cipher_mode = (uint8_t) c_mode;
129
Antonio de Angelis8908f472018-08-31 15:44:25 +0100130 /* Bind the algorithm to the cipher operation */
Antonio de Angelis377a1552018-11-22 17:02:40 +0000131 ctx->alg = alg;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100132
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100133 /* Start the crypto engine */
134 status = tfm_crypto_engine_cipher_start(&(ctx->engine_ctx), &engine_info);
135 if (status != PSA_SUCCESS) {
Hugues de Valon8b442442019-02-19 14:30:52 +0000136 /* Release the operation context, ignore if this operation fails. */
Antonio de Angelis4743e672019-04-11 11:38:48 +0100137 (void)tfm_crypto_cipher_release(handle, ctx);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000138 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100139 }
140
Jamie Foxefd82732018-11-26 10:34:32 +0000141 /* Set the key usage based on the cipher mode */
142 usage = (c_mode == ENGINE_CIPHER_MODE_DECRYPT) ? PSA_KEY_USAGE_DECRYPT
143 : PSA_KEY_USAGE_ENCRYPT;
144
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100145 /* Access the crypto service key module to retrieve key data */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000146 status = tfm_crypto_get_key(key,
147 usage,
148 alg,
149 key_data,
150 CRYPTO_CIPHER_MAX_KEY_LENGTH,
151 &key_size);
152 if (status != PSA_SUCCESS) {
Hugues de Valon8b442442019-02-19 14:30:52 +0000153 /* Release the operation context, ignore if this operation fails. */
Antonio de Angelis4743e672019-04-11 11:38:48 +0100154 (void)tfm_crypto_cipher_release(handle, ctx);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000155 return status;
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100156 }
157
158 /* Set the key on the engine */
159 status = tfm_crypto_engine_cipher_set_key(&(ctx->engine_ctx),
160 key_data,
161 key_size,
162 &engine_info);
163 if (status != PSA_SUCCESS) {
Hugues de Valon8b442442019-02-19 14:30:52 +0000164 /* Release the operation context, ignore if this operation fails. */
Antonio de Angelis4743e672019-04-11 11:38:48 +0100165 (void)tfm_crypto_cipher_release(handle, ctx);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000166 return status;
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100167 }
Antonio de Angelis8908f472018-08-31 15:44:25 +0100168
169 /* Bind the key to the cipher operation */
Antonio de Angelis377a1552018-11-22 17:02:40 +0000170 ctx->key = key;
171 ctx->key_set = 1;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100172
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100173 /* Set padding mode on engine in case of CBC */
Antonio de Angelis8908f472018-08-31 15:44:25 +0100174 if ((alg & ~PSA_ALG_BLOCK_CIPHER_PADDING_MASK) == PSA_ALG_CBC_BASE) {
175
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100176 status = tfm_crypto_engine_cipher_set_padding_mode(&(ctx->engine_ctx),
177 &engine_info);
178 if (status != PSA_SUCCESS) {
Hugues de Valon8b442442019-02-19 14:30:52 +0000179 /* Release the operation context, ignore if this operation fails. */
Antonio de Angelis4743e672019-04-11 11:38:48 +0100180 (void)tfm_crypto_cipher_release(handle, ctx);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000181 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100182 }
183 }
184
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100185 /* FIXME: Check based on the algorithm, if we need to have an IV */
186 ctx->iv_required = 1;
187 ctx->block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE(key_type);
188
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000189 return PSA_SUCCESS;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100190}
191
192/*!
193 * \defgroup public_psa Public functions, PSA
194 *
195 */
196
197/*!@{*/
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000198psa_status_t tfm_crypto_cipher_set_iv(psa_invec in_vec[],
199 size_t in_len,
200 psa_outvec out_vec[],
201 size_t out_len)
Antonio de Angelis8908f472018-08-31 15:44:25 +0100202{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100203 psa_status_t status = PSA_SUCCESS;
Antonio de Angelis377a1552018-11-22 17:02:40 +0000204 struct tfm_cipher_operation_s *ctx = NULL;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100205
Antonio de Angelis4743e672019-04-11 11:38:48 +0100206 if ((in_len != 2) || (out_len != 1)) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000207 return PSA_CONNECTION_REFUSED;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100208 }
209
Antonio de Angelis4743e672019-04-11 11:38:48 +0100210 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
211 (out_vec[0].len != sizeof(uint32_t))) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000212 return PSA_CONNECTION_REFUSED;
213 }
Antonio de Angelis4743e672019-04-11 11:38:48 +0100214 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
215 uint32_t handle = iov->handle;
216 uint32_t *handle_out = out_vec[0].base;
217 const unsigned char *iv = in_vec[1].base;
218 size_t iv_length = in_vec[1].len;
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000219
Antonio de Angelis4743e672019-04-11 11:38:48 +0100220 /* Init the handle in the operation with the one passed from the iov */
221 *handle_out = iov->handle;
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000222
Antonio de Angelis8908f472018-08-31 15:44:25 +0100223 /* Look up the corresponding operation context */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000224 status = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
Antonio de Angelis4743e672019-04-11 11:38:48 +0100225 handle,
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000226 (void **)&ctx);
227 if (status != PSA_SUCCESS) {
228 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100229 }
230
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100231 if ((iv_length != ctx->block_size) || (iv_length > TFM_CIPHER_IV_MAX_SIZE)){
Antonio de Angelis4743e672019-04-11 11:38:48 +0100232 if (tfm_crypto_cipher_release(&handle, ctx) == PSA_SUCCESS) {
233 *handle_out = handle;
234 }
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000235 return PSA_ERROR_INVALID_ARGUMENT;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100236 }
237
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100238 if ((ctx->iv_set == 1) || (ctx->iv_required == 0)) {
Antonio de Angelis4743e672019-04-11 11:38:48 +0100239 if (tfm_crypto_cipher_release(&handle, ctx) == PSA_SUCCESS) {
240 *handle_out = handle;
241 }
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000242 return PSA_ERROR_BAD_STATE;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100243 }
244
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100245 /* Set the IV on the crypto engine */
246 status = tfm_crypto_engine_cipher_set_iv(&(ctx->engine_ctx),
247 iv,
248 iv_length);
249 if (status != PSA_SUCCESS) {
Antonio de Angelis4743e672019-04-11 11:38:48 +0100250 if (tfm_crypto_cipher_release(&handle, ctx) == PSA_SUCCESS) {
251 *handle_out = handle;
252 }
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000253 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100254 }
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100255
Antonio de Angelis377a1552018-11-22 17:02:40 +0000256 ctx->iv_set = 1;
257 ctx->iv_size = iv_length;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100258
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000259 return PSA_SUCCESS;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100260}
261
Antonio de Angelis4743e672019-04-11 11:38:48 +0100262static psa_status_t _psa_cipher_set_iv(uint32_t *handle,
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000263 const unsigned char *iv,
264 size_t iv_length)
Antonio de Angelis8908f472018-08-31 15:44:25 +0100265{
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000266 psa_status_t status;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100267 struct tfm_crypto_pack_iovec iov = {
268 .sfn_id = TFM_CRYPTO_CIPHER_SET_IV_SFID,
269 .handle = *handle,
270 };
271
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000272 psa_invec in_vec[] = {
Antonio de Angelis4743e672019-04-11 11:38:48 +0100273 {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000274 {.base = iv, .len = iv_length},
275 };
276 psa_outvec out_vec[] = {
Antonio de Angelis4743e672019-04-11 11:38:48 +0100277 {.base = handle, .len = sizeof(uint32_t)},
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000278 };
279
280 status = tfm_crypto_cipher_set_iv(in_vec, sizeof(in_vec)/sizeof(in_vec[0]),
281 out_vec, sizeof(out_vec)/sizeof(out_vec[0]));
282 return status;
283}
Antonio de Angelis4743e672019-04-11 11:38:48 +0100284
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000285psa_status_t tfm_crypto_cipher_encrypt_setup(psa_invec in_vec[],
286 size_t in_len,
287 psa_outvec out_vec[],
288 size_t out_len)
289{
Antonio de Angelis4743e672019-04-11 11:38:48 +0100290 psa_status_t status = PSA_SUCCESS;
291 if ((in_len != 1) || (out_len != 1)) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000292 return PSA_CONNECTION_REFUSED;
293 }
294
Antonio de Angelis4743e672019-04-11 11:38:48 +0100295 if ((out_vec[0].len != sizeof(uint32_t)) ||
296 (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000297 return PSA_CONNECTION_REFUSED;
298 }
Antonio de Angelis4743e672019-04-11 11:38:48 +0100299 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
300 uint32_t handle = iov->handle;
301 uint32_t *handle_out = out_vec[0].base;
302 psa_key_slot_t key = iov->key;
303 psa_algorithm_t alg = iov->alg;
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000304
Antonio de Angelis4743e672019-04-11 11:38:48 +0100305 status = tfm_crypto_cipher_setup(&handle,
306 key,
307 alg,
308 ENGINE_CIPHER_MODE_ENCRYPT);
309 if (status == PSA_SUCCESS) {
310 *handle_out = handle;
311 } else {
312 *handle_out = iov->handle;
313 }
314 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100315}
316
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000317psa_status_t tfm_crypto_cipher_decrypt_setup(psa_invec in_vec[],
318 size_t in_len,
319 psa_outvec out_vec[],
320 size_t out_len)
Antonio de Angelis8908f472018-08-31 15:44:25 +0100321{
Antonio de Angelis4743e672019-04-11 11:38:48 +0100322 psa_status_t status = PSA_SUCCESS;
323 if ((in_len != 1) || (out_len != 1)) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000324 return PSA_CONNECTION_REFUSED;
325 }
326
Antonio de Angelis4743e672019-04-11 11:38:48 +0100327 if ((out_vec[0].len != sizeof(uint32_t)) ||
328 (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000329 return PSA_CONNECTION_REFUSED;
330 }
Antonio de Angelis4743e672019-04-11 11:38:48 +0100331 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
332 uint32_t handle = iov->handle;
333 uint32_t *handle_out = out_vec[0].base;
334 psa_key_slot_t key = iov->key;
335 psa_algorithm_t alg = iov->alg;
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000336
Antonio de Angelis4743e672019-04-11 11:38:48 +0100337 status = tfm_crypto_cipher_setup(&handle,
338 key,
339 alg,
340 ENGINE_CIPHER_MODE_DECRYPT);
341 if (status == PSA_SUCCESS) {
342 *handle_out = handle;
343 }
344 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100345}
346
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000347psa_status_t tfm_crypto_cipher_update(psa_invec in_vec[],
348 size_t in_len,
349 psa_outvec out_vec[],
350 size_t out_len)
Antonio de Angelis8908f472018-08-31 15:44:25 +0100351{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100352 psa_status_t status = PSA_SUCCESS;
Antonio de Angelis377a1552018-11-22 17:02:40 +0000353 struct tfm_cipher_operation_s *ctx = NULL;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100354
Antonio de Angelis4743e672019-04-11 11:38:48 +0100355 if ((in_len != 2) || (out_len != 2)) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000356 return PSA_CONNECTION_REFUSED;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100357 }
358
Antonio de Angelis4743e672019-04-11 11:38:48 +0100359 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
360 (out_vec[0].len != sizeof(uint32_t))) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000361 return PSA_CONNECTION_REFUSED;
362 }
Antonio de Angelis4743e672019-04-11 11:38:48 +0100363 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
364 uint32_t handle = iov->handle;
365 uint32_t *handle_out = out_vec[0].base;
366 const uint8_t *input = in_vec[1].base;
367 size_t input_length = in_vec[1].len;
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000368 unsigned char *output = out_vec[1].base;
369 size_t output_size = out_vec[1].len;
370
Antonio de Angelis4743e672019-04-11 11:38:48 +0100371 /* Init the handle in the operation with the one passed from the iov */
372 *handle_out = iov->handle;
373
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000374 /* Initialise the output_length to zero */
375 out_vec[1].len = 0;
Jamie Fox82b87ca2018-12-11 16:41:11 +0000376
Antonio de Angelis8908f472018-08-31 15:44:25 +0100377 /* Look up the corresponding operation context */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000378 status = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
Antonio de Angelis4743e672019-04-11 11:38:48 +0100379 handle,
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000380 (void **)&ctx);
381 if (status != PSA_SUCCESS) {
382 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100383 }
384
385 /* If the IV is required and it's not been set yet */
Antonio de Angelis377a1552018-11-22 17:02:40 +0000386 if ((ctx->iv_required == 1) && (ctx->iv_set == 0)) {
Antonio de Angelis8908f472018-08-31 15:44:25 +0100387
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100388 if (ctx->cipher_mode != ENGINE_CIPHER_MODE_DECRYPT) {
Antonio de Angelis4743e672019-04-11 11:38:48 +0100389 if (tfm_crypto_cipher_release(&handle, ctx) == PSA_SUCCESS) {
390 *handle_out = handle;
391 }
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000392 return PSA_ERROR_BAD_STATE;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100393 }
394
395 /* This call is used to set the IV on the object */
Antonio de Angelis4743e672019-04-11 11:38:48 +0100396 return _psa_cipher_set_iv(handle_out, input, input_length);
Antonio de Angelis8908f472018-08-31 15:44:25 +0100397 }
398
399 /* If the key is not set, setup phase has not been completed */
Antonio de Angelis377a1552018-11-22 17:02:40 +0000400 if (ctx->key_set == 0) {
Antonio de Angelis4743e672019-04-11 11:38:48 +0100401 if (tfm_crypto_cipher_release(&handle, ctx) == PSA_SUCCESS) {
402 *handle_out = handle;
403 }
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000404 return PSA_ERROR_BAD_STATE;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100405 }
406
Jamie Fox82b87ca2018-12-11 16:41:11 +0000407 /* FIXME: The implementation currently expects to work only on blocks
408 * of input data whose length is equal to the block size
409 */
410 if (input_length > output_size) {
Antonio de Angelis4743e672019-04-11 11:38:48 +0100411 if (tfm_crypto_cipher_release(&handle, ctx) == PSA_SUCCESS) {
412 *handle_out = handle;
413 }
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000414 return PSA_ERROR_BUFFER_TOO_SMALL;
Jamie Fox82b87ca2018-12-11 16:41:11 +0000415 }
416
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100417 /* Update the cipher output with the input chunk on the engine */
418 status = tfm_crypto_engine_cipher_update(&(ctx->engine_ctx),
419 input,
420 input_length,
421 output,
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000422 (uint32_t *)&(out_vec[1].len));
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100423 if (status != PSA_SUCCESS) {
Antonio de Angelis4743e672019-04-11 11:38:48 +0100424 if (tfm_crypto_cipher_release(&handle, ctx) == PSA_SUCCESS) {
425 *handle_out = handle;
426 }
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000427 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100428 }
429
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000430 return PSA_SUCCESS;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100431}
432
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000433psa_status_t tfm_crypto_cipher_finish(psa_invec in_vec[],
434 size_t in_len,
435 psa_outvec out_vec[],
436 size_t out_len)
Antonio de Angelis8908f472018-08-31 15:44:25 +0100437{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100438 psa_status_t status = PSA_SUCCESS;
Antonio de Angelis377a1552018-11-22 17:02:40 +0000439 struct tfm_cipher_operation_s *ctx = NULL;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100440
Antonio de Angelis4743e672019-04-11 11:38:48 +0100441 if ((in_len != 1) || (out_len != 2)) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000442 return PSA_CONNECTION_REFUSED;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100443 }
444
Antonio de Angelis4743e672019-04-11 11:38:48 +0100445 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
446 (out_vec[0].len != sizeof(uint32_t))) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000447 return PSA_CONNECTION_REFUSED;
448 }
Antonio de Angelis4743e672019-04-11 11:38:48 +0100449 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
450 uint32_t handle = iov->handle;
451 uint32_t *handle_out = out_vec[0].base;
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000452 unsigned char *output = out_vec[1].base;
453 size_t output_size = out_vec[1].len;
454
Antonio de Angelis4743e672019-04-11 11:38:48 +0100455 /* Init the handle in the operation with the one passed from the iov */
456 *handle_out = iov->handle;
457
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000458 /* Initialise the output_length to zero */
459 out_vec[1].len = 0;
460
Antonio de Angelis8908f472018-08-31 15:44:25 +0100461 /* Look up the corresponding operation context */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000462 status = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
Antonio de Angelis4743e672019-04-11 11:38:48 +0100463 handle,
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000464 (void **)&ctx);
465 if (status != PSA_SUCCESS) {
466 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100467 }
468
Jamie Fox82b87ca2018-12-11 16:41:11 +0000469 /* Check that the output buffer is large enough for up to one block size of
470 * output data.
471 */
472 if (output_size < ctx->block_size) {
Antonio de Angelis4743e672019-04-11 11:38:48 +0100473 if (tfm_crypto_cipher_release(&handle, ctx) == PSA_SUCCESS) {
474 *handle_out = handle;
475 }
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000476 return PSA_ERROR_BUFFER_TOO_SMALL;
Jamie Fox82b87ca2018-12-11 16:41:11 +0000477 }
478
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100479 /* Finalise the operation on the crypto engine */
480 status = tfm_crypto_engine_cipher_finish(&(ctx->engine_ctx),
481 output,
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000482 (uint32_t *)&(out_vec[1].len));
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100483 if (status != PSA_SUCCESS) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000484 out_vec[1].len = 0;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100485 if (tfm_crypto_cipher_release(&handle, ctx) == PSA_SUCCESS) {
486 *handle_out = handle;
487 }
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000488 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100489 }
490
Antonio de Angelis4743e672019-04-11 11:38:48 +0100491 status = tfm_crypto_cipher_release(&handle, ctx);
492 if (status == PSA_SUCCESS) {
493 *handle_out = handle;
494 }
495 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100496}
497
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000498psa_status_t tfm_crypto_cipher_abort(psa_invec in_vec[],
499 size_t in_len,
500 psa_outvec out_vec[],
501 size_t out_len)
Antonio de Angelis8908f472018-08-31 15:44:25 +0100502{
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000503 psa_status_t status = PSA_SUCCESS;
Antonio de Angelis377a1552018-11-22 17:02:40 +0000504 struct tfm_cipher_operation_s *ctx = NULL;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100505
Antonio de Angelis4743e672019-04-11 11:38:48 +0100506 if ((in_len != 1) || (out_len != 1)) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000507 return PSA_CONNECTION_REFUSED;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100508 }
509
Antonio de Angelis4743e672019-04-11 11:38:48 +0100510 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
511 (out_vec[0].len != sizeof(uint32_t))) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000512 return PSA_CONNECTION_REFUSED;
513 }
Antonio de Angelis4743e672019-04-11 11:38:48 +0100514 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
515 uint32_t handle = iov->handle;
516 uint32_t *handle_out = out_vec[0].base;
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000517
Antonio de Angelis4743e672019-04-11 11:38:48 +0100518 /* Init the handle in the operation with the one passed from the iov */
519 *handle_out = iov->handle;
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000520
Antonio de Angelis8908f472018-08-31 15:44:25 +0100521 /* Look up the corresponding operation context */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000522 status = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
Antonio de Angelis4743e672019-04-11 11:38:48 +0100523 handle,
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000524 (void **)&ctx);
525 if (status != PSA_SUCCESS) {
526 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100527 }
528
Antonio de Angelis4743e672019-04-11 11:38:48 +0100529 status = tfm_crypto_cipher_release(&handle, ctx);
530 if (status == PSA_SUCCESS) {
531 *handle_out = handle;
532 }
533 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100534}
535/*!@}*/