blob: d6e65400b50947f6e18f669d16db4ae4662411fc [file] [log] [blame]
Julian Halld4071382021-07-07 16:45:53 +01001/*
Julian Hallb8b026e2022-02-11 14:19:26 +00002 * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
Julian Halld4071382021-07-07 16:45:53 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Julian Halld4071382021-07-07 16:45:53 +01007#include <psa/crypto.h>
8#include "psa_crypto_client.h"
Julian Halla9490042021-08-04 10:43:34 +01009#include "crypto_caller_selector.h"
Julian Halld4071382021-07-07 16:45:53 +010010
11psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation,
12 psa_key_id_t key,
13 psa_algorithm_t alg)
14{
Julian Hallb8b026e2022-02-11 14:19:26 +000015 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
Julian Hall7a703402021-08-04 09:20:43 +010021 return crypto_caller_cipher_encrypt_setup(&psa_crypto_client_instance.base,
22 &operation->handle,
23 key, alg);
Julian Halld4071382021-07-07 16:45:53 +010024}
25
26psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation,
27 psa_key_id_t key,
28 psa_algorithm_t alg)
29{
Julian Hallb8b026e2022-02-11 14:19:26 +000030 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
Julian Hall7a703402021-08-04 09:20:43 +010036 return crypto_caller_cipher_decrypt_setup(&psa_crypto_client_instance.base,
37 &operation->handle,
38 key, alg);
Julian Halld4071382021-07-07 16:45:53 +010039}
40
41psa_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{
Julian Hall7a703402021-08-04 09:20:43 +010046 return crypto_caller_cipher_generate_iv(&psa_crypto_client_instance.base,
47 operation->handle,
48 iv, iv_size, iv_length);
Julian Halld4071382021-07-07 16:45:53 +010049}
50
51psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation,
52 const uint8_t *iv,
53 size_t iv_length)
54{
Julian Hall7a703402021-08-04 09:20:43 +010055 return crypto_caller_cipher_set_iv(&psa_crypto_client_instance.base,
56 operation->handle,
57 iv, iv_length);
Julian Halld4071382021-07-07 16:45:53 +010058}
59
60psa_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{
Julian Hall7a703402021-08-04 09:20:43 +010067 return crypto_caller_cipher_update(&psa_crypto_client_instance.base,
68 operation->handle,
69 input, input_length,
70 output, output_size, output_length);
Julian Halld4071382021-07-07 16:45:53 +010071}
72
73psa_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{
Julian Hall7a703402021-08-04 09:20:43 +010078 return crypto_caller_cipher_finish(&psa_crypto_client_instance.base,
79 operation->handle,
80 output, output_size, output_length);
Julian Halld4071382021-07-07 16:45:53 +010081}
82
83psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation)
84{
Julian Hall7a703402021-08-04 09:20:43 +010085 return crypto_caller_cipher_abort(&psa_crypto_client_instance.base,
86 operation->handle);
Julian Hall188953d2021-07-30 12:11:43 +010087}
88
89static 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;
Julian Hall7a703402021-08-04 09:20:43 +010097 size_t max_update_size =
98 crypto_caller_cipher_max_update_size(&psa_crypto_client_instance.base);
Julian Hall188953d2021-07-30 12:11:43 +010099 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
Julian Hall1fc2d922022-02-15 15:46:58 +0000114 while (bytes_input < input_length) {
115
116 if (bytes_output >= output_size) {
117
118 psa_status = PSA_ERROR_BUFFER_TOO_SMALL;
119 break;
120 }
Julian Hall188953d2021-07-30 12:11:43 +0100121
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
Julian Hall1fc2d922022-02-15 15:46:58 +0000132 if (psa_status != PSA_SUCCESS)
Julian Hall188953d2021-07-30 12:11:43 +0100133 break;
Julian Hall188953d2021-07-30 12:11:43 +0100134
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 }
Julian Hallc6d7e4d2022-02-16 10:37:04 +0000152 else {
153
154 psa_cipher_abort(operation);
155 }
Julian Hall188953d2021-07-30 12:11:43 +0100156 }
157 else {
158
Julian Hall188953d2021-07-30 12:11:43 +0100159 psa_status = PSA_ERROR_BUFFER_TOO_SMALL;
160 }
161 }
162
163 return psa_status;
164}
165
Julian Halld670b412021-07-19 15:16:27 +0100166psa_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{
Julian Hall188953d2021-07-30 12:11:43 +0100174 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
Julian Hall1fc2d922022-02-15 15:46:58 +0000179 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 }
Julian Hall188953d2021-07-30 12:11:43 +0100204 }
205
206 return psa_status;
Julian Halld670b412021-07-19 15:16:27 +0100207}
208
209psa_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{
Julian Hall1fc2d922022-02-15 15:46:58 +0000217 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
218 psa_status_t psa_status = psa_get_key_attributes(key, &attributes);
Julian Hall188953d2021-07-30 12:11:43 +0100219
220 if (psa_status == PSA_SUCCESS) {
221
Julian Hall1fc2d922022-02-15 15:46:58 +0000222 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);
Julian Hall188953d2021-07-30 12:11:43 +0100252 }
253
254 return psa_status;
Julian Halld670b412021-07-19 15:16:27 +0100255}