blob: aa61025c3d16f117ecf27a8db581eca06e246f0e [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
Jamie Fox0e54ebc2019-04-09 14:21:04 +01008#include <stddef.h>
9#include <stdint.h>
Antonio de Angelis8908f472018-08-31 15:44:25 +010010
Antonio de Angelis4743e672019-04-11 11:38:48 +010011/* FixMe: Use PSA_CONNECTION_REFUSED when performing parameter
12 * integrity checks but this will have to be revised
13 * when the full set of error codes mandated by PSA FF
14 * is available.
15 */
Jamie Fox0e54ebc2019-04-09 14:21:04 +010016#include "tfm_mbedcrypto_include.h"
Antonio de Angelis4743e672019-04-11 11:38:48 +010017
Jamie Fox0e54ebc2019-04-09 14:21:04 +010018#include "tfm_crypto_api.h"
19#include "tfm_crypto_defs.h"
Antonio de Angelis8908f472018-08-31 15:44:25 +010020
21/*!
22 * \defgroup public_psa Public functions, PSA
23 *
24 */
25
26/*!@{*/
Antonio de Angelis25e2b2d2019-04-25 14:49:50 +010027psa_status_t tfm_crypto_cipher_generate_iv(psa_invec in_vec[],
28 size_t in_len,
29 psa_outvec out_vec[],
30 size_t out_len)
31{
32 psa_status_t status = PSA_SUCCESS;
33 psa_cipher_operation_t *operation = NULL;
34
35 if ((in_len != 1) || (out_len != 2)) {
36 return PSA_CONNECTION_REFUSED;
37 }
38
39 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
40 (out_vec[0].len != sizeof(uint32_t))) {
41 return PSA_CONNECTION_REFUSED;
42 }
43
44 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
45 uint32_t handle = iov->op_handle;
46 uint32_t *handle_out = out_vec[0].base;
47 unsigned char *iv = out_vec[1].base;
48 size_t iv_size = out_vec[1].len;
49
50 /* Init the handle in the operation with the one passed from the iov */
51 *handle_out = iov->op_handle;
52
53 /* Look up the corresponding operation context */
54 status = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
55 handle,
56 (void **)&operation);
57 if (status != PSA_SUCCESS) {
58 return status;
59 }
60
61 *handle_out = handle;
62
63 status = psa_cipher_generate_iv(operation, iv, iv_size, &out_vec[1].len);
64 if (status != PSA_SUCCESS) {
65 /* Release the operation context, ignore if the operation fails. */
66 (void)tfm_crypto_operation_release(handle_out);
67 return status;
68 }
69
70 return status;
71}
72
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000073psa_status_t tfm_crypto_cipher_set_iv(psa_invec in_vec[],
74 size_t in_len,
75 psa_outvec out_vec[],
76 size_t out_len)
Antonio de Angelis8908f472018-08-31 15:44:25 +010077{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010078 psa_status_t status = PSA_SUCCESS;
Jamie Fox0e54ebc2019-04-09 14:21:04 +010079 psa_cipher_operation_t *operation = NULL;
Antonio de Angelis8908f472018-08-31 15:44:25 +010080
Antonio de Angelis4743e672019-04-11 11:38:48 +010081 if ((in_len != 2) || (out_len != 1)) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000082 return PSA_CONNECTION_REFUSED;
Antonio de Angelis8908f472018-08-31 15:44:25 +010083 }
84
Antonio de Angelis4743e672019-04-11 11:38:48 +010085 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
Jamie Fox0e54ebc2019-04-09 14:21:04 +010086 (out_vec[0].len != sizeof(uint32_t))) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000087 return PSA_CONNECTION_REFUSED;
88 }
Antonio de Angelis4743e672019-04-11 11:38:48 +010089 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
Jamie Fox0e54ebc2019-04-09 14:21:04 +010090 uint32_t handle = iov->op_handle;
Antonio de Angelis4743e672019-04-11 11:38:48 +010091 uint32_t *handle_out = out_vec[0].base;
92 const unsigned char *iv = in_vec[1].base;
93 size_t iv_length = in_vec[1].len;
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000094
Antonio de Angelis4743e672019-04-11 11:38:48 +010095 /* Init the handle in the operation with the one passed from the iov */
Jamie Fox0e54ebc2019-04-09 14:21:04 +010096 *handle_out = iov->op_handle;
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000097
Antonio de Angelis8908f472018-08-31 15:44:25 +010098 /* Look up the corresponding operation context */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000099 status = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
Antonio de Angelis4743e672019-04-11 11:38:48 +0100100 handle,
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100101 (void **)&operation);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000102 if (status != PSA_SUCCESS) {
103 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100104 }
105
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100106 status = psa_cipher_set_iv(operation, iv, iv_length);
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100107 if (status != PSA_SUCCESS) {
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100108 /* Release the operation context, ignore if the operation fails. */
109 (void)tfm_crypto_operation_release(handle_out);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000110 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100111 }
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100112
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000113 return status;
114}
Antonio de Angelis4743e672019-04-11 11:38:48 +0100115
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000116psa_status_t tfm_crypto_cipher_encrypt_setup(psa_invec in_vec[],
117 size_t in_len,
118 psa_outvec out_vec[],
119 size_t out_len)
120{
Antonio de Angelis4743e672019-04-11 11:38:48 +0100121 psa_status_t status = PSA_SUCCESS;
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100122 psa_cipher_operation_t *operation = NULL;
123
Antonio de Angelis4743e672019-04-11 11:38:48 +0100124 if ((in_len != 1) || (out_len != 1)) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000125 return PSA_CONNECTION_REFUSED;
126 }
127
Antonio de Angelis4743e672019-04-11 11:38:48 +0100128 if ((out_vec[0].len != sizeof(uint32_t)) ||
129 (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000130 return PSA_CONNECTION_REFUSED;
131 }
Antonio de Angelis4743e672019-04-11 11:38:48 +0100132 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100133 uint32_t handle = iov->op_handle;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100134 uint32_t *handle_out = out_vec[0].base;
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100135 psa_key_handle_t key_handle = iov->key_handle;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100136 psa_algorithm_t alg = iov->alg;
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000137
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100138 /* Allocate the operation context in the secure world */
139 status = tfm_crypto_operation_alloc(TFM_CRYPTO_CIPHER_OPERATION,
140 &handle,
141 (void **)&operation);
142 if (status != PSA_SUCCESS) {
143 return status;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100144 }
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100145
146 *handle_out = handle;
147
148 status = psa_cipher_encrypt_setup(operation, key_handle, alg);
149 if (status != PSA_SUCCESS) {
150 /* Release the operation context, ignore if the operation fails. */
151 (void)tfm_crypto_operation_release(handle_out);
152 return status;
153 }
154
Antonio de Angelis4743e672019-04-11 11:38:48 +0100155 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100156}
157
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000158psa_status_t tfm_crypto_cipher_decrypt_setup(psa_invec in_vec[],
159 size_t in_len,
160 psa_outvec out_vec[],
161 size_t out_len)
Antonio de Angelis8908f472018-08-31 15:44:25 +0100162{
Antonio de Angelis4743e672019-04-11 11:38:48 +0100163 psa_status_t status = PSA_SUCCESS;
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100164 psa_cipher_operation_t *operation = NULL;
165
Antonio de Angelis4743e672019-04-11 11:38:48 +0100166 if ((in_len != 1) || (out_len != 1)) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000167 return PSA_CONNECTION_REFUSED;
168 }
169
Antonio de Angelis4743e672019-04-11 11:38:48 +0100170 if ((out_vec[0].len != sizeof(uint32_t)) ||
171 (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000172 return PSA_CONNECTION_REFUSED;
173 }
Antonio de Angelis4743e672019-04-11 11:38:48 +0100174 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100175 uint32_t handle = iov->op_handle;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100176 uint32_t *handle_out = out_vec[0].base;
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100177 psa_key_handle_t key_handle = iov->key_handle;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100178 psa_algorithm_t alg = iov->alg;
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000179
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100180 /* Allocate the operation context in the secure world */
181 status = tfm_crypto_operation_alloc(TFM_CRYPTO_CIPHER_OPERATION,
182 &handle,
183 (void **)&operation);
184 if (status != PSA_SUCCESS) {
185 return status;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100186 }
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100187
188 *handle_out = handle;
189
190 status = psa_cipher_decrypt_setup(operation, key_handle, alg);
191 if (status != PSA_SUCCESS) {
192 /* Release the operation context, ignore if the operation fails. */
193 (void)tfm_crypto_operation_release(handle_out);
194 return status;
195 }
196
Antonio de Angelis4743e672019-04-11 11:38:48 +0100197 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100198}
199
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000200psa_status_t tfm_crypto_cipher_update(psa_invec in_vec[],
201 size_t in_len,
202 psa_outvec out_vec[],
203 size_t out_len)
Antonio de Angelis8908f472018-08-31 15:44:25 +0100204{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100205 psa_status_t status = PSA_SUCCESS;
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100206 psa_cipher_operation_t *operation = NULL;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100207
Antonio de Angelis4743e672019-04-11 11:38:48 +0100208 if ((in_len != 2) || (out_len != 2)) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000209 return PSA_CONNECTION_REFUSED;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100210 }
211
Antonio de Angelis4743e672019-04-11 11:38:48 +0100212 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
213 (out_vec[0].len != sizeof(uint32_t))) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000214 return PSA_CONNECTION_REFUSED;
215 }
Antonio de Angelis4743e672019-04-11 11:38:48 +0100216 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100217 uint32_t handle = iov->op_handle;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100218 uint32_t *handle_out = out_vec[0].base;
219 const uint8_t *input = in_vec[1].base;
220 size_t input_length = in_vec[1].len;
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000221 unsigned char *output = out_vec[1].base;
222 size_t output_size = out_vec[1].len;
223
Antonio de Angelis4743e672019-04-11 11:38:48 +0100224 /* Init the handle in the operation with the one passed from the iov */
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100225 *handle_out = iov->op_handle;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100226
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000227 /* Initialise the output_length to zero */
228 out_vec[1].len = 0;
Jamie Fox82b87ca2018-12-11 16:41:11 +0000229
Antonio de Angelis8908f472018-08-31 15:44:25 +0100230 /* Look up the corresponding operation context */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000231 status = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
Antonio de Angelis4743e672019-04-11 11:38:48 +0100232 handle,
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100233 (void **)&operation);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000234 if (status != PSA_SUCCESS) {
235 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100236 }
237
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100238 status = psa_cipher_update(operation, input, input_length,
239 output, output_size, &out_vec[1].len);
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100240 if (status != PSA_SUCCESS) {
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100241 /* Release the operation context, ignore if the operation fails. */
242 (void)tfm_crypto_operation_release(handle_out);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000243 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100244 }
245
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100246 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100247}
248
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000249psa_status_t tfm_crypto_cipher_finish(psa_invec in_vec[],
250 size_t in_len,
251 psa_outvec out_vec[],
252 size_t out_len)
Antonio de Angelis8908f472018-08-31 15:44:25 +0100253{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100254 psa_status_t status = PSA_SUCCESS;
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100255 psa_cipher_operation_t *operation = NULL;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100256
Antonio de Angelis4743e672019-04-11 11:38:48 +0100257 if ((in_len != 1) || (out_len != 2)) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000258 return PSA_CONNECTION_REFUSED;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100259 }
260
Antonio de Angelis4743e672019-04-11 11:38:48 +0100261 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
262 (out_vec[0].len != sizeof(uint32_t))) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000263 return PSA_CONNECTION_REFUSED;
264 }
Antonio de Angelis4743e672019-04-11 11:38:48 +0100265 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100266 uint32_t handle = iov->op_handle;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100267 uint32_t *handle_out = out_vec[0].base;
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000268 unsigned char *output = out_vec[1].base;
269 size_t output_size = out_vec[1].len;
270
Antonio de Angelis4743e672019-04-11 11:38:48 +0100271 /* Init the handle in the operation with the one passed from the iov */
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100272 *handle_out = iov->op_handle;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100273
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000274 /* Initialise the output_length to zero */
275 out_vec[1].len = 0;
276
Antonio de Angelis8908f472018-08-31 15:44:25 +0100277 /* Look up the corresponding operation context */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000278 status = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
Antonio de Angelis4743e672019-04-11 11:38:48 +0100279 handle,
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100280 (void **)&operation);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000281 if (status != PSA_SUCCESS) {
282 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100283 }
284
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100285 status = psa_cipher_finish(operation, output, output_size, &out_vec[1].len);
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100286 if (status != PSA_SUCCESS) {
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100287 /* Release the operation context, ignore if the operation fails. */
288 (void)tfm_crypto_operation_release(handle_out);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000289 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100290 }
291
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100292 status = tfm_crypto_operation_release(handle_out);
293
Antonio de Angelis4743e672019-04-11 11:38:48 +0100294 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100295}
296
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000297psa_status_t tfm_crypto_cipher_abort(psa_invec in_vec[],
298 size_t in_len,
299 psa_outvec out_vec[],
300 size_t out_len)
Antonio de Angelis8908f472018-08-31 15:44:25 +0100301{
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000302 psa_status_t status = PSA_SUCCESS;
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100303 psa_cipher_operation_t *operation = NULL;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100304
Antonio de Angelis4743e672019-04-11 11:38:48 +0100305 if ((in_len != 1) || (out_len != 1)) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000306 return PSA_CONNECTION_REFUSED;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100307 }
308
Antonio de Angelis4743e672019-04-11 11:38:48 +0100309 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
310 (out_vec[0].len != sizeof(uint32_t))) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000311 return PSA_CONNECTION_REFUSED;
312 }
Antonio de Angelis4743e672019-04-11 11:38:48 +0100313 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100314 uint32_t handle = iov->op_handle;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100315 uint32_t *handle_out = out_vec[0].base;
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000316
Antonio de Angelis4743e672019-04-11 11:38:48 +0100317 /* Init the handle in the operation with the one passed from the iov */
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100318 *handle_out = iov->op_handle;
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000319
Antonio de Angelis8908f472018-08-31 15:44:25 +0100320 /* Look up the corresponding operation context */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000321 status = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
Antonio de Angelis4743e672019-04-11 11:38:48 +0100322 handle,
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100323 (void **)&operation);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000324 if (status != PSA_SUCCESS) {
Antonio de Angelis25e2b2d2019-04-25 14:49:50 +0100325 /* Operation does not exist, so abort has no effect */
326 return PSA_SUCCESS;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100327 }
328
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100329 status = psa_cipher_abort(operation);
330
331 if (status != PSA_SUCCESS) {
332 /* Release the operation context, ignore if the operation fails. */
333 (void)tfm_crypto_operation_release(handle_out);
334 return status;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100335 }
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100336
337 status = tfm_crypto_operation_release(handle_out);
338
Antonio de Angelis4743e672019-04-11 11:38:48 +0100339 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100340}
341/*!@}*/