blob: cd546b91ece19f512ebc8054106e46327a26ea6c [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
Jamie Fox0ff04ba2019-02-05 14:19:07 +000012/**
13 * \brief Release all resources associated with a hash operation.
14 *
15 * \param[in] operation Frontend hash operation context
16 * \param[in] ctx Backend hash operation context
17 *
18 * \return Return values as described in \ref tfm_crypto_err_t
19 */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000020static psa_status_t tfm_crypto_hash_release(psa_hash_operation_t *operation,
21 struct tfm_hash_operation_s *ctx)
Jamie Fox0ff04ba2019-02-05 14:19:07 +000022{
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000023 psa_status_t status = PSA_SUCCESS;
Jamie Fox0ff04ba2019-02-05 14:19:07 +000024
25 /* Release resources in the engine */
26 status = tfm_crypto_engine_hash_release(&(ctx->engine_ctx));
27 if (status != PSA_SUCCESS) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000028 return status;
Jamie Fox0ff04ba2019-02-05 14:19:07 +000029 }
30
31 /* Release the operation context */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000032 return tfm_crypto_operation_release(TFM_CRYPTO_HASH_OPERATION, operation);
Jamie Fox0ff04ba2019-02-05 14:19:07 +000033}
34
Antonio de Angelisa6f72162018-09-05 11:00:37 +010035/*!
36 * \defgroup public_psa Public functions, PSA
37 *
38 */
39
40/*!@{*/
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000041psa_status_t tfm_crypto_hash_setup(psa_invec in_vec[],
42 size_t in_len,
43 psa_outvec out_vec[],
44 size_t out_len)
Antonio de Angelisa6f72162018-09-05 11:00:37 +010045{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010046 psa_status_t status = PSA_SUCCESS;
Antonio de Angelis377a1552018-11-22 17:02:40 +000047 struct tfm_hash_operation_s *ctx = NULL;
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010048 struct hash_engine_info engine_info;
Antonio de Angelisa6f72162018-09-05 11:00:37 +010049
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000050 if ((in_len != 1) || (out_len != 1)) {
51 return PSA_CONNECTION_REFUSED;
Antonio de Angelisa6f72162018-09-05 11:00:37 +010052 }
53
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000054 if ((out_vec[0].len != sizeof(psa_hash_operation_t)) ||
55 (in_vec[0].len != sizeof(psa_algorithm_t))) {
56 return PSA_CONNECTION_REFUSED;
57 }
58
59 psa_hash_operation_t *operation = out_vec[0].base;
60 psa_algorithm_t alg = *((psa_algorithm_t *)in_vec[0].base);
61
Antonio de Angelisa6f72162018-09-05 11:00:37 +010062 if (PSA_ALG_IS_HASH(alg) == 0) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000063 return PSA_ERROR_INVALID_ARGUMENT;
Antonio de Angelisa6f72162018-09-05 11:00:37 +010064 }
65
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010066 /* Setup the engine for the requested algorithm */
67 status = tfm_crypto_engine_hash_setup(alg, &engine_info);
68 if (status != PSA_SUCCESS) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000069 return PSA_ERROR_NOT_SUPPORTED;
Antonio de Angelisa6f72162018-09-05 11:00:37 +010070 }
71
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010072 /* Allocate the operation context in the secure world */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000073 status = tfm_crypto_operation_alloc(TFM_CRYPTO_HASH_OPERATION,
74 operation,
75 (void **)&ctx);
76 if (status != PSA_SUCCESS) {
77 return status;
Antonio de Angelisa6f72162018-09-05 11:00:37 +010078 }
79
Antonio de Angelis377a1552018-11-22 17:02:40 +000080 /* Bind the algorithm to the hash context */
81 ctx->alg = alg;
Antonio de Angelisa6f72162018-09-05 11:00:37 +010082
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010083 /* Start the engine */
84 status = tfm_crypto_engine_hash_start(&(ctx->engine_ctx), &engine_info);
85 if (status != PSA_SUCCESS) {
Hugues de Valon8b442442019-02-19 14:30:52 +000086 /* Release the operation context, ignore if the operation fails. */
Jamie Fox0ff04ba2019-02-05 14:19:07 +000087 (void)tfm_crypto_hash_release(operation, ctx);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000088 return status;
Antonio de Angelisa6f72162018-09-05 11:00:37 +010089 }
90
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000091 return PSA_SUCCESS;
Antonio de Angelisa6f72162018-09-05 11:00:37 +010092}
93
Antonio de Angelisab85ccd2019-03-25 15:14:29 +000094psa_status_t tfm_crypto_hash_update(psa_invec in_vec[],
95 size_t in_len,
96 psa_outvec out_vec[],
97 size_t out_len)
Antonio de Angelisa6f72162018-09-05 11:00:37 +010098{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010099 psa_status_t status = PSA_SUCCESS;
Antonio de Angelis377a1552018-11-22 17:02:40 +0000100 struct tfm_hash_operation_s *ctx = NULL;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100101
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000102 if ((in_len != 1) || (out_len != 1)) {
103 return PSA_CONNECTION_REFUSED;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100104 }
105
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000106 if ((out_vec[0].len != sizeof(psa_hash_operation_t))) {
107 return PSA_CONNECTION_REFUSED;
108 }
109
110 psa_hash_operation_t *operation = out_vec[0].base;
111 const uint8_t *input = in_vec[0].base;
112 size_t input_length = in_vec[0].len;
113
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100114 /* Look up the corresponding operation context */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000115 status = tfm_crypto_operation_lookup(TFM_CRYPTO_HASH_OPERATION,
116 operation,
117 (void **)&ctx);
118 if (status != PSA_SUCCESS) {
119 return status;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100120 }
121
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100122 /* Process the input chunk with the engine */
123 status = tfm_crypto_engine_hash_update(&(ctx->engine_ctx),
124 input,
125 input_length);
126 if (status != PSA_SUCCESS) {
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000127 (void)tfm_crypto_hash_release(operation, ctx);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000128 return status;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100129 }
130
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000131 return PSA_SUCCESS;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100132}
133
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000134psa_status_t tfm_crypto_hash_finish(psa_invec in_vec[],
135 size_t in_len,
136 psa_outvec out_vec[],
137 size_t out_len)
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100138{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100139 psa_status_t status = PSA_SUCCESS;
Antonio de Angelis377a1552018-11-22 17:02:40 +0000140 struct tfm_hash_operation_s *ctx = NULL;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100141
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000142 if ((in_len != 0) || (out_len != 2)) {
143 return PSA_CONNECTION_REFUSED;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100144 }
145
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000146 if ((out_vec[0].len != sizeof(psa_hash_operation_t))) {
147 return PSA_CONNECTION_REFUSED;
148 }
149
150 psa_hash_operation_t *operation = out_vec[0].base;
151 uint8_t *hash = out_vec[1].base;
152 size_t hash_size = out_vec[1].len;
153
154 /* Initialise hash_length to zero */
155 out_vec[1].len = 0;
156
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100157 /* Look up the corresponding operation context */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000158 status = tfm_crypto_operation_lookup(TFM_CRYPTO_HASH_OPERATION,
159 operation,
160 (void **)&ctx);
161 if (status != PSA_SUCCESS) {
162 return status;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100163 }
164
Antonio de Angelis377a1552018-11-22 17:02:40 +0000165 if (hash_size < PSA_HASH_SIZE(ctx->alg)) {
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000166 (void)tfm_crypto_hash_release(operation, ctx);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000167 return PSA_ERROR_BUFFER_TOO_SMALL;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100168 }
169
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100170 /* Finalise the hash value using the engine */
171 status = tfm_crypto_engine_hash_finish(&(ctx->engine_ctx), hash);
172 if (status != PSA_SUCCESS) {
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000173 (void)tfm_crypto_hash_release(operation, ctx);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000174 return status;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100175 }
176
177 /* Set the length of the hash that has been produced */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000178 out_vec[1].len = PSA_HASH_SIZE(ctx->alg);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100179
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000180 return tfm_crypto_hash_release(operation, ctx);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100181}
182
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000183static psa_status_t _psa_hash_finish(psa_hash_operation_t *operation,
184 uint8_t *hash,
185 size_t hash_size,
186 size_t *hash_length)
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100187{
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000188 psa_status_t status;
189 psa_outvec out_vec[] = {
190 {.base = operation, .len = sizeof(psa_hash_operation_t)},
191 {.base = hash, .len = hash_size},
192 };
193
194 status = tfm_crypto_hash_finish(NULL, 0,
195 out_vec, sizeof(out_vec)/sizeof(out_vec[0]));
196 *hash_length = out_vec[1].len;
197
198 return status;
199}
200
201psa_status_t tfm_crypto_hash_verify(psa_invec in_vec[],
202 size_t in_len,
203 psa_outvec out_vec[],
204 size_t out_len)
205{
206 psa_status_t status = PSA_SUCCESS;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100207 uint8_t digest[PSA_HASH_MAX_SIZE] = {0};
208 size_t digest_length;
209 uint32_t idx, comp_mismatch = 0;
210
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000211 if ((in_len != 1) || (out_len != 1)) {
212 return PSA_CONNECTION_REFUSED;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100213 }
214
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000215 if ((out_vec[0].len != sizeof(psa_hash_operation_t))) {
216 return PSA_CONNECTION_REFUSED;
217 }
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100218
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000219 psa_hash_operation_t *operation = out_vec[0].base;
220 const uint8_t *hash = in_vec[0].base;
221 size_t hash_length = in_vec[0].len;
222
223 /* Finalise the hash operation */
224 status = _psa_hash_finish(operation,
225 digest,
226 PSA_HASH_MAX_SIZE,
227 &digest_length);
228
229 if (status != PSA_SUCCESS) {
230 return status;
231 }
232
233 /* Check that the computed hash has the same legnth as the provided one */
234 if (hash_length != digest_length) {
235 return PSA_ERROR_INVALID_SIGNATURE;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100236 }
237
238 /* Verify that the computed hash matches the provided one */
239 for (idx=0; idx<(uint32_t)digest_length; idx++) {
240 if (digest[idx] != hash[idx]) {
241 comp_mismatch = 1;
242 }
243 }
244
245 if (comp_mismatch == 1) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000246 return PSA_ERROR_INVALID_SIGNATURE;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100247 }
248
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000249 return PSA_SUCCESS;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100250}
251
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000252psa_status_t tfm_crypto_hash_abort(psa_invec in_vec[],
253 size_t in_len,
254 psa_outvec out_vec[],
255 size_t out_len)
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100256{
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000257 psa_status_t status = PSA_SUCCESS;
Antonio de Angelis377a1552018-11-22 17:02:40 +0000258 struct tfm_hash_operation_s *ctx = NULL;
259
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000260 if ((in_len != 0) || (out_len != 1)) {
261 return PSA_CONNECTION_REFUSED;
Antonio de Angelis377a1552018-11-22 17:02:40 +0000262 }
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100263
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000264 if ((out_vec[0].len != sizeof(psa_hash_operation_t))) {
265 return PSA_CONNECTION_REFUSED;
266 }
267
268 psa_hash_operation_t *operation = out_vec[0].base;
269
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100270 /* Look up the corresponding operation context */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000271 status = tfm_crypto_operation_lookup(TFM_CRYPTO_HASH_OPERATION,
272 operation,
273 (void **)&ctx);
274 if (status != PSA_SUCCESS) {
275 return status;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100276 }
277
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000278 return tfm_crypto_hash_release(operation, ctx);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100279}
280/*!@}*/