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