blob: 7dc658237ff64a9d5ab68e0b804af426e1f65cd3 [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 */
Antonio de Angelis819c2f32019-02-06 14:32:02 +000041 err = tfm_crypto_operation_release(TFM_CRYPTO_HASH_OPERATION, operation);
Jamie Fox0ff04ba2019-02-05 14:19:07 +000042 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,
Antonio de Angelis819c2f32019-02-06 14:32:02 +000083 operation,
84 (void **)&ctx);
Antonio de Angelisa6f72162018-09-05 11:00:37 +010085 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
86 return err;
87 }
88
Antonio de Angelis377a1552018-11-22 17:02:40 +000089 /* Bind the algorithm to the hash context */
90 ctx->alg = alg;
Antonio de Angelisa6f72162018-09-05 11:00:37 +010091
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010092 /* Start the engine */
93 status = tfm_crypto_engine_hash_start(&(ctx->engine_ctx), &engine_info);
94 if (status != PSA_SUCCESS) {
Hugues de Valon8b442442019-02-19 14:30:52 +000095 /* Release the operation context, ignore if the operation fails. */
Jamie Fox0ff04ba2019-02-05 14:19:07 +000096 (void)tfm_crypto_hash_release(operation, ctx);
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010097 return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
Antonio de Angelisa6f72162018-09-05 11:00:37 +010098 }
99
100 return TFM_CRYPTO_ERR_PSA_SUCCESS;
101}
102
Antonio de Angelis377a1552018-11-22 17:02:40 +0000103enum tfm_crypto_err_t tfm_crypto_hash_update(psa_hash_operation_t *operation,
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100104 const uint8_t *input,
105 size_t input_length)
106{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100107 psa_status_t status = PSA_SUCCESS;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100108 enum tfm_crypto_err_t err;
Antonio de Angelis377a1552018-11-22 17:02:40 +0000109 struct tfm_hash_operation_s *ctx = NULL;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100110
111 /* Validate pointers */
Antonio de Angelis377a1552018-11-22 17:02:40 +0000112 err = tfm_crypto_memory_check(operation,
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100113 sizeof(psa_hash_operation_t),
114 TFM_MEMORY_ACCESS_RW);
115 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
116 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
117 }
118 err = tfm_crypto_memory_check((void *)input,
119 input_length,
120 TFM_MEMORY_ACCESS_RO);
121 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
122 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
123 }
124
125 /* Look up the corresponding operation context */
126 err = tfm_crypto_operation_lookup(TFM_CRYPTO_HASH_OPERATION,
Antonio de Angelis819c2f32019-02-06 14:32:02 +0000127 operation,
Antonio de Angelis377a1552018-11-22 17:02:40 +0000128 (void **)&ctx);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100129 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
130 return err;
131 }
132
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100133 /* Process the input chunk with the engine */
134 status = tfm_crypto_engine_hash_update(&(ctx->engine_ctx),
135 input,
136 input_length);
137 if (status != PSA_SUCCESS) {
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000138 (void)tfm_crypto_hash_release(operation, ctx);
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100139 return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100140 }
141
142 return TFM_CRYPTO_ERR_PSA_SUCCESS;
143}
144
Antonio de Angelis377a1552018-11-22 17:02:40 +0000145enum tfm_crypto_err_t tfm_crypto_hash_finish(psa_hash_operation_t *operation,
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100146 uint8_t *hash,
147 size_t hash_size,
148 size_t *hash_length)
149{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100150 psa_status_t status = PSA_SUCCESS;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100151 enum tfm_crypto_err_t err;
Antonio de Angelis377a1552018-11-22 17:02:40 +0000152 struct tfm_hash_operation_s *ctx = NULL;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100153
154 /* Validate pointers */
Antonio de Angelis377a1552018-11-22 17:02:40 +0000155 err = tfm_crypto_memory_check(operation,
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100156 sizeof(psa_hash_operation_t),
157 TFM_MEMORY_ACCESS_RW);
158 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
159 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
160 }
Antonio de Angelis377a1552018-11-22 17:02:40 +0000161 err = tfm_crypto_memory_check(hash,
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100162 hash_size,
Antonio de Angelis377a1552018-11-22 17:02:40 +0000163 TFM_MEMORY_ACCESS_RW);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100164 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
165 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
166 }
167 err = tfm_crypto_memory_check(hash_length,
168 sizeof(size_t),
169 TFM_MEMORY_ACCESS_RW);
170 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
171 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
172 }
173
174 /* Look up the corresponding operation context */
175 err = tfm_crypto_operation_lookup(TFM_CRYPTO_HASH_OPERATION,
Antonio de Angelis819c2f32019-02-06 14:32:02 +0000176 operation,
Antonio de Angelis377a1552018-11-22 17:02:40 +0000177 (void **)&ctx);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100178 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
179 return err;
180 }
181
Antonio de Angelis377a1552018-11-22 17:02:40 +0000182 if (hash_size < PSA_HASH_SIZE(ctx->alg)) {
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000183 (void)tfm_crypto_hash_release(operation, ctx);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100184 return TFM_CRYPTO_ERR_PSA_ERROR_BUFFER_TOO_SMALL;
185 }
186
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100187 /* Finalise the hash value using the engine */
188 status = tfm_crypto_engine_hash_finish(&(ctx->engine_ctx), hash);
189 if (status != PSA_SUCCESS) {
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000190 (void)tfm_crypto_hash_release(operation, ctx);
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100191 return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100192 }
193
194 /* Set the length of the hash that has been produced */
Antonio de Angelis377a1552018-11-22 17:02:40 +0000195 *hash_length = PSA_HASH_SIZE(ctx->alg);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100196
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000197 return tfm_crypto_hash_release(operation, ctx);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100198}
199
Antonio de Angelis377a1552018-11-22 17:02:40 +0000200enum tfm_crypto_err_t tfm_crypto_hash_verify(psa_hash_operation_t *operation,
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100201 const uint8_t *hash,
202 size_t hash_length)
203{
204 enum tfm_crypto_err_t err;
205 uint8_t digest[PSA_HASH_MAX_SIZE] = {0};
206 size_t digest_length;
207 uint32_t idx, comp_mismatch = 0;
208
209 /* Validate pointers */
Antonio de Angelis377a1552018-11-22 17:02:40 +0000210 err = tfm_crypto_memory_check(operation,
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100211 sizeof(psa_hash_operation_t),
212 TFM_MEMORY_ACCESS_RW);
213 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
214 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
215 }
216
217 /* Finalise the hash operation */
Antonio de Angelis377a1552018-11-22 17:02:40 +0000218 err = tfm_crypto_hash_finish(operation,
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100219 digest,
220 PSA_HASH_MAX_SIZE,
221 &digest_length);
222
223 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
224 return err;
225 }
226
227 /* Verify that the computed hash matches the provided one */
228 for (idx=0; idx<(uint32_t)digest_length; idx++) {
229 if (digest[idx] != hash[idx]) {
230 comp_mismatch = 1;
231 }
232 }
233
234 if (comp_mismatch == 1) {
235 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_SIGNATURE;
236 }
237
238 return TFM_CRYPTO_ERR_PSA_SUCCESS;
239}
240
Antonio de Angelis377a1552018-11-22 17:02:40 +0000241enum tfm_crypto_err_t tfm_crypto_hash_abort(psa_hash_operation_t *operation)
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100242{
243 enum tfm_crypto_err_t err;
Antonio de Angelis377a1552018-11-22 17:02:40 +0000244 struct tfm_hash_operation_s *ctx = NULL;
245
246 /* Validate pointers */
247 err = tfm_crypto_memory_check(operation,
248 sizeof(psa_hash_operation_t),
249 TFM_MEMORY_ACCESS_RW);
250 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
251 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
252 }
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100253
254 /* Look up the corresponding operation context */
255 err = tfm_crypto_operation_lookup(TFM_CRYPTO_HASH_OPERATION,
Antonio de Angelis819c2f32019-02-06 14:32:02 +0000256 operation,
Antonio de Angelis377a1552018-11-22 17:02:40 +0000257 (void **)&ctx);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100258 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
259 return err;
260 }
261
Jamie Fox0ff04ba2019-02-05 14:19:07 +0000262 return tfm_crypto_hash_release(operation, ctx);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100263}
264/*!@}*/