1 /*
2 * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <psa/crypto.h>
8 #include "psa_crypto_client.h"
9 #include "crypto_caller_selector.h"
10
psa_hash_setup(psa_hash_operation_t * operation,psa_algorithm_t alg)11 psa_status_t psa_hash_setup(psa_hash_operation_t *operation,
12 psa_algorithm_t alg)
13 {
14 if (psa_crypto_client_instance.init_status != PSA_SUCCESS)
15 return psa_crypto_client_instance.init_status;
16
17 if (operation->handle)
18 return PSA_ERROR_BAD_STATE;
19
20 return crypto_caller_hash_setup(&psa_crypto_client_instance.base,
21 &operation->handle, alg);
22 }
23
psa_hash_update(psa_hash_operation_t * operation,const uint8_t * input,size_t input_length)24 psa_status_t psa_hash_update(psa_hash_operation_t *operation,
25 const uint8_t *input,
26 size_t input_length)
27 {
28 return crypto_caller_hash_update(&psa_crypto_client_instance.base,
29 operation->handle,
30 input, input_length);
31 }
32
psa_hash_finish(psa_hash_operation_t * operation,uint8_t * hash,size_t hash_size,size_t * hash_length)33 psa_status_t psa_hash_finish(psa_hash_operation_t *operation,
34 uint8_t *hash,
35 size_t hash_size,
36 size_t *hash_length)
37 {
38 return crypto_caller_hash_finish(&psa_crypto_client_instance.base,
39 operation->handle,
40 hash, hash_size, hash_length);
41 }
42
psa_hash_abort(psa_hash_operation_t * operation)43 psa_status_t psa_hash_abort(psa_hash_operation_t *operation)
44 {
45 return crypto_caller_hash_abort(&psa_crypto_client_instance.base,
46 operation->handle);
47 }
48
psa_hash_verify(psa_hash_operation_t * operation,const uint8_t * hash,size_t hash_length)49 psa_status_t psa_hash_verify(psa_hash_operation_t *operation,
50 const uint8_t *hash,
51 size_t hash_length)
52 {
53 return crypto_caller_hash_verify(&psa_crypto_client_instance.base,
54 operation->handle,
55 hash, hash_length);
56 }
57
psa_hash_clone(const psa_hash_operation_t * source_operation,psa_hash_operation_t * target_operation)58 psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation,
59 psa_hash_operation_t *target_operation)
60 {
61 if (target_operation->handle)
62 return PSA_ERROR_BAD_STATE;
63
64 return crypto_caller_hash_clone(&psa_crypto_client_instance.base,
65 source_operation->handle,
66 &target_operation->handle);
67 }
68
psa_hash_suspend(psa_hash_operation_t * operation,uint8_t * hash_state,size_t hash_state_size,size_t * hash_state_length)69 psa_status_t psa_hash_suspend(psa_hash_operation_t *operation,
70 uint8_t *hash_state,
71 size_t hash_state_size,
72 size_t *hash_state_length)
73 {
74 (void)operation;
75 (void)hash_state;
76 (void)hash_state_size;
77 (void)hash_state_length;
78
79 return PSA_ERROR_NOT_SUPPORTED;
80 }
81
psa_hash_resume(psa_hash_operation_t * operation,const uint8_t * hash_state,size_t hash_state_length)82 psa_status_t psa_hash_resume(psa_hash_operation_t *operation,
83 const uint8_t *hash_state,
84 size_t hash_state_length)
85 {
86 (void)operation;
87 (void)hash_state;
88 (void)hash_state_length;
89
90 return PSA_ERROR_NOT_SUPPORTED;
91 }
92
multi_hash_update(psa_hash_operation_t * operation,psa_algorithm_t alg,const uint8_t * input,size_t input_length)93 static psa_status_t multi_hash_update(psa_hash_operation_t *operation,
94 psa_algorithm_t alg,
95 const uint8_t *input,
96 size_t input_length)
97 {
98 *operation = psa_hash_operation_init();
99 psa_status_t psa_status = psa_hash_setup(operation, alg);
100 size_t max_update_size = crypto_caller_hash_max_update_size(&psa_crypto_client_instance.base);
101
102 if (!max_update_size) {
103
104 /* Don't know the max update size so assume that the entire
105 * input can be handled in a single update. If this isn't
106 * true, the first hash update operation will fail safely.
107 */
108 max_update_size = input_length;
109 }
110
111 if (psa_status == PSA_SUCCESS) {
112
113 size_t bytes_processed = 0;
114
115 while (bytes_processed < input_length) {
116
117 size_t bytes_remaining = input_length - bytes_processed;
118 size_t update_len = (bytes_remaining < max_update_size) ?
119 bytes_remaining :
120 max_update_size;
121
122 psa_status = psa_hash_update(operation, &input[bytes_processed], update_len);
123
124 if (psa_status != PSA_SUCCESS) {
125
126 psa_hash_abort(operation);
127 break;
128 }
129
130 bytes_processed += update_len;
131 }
132 }
133
134 return psa_status;
135 }
136
psa_hash_compare(psa_algorithm_t alg,const uint8_t * input,size_t input_length,const uint8_t * hash,size_t hash_length)137 psa_status_t psa_hash_compare(psa_algorithm_t alg,
138 const uint8_t *input,
139 size_t input_length,
140 const uint8_t *hash,
141 size_t hash_length)
142 {
143 psa_hash_operation_t operation;
144 psa_status_t psa_status = multi_hash_update(&operation, alg, input, input_length);
145
146 if (psa_status == PSA_SUCCESS) {
147
148 psa_status = psa_hash_verify(&operation, hash, hash_length);
149
150 if (psa_status != PSA_SUCCESS) {
151
152 psa_hash_abort(&operation);
153 }
154 }
155
156 return psa_status;
157 }
158
psa_hash_compute(psa_algorithm_t alg,const uint8_t * input,size_t input_length,uint8_t * hash,size_t hash_size,size_t * hash_length)159 psa_status_t psa_hash_compute(psa_algorithm_t alg,
160 const uint8_t *input,
161 size_t input_length,
162 uint8_t *hash,
163 size_t hash_size,
164 size_t *hash_length)
165 {
166 psa_hash_operation_t operation;
167 psa_status_t psa_status = multi_hash_update(&operation, alg, input, input_length);
168
169 if (psa_status == PSA_SUCCESS) {
170
171 psa_status = psa_hash_finish(&operation, hash, hash_size, hash_length);
172
173 if (psa_status != PSA_SUCCESS) {
174
175 psa_hash_abort(&operation);
176 }
177 }
178
179 return psa_status;
180 }
181