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_cipher_encrypt_setup(psa_cipher_operation_t * operation,psa_key_id_t key,psa_algorithm_t alg)11 psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation,
12 	psa_key_id_t key,
13 	psa_algorithm_t alg)
14 {
15 	if (psa_crypto_client_instance.init_status != PSA_SUCCESS)
16 		return psa_crypto_client_instance.init_status;
17 
18 	if (operation->handle)
19 		return PSA_ERROR_BAD_STATE;
20 
21 	return crypto_caller_cipher_encrypt_setup(&psa_crypto_client_instance.base,
22 		&operation->handle,
23 		key, alg);
24 }
25 
psa_cipher_decrypt_setup(psa_cipher_operation_t * operation,psa_key_id_t key,psa_algorithm_t alg)26 psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation,
27 	psa_key_id_t key,
28 	psa_algorithm_t alg)
29 {
30 	if (psa_crypto_client_instance.init_status != PSA_SUCCESS)
31 		return psa_crypto_client_instance.init_status;
32 
33 	if (operation->handle)
34 		return PSA_ERROR_BAD_STATE;
35 
36 	return crypto_caller_cipher_decrypt_setup(&psa_crypto_client_instance.base,
37 		&operation->handle,
38 		key, alg);
39 }
40 
psa_cipher_generate_iv(psa_cipher_operation_t * operation,uint8_t * iv,size_t iv_size,size_t * iv_length)41 psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation,
42 	uint8_t *iv,
43 	size_t iv_size,
44 	size_t *iv_length)
45 {
46 	return crypto_caller_cipher_generate_iv(&psa_crypto_client_instance.base,
47 		operation->handle,
48 		iv, iv_size, iv_length);
49 }
50 
psa_cipher_set_iv(psa_cipher_operation_t * operation,const uint8_t * iv,size_t iv_length)51 psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation,
52 	const uint8_t *iv,
53 	size_t iv_length)
54 {
55 	return crypto_caller_cipher_set_iv(&psa_crypto_client_instance.base,
56 		operation->handle,
57 		iv, iv_length);
58 }
59 
psa_cipher_update(psa_cipher_operation_t * operation,const uint8_t * input,size_t input_length,uint8_t * output,size_t output_size,size_t * output_length)60 psa_status_t psa_cipher_update(psa_cipher_operation_t *operation,
61 	const uint8_t *input,
62 	size_t input_length,
63 	uint8_t *output,
64 	size_t output_size,
65 	size_t *output_length)
66 {
67 	return crypto_caller_cipher_update(&psa_crypto_client_instance.base,
68 		operation->handle,
69 		input, input_length,
70 		output, output_size, output_length);
71 }
72 
psa_cipher_finish(psa_cipher_operation_t * operation,uint8_t * output,size_t output_size,size_t * output_length)73 psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation,
74 	uint8_t *output,
75 	size_t output_size,
76 	size_t *output_length)
77 {
78 	return crypto_caller_cipher_finish(&psa_crypto_client_instance.base,
79 		operation->handle,
80 		output, output_size, output_length);
81 }
82 
psa_cipher_abort(psa_cipher_operation_t * operation)83 psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation)
84 {
85 	return crypto_caller_cipher_abort(&psa_crypto_client_instance.base,
86 		operation->handle);
87 }
88 
multi_cipher_update(psa_cipher_operation_t * operation,const uint8_t * input,size_t input_length,uint8_t * output,size_t output_size,size_t * output_length)89 static psa_status_t multi_cipher_update(psa_cipher_operation_t *operation,
90 	const uint8_t *input,
91 	size_t input_length,
92 	uint8_t *output,
93 	size_t output_size,
94 	size_t *output_length)
95 {
96 	psa_status_t psa_status = PSA_SUCCESS;
97 	size_t max_update_size =
98 		crypto_caller_cipher_max_update_size(&psa_crypto_client_instance.base);
99 	size_t bytes_input = 0;
100 	size_t bytes_output = 0;
101 
102 	*output_length = 0;
103 
104 	if (!max_update_size) {
105 
106 		/* Don't know the max update size so assume that the entire
107 		 * input and output can be handled in a single update.  If
108 		 * this isn't true, the first cipher update operation will fail
109 		 * safely.
110 		 */
111 		max_update_size = input_length;
112 	}
113 
114 	while (bytes_input < input_length) {
115 
116 		if (bytes_output >= output_size) {
117 
118 			psa_status = PSA_ERROR_BUFFER_TOO_SMALL;
119 			break;
120 		}
121 
122 		size_t update_output_len = 0;
123 		size_t bytes_remaining = input_length - bytes_input;
124 		size_t update_len = (bytes_remaining < max_update_size) ?
125 			bytes_remaining :
126 			max_update_size;
127 
128 		psa_status = psa_cipher_update(operation,
129 			&input[bytes_input], update_len,
130 			&output[bytes_output], output_size - bytes_output, &update_output_len);
131 
132 		if (psa_status != PSA_SUCCESS)
133 			break;
134 
135 		bytes_input += update_len;
136 		bytes_output += update_output_len;
137 	}
138 
139 	if (psa_status == PSA_SUCCESS) {
140 
141 		if (bytes_output < output_size) {
142 
143 			size_t finish_output_len = 0;
144 
145 			psa_status = psa_cipher_finish(operation,
146 				&output[bytes_output], output_size - bytes_output, &finish_output_len);
147 
148 			if (psa_status == PSA_SUCCESS) {
149 
150 				*output_length = bytes_output + finish_output_len;
151 			}
152 			else {
153 
154 				psa_cipher_abort(operation);
155 			}
156 		}
157 		else {
158 
159 			psa_status = PSA_ERROR_BUFFER_TOO_SMALL;
160 		}
161 	}
162 
163 	return psa_status;
164 }
165 
psa_cipher_encrypt(psa_key_id_t key,psa_algorithm_t alg,const uint8_t * input,size_t input_length,uint8_t * output,size_t output_size,size_t * output_length)166 psa_status_t psa_cipher_encrypt(psa_key_id_t key,
167 	psa_algorithm_t alg,
168 	const uint8_t *input,
169 	size_t input_length,
170 	uint8_t *output,
171 	size_t output_size,
172 	size_t *output_length)
173 {
174 	psa_cipher_operation_t operation = psa_cipher_operation_init();
175 	psa_status_t psa_status = psa_cipher_encrypt_setup(&operation, key, alg);
176 
177 	if (psa_status == PSA_SUCCESS) {
178 
179 		size_t ciphertext_len = 0;
180 		size_t iv_len = 0;
181 
182 		psa_status = psa_cipher_generate_iv(&operation, output, output_size, &iv_len);
183 
184 		if (psa_status == PSA_SUCCESS) {
185 
186 			if (iv_len <= output_size) {
187 
188 				psa_status = multi_cipher_update(&operation,
189 					input, input_length,
190 					&output[iv_len], output_size - iv_len, &ciphertext_len);
191 
192 				*output_length = iv_len + ciphertext_len;
193 			}
194 			else {
195 
196 				psa_status = PSA_ERROR_BUFFER_TOO_SMALL;
197 			}
198 		}
199 
200 		if (psa_status != PSA_SUCCESS) {
201 
202 			psa_cipher_abort(&operation);
203 		}
204 	}
205 
206 	return psa_status;
207 }
208 
psa_cipher_decrypt(psa_key_id_t key,psa_algorithm_t alg,const uint8_t * input,size_t input_length,uint8_t * output,size_t output_size,size_t * output_length)209 psa_status_t psa_cipher_decrypt(psa_key_id_t key,
210 	psa_algorithm_t alg,
211 	const uint8_t *input,
212 	size_t input_length,
213 	uint8_t *output,
214 	size_t output_size,
215 	size_t *output_length)
216 {
217 	psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
218 	psa_status_t psa_status = psa_get_key_attributes(key, &attributes);
219 
220 	if (psa_status == PSA_SUCCESS) {
221 
222 		psa_cipher_operation_t operation = psa_cipher_operation_init();
223 		psa_status = psa_cipher_decrypt_setup(&operation, key, alg);
224 
225 		if (psa_status == PSA_SUCCESS) {
226 
227 			size_t iv_len = PSA_CIPHER_IV_LENGTH(psa_get_key_type(&attributes), alg);
228 
229 			if (input_length >= iv_len) {
230 
231 				psa_status = psa_cipher_set_iv(&operation, input, iv_len);
232 
233 				if (psa_status == PSA_SUCCESS) {
234 
235 					psa_status = multi_cipher_update(&operation,
236 						&input[iv_len], input_length - iv_len,
237 						output, output_size, output_length);
238 				}
239 			}
240 			else {
241 
242 				psa_status = PSA_ERROR_INVALID_ARGUMENT;
243 			}
244 
245 			if (psa_status != PSA_SUCCESS) {
246 
247 				psa_cipher_abort(&operation);
248 			}
249 		}
250 
251 		psa_reset_key_attributes(&attributes);
252 	}
253 
254 	return psa_status;
255 }
256