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 
11 
psa_mac_sign_setup(psa_mac_operation_t * operation,psa_key_id_t key,psa_algorithm_t alg)12 psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation,
13 	psa_key_id_t key,
14 	psa_algorithm_t alg)
15 {
16 	if (psa_crypto_client_instance.init_status != PSA_SUCCESS)
17 		return psa_crypto_client_instance.init_status;
18 
19 	if (operation->handle)
20 		return PSA_ERROR_BAD_STATE;
21 
22 	return crypto_caller_mac_sign_setup(&psa_crypto_client_instance.base,
23 		&operation->handle,
24 		key, alg);
25 }
26 
psa_mac_verify_setup(psa_mac_operation_t * operation,psa_key_id_t key,psa_algorithm_t alg)27 psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation,
28 	psa_key_id_t key,
29 	psa_algorithm_t alg)
30 {
31 	if (psa_crypto_client_instance.init_status != PSA_SUCCESS)
32 		return psa_crypto_client_instance.init_status;
33 
34 	if (operation->handle)
35 		return PSA_ERROR_BAD_STATE;
36 
37 	return crypto_caller_mac_verify_setup(&psa_crypto_client_instance.base,
38 		&operation->handle,
39 		key, alg);
40 }
41 
psa_mac_update(psa_mac_operation_t * operation,const uint8_t * input,size_t input_length)42 psa_status_t psa_mac_update(psa_mac_operation_t *operation,
43 	const uint8_t *input,
44 	size_t input_length)
45 {
46 	return crypto_caller_mac_update(&psa_crypto_client_instance.base,
47 		operation->handle,
48 		input, input_length);
49 }
50 
psa_mac_sign_finish(psa_mac_operation_t * operation,uint8_t * mac,size_t mac_size,size_t * mac_length)51 psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation,
52 	uint8_t *mac,
53 	size_t mac_size,
54 	size_t *mac_length)
55 {
56 	return crypto_caller_mac_sign_finish(&psa_crypto_client_instance.base,
57 		operation->handle,
58 		mac, mac_size, mac_length);
59 }
60 
psa_mac_verify_finish(psa_mac_operation_t * operation,const uint8_t * mac,size_t mac_length)61 psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation,
62 	const uint8_t *mac,
63 	size_t mac_length)
64 {
65 	return crypto_caller_mac_verify_finish(&psa_crypto_client_instance.base,
66 		operation->handle,
67 		mac, mac_length);
68 }
69 
psa_mac_abort(psa_mac_operation_t * operation)70 psa_status_t psa_mac_abort(psa_mac_operation_t *operation)
71 {
72 	return crypto_caller_mac_abort(&psa_crypto_client_instance.base,
73 		operation->handle);
74 }
75 
multi_mac_update(psa_mac_operation_t * operation,const uint8_t * input,size_t input_length)76 static psa_status_t multi_mac_update(psa_mac_operation_t *operation,
77 	const uint8_t *input,
78 	size_t input_length)
79 {
80 	psa_status_t psa_status = PSA_SUCCESS;
81 	size_t max_update_size = crypto_caller_mac_max_update_size(&psa_crypto_client_instance.base);
82 	size_t bytes_processed = 0;
83 
84 	if (!max_update_size) {
85 
86 		/* Don't know the max update size so assume that the entire
87 		 * input can be handled in a single update.  If this isn't
88 		 * true, the first mac update operation will fail safely.
89 		 */
90 		max_update_size = input_length;
91 	}
92 
93 	while (bytes_processed < input_length) {
94 
95 		size_t bytes_remaining = input_length - bytes_processed;
96 		size_t update_len = (bytes_remaining < max_update_size) ?
97 			bytes_remaining :
98 			max_update_size;
99 
100 		psa_status = psa_mac_update(operation, &input[bytes_processed], update_len);
101 
102 		if (psa_status != PSA_SUCCESS) {
103 
104 			psa_mac_abort(operation);
105 			break;
106 		}
107 
108 		bytes_processed += update_len;
109 	}
110 
111 	return psa_status;
112 }
113 
psa_mac_verify(psa_key_id_t key,psa_algorithm_t alg,const uint8_t * input,size_t input_length,const uint8_t * mac,size_t mac_length)114 psa_status_t psa_mac_verify(psa_key_id_t key,
115 	psa_algorithm_t alg,
116 	const uint8_t *input,
117 	size_t input_length,
118 	const uint8_t *mac,
119 	size_t mac_length)
120 {
121 	psa_mac_operation_t operation = psa_mac_operation_init();
122 	psa_status_t psa_status = psa_mac_verify_setup(&operation, key, alg);
123 
124 	if (psa_status == PSA_SUCCESS) {
125 
126 		psa_status = multi_mac_update(&operation, input, input_length);
127 	}
128 
129 	if (psa_status == PSA_SUCCESS) {
130 
131 		psa_status = psa_mac_verify_finish(&operation, mac, mac_length);
132 
133 		if (psa_status != PSA_SUCCESS) {
134 
135 			psa_mac_abort(&operation);
136 		}
137 	}
138 
139 	return psa_status;
140 }
141 
psa_mac_compute(psa_key_id_t key,psa_algorithm_t alg,const uint8_t * input,size_t input_length,uint8_t * mac,size_t mac_size,size_t * mac_length)142 psa_status_t psa_mac_compute(psa_key_id_t key,
143 	psa_algorithm_t alg,
144 	const uint8_t *input,
145 	size_t input_length,
146 	uint8_t *mac,
147 	size_t mac_size,
148 	size_t *mac_length)
149 {
150 	psa_mac_operation_t operation = psa_mac_operation_init();
151 	psa_status_t psa_status = psa_mac_sign_setup(&operation, key, alg);
152 
153 	if (psa_status == PSA_SUCCESS) {
154 
155 		psa_status = multi_mac_update(&operation, input, input_length);
156 	}
157 
158 	if (psa_status == PSA_SUCCESS) {
159 
160 		psa_status = psa_mac_sign_finish(&operation, mac, mac_size, mac_length);
161 
162 		if (psa_status != PSA_SUCCESS) {
163 
164 			psa_mac_abort(&operation);
165 		}
166 	}
167 
168 	return psa_status;
169 }
170