blob: 4926b28867c087d8fa42c9d81bc203551a65893f [file] [log] [blame]
Antonio de Angelis3a480992018-11-07 11:53:28 +00001/*
2 * Copyright (c) 2019, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8#include <limits.h>
9
Antonio de Angelis3a480992018-11-07 11:53:28 +000010#include "tfm_crypto_api.h"
Antonio de Angelis4743e672019-04-11 11:38:48 +010011#include "crypto_engine.h"
12#include "tfm_crypto_struct.h"
13
14/* FixMe: Use PSA_CONNECTION_REFUSED when performing parameter
15 * integrity checks but this will have to be revised
16 * when the full set of error codes mandated by PSA FF
17 * is available.
18 */
Antonio de Angelis3a480992018-11-07 11:53:28 +000019
Jamie Fox82b87ca2018-12-11 16:41:11 +000020/**
21 * \def CRYPTO_AEAD_MAX_KEY_LENGTH
22 *
23 * \brief Specifies the maximum key length supported by the
24 * AEAD operations in this implementation
25 */
26#ifndef CRYPTO_AEAD_MAX_KEY_LENGTH
27#define CRYPTO_AEAD_MAX_KEY_LENGTH (32)
28#endif
29
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000030static psa_status_t _psa_get_key_information(psa_key_slot_t key,
31 psa_key_type_t *type,
32 size_t *bits)
33{
Antonio de Angelis4743e672019-04-11 11:38:48 +010034 psa_status_t status;
35 struct tfm_crypto_pack_iovec iov = {
36 .sfn_id = TFM_CRYPTO_GET_KEY_INFORMATION_SFID,
37 .key = key,
38 };
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000039 psa_invec in_vec[] = {
Antonio de Angelis4743e672019-04-11 11:38:48 +010040 {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000041 };
42 psa_outvec out_vec[] = {
43 {.base = type, .len = sizeof(psa_key_type_t)},
44 {.base = bits, .len = sizeof(size_t)}
45 };
46
Antonio de Angelis4743e672019-04-11 11:38:48 +010047 status = tfm_crypto_get_key_information(
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000048 in_vec, sizeof(in_vec)/sizeof(in_vec[0]),
49 out_vec, sizeof(out_vec)/sizeof(out_vec[0]));
Antonio de Angelis4743e672019-04-11 11:38:48 +010050
51 return status;
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000052}
53
Antonio de Angelis3a480992018-11-07 11:53:28 +000054/*!
55 * \defgroup public_psa Public functions, PSA
56 *
57 */
58
59/*!@{*/
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000060psa_status_t tfm_crypto_aead_encrypt(psa_invec in_vec[],
61 size_t in_len,
62 psa_outvec out_vec[],
63 size_t out_len)
Antonio de Angelis3a480992018-11-07 11:53:28 +000064{
65 psa_status_t status = PSA_SUCCESS;
Jamie Fox82b87ca2018-12-11 16:41:11 +000066 uint8_t key_data[CRYPTO_AEAD_MAX_KEY_LENGTH];
Antonio de Angelis3a480992018-11-07 11:53:28 +000067 uint32_t key_size;
68 psa_key_type_t key_type;
69
Antonio de Angelis4743e672019-04-11 11:38:48 +010070 if ( !((in_len == 2) || (in_len == 3)) || (out_len != 1)) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000071 return PSA_CONNECTION_REFUSED;
72 }
73
Antonio de Angelis4743e672019-04-11 11:38:48 +010074 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000075 return PSA_CONNECTION_REFUSED;
76 }
Antonio de Angelis4743e672019-04-11 11:38:48 +010077 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
78 const struct tfm_crypto_aead_pack_input *aead_pack_input = &iov->aead_in;
79 psa_key_slot_t key = iov->key;
80 psa_algorithm_t alg = iov->alg;
81 const uint8_t *nonce = aead_pack_input->nonce;
82 size_t nonce_length = aead_pack_input->nonce_length;
83 const uint8_t *plaintext = in_vec[1].base;
84 size_t plaintext_length = in_vec[1].len;
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000085 uint8_t *ciphertext = out_vec[0].base;
86 size_t ciphertext_size = out_vec[0].len;
Antonio de Angelis4743e672019-04-11 11:38:48 +010087 const uint8_t *additional_data = NULL;
88 size_t additional_data_length = 0;
89
90 /* Check if additional data has been passed and initialise it */
91 if (in_len == 3) {
92 additional_data = in_vec[2].base;
93 additional_data_length = in_vec[2].len;
94 }
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000095
Jamie Fox82b87ca2018-12-11 16:41:11 +000096 /* Initialise ciphertext_length to zero */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000097 out_vec[0].len = 0;
Jamie Fox82b87ca2018-12-11 16:41:11 +000098
Antonio de Angelis3a480992018-11-07 11:53:28 +000099 if (PSA_ALG_IS_AEAD(alg) == 0) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000100 return PSA_ERROR_NOT_SUPPORTED;
Antonio de Angelis3a480992018-11-07 11:53:28 +0000101 }
102
103 if (PSA_AEAD_TAG_SIZE(alg) == 0) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000104 return PSA_ERROR_INVALID_ARGUMENT;
Antonio de Angelis3a480992018-11-07 11:53:28 +0000105 }
106
107 if (PSA_AEAD_ENCRYPT_OUTPUT_SIZE(alg, plaintext_length) > ciphertext_size) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000108 return PSA_ERROR_BUFFER_TOO_SMALL;
Antonio de Angelis3a480992018-11-07 11:53:28 +0000109 }
110
111 if ((nonce_length == 0) ||
112 ((additional_data_length == 0) && (additional_data != NULL))) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000113 return PSA_ERROR_INVALID_ARGUMENT;
Antonio de Angelis3a480992018-11-07 11:53:28 +0000114 }
115
116 /* Access the key data */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000117 status = _psa_get_key_information(key, &key_type, (size_t *)&key_size);
118 if (status != PSA_SUCCESS) {
119 return status;
Jamie Fox82b87ca2018-12-11 16:41:11 +0000120 }
121
122 /* Support only AES based AEAD */
123 if (key_type != PSA_KEY_TYPE_AES) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000124 return PSA_ERROR_NOT_SUPPORTED;
Antonio de Angelis3a480992018-11-07 11:53:28 +0000125 }
126
127 /* Access the crypto service key module to retrieve key data */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000128 status = tfm_crypto_get_key(key,
129 PSA_KEY_USAGE_ENCRYPT,
130 alg,
131 key_data,
132 CRYPTO_AEAD_MAX_KEY_LENGTH,
133 (size_t *)&key_size);
134 if (status != PSA_SUCCESS) {
135 return status;
Antonio de Angelis3a480992018-11-07 11:53:28 +0000136 }
137
138 /* Request AEAD encryption on the crypto engine */
139 status = tfm_crypto_engine_aead_encrypt(key_type,
140 alg,
141 key_data,
142 key_size,
143 nonce,
144 nonce_length,
145 additional_data,
146 additional_data_length,
147 plaintext,
148 plaintext_length,
149 ciphertext,
150 ciphertext_size,
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000151 (uint32_t *)&(out_vec[0].len));
Jamie Fox82b87ca2018-12-11 16:41:11 +0000152 if (status == PSA_SUCCESS) {
153 /* The ciphertext_length needs to take into account the tag length */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000154 out_vec[0].len += PSA_AEAD_TAG_SIZE(alg);
Jamie Fox82b87ca2018-12-11 16:41:11 +0000155 } else {
156 /* In case of failure set the ciphertext_length to zero */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000157 out_vec[0].len = 0;
Jamie Fox82b87ca2018-12-11 16:41:11 +0000158 }
Antonio de Angelis3a480992018-11-07 11:53:28 +0000159
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000160 return status;
Antonio de Angelis3a480992018-11-07 11:53:28 +0000161}
162
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000163psa_status_t tfm_crypto_aead_decrypt(psa_invec in_vec[],
164 size_t in_len,
165 psa_outvec out_vec[],
166 size_t out_len)
Antonio de Angelis3a480992018-11-07 11:53:28 +0000167{
168 psa_status_t status = PSA_SUCCESS;
Jamie Fox82b87ca2018-12-11 16:41:11 +0000169 uint8_t key_data[CRYPTO_AEAD_MAX_KEY_LENGTH];
Antonio de Angelis3a480992018-11-07 11:53:28 +0000170 uint32_t key_size;
171 psa_key_type_t key_type;
172
Antonio de Angelis4743e672019-04-11 11:38:48 +0100173 if ( !((in_len == 2) || (in_len == 3)) || (out_len != 1)) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000174 return PSA_CONNECTION_REFUSED;
175 }
176
Antonio de Angelis4743e672019-04-11 11:38:48 +0100177 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
178 return PSA_CONNECTION_REFUSED;
179 }
180 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
181 const struct tfm_crypto_aead_pack_input *aead_pack_input = &iov->aead_in;
182 psa_key_slot_t key = iov->key;
183 psa_algorithm_t alg = iov->alg;
184 const uint8_t *nonce = aead_pack_input->nonce;
185 size_t nonce_length = aead_pack_input->nonce_length;
186 const uint8_t *ciphertext = in_vec[1].base;
187 size_t ciphertext_length = in_vec[1].len;
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000188 uint8_t *plaintext = out_vec[0].base;
189 size_t plaintext_size = out_vec[0].len;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100190 const uint8_t *additional_data = NULL;
191 size_t additional_data_length = 0;
192
193 /* Check if additional data has been passed and initialise it */
194 if (in_len == 3) {
195 additional_data = in_vec[2].base;
196 additional_data_length = in_vec[2].len;
197 }
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000198
Jamie Fox82b87ca2018-12-11 16:41:11 +0000199 /* Initialise plaintext_length to zero */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000200 out_vec[0].len = 0;
Jamie Fox82b87ca2018-12-11 16:41:11 +0000201
Antonio de Angelis3a480992018-11-07 11:53:28 +0000202 if (PSA_ALG_IS_AEAD(alg) == 0) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000203 return PSA_ERROR_NOT_SUPPORTED;
Jamie Fox82b87ca2018-12-11 16:41:11 +0000204 }
205
206 if ((PSA_AEAD_TAG_SIZE(alg) == 0) ||
207 (ciphertext_length < PSA_AEAD_TAG_SIZE(alg))) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000208 return PSA_ERROR_INVALID_ARGUMENT;
Antonio de Angelis3a480992018-11-07 11:53:28 +0000209 }
210
Jamie Fox82b87ca2018-12-11 16:41:11 +0000211 if (PSA_AEAD_DECRYPT_OUTPUT_SIZE(alg,ciphertext_length) > plaintext_size) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000212 return PSA_ERROR_BUFFER_TOO_SMALL;
Antonio de Angelis3a480992018-11-07 11:53:28 +0000213 }
214
215 if ((nonce_length == 0) ||
216 ((additional_data_length == 0) && (additional_data != NULL))) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000217 return PSA_ERROR_INVALID_ARGUMENT;
Antonio de Angelis3a480992018-11-07 11:53:28 +0000218 }
219
220 /* Access the key data */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000221 status = _psa_get_key_information(key, &key_type, (size_t *)&key_size);
222 if (status != PSA_SUCCESS) {
223 return status;
Jamie Fox82b87ca2018-12-11 16:41:11 +0000224 }
225
226 /* Support only AES based AEAD */
227 if (key_type != PSA_KEY_TYPE_AES) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000228 return PSA_ERROR_NOT_SUPPORTED;
Antonio de Angelis3a480992018-11-07 11:53:28 +0000229 }
230
231 /* Access the crypto service key module to retrieve key data */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000232 status = tfm_crypto_get_key(key,
233 PSA_KEY_USAGE_DECRYPT,
234 alg,
235 key_data,
236 CRYPTO_AEAD_MAX_KEY_LENGTH,
237 (size_t *)&key_size);
238 if (status != PSA_SUCCESS) {
239 return status;
Antonio de Angelis3a480992018-11-07 11:53:28 +0000240 }
241
242 /* Request AEAD decryption on the crypto engine */
243 status = tfm_crypto_engine_aead_decrypt(key_type,
244 alg,
245 key_data,
246 key_size,
247 nonce,
248 nonce_length,
249 additional_data,
250 additional_data_length,
251 ciphertext,
252 ciphertext_length,
253 plaintext,
254 plaintext_size,
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000255 (uint32_t *)&(out_vec[0].len));
Jamie Fox82b87ca2018-12-11 16:41:11 +0000256 if (status != PSA_SUCCESS) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000257 out_vec[0].len = 0;
Jamie Fox82b87ca2018-12-11 16:41:11 +0000258 }
Antonio de Angelis3a480992018-11-07 11:53:28 +0000259
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000260 return status;
Antonio de Angelis3a480992018-11-07 11:53:28 +0000261}
262/*!@}*/