blob: 125b1734e73fc7db2a4316ced4c68ef34b01ba8c [file] [log] [blame]
Andrzej Kurek8a045ce2022-12-23 11:00:06 -05001/*
2 * PSA hashing layer on top of Mbed TLS software crypto
3 */
4/*
5 * Copyright The Mbed TLS Contributors
Dave Rodgman16799db2023-11-02 19:47:20 +00006 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Andrzej Kurek8a045ce2022-12-23 11:00:06 -05007 */
8
9#include "common.h"
10
Valerio Settic22e3ce2024-01-10 08:46:59 +010011/* This is needed for MBEDTLS_ERR_XXX macros */
12#include <mbedtls/error.h>
13
14#if defined(MBEDTLS_ASN1_WRITE_C)
15#include <mbedtls/asn1write.h>
16#include <psa/crypto_sizes.h>
17#endif
18
19#include "psa_util_internal.h"
20
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050021#if defined(MBEDTLS_PSA_CRYPTO_C)
22
23#include <psa/crypto.h>
24
Manuel Pégourié-Gonnardabfe6402023-06-20 09:59:13 +020025#if defined(MBEDTLS_MD_LIGHT)
26#include <mbedtls/md.h>
27#endif
28#if defined(MBEDTLS_LMS_C)
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050029#include <mbedtls/lms.h>
Manuel Pégourié-Gonnardabfe6402023-06-20 09:59:13 +020030#endif
31#if defined(MBEDTLS_SSL_TLS_C) && \
32 (defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3))
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050033#include <mbedtls/ssl.h>
Manuel Pégourié-Gonnardabfe6402023-06-20 09:59:13 +020034#endif
35#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) || \
Valerio Setti7e6aaa12023-07-11 16:59:21 +020036 defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC)
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050037#include <mbedtls/rsa.h>
Manuel Pégourié-Gonnardabfe6402023-06-20 09:59:13 +020038#endif
39#if defined(MBEDTLS_USE_PSA_CRYPTO) && \
40 defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
41#include <mbedtls/ecp.h>
42#endif
43#if defined(MBEDTLS_PK_C)
44#include <mbedtls/pk.h>
45#endif
Valerio Setti8ceaa752023-12-12 11:20:18 +010046#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
47#include <mbedtls/cipher.h>
48#endif
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050049
50/* PSA_SUCCESS is kept at the top of each error table since
51 * it's the most common status when everything functions properly. */
Manuel Pégourié-Gonnard725d2e22023-03-29 12:38:37 +020052#if defined(MBEDTLS_MD_LIGHT)
Andrzej Kurek270b3f92023-03-03 05:54:13 -050053const mbedtls_error_pair_t psa_to_md_errors[] =
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050054{
Andrzej Kurek747ab4e2023-02-28 10:32:47 -050055 { PSA_SUCCESS, 0 },
56 { PSA_ERROR_NOT_SUPPORTED, MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE },
57 { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_MD_BAD_INPUT_DATA },
58 { PSA_ERROR_INSUFFICIENT_MEMORY, MBEDTLS_ERR_MD_ALLOC_FAILED }
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050059};
60#endif
Valerio Setti8ceaa752023-12-12 11:20:18 +010061
62#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
63const mbedtls_error_pair_t psa_to_cipher_errors[] =
64{
65 { PSA_SUCCESS, 0 },
66 { PSA_ERROR_NOT_SUPPORTED, MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE },
67 { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA },
68 { PSA_ERROR_INSUFFICIENT_MEMORY, MBEDTLS_ERR_CIPHER_ALLOC_FAILED }
69};
70#endif
71
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050072#if defined(MBEDTLS_LMS_C)
Andrzej Kurek270b3f92023-03-03 05:54:13 -050073const mbedtls_error_pair_t psa_to_lms_errors[] =
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050074{
Andrzej Kurek747ab4e2023-02-28 10:32:47 -050075 { PSA_SUCCESS, 0 },
76 { PSA_ERROR_BUFFER_TOO_SMALL, MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL },
77 { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_LMS_BAD_INPUT_DATA }
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050078};
79#endif
Valerio Setti8ceaa752023-12-12 11:20:18 +010080
Manuel Pégourié-Gonnardabfe6402023-06-20 09:59:13 +020081#if defined(MBEDTLS_SSL_TLS_C) && \
82 (defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3))
Andrzej Kurek270b3f92023-03-03 05:54:13 -050083const mbedtls_error_pair_t psa_to_ssl_errors[] =
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050084{
Andrzej Kurek747ab4e2023-02-28 10:32:47 -050085 { PSA_SUCCESS, 0 },
86 { PSA_ERROR_INSUFFICIENT_MEMORY, MBEDTLS_ERR_SSL_ALLOC_FAILED },
87 { PSA_ERROR_NOT_SUPPORTED, MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE },
88 { PSA_ERROR_INVALID_SIGNATURE, MBEDTLS_ERR_SSL_INVALID_MAC },
89 { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_SSL_BAD_INPUT_DATA },
90 { PSA_ERROR_BAD_STATE, MBEDTLS_ERR_SSL_INTERNAL_ERROR },
91 { PSA_ERROR_BUFFER_TOO_SMALL, MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL }
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050092};
93#endif
94
95#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) || \
Valerio Settif6d4dfb2023-07-10 10:55:12 +020096 defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC)
Andrzej Kurek270b3f92023-03-03 05:54:13 -050097const mbedtls_error_pair_t psa_to_pk_rsa_errors[] =
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050098{
Andrzej Kurek747ab4e2023-02-28 10:32:47 -050099 { PSA_SUCCESS, 0 },
100 { PSA_ERROR_NOT_PERMITTED, MBEDTLS_ERR_RSA_BAD_INPUT_DATA },
101 { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_RSA_BAD_INPUT_DATA },
102 { PSA_ERROR_INVALID_HANDLE, MBEDTLS_ERR_RSA_BAD_INPUT_DATA },
103 { PSA_ERROR_BUFFER_TOO_SMALL, MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE },
104 { PSA_ERROR_INSUFFICIENT_ENTROPY, MBEDTLS_ERR_RSA_RNG_FAILED },
105 { PSA_ERROR_INVALID_SIGNATURE, MBEDTLS_ERR_RSA_VERIFY_FAILED },
106 { PSA_ERROR_INVALID_PADDING, MBEDTLS_ERR_RSA_INVALID_PADDING }
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500107};
108#endif
109
110#if defined(MBEDTLS_USE_PSA_CRYPTO) && \
111 defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
Andrzej Kurek270b3f92023-03-03 05:54:13 -0500112const mbedtls_error_pair_t psa_to_pk_ecdsa_errors[] =
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500113{
Andrzej Kurek747ab4e2023-02-28 10:32:47 -0500114 { PSA_SUCCESS, 0 },
115 { PSA_ERROR_NOT_PERMITTED, MBEDTLS_ERR_ECP_BAD_INPUT_DATA },
116 { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_ECP_BAD_INPUT_DATA },
117 { PSA_ERROR_INVALID_HANDLE, MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE },
118 { PSA_ERROR_BUFFER_TOO_SMALL, MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL },
119 { PSA_ERROR_INSUFFICIENT_ENTROPY, MBEDTLS_ERR_ECP_RANDOM_FAILED },
120 { PSA_ERROR_INVALID_SIGNATURE, MBEDTLS_ERR_ECP_VERIFY_FAILED }
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500121};
122#endif
123
124int psa_generic_status_to_mbedtls(psa_status_t status)
125{
126 switch (status) {
127 case PSA_SUCCESS:
128 return 0;
129 case PSA_ERROR_NOT_SUPPORTED:
130 return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;
131 case PSA_ERROR_CORRUPTION_DETECTED:
132 return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
133 case PSA_ERROR_COMMUNICATION_FAILURE:
134 case PSA_ERROR_HARDWARE_FAILURE:
135 return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
136 case PSA_ERROR_NOT_PERMITTED:
137 default:
138 return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
139 }
140}
141
142int psa_status_to_mbedtls(psa_status_t status,
Andrzej Kurek270b3f92023-03-03 05:54:13 -0500143 const mbedtls_error_pair_t *local_translations,
Valerio Settiab9dc662023-03-27 14:02:08 +0200144 size_t local_errors_num,
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500145 int (*fallback_f)(psa_status_t))
146{
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500147 for (size_t i = 0; i < local_errors_num; i++) {
Andrzej Kurek747ab4e2023-02-28 10:32:47 -0500148 if (status == local_translations[i].psa_status) {
149 return local_translations[i].mbedtls_error;
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500150 }
151 }
152 return fallback_f(status);
153}
154
Manuel Pégourié-Gonnardabfe6402023-06-20 09:59:13 +0200155#if defined(MBEDTLS_PK_C)
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500156int psa_pk_status_to_mbedtls(psa_status_t status)
157{
158 switch (status) {
159 case PSA_ERROR_INVALID_HANDLE:
160 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
161 case PSA_ERROR_BUFFER_TOO_SMALL:
162 return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;
163 case PSA_ERROR_NOT_SUPPORTED:
164 return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
165 case PSA_ERROR_INVALID_ARGUMENT:
166 return MBEDTLS_ERR_PK_INVALID_ALG;
Gilles Peskinefc3d8662024-02-09 19:26:37 +0100167 case PSA_ERROR_NOT_PERMITTED:
168 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500169 case PSA_ERROR_INSUFFICIENT_MEMORY:
170 return MBEDTLS_ERR_PK_ALLOC_FAILED;
171 case PSA_ERROR_BAD_STATE:
172 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
173 case PSA_ERROR_DATA_CORRUPT:
174 case PSA_ERROR_DATA_INVALID:
175 case PSA_ERROR_STORAGE_FAILURE:
176 return MBEDTLS_ERR_PK_FILE_IO_ERROR;
177 default:
178 return psa_generic_status_to_mbedtls(status);
179 }
180}
Manuel Pégourié-Gonnardabfe6402023-06-20 09:59:13 +0200181#endif /* MBEDTLS_PK_C */
Joakim Anderssonb3491082023-12-11 21:29:19 +0100182
183/****************************************************************/
184/* Key management */
185/****************************************************************/
186
187#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
188psa_ecc_family_t mbedtls_ecc_group_to_psa(mbedtls_ecp_group_id grpid,
189 size_t *bits)
190{
191 switch (grpid) {
192#if defined(MBEDTLS_ECP_HAVE_SECP192R1)
193 case MBEDTLS_ECP_DP_SECP192R1:
194 *bits = 192;
195 return PSA_ECC_FAMILY_SECP_R1;
196#endif
197#if defined(MBEDTLS_ECP_HAVE_SECP224R1)
198 case MBEDTLS_ECP_DP_SECP224R1:
199 *bits = 224;
200 return PSA_ECC_FAMILY_SECP_R1;
201#endif
202#if defined(MBEDTLS_ECP_HAVE_SECP256R1)
203 case MBEDTLS_ECP_DP_SECP256R1:
204 *bits = 256;
205 return PSA_ECC_FAMILY_SECP_R1;
206#endif
207#if defined(MBEDTLS_ECP_HAVE_SECP384R1)
208 case MBEDTLS_ECP_DP_SECP384R1:
209 *bits = 384;
210 return PSA_ECC_FAMILY_SECP_R1;
211#endif
212#if defined(MBEDTLS_ECP_HAVE_SECP521R1)
213 case MBEDTLS_ECP_DP_SECP521R1:
214 *bits = 521;
215 return PSA_ECC_FAMILY_SECP_R1;
216#endif
217#if defined(MBEDTLS_ECP_HAVE_BP256R1)
218 case MBEDTLS_ECP_DP_BP256R1:
219 *bits = 256;
220 return PSA_ECC_FAMILY_BRAINPOOL_P_R1;
221#endif
222#if defined(MBEDTLS_ECP_HAVE_BP384R1)
223 case MBEDTLS_ECP_DP_BP384R1:
224 *bits = 384;
225 return PSA_ECC_FAMILY_BRAINPOOL_P_R1;
226#endif
227#if defined(MBEDTLS_ECP_HAVE_BP512R1)
228 case MBEDTLS_ECP_DP_BP512R1:
229 *bits = 512;
230 return PSA_ECC_FAMILY_BRAINPOOL_P_R1;
231#endif
232#if defined(MBEDTLS_ECP_HAVE_CURVE25519)
233 case MBEDTLS_ECP_DP_CURVE25519:
234 *bits = 255;
235 return PSA_ECC_FAMILY_MONTGOMERY;
236#endif
237#if defined(MBEDTLS_ECP_HAVE_SECP192K1)
238 case MBEDTLS_ECP_DP_SECP192K1:
239 *bits = 192;
240 return PSA_ECC_FAMILY_SECP_K1;
241#endif
242#if defined(MBEDTLS_ECP_HAVE_SECP224K1)
Valerio Setti78636272024-01-04 13:17:04 +0100243 /* secp224k1 is not and will not be supported in PSA (#3541). */
Joakim Anderssonb3491082023-12-11 21:29:19 +0100244#endif
245#if defined(MBEDTLS_ECP_HAVE_SECP256K1)
246 case MBEDTLS_ECP_DP_SECP256K1:
247 *bits = 256;
248 return PSA_ECC_FAMILY_SECP_K1;
249#endif
250#if defined(MBEDTLS_ECP_HAVE_CURVE448)
251 case MBEDTLS_ECP_DP_CURVE448:
252 *bits = 448;
253 return PSA_ECC_FAMILY_MONTGOMERY;
254#endif
255 default:
256 *bits = 0;
257 return 0;
258 }
259}
260
Valerio Setti39faa9c2024-01-09 09:11:22 +0100261mbedtls_ecp_group_id mbedtls_ecc_group_from_psa(psa_ecc_family_t family,
Valerio Settid36c3132023-12-21 14:03:51 +0100262 size_t bits)
Joakim Anderssonb3491082023-12-11 21:29:19 +0100263{
Valerio Setti39faa9c2024-01-09 09:11:22 +0100264 switch (family) {
Joakim Anderssonb3491082023-12-11 21:29:19 +0100265 case PSA_ECC_FAMILY_SECP_R1:
266 switch (bits) {
267#if defined(PSA_WANT_ECC_SECP_R1_192)
268 case 192:
269 return MBEDTLS_ECP_DP_SECP192R1;
270#endif
271#if defined(PSA_WANT_ECC_SECP_R1_224)
272 case 224:
273 return MBEDTLS_ECP_DP_SECP224R1;
274#endif
275#if defined(PSA_WANT_ECC_SECP_R1_256)
276 case 256:
277 return MBEDTLS_ECP_DP_SECP256R1;
278#endif
279#if defined(PSA_WANT_ECC_SECP_R1_384)
280 case 384:
281 return MBEDTLS_ECP_DP_SECP384R1;
282#endif
283#if defined(PSA_WANT_ECC_SECP_R1_521)
284 case 521:
Valerio Settid36c3132023-12-21 14:03:51 +0100285 return MBEDTLS_ECP_DP_SECP521R1;
Joakim Anderssonb3491082023-12-11 21:29:19 +0100286#endif
287 }
288 break;
289
290 case PSA_ECC_FAMILY_BRAINPOOL_P_R1:
291 switch (bits) {
292#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256)
293 case 256:
294 return MBEDTLS_ECP_DP_BP256R1;
295#endif
296#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384)
297 case 384:
298 return MBEDTLS_ECP_DP_BP384R1;
299#endif
300#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512)
301 case 512:
302 return MBEDTLS_ECP_DP_BP512R1;
303#endif
304 }
305 break;
306
307 case PSA_ECC_FAMILY_MONTGOMERY:
308 switch (bits) {
309#if defined(PSA_WANT_ECC_MONTGOMERY_255)
310 case 255:
Valerio Settid36c3132023-12-21 14:03:51 +0100311 return MBEDTLS_ECP_DP_CURVE25519;
Joakim Anderssonb3491082023-12-11 21:29:19 +0100312#endif
313#if defined(PSA_WANT_ECC_MONTGOMERY_448)
314 case 448:
315 return MBEDTLS_ECP_DP_CURVE448;
316#endif
317 }
318 break;
319
320 case PSA_ECC_FAMILY_SECP_K1:
321 switch (bits) {
322#if defined(PSA_WANT_ECC_SECP_K1_192)
323 case 192:
324 return MBEDTLS_ECP_DP_SECP192K1;
325#endif
326#if defined(PSA_WANT_ECC_SECP_K1_224)
Valerio Setti78636272024-01-04 13:17:04 +0100327 /* secp224k1 is not and will not be supported in PSA (#3541). */
Joakim Anderssonb3491082023-12-11 21:29:19 +0100328#endif
329#if defined(PSA_WANT_ECC_SECP_K1_256)
330 case 256:
331 return MBEDTLS_ECP_DP_SECP256K1;
332#endif
333 }
334 break;
335 }
336
Joakim Anderssonb3491082023-12-11 21:29:19 +0100337 return MBEDTLS_ECP_DP_NONE;
338}
339#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */
340
Valerio Settic22e3ce2024-01-10 08:46:59 +0100341#endif /* MBEDTLS_PSA_CRYPTO_C */
342
Valerio Settif4d2dc22024-01-16 10:57:48 +0100343#if defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA)
344
Valerio Setti84890c92024-01-09 14:20:23 +0100345/**
346 * \brief Convert a single raw coordinate to DER ASN.1 format. The output der
347 * buffer is filled backward (i.e. starting from its end).
348 *
349 * \param raw_buf Buffer containing the raw coordinate to be
350 * converted.
Valerio Setti2bd0ecd2024-02-05 15:25:15 +0100351 * \param raw_len Length of raw_buf in bytes. This must be > 0.
Valerio Setti84890c92024-01-09 14:20:23 +0100352 * \param der_buf_start Pointer to the beginning of the buffer which
353 * will be filled with the DER converted data.
354 * \param der_buf_end End of the buffer used to store the DER output.
355 *
356 * \return On success, the amount of data (in bytes) written to
357 * the DER buffer.
358 * \return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if the provided der
359 * buffer is too small to contain all the converted data.
360 * \return MBEDTLS_ERR_ASN1_INVALID_DATA if the input raw
361 * coordinate is null (i.e. all zeros).
362 *
363 * \warning Raw and der buffer must not be overlapping.
Valerio Setti75501f52024-01-08 16:49:17 +0100364 */
365static int convert_raw_to_der_single_int(const unsigned char *raw_buf, size_t raw_len,
366 unsigned char *der_buf_start,
367 unsigned char *der_buf_end)
368{
369 unsigned char *p = der_buf_end;
Valerio Setti954ef4b2024-02-05 12:06:46 +0100370 int len;
Valerio Setti75501f52024-01-08 16:49:17 +0100371 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
372
Valerio Setti954ef4b2024-02-05 12:06:46 +0100373 /* ASN.1 DER encoding requires minimal length, so skip leading 0s.
374 * Provided input MPIs should not be 0, but as a failsafe measure, still
375 * detect that and return error in case. */
376 while (*raw_buf == 0x00) {
377 ++raw_buf;
378 --raw_len;
379 if (raw_len == 0) {
380 return MBEDTLS_ERR_ASN1_INVALID_DATA;
381 }
382 }
383 len = (int) raw_len;
384
Valerio Setti75501f52024-01-08 16:49:17 +0100385 /* Copy the raw coordinate to the end of der_buf. */
386 if ((p - der_buf_start) < len) {
387 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
388 }
389 p -= len;
390 memcpy(p, raw_buf, len);
391
Valerio Setti75501f52024-01-08 16:49:17 +0100392 /* If MSb is 1, ASN.1 requires that we prepend a 0. */
393 if (*p & 0x80) {
394 if ((p - der_buf_start) < 1) {
395 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
396 }
397 --p;
398 *p = 0x00;
399 ++len;
400 }
401
402 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, der_buf_start, len));
403 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, der_buf_start, MBEDTLS_ASN1_INTEGER));
404
405 return len;
406}
407
Valerio Setti315e4af2024-02-05 10:09:15 +0100408int mbedtls_ecdsa_raw_to_der(size_t bits, const unsigned char *raw, size_t raw_len,
409 unsigned char *der, size_t der_size, size_t *der_len)
Valerio Setti75501f52024-01-08 16:49:17 +0100410{
411 unsigned char r[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)];
412 unsigned char s[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)];
413 const size_t coordinate_len = PSA_BITS_TO_BYTES(bits);
414 size_t len = 0;
415 unsigned char *p = der + der_size;
416 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
417
Valerio Setticf81f692024-02-06 16:57:12 +0100418 if (raw_len != (2 * coordinate_len)) {
Valerio Setti75501f52024-01-08 16:49:17 +0100419 return MBEDTLS_ERR_ASN1_INVALID_DATA;
420 }
421
422 /* Since raw and der buffers might overlap, dump r and s before starting
423 * the conversion. */
Valerio Setti75501f52024-01-08 16:49:17 +0100424 memcpy(r, raw, coordinate_len);
Valerio Setti75501f52024-01-08 16:49:17 +0100425 memcpy(s, raw + coordinate_len, coordinate_len);
426
427 /* der buffer will initially be written starting from its end so we pick s
428 * first and then r. */
429 ret = convert_raw_to_der_single_int(s, coordinate_len, der, p);
430 if (ret < 0) {
431 return ret;
432 }
433 p -= ret;
434 len += ret;
435
436 ret = convert_raw_to_der_single_int(r, coordinate_len, der, p);
437 if (ret < 0) {
438 return ret;
439 }
440 p -= ret;
441 len += ret;
442
443 /* Add ASN.1 header (len + tag). */
444 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, der, len));
445 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, der,
446 MBEDTLS_ASN1_CONSTRUCTED |
447 MBEDTLS_ASN1_SEQUENCE));
448
449 /* memmove the content of der buffer to its beginnig. */
450 memmove(der, p, len);
451 *der_len = len;
452
453 return 0;
454}
Valerio Setti75501f52024-01-08 16:49:17 +0100455
Valerio Setti84890c92024-01-09 14:20:23 +0100456/**
457 * \brief Convert a single integer from ASN.1 DER format to raw.
458 *
459 * \param der Buffer containing the DER integer value to be
460 * converted.
461 * \param der_len Length of the der buffer in bytes.
462 * \param raw Output buffer that will be filled with the
463 * converted data. This should be at least
Valerio Setti78da7462024-01-30 15:08:40 +0100464 * coordinate_size bytes and it must be zeroed before
465 * calling this function.
Valerio Setti84890c92024-01-09 14:20:23 +0100466 * \param coordinate_size Size (in bytes) of a single coordinate in raw
467 * format.
468 *
469 * \return On success, the amount of DER data parsed from the
470 * provided der buffer.
471 * \return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the integer tag
472 * is missing in the der buffer.
473 * \return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the integer
474 * is null (i.e. all zeros) or if the output raw buffer
475 * is too small to contain the converted raw value.
476 *
477 * \warning Der and raw buffers must not be overlapping.
Valerio Setti75501f52024-01-08 16:49:17 +0100478 */
479static int convert_der_to_raw_single_int(unsigned char *der, size_t der_len,
Valerio Setti122c94f2024-01-29 18:02:03 +0100480 unsigned char *raw, size_t coordinate_size)
Valerio Setti75501f52024-01-08 16:49:17 +0100481{
482 unsigned char *p = der;
483 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
484 size_t unpadded_len, padding_len = 0;
485
486 /* Get the length of ASN.1 element (i.e. the integer we need to parse). */
487 ret = mbedtls_asn1_get_tag(&p, p + der_len, &unpadded_len,
488 MBEDTLS_ASN1_INTEGER);
489 if (ret != 0) {
490 return ret;
491 }
492
Valerio Setti19103902024-02-07 16:16:58 +0100493 /* It's invalid to have:
494 * - unpadded_len == 0.
495 * - MSb set without a leading 0x00 (leading 0x00 is checked below). */
496 if (((unpadded_len == 0) || (*p & 0x80) != 0)) {
Valerio Setti091bdc42024-02-05 16:17:44 +0100497 return MBEDTLS_ERR_ASN1_INVALID_DATA;
498 }
499
Valerio Setti86bae522024-01-10 11:12:31 +0100500 /* Skip possible leading zero */
Valerio Setti19103902024-02-07 16:16:58 +0100501 if (*p == 0x00) {
Valerio Setti75501f52024-01-08 16:49:17 +0100502 p++;
503 unpadded_len--;
Valerio Setti19103902024-02-07 16:16:58 +0100504 /* It is not allowed to have more than 1 leading zero.
505 * Ignore the case in which unpadded_len = 0 because that's a 0 encoded
506 * in ASN.1 format (i.e. 020100). */
507 if ((unpadded_len > 0) && (*p == 0x00)) {
Valerio Setti091bdc42024-02-05 16:17:44 +0100508 return MBEDTLS_ERR_ASN1_INVALID_DATA;
509 }
Valerio Setti2d73baf2024-02-01 15:25:17 +0100510 }
Valerio Setti75501f52024-01-08 16:49:17 +0100511
Valerio Setti9b9b5a52024-01-29 16:53:03 +0100512 if (unpadded_len > coordinate_size) {
513 /* Parsed number is longer than the maximum expected value. */
514 return MBEDTLS_ERR_ASN1_INVALID_DATA;
Valerio Setti75501f52024-01-08 16:49:17 +0100515 }
Valerio Setti78da7462024-01-30 15:08:40 +0100516 padding_len = coordinate_size - unpadded_len;
517 /* raw buffer was already zeroed by the calling function so zero-padding
518 * operation is skipped here. */
Valerio Setti75501f52024-01-08 16:49:17 +0100519 memcpy(raw + padding_len, p, unpadded_len);
520 p += unpadded_len;
521
522 return (int) (p - der);
523}
524
Valerio Setti315e4af2024-02-05 10:09:15 +0100525int mbedtls_ecdsa_der_to_raw(size_t bits, const unsigned char *der, size_t der_len,
526 unsigned char *raw, size_t raw_size, size_t *raw_len)
Valerio Setti75501f52024-01-08 16:49:17 +0100527{
528 unsigned char raw_tmp[PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE];
529 unsigned char *p = (unsigned char *) der;
530 size_t data_len;
531 size_t coordinate_size = PSA_BITS_TO_BYTES(bits);
532 int ret;
533
534 /* The output raw buffer should be at least twice the size of a raw
535 * coordinate in order to store r and s. */
536 if (raw_size < coordinate_size * 2) {
537 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
538 }
539
540 /* Check that the provided input DER buffer has the right header. */
541 ret = mbedtls_asn1_get_tag(&p, der + der_len, &data_len,
542 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
543 if (ret != 0) {
544 return ret;
545 }
546
Valerio Setti05c256f2024-02-05 16:02:11 +0100547 memset(raw_tmp, 0, 2 * coordinate_size);
Valerio Setti75501f52024-01-08 16:49:17 +0100548
549 /* Extract r */
Valerio Setti122c94f2024-01-29 18:02:03 +0100550 ret = convert_der_to_raw_single_int(p, data_len, raw_tmp, coordinate_size);
Valerio Setti75501f52024-01-08 16:49:17 +0100551 if (ret < 0) {
552 return ret;
553 }
554 p += ret;
555 data_len -= ret;
556
557 /* Extract s */
558 ret = convert_der_to_raw_single_int(p, data_len, raw_tmp + coordinate_size,
Valerio Setti75501f52024-01-08 16:49:17 +0100559 coordinate_size);
560 if (ret < 0) {
561 return ret;
562 }
563 p += ret;
564 data_len -= ret;
565
566 /* Check that we consumed all the input der data. */
Valerio Setti5713c8a2024-01-09 15:48:37 +0100567 if ((size_t) (p - der) != der_len) {
Valerio Setti75501f52024-01-08 16:49:17 +0100568 return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
569 }
570
571 memcpy(raw, raw_tmp, 2 * coordinate_size);
572 *raw_len = 2 * coordinate_size;
573
574 return 0;
575}
Valerio Settif4d2dc22024-01-16 10:57:48 +0100576
577#endif /* MBEDTLS_PSA_UTIL_HAVE_ECDSA */