blob: 54550cc4d91dbcd97eed9d1f5807cb5c4d2539d2 [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
8#include <limits.h>
9
10#include "tfm_crypto_defs.h"
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010011#include "crypto_engine.h"
Antonio de Angelisa6f72162018-09-05 11:00:37 +010012#include "psa_crypto.h"
13
Antonio de Angelis377a1552018-11-22 17:02:40 +000014#include "tfm_crypto_struct.h"
Antonio de Angelisa6f72162018-09-05 11:00:37 +010015
16#include "tfm_crypto_api.h"
17#include "crypto_utils.h"
18
Jamie Fox0ff04ba2019-02-05 14:19:07 +000019/**
20 * \brief Release all resources associated with a hash operation.
21 *
22 * \param[in] operation Frontend hash operation context
23 * \param[in] ctx Backend hash operation context
24 *
25 * \return Return values as described in \ref tfm_crypto_err_t
26 */
27static enum tfm_crypto_err_t tfm_crypto_hash_release(
28 psa_hash_operation_t *operation,
29 struct tfm_hash_operation_s *ctx)
30{
31 psa_status_t status;
32 enum tfm_crypto_err_t err;
33
34 /* Release resources in the engine */
35 status = tfm_crypto_engine_hash_release(&(ctx->engine_ctx));
36 if (status != PSA_SUCCESS) {
37 return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
38 }
39
40 /* Release the operation context */
41 err = tfm_crypto_operation_release(&(operation->handle));
42 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
43 return err;
44 }
45
46 return TFM_CRYPTO_ERR_PSA_SUCCESS;
47}
48
Antonio de Angelisa6f72162018-09-05 11:00:37 +010049/*!
50 * \defgroup public_psa Public functions, PSA
51 *
52 */
53
54/*!@{*/
Antonio de Angelis377a1552018-11-22 17:02:40 +000055enum tfm_crypto_err_t tfm_crypto_hash_setup(psa_hash_operation_t *operation,
Antonio de Angelisa6f72162018-09-05 11:00:37 +010056 psa_algorithm_t alg)
57{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010058 psa_status_t status = PSA_SUCCESS;
Antonio de Angelisa6f72162018-09-05 11:00:37 +010059 enum tfm_crypto_err_t err;
Antonio de Angelis377a1552018-11-22 17:02:40 +000060 struct tfm_hash_operation_s *ctx = NULL;
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010061 struct hash_engine_info engine_info;
Antonio de Angelisa6f72162018-09-05 11:00:37 +010062
63 /* Validate pointers */
Antonio de Angelis377a1552018-11-22 17:02:40 +000064 err = tfm_crypto_memory_check(operation,
Antonio de Angelisa6f72162018-09-05 11:00:37 +010065 sizeof(psa_hash_operation_t),
66 TFM_MEMORY_ACCESS_RW);
67 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
68 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
69 }
70
71 if (PSA_ALG_IS_HASH(alg) == 0) {
72 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
73 }
74
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010075 /* Setup the engine for the requested algorithm */
76 status = tfm_crypto_engine_hash_setup(alg, &engine_info);
77 if (status != PSA_SUCCESS) {
Antonio de Angelisa6f72162018-09-05 11:00:37 +010078 return TFM_CRYPTO_ERR_PSA_ERROR_NOT_SUPPORTED;
79 }
80
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010081 /* Allocate the operation context in the secure world */
Antonio de Angelis377a1552018-11-22 17:02:40 +000082 err = tfm_crypto_operation_alloc(TFM_CRYPTO_HASH_OPERATION,
83 &(operation->handle));
Antonio de Angelisa6f72162018-09-05 11:00:37 +010084 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
85 return err;
86 }
87
88 /* Look up the corresponding operation context */
89 err = tfm_crypto_operation_lookup(TFM_CRYPTO_HASH_OPERATION,
Antonio de Angelis377a1552018-11-22 17:02:40 +000090 operation->handle,
91 (void **)&ctx);
Antonio de Angelisa6f72162018-09-05 11:00:37 +010092 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
93 /* Release the operation context */
Jamie Fox0ff04ba2019-02-05 14:19:07 +000094 (void)tfm_crypto_operation_release(&(operation->handle));
Antonio de Angelisa6f72162018-09-05 11:00:37 +010095 return err;
96 }
97
Antonio de Angelis377a1552018-11-22 17:02:40 +000098 /* Bind the algorithm to the hash context */
99 ctx->alg = alg;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100100
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100101 /* Start the engine */
102 status = tfm_crypto_engine_hash_start(&(ctx->engine_ctx), &engine_info);
103 if (status != PSA_SUCCESS) {
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100104 /* Release the operation context */
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000105 (void)tfm_crypto_hash_release(operation, ctx);
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100106 return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100107 }
108
109 return TFM_CRYPTO_ERR_PSA_SUCCESS;
110}
111
Antonio de Angelis377a1552018-11-22 17:02:40 +0000112enum tfm_crypto_err_t tfm_crypto_hash_update(psa_hash_operation_t *operation,
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100113 const uint8_t *input,
114 size_t input_length)
115{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100116 psa_status_t status = PSA_SUCCESS;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100117 enum tfm_crypto_err_t err;
Antonio de Angelis377a1552018-11-22 17:02:40 +0000118 struct tfm_hash_operation_s *ctx = NULL;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100119
120 /* Validate pointers */
Antonio de Angelis377a1552018-11-22 17:02:40 +0000121 err = tfm_crypto_memory_check(operation,
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100122 sizeof(psa_hash_operation_t),
123 TFM_MEMORY_ACCESS_RW);
124 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
125 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
126 }
127 err = tfm_crypto_memory_check((void *)input,
128 input_length,
129 TFM_MEMORY_ACCESS_RO);
130 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
131 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
132 }
133
134 /* Look up the corresponding operation context */
135 err = tfm_crypto_operation_lookup(TFM_CRYPTO_HASH_OPERATION,
Antonio de Angelis377a1552018-11-22 17:02:40 +0000136 operation->handle,
137 (void **)&ctx);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100138 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
139 return err;
140 }
141
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100142 /* Process the input chunk with the engine */
143 status = tfm_crypto_engine_hash_update(&(ctx->engine_ctx),
144 input,
145 input_length);
146 if (status != PSA_SUCCESS) {
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000147 (void)tfm_crypto_hash_release(operation, ctx);
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100148 return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100149 }
150
151 return TFM_CRYPTO_ERR_PSA_SUCCESS;
152}
153
Antonio de Angelis377a1552018-11-22 17:02:40 +0000154enum tfm_crypto_err_t tfm_crypto_hash_finish(psa_hash_operation_t *operation,
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100155 uint8_t *hash,
156 size_t hash_size,
157 size_t *hash_length)
158{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100159 psa_status_t status = PSA_SUCCESS;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100160 enum tfm_crypto_err_t err;
Antonio de Angelis377a1552018-11-22 17:02:40 +0000161 struct tfm_hash_operation_s *ctx = NULL;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100162
163 /* Validate pointers */
Antonio de Angelis377a1552018-11-22 17:02:40 +0000164 err = tfm_crypto_memory_check(operation,
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100165 sizeof(psa_hash_operation_t),
166 TFM_MEMORY_ACCESS_RW);
167 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
168 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
169 }
Antonio de Angelis377a1552018-11-22 17:02:40 +0000170 err = tfm_crypto_memory_check(hash,
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100171 hash_size,
Antonio de Angelis377a1552018-11-22 17:02:40 +0000172 TFM_MEMORY_ACCESS_RW);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100173 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
174 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
175 }
176 err = tfm_crypto_memory_check(hash_length,
177 sizeof(size_t),
178 TFM_MEMORY_ACCESS_RW);
179 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
180 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
181 }
182
183 /* Look up the corresponding operation context */
184 err = tfm_crypto_operation_lookup(TFM_CRYPTO_HASH_OPERATION,
Antonio de Angelis377a1552018-11-22 17:02:40 +0000185 operation->handle,
186 (void **)&ctx);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100187 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
188 return err;
189 }
190
Antonio de Angelis377a1552018-11-22 17:02:40 +0000191 if (hash_size < PSA_HASH_SIZE(ctx->alg)) {
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000192 (void)tfm_crypto_hash_release(operation, ctx);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100193 return TFM_CRYPTO_ERR_PSA_ERROR_BUFFER_TOO_SMALL;
194 }
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) {
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000199 (void)tfm_crypto_hash_release(operation, ctx);
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100200 return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100201 }
202
203 /* Set the length of the hash that has been produced */
Antonio de Angelis377a1552018-11-22 17:02:40 +0000204 *hash_length = PSA_HASH_SIZE(ctx->alg);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100205
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000206 return tfm_crypto_hash_release(operation, ctx);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100207}
208
Antonio de Angelis377a1552018-11-22 17:02:40 +0000209enum tfm_crypto_err_t tfm_crypto_hash_verify(psa_hash_operation_t *operation,
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100210 const uint8_t *hash,
211 size_t hash_length)
212{
213 enum tfm_crypto_err_t err;
214 uint8_t digest[PSA_HASH_MAX_SIZE] = {0};
215 size_t digest_length;
216 uint32_t idx, comp_mismatch = 0;
217
218 /* Validate pointers */
Antonio de Angelis377a1552018-11-22 17:02:40 +0000219 err = tfm_crypto_memory_check(operation,
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100220 sizeof(psa_hash_operation_t),
221 TFM_MEMORY_ACCESS_RW);
222 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
223 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
224 }
225
226 /* Finalise the hash operation */
Antonio de Angelis377a1552018-11-22 17:02:40 +0000227 err = tfm_crypto_hash_finish(operation,
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100228 digest,
229 PSA_HASH_MAX_SIZE,
230 &digest_length);
231
232 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
233 return err;
234 }
235
236 /* Verify that the computed hash matches the provided one */
237 for (idx=0; idx<(uint32_t)digest_length; idx++) {
238 if (digest[idx] != hash[idx]) {
239 comp_mismatch = 1;
240 }
241 }
242
243 if (comp_mismatch == 1) {
244 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_SIGNATURE;
245 }
246
247 return TFM_CRYPTO_ERR_PSA_SUCCESS;
248}
249
Antonio de Angelis377a1552018-11-22 17:02:40 +0000250enum tfm_crypto_err_t tfm_crypto_hash_abort(psa_hash_operation_t *operation)
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100251{
252 enum tfm_crypto_err_t err;
Antonio de Angelis377a1552018-11-22 17:02:40 +0000253 struct tfm_hash_operation_s *ctx = NULL;
254
255 /* Validate pointers */
256 err = tfm_crypto_memory_check(operation,
257 sizeof(psa_hash_operation_t),
258 TFM_MEMORY_ACCESS_RW);
259 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
260 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
261 }
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100262
263 /* Look up the corresponding operation context */
264 err = tfm_crypto_operation_lookup(TFM_CRYPTO_HASH_OPERATION,
Antonio de Angelis377a1552018-11-22 17:02:40 +0000265 operation->handle,
266 (void **)&ctx);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100267 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
268 return err;
269 }
270
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000271 return tfm_crypto_hash_release(operation, ctx);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100272}
273/*!@}*/