blob: 36e575919ea6d83e864ccb2a465ecc833455cffa [file] [log] [blame]
Antonio de Angelisa6f72162018-09-05 11:00:37 +01001/*
Antonio de Angelis377a1552018-11-22 17:02:40 +00002 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
Antonio de Angelisa6f72162018-09-05 11:00:37 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
Antonio de Angelisa6f72162018-09-05 11:00:37 +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 Angelisa6f72162018-09-05 11:00:37 +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 Fox0ff04ba2019-02-05 14:19:07 +000018/**
19 * \brief Release all resources associated with a hash operation.
20 *
21 * \param[in] operation Frontend hash operation context
22 * \param[in] ctx Backend hash operation context
23 *
24 * \return Return values as described in \ref tfm_crypto_err_t
25 */
Antonio de Angelis4743e672019-04-11 11:38:48 +010026static psa_status_t tfm_crypto_hash_release(uint32_t *handle,
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000027 struct tfm_hash_operation_s *ctx)
Jamie Fox0ff04ba2019-02-05 14:19:07 +000028{
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000029 psa_status_t status = PSA_SUCCESS;
Jamie Fox0ff04ba2019-02-05 14:19:07 +000030
31 /* Release resources in the engine */
32 status = tfm_crypto_engine_hash_release(&(ctx->engine_ctx));
33 if (status != PSA_SUCCESS) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000034 return status;
Jamie Fox0ff04ba2019-02-05 14:19:07 +000035 }
36
37 /* Release the operation context */
Antonio de Angelis4743e672019-04-11 11:38:48 +010038 return tfm_crypto_operation_release(handle);
Jamie Fox0ff04ba2019-02-05 14:19:07 +000039}
40
Antonio de Angelisa6f72162018-09-05 11:00:37 +010041/*!
42 * \defgroup public_psa Public functions, PSA
43 *
44 */
45
46/*!@{*/
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000047psa_status_t tfm_crypto_hash_setup(psa_invec in_vec[],
48 size_t in_len,
49 psa_outvec out_vec[],
50 size_t out_len)
Antonio de Angelisa6f72162018-09-05 11:00:37 +010051{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010052 psa_status_t status = PSA_SUCCESS;
Antonio de Angelis377a1552018-11-22 17:02:40 +000053 struct tfm_hash_operation_s *ctx = NULL;
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010054 struct hash_engine_info engine_info;
Antonio de Angelisa6f72162018-09-05 11:00:37 +010055
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000056 if ((in_len != 1) || (out_len != 1)) {
57 return PSA_CONNECTION_REFUSED;
Antonio de Angelisa6f72162018-09-05 11:00:37 +010058 }
59
Antonio de Angelis4743e672019-04-11 11:38:48 +010060 if ((out_vec[0].len != sizeof(uint32_t)) ||
61 (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000062 return PSA_CONNECTION_REFUSED;
63 }
Antonio de Angelis4743e672019-04-11 11:38:48 +010064 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
65 uint32_t handle = iov->handle;
66 uint32_t *handle_out = out_vec[0].base;
67 psa_algorithm_t alg = iov->alg;
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000068
Antonio de Angelis4743e672019-04-11 11:38:48 +010069 /* Init the handle in the operation with the one passed from the iov */
70 *handle_out = iov->handle;
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000071
Antonio de Angelisa6f72162018-09-05 11:00:37 +010072 if (PSA_ALG_IS_HASH(alg) == 0) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000073 return PSA_ERROR_INVALID_ARGUMENT;
Antonio de Angelisa6f72162018-09-05 11:00:37 +010074 }
75
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010076 /* Setup the engine for the requested algorithm */
77 status = tfm_crypto_engine_hash_setup(alg, &engine_info);
78 if (status != PSA_SUCCESS) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000079 return PSA_ERROR_NOT_SUPPORTED;
Antonio de Angelisa6f72162018-09-05 11:00:37 +010080 }
81
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010082 /* Allocate the operation context in the secure world */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000083 status = tfm_crypto_operation_alloc(TFM_CRYPTO_HASH_OPERATION,
Antonio de Angelis4743e672019-04-11 11:38:48 +010084 &handle,
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000085 (void **)&ctx);
86 if (status != PSA_SUCCESS) {
87 return status;
Antonio de Angelisa6f72162018-09-05 11:00:37 +010088 }
89
Antonio de Angelis4743e672019-04-11 11:38:48 +010090 *handle_out = handle;
91
Antonio de Angelis377a1552018-11-22 17:02:40 +000092 /* Bind the algorithm to the hash context */
93 ctx->alg = alg;
Antonio de Angelisa6f72162018-09-05 11:00:37 +010094
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010095 /* Start the engine */
96 status = tfm_crypto_engine_hash_start(&(ctx->engine_ctx), &engine_info);
97 if (status != PSA_SUCCESS) {
Hugues de Valon8b442442019-02-19 14:30:52 +000098 /* Release the operation context, ignore if the operation fails. */
Antonio de Angelis4743e672019-04-11 11:38:48 +010099 (void)tfm_crypto_hash_release(&handle, ctx);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000100 return status;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100101 }
102
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000103 return PSA_SUCCESS;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100104}
105
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000106psa_status_t tfm_crypto_hash_update(psa_invec in_vec[],
107 size_t in_len,
108 psa_outvec out_vec[],
109 size_t out_len)
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100110{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100111 psa_status_t status = PSA_SUCCESS;
Antonio de Angelis377a1552018-11-22 17:02:40 +0000112 struct tfm_hash_operation_s *ctx = NULL;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100113
Antonio de Angelis4743e672019-04-11 11:38:48 +0100114 if ((in_len != 2) || (out_len != 1)) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000115 return PSA_CONNECTION_REFUSED;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100116 }
117
Antonio de Angelis4743e672019-04-11 11:38:48 +0100118 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
119 (out_vec[0].len != sizeof(uint32_t))) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000120 return PSA_CONNECTION_REFUSED;
121 }
Antonio de Angelis4743e672019-04-11 11:38:48 +0100122 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
123 uint32_t handle = iov->handle;
124 uint32_t *handle_out = out_vec[0].base;
125 const uint8_t *input = in_vec[1].base;
126 size_t input_length = in_vec[1].len;
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000127
Antonio de Angelis4743e672019-04-11 11:38:48 +0100128 /* Init the handle in the operation with the one passed from the iov */
129 *handle_out = iov->handle;
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000130
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100131 /* Look up the corresponding operation context */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000132 status = tfm_crypto_operation_lookup(TFM_CRYPTO_HASH_OPERATION,
Antonio de Angelis4743e672019-04-11 11:38:48 +0100133 handle,
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000134 (void **)&ctx);
135 if (status != PSA_SUCCESS) {
136 return status;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100137 }
138
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100139 /* Process the input chunk with the engine */
140 status = tfm_crypto_engine_hash_update(&(ctx->engine_ctx),
141 input,
142 input_length);
143 if (status != PSA_SUCCESS) {
Antonio de Angelis4743e672019-04-11 11:38:48 +0100144 if (tfm_crypto_hash_release(&handle, ctx) == PSA_SUCCESS) {
145 *handle_out = handle;
146 }
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000147 return status;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100148 }
149
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000150 return PSA_SUCCESS;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100151}
152
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000153psa_status_t tfm_crypto_hash_finish(psa_invec in_vec[],
154 size_t in_len,
155 psa_outvec out_vec[],
156 size_t out_len)
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100157{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100158 psa_status_t status = PSA_SUCCESS;
Antonio de Angelis377a1552018-11-22 17:02:40 +0000159 struct tfm_hash_operation_s *ctx = NULL;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100160
Antonio de Angelis4743e672019-04-11 11:38:48 +0100161 if ((in_len != 1) || (out_len != 2)) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000162 return PSA_CONNECTION_REFUSED;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100163 }
164
Antonio de Angelis4743e672019-04-11 11:38:48 +0100165 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
166 (out_vec[0].len != sizeof(uint32_t))) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000167 return PSA_CONNECTION_REFUSED;
168 }
Antonio de Angelis4743e672019-04-11 11:38:48 +0100169 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
170 uint32_t handle = iov->handle;
171 uint32_t *handle_out = out_vec[0].base;
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000172 uint8_t *hash = out_vec[1].base;
173 size_t hash_size = out_vec[1].len;
174
Antonio de Angelis4743e672019-04-11 11:38:48 +0100175 /* Init the handle in the operation with the one passed from the iov */
176 *handle_out = iov->handle;
177
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000178 /* Initialise hash_length to zero */
179 out_vec[1].len = 0;
180
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100181 /* Look up the corresponding operation context */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000182 status = tfm_crypto_operation_lookup(TFM_CRYPTO_HASH_OPERATION,
Antonio de Angelis4743e672019-04-11 11:38:48 +0100183 handle,
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000184 (void **)&ctx);
185 if (status != PSA_SUCCESS) {
186 return status;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100187 }
188
Antonio de Angelis377a1552018-11-22 17:02:40 +0000189 if (hash_size < PSA_HASH_SIZE(ctx->alg)) {
Antonio de Angelis4743e672019-04-11 11:38:48 +0100190 if (tfm_crypto_hash_release(&handle, ctx) == PSA_SUCCESS) {
191 *handle_out = handle;
192 }
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000193 return PSA_ERROR_BUFFER_TOO_SMALL;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100194 }
195
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100196 /* Finalise the hash value using the engine */
197 status = tfm_crypto_engine_hash_finish(&(ctx->engine_ctx), hash);
198 if (status != PSA_SUCCESS) {
Antonio de Angelis4743e672019-04-11 11:38:48 +0100199 if (tfm_crypto_hash_release(&handle, ctx) == PSA_SUCCESS) {
200 *handle_out = handle;
201 }
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000202 return status;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100203 }
204
205 /* Set the length of the hash that has been produced */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000206 out_vec[1].len = PSA_HASH_SIZE(ctx->alg);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100207
Antonio de Angelis4743e672019-04-11 11:38:48 +0100208 status = tfm_crypto_hash_release(&handle, ctx);
209 if (status == PSA_SUCCESS) {
210 *handle_out = handle;
211 }
212 return status;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100213}
214
Antonio de Angelis4743e672019-04-11 11:38:48 +0100215static psa_status_t _psa_hash_finish(uint32_t *handle,
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000216 uint8_t *hash,
217 size_t hash_size,
218 size_t *hash_length)
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100219{
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000220 psa_status_t status;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100221 struct tfm_crypto_pack_iovec iov = {
222 .sfn_id = TFM_CRYPTO_HASH_FINISH_SFID,
223 .handle = *handle,
224 };
225
226 psa_invec in_vec[] = {
227 {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
228 };
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000229 psa_outvec out_vec[] = {
Antonio de Angelis4743e672019-04-11 11:38:48 +0100230 {.base = handle, .len = sizeof(uint32_t)},
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000231 {.base = hash, .len = hash_size},
232 };
233
Antonio de Angelis4743e672019-04-11 11:38:48 +0100234 status = tfm_crypto_hash_finish(in_vec, sizeof(in_vec)/sizeof(in_vec[0]),
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000235 out_vec, sizeof(out_vec)/sizeof(out_vec[0]));
236 *hash_length = out_vec[1].len;
237
238 return status;
239}
240
241psa_status_t tfm_crypto_hash_verify(psa_invec in_vec[],
242 size_t in_len,
243 psa_outvec out_vec[],
244 size_t out_len)
245{
246 psa_status_t status = PSA_SUCCESS;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100247 uint8_t digest[PSA_HASH_MAX_SIZE] = {0};
248 size_t digest_length;
249 uint32_t idx, comp_mismatch = 0;
250
Antonio de Angelis4743e672019-04-11 11:38:48 +0100251 if ((in_len != 2) || (out_len != 1)) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000252 return PSA_CONNECTION_REFUSED;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100253 }
254
Antonio de Angelis4743e672019-04-11 11:38:48 +0100255 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
256 (out_vec[0].len != sizeof(uint32_t))) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000257 return PSA_CONNECTION_REFUSED;
258 }
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100259
Antonio de Angelis4743e672019-04-11 11:38:48 +0100260 uint32_t *handle_out = out_vec[0].base;
261 const uint8_t *hash = in_vec[1].base;
262 size_t hash_length = in_vec[1].len;
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000263
264 /* Finalise the hash operation */
Antonio de Angelis4743e672019-04-11 11:38:48 +0100265 status = _psa_hash_finish(handle_out,
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000266 digest,
267 PSA_HASH_MAX_SIZE,
268 &digest_length);
269
270 if (status != PSA_SUCCESS) {
271 return status;
272 }
273
274 /* Check that the computed hash has the same legnth as the provided one */
275 if (hash_length != digest_length) {
276 return PSA_ERROR_INVALID_SIGNATURE;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100277 }
278
279 /* Verify that the computed hash matches the provided one */
280 for (idx=0; idx<(uint32_t)digest_length; idx++) {
281 if (digest[idx] != hash[idx]) {
282 comp_mismatch = 1;
283 }
284 }
285
286 if (comp_mismatch == 1) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000287 return PSA_ERROR_INVALID_SIGNATURE;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100288 }
289
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000290 return PSA_SUCCESS;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100291}
292
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000293psa_status_t tfm_crypto_hash_abort(psa_invec in_vec[],
294 size_t in_len,
295 psa_outvec out_vec[],
296 size_t out_len)
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100297{
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000298 psa_status_t status = PSA_SUCCESS;
Antonio de Angelis377a1552018-11-22 17:02:40 +0000299 struct tfm_hash_operation_s *ctx = NULL;
300
Antonio de Angelis4743e672019-04-11 11:38:48 +0100301 if ((in_len != 1) || (out_len != 1)) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000302 return PSA_CONNECTION_REFUSED;
Antonio de Angelis377a1552018-11-22 17:02:40 +0000303 }
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100304
Antonio de Angelis4743e672019-04-11 11:38:48 +0100305 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
306 (out_vec[0].len != sizeof(uint32_t))) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000307 return PSA_CONNECTION_REFUSED;
308 }
Antonio de Angelis4743e672019-04-11 11:38:48 +0100309 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
310 uint32_t handle = iov->handle;
311 uint32_t *handle_out = out_vec[0].base;
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000312
Antonio de Angelis4743e672019-04-11 11:38:48 +0100313 /* Init the handle in the operation with the one passed from the iov */
314 *handle_out = iov->handle;
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000315
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100316 /* Look up the corresponding operation context */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000317 status = tfm_crypto_operation_lookup(TFM_CRYPTO_HASH_OPERATION,
Antonio de Angelis4743e672019-04-11 11:38:48 +0100318 handle,
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000319 (void **)&ctx);
320 if (status != PSA_SUCCESS) {
321 return status;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100322 }
323
Antonio de Angelis4743e672019-04-11 11:38:48 +0100324 status = tfm_crypto_hash_release(&handle, ctx);
325 if (status == PSA_SUCCESS) {
326 *handle_out = handle;
327 }
328 return status;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100329}
330/*!@}*/