blob: 265385bcb9d49da4ec409dd26b82bc8556ccebb0 [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
19/*!
20 * \defgroup public_psa Public functions, PSA
21 *
22 */
23
24/*!@{*/
Antonio de Angelis377a1552018-11-22 17:02:40 +000025enum tfm_crypto_err_t tfm_crypto_hash_setup(psa_hash_operation_t *operation,
Antonio de Angelisa6f72162018-09-05 11:00:37 +010026 psa_algorithm_t alg)
27{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010028 psa_status_t status = PSA_SUCCESS;
Antonio de Angelisa6f72162018-09-05 11:00:37 +010029 enum tfm_crypto_err_t err;
Antonio de Angelis377a1552018-11-22 17:02:40 +000030 struct tfm_hash_operation_s *ctx = NULL;
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010031 struct hash_engine_info engine_info;
Antonio de Angelisa6f72162018-09-05 11:00:37 +010032
33 /* Validate pointers */
Antonio de Angelis377a1552018-11-22 17:02:40 +000034 err = tfm_crypto_memory_check(operation,
Antonio de Angelisa6f72162018-09-05 11:00:37 +010035 sizeof(psa_hash_operation_t),
36 TFM_MEMORY_ACCESS_RW);
37 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
38 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
39 }
40
41 if (PSA_ALG_IS_HASH(alg) == 0) {
42 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
43 }
44
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010045 /* Setup the engine for the requested algorithm */
46 status = tfm_crypto_engine_hash_setup(alg, &engine_info);
47 if (status != PSA_SUCCESS) {
Antonio de Angelisa6f72162018-09-05 11:00:37 +010048 return TFM_CRYPTO_ERR_PSA_ERROR_NOT_SUPPORTED;
49 }
50
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010051 /* Allocate the operation context in the secure world */
Antonio de Angelis377a1552018-11-22 17:02:40 +000052 err = tfm_crypto_operation_alloc(TFM_CRYPTO_HASH_OPERATION,
53 &(operation->handle));
Antonio de Angelisa6f72162018-09-05 11:00:37 +010054 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
55 return err;
56 }
57
58 /* Look up the corresponding operation context */
59 err = tfm_crypto_operation_lookup(TFM_CRYPTO_HASH_OPERATION,
Antonio de Angelis377a1552018-11-22 17:02:40 +000060 operation->handle,
61 (void **)&ctx);
Antonio de Angelisa6f72162018-09-05 11:00:37 +010062 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
63 /* Release the operation context */
Antonio de Angelis377a1552018-11-22 17:02:40 +000064 tfm_crypto_operation_release(&(operation->handle));
Antonio de Angelisa6f72162018-09-05 11:00:37 +010065 return err;
66 }
67
Antonio de Angelis377a1552018-11-22 17:02:40 +000068 /* Bind the algorithm to the hash context */
69 ctx->alg = alg;
Antonio de Angelisa6f72162018-09-05 11:00:37 +010070
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010071 /* Start the engine */
72 status = tfm_crypto_engine_hash_start(&(ctx->engine_ctx), &engine_info);
73 if (status != PSA_SUCCESS) {
Antonio de Angelisa6f72162018-09-05 11:00:37 +010074 /* Release the operation context */
Antonio de Angelis377a1552018-11-22 17:02:40 +000075 tfm_crypto_operation_release(&(operation->handle));
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010076 return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
Antonio de Angelisa6f72162018-09-05 11:00:37 +010077 }
78
79 return TFM_CRYPTO_ERR_PSA_SUCCESS;
80}
81
Antonio de Angelis377a1552018-11-22 17:02:40 +000082enum tfm_crypto_err_t tfm_crypto_hash_update(psa_hash_operation_t *operation,
Antonio de Angelisa6f72162018-09-05 11:00:37 +010083 const uint8_t *input,
84 size_t input_length)
85{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010086 psa_status_t status = PSA_SUCCESS;
Antonio de Angelisa6f72162018-09-05 11:00:37 +010087 enum tfm_crypto_err_t err;
Antonio de Angelis377a1552018-11-22 17:02:40 +000088 struct tfm_hash_operation_s *ctx = NULL;
Antonio de Angelisa6f72162018-09-05 11:00:37 +010089
90 /* Validate pointers */
Antonio de Angelis377a1552018-11-22 17:02:40 +000091 err = tfm_crypto_memory_check(operation,
Antonio de Angelisa6f72162018-09-05 11:00:37 +010092 sizeof(psa_hash_operation_t),
93 TFM_MEMORY_ACCESS_RW);
94 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
95 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
96 }
97 err = tfm_crypto_memory_check((void *)input,
98 input_length,
99 TFM_MEMORY_ACCESS_RO);
100 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
101 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
102 }
103
104 /* Look up the corresponding operation context */
105 err = tfm_crypto_operation_lookup(TFM_CRYPTO_HASH_OPERATION,
Antonio de Angelis377a1552018-11-22 17:02:40 +0000106 operation->handle,
107 (void **)&ctx);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100108 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
109 return err;
110 }
111
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100112 /* Process the input chunk with the engine */
113 status = tfm_crypto_engine_hash_update(&(ctx->engine_ctx),
114 input,
115 input_length);
116 if (status != PSA_SUCCESS) {
117 return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100118 }
119
120 return TFM_CRYPTO_ERR_PSA_SUCCESS;
121}
122
Antonio de Angelis377a1552018-11-22 17:02:40 +0000123enum tfm_crypto_err_t tfm_crypto_hash_finish(psa_hash_operation_t *operation,
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100124 uint8_t *hash,
125 size_t hash_size,
126 size_t *hash_length)
127{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100128 psa_status_t status = PSA_SUCCESS;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100129 enum tfm_crypto_err_t err;
Antonio de Angelis377a1552018-11-22 17:02:40 +0000130 struct tfm_hash_operation_s *ctx = NULL;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100131
132 /* Validate pointers */
Antonio de Angelis377a1552018-11-22 17:02:40 +0000133 err = tfm_crypto_memory_check(operation,
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100134 sizeof(psa_hash_operation_t),
135 TFM_MEMORY_ACCESS_RW);
136 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
137 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
138 }
Antonio de Angelis377a1552018-11-22 17:02:40 +0000139 err = tfm_crypto_memory_check(hash,
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100140 hash_size,
Antonio de Angelis377a1552018-11-22 17:02:40 +0000141 TFM_MEMORY_ACCESS_RW);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100142 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
143 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
144 }
145 err = tfm_crypto_memory_check(hash_length,
146 sizeof(size_t),
147 TFM_MEMORY_ACCESS_RW);
148 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
149 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
150 }
151
152 /* Look up the corresponding operation context */
153 err = tfm_crypto_operation_lookup(TFM_CRYPTO_HASH_OPERATION,
Antonio de Angelis377a1552018-11-22 17:02:40 +0000154 operation->handle,
155 (void **)&ctx);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100156 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
157 return err;
158 }
159
Antonio de Angelis377a1552018-11-22 17:02:40 +0000160 if (hash_size < PSA_HASH_SIZE(ctx->alg)) {
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100161 return TFM_CRYPTO_ERR_PSA_ERROR_BUFFER_TOO_SMALL;
162 }
163
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100164 /* Finalise the hash value using the engine */
165 status = tfm_crypto_engine_hash_finish(&(ctx->engine_ctx), hash);
166 if (status != PSA_SUCCESS) {
167 return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
168 }
169
170 /* Release engine resources */
171 status = tfm_crypto_engine_hash_release(&(ctx->engine_ctx));
172 if (status != PSA_SUCCESS) {
173 return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100174 }
175
176 /* Set the length of the hash that has been produced */
Antonio de Angelis377a1552018-11-22 17:02:40 +0000177 *hash_length = PSA_HASH_SIZE(ctx->alg);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100178
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100179 /* Release the operation context */
Antonio de Angelis377a1552018-11-22 17:02:40 +0000180 err = tfm_crypto_operation_release(&(operation->handle));
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100181 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
182 return err;
183 }
184
185 return TFM_CRYPTO_ERR_PSA_SUCCESS;
186}
187
Antonio de Angelis377a1552018-11-22 17:02:40 +0000188enum tfm_crypto_err_t tfm_crypto_hash_verify(psa_hash_operation_t *operation,
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100189 const uint8_t *hash,
190 size_t hash_length)
191{
192 enum tfm_crypto_err_t err;
193 uint8_t digest[PSA_HASH_MAX_SIZE] = {0};
194 size_t digest_length;
195 uint32_t idx, comp_mismatch = 0;
196
197 /* Validate pointers */
Antonio de Angelis377a1552018-11-22 17:02:40 +0000198 err = tfm_crypto_memory_check(operation,
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100199 sizeof(psa_hash_operation_t),
200 TFM_MEMORY_ACCESS_RW);
201 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
202 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
203 }
204
205 /* Finalise the hash operation */
Antonio de Angelis377a1552018-11-22 17:02:40 +0000206 err = tfm_crypto_hash_finish(operation,
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100207 digest,
208 PSA_HASH_MAX_SIZE,
209 &digest_length);
210
211 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
212 return err;
213 }
214
215 /* Verify that the computed hash matches the provided one */
216 for (idx=0; idx<(uint32_t)digest_length; idx++) {
217 if (digest[idx] != hash[idx]) {
218 comp_mismatch = 1;
219 }
220 }
221
222 if (comp_mismatch == 1) {
223 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_SIGNATURE;
224 }
225
226 return TFM_CRYPTO_ERR_PSA_SUCCESS;
227}
228
Antonio de Angelis377a1552018-11-22 17:02:40 +0000229enum tfm_crypto_err_t tfm_crypto_hash_abort(psa_hash_operation_t *operation)
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100230{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100231 psa_status_t status = PSA_SUCCESS;
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100232 enum tfm_crypto_err_t err;
Antonio de Angelis377a1552018-11-22 17:02:40 +0000233 struct tfm_hash_operation_s *ctx = NULL;
234
235 /* Validate pointers */
236 err = tfm_crypto_memory_check(operation,
237 sizeof(psa_hash_operation_t),
238 TFM_MEMORY_ACCESS_RW);
239 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
240 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
241 }
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100242
243 /* Look up the corresponding operation context */
244 err = tfm_crypto_operation_lookup(TFM_CRYPTO_HASH_OPERATION,
Antonio de Angelis377a1552018-11-22 17:02:40 +0000245 operation->handle,
246 (void **)&ctx);
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100247 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
248 return err;
249 }
250
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100251 /* Release engine resources */
252 status = tfm_crypto_engine_hash_release(&(ctx->engine_ctx));
253 if (status != PSA_SUCCESS) {
254 return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
255 }
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100256
257 /* Release the operation context */
Antonio de Angelis377a1552018-11-22 17:02:40 +0000258 err = tfm_crypto_operation_release(&(operation->handle));
Antonio de Angelisa6f72162018-09-05 11:00:37 +0100259 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
260 return err;
261 }
262
263 return TFM_CRYPTO_ERR_PSA_SUCCESS;
264}
265/*!@}*/