blob: f4417794451c2292be6fe8961b670354e6a235cb [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 */
Harry Ramseya05bfee2024-10-14 07:19:01 +010012#include <mbedtls/error_common.h>
Valerio Settic22e3ce2024-01-10 08:46:59 +010013
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
Valerio Setti1a58e9a2024-02-29 16:14:29 +010021#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050022
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
Manuel Pégourié-Gonnardabfe6402023-06-20 09:59:13 +020031#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) || \
Valerio Setti7e6aaa12023-07-11 16:59:21 +020032 defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC)
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050033#include <mbedtls/rsa.h>
Manuel Pégourié-Gonnardabfe6402023-06-20 09:59:13 +020034#endif
35#if defined(MBEDTLS_USE_PSA_CRYPTO) && \
36 defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
37#include <mbedtls/ecp.h>
38#endif
39#if defined(MBEDTLS_PK_C)
40#include <mbedtls/pk.h>
41#endif
Valerio Setti8ceaa752023-12-12 11:20:18 +010042#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
43#include <mbedtls/cipher.h>
44#endif
Valerio Settia53e7a52024-02-26 12:03:59 +010045#include <mbedtls/entropy.h>
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050046
47/* PSA_SUCCESS is kept at the top of each error table since
48 * it's the most common status when everything functions properly. */
Manuel Pégourié-Gonnard725d2e22023-03-29 12:38:37 +020049#if defined(MBEDTLS_MD_LIGHT)
Andrzej Kurek270b3f92023-03-03 05:54:13 -050050const mbedtls_error_pair_t psa_to_md_errors[] =
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050051{
Andrzej Kurek747ab4e2023-02-28 10:32:47 -050052 { PSA_SUCCESS, 0 },
53 { PSA_ERROR_NOT_SUPPORTED, MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE },
54 { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_MD_BAD_INPUT_DATA },
55 { PSA_ERROR_INSUFFICIENT_MEMORY, MBEDTLS_ERR_MD_ALLOC_FAILED }
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050056};
57#endif
Valerio Setti8ceaa752023-12-12 11:20:18 +010058
59#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
60const mbedtls_error_pair_t psa_to_cipher_errors[] =
61{
62 { PSA_SUCCESS, 0 },
63 { PSA_ERROR_NOT_SUPPORTED, MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE },
64 { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA },
65 { PSA_ERROR_INSUFFICIENT_MEMORY, MBEDTLS_ERR_CIPHER_ALLOC_FAILED }
66};
67#endif
68
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050069#if defined(MBEDTLS_LMS_C)
Andrzej Kurek270b3f92023-03-03 05:54:13 -050070const mbedtls_error_pair_t psa_to_lms_errors[] =
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050071{
Andrzej Kurek747ab4e2023-02-28 10:32:47 -050072 { PSA_SUCCESS, 0 },
73 { PSA_ERROR_BUFFER_TOO_SMALL, MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL },
74 { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_LMS_BAD_INPUT_DATA }
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050075};
76#endif
Valerio Setti8ceaa752023-12-12 11:20:18 +010077
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050078#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) || \
Valerio Settif6d4dfb2023-07-10 10:55:12 +020079 defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC)
Andrzej Kurek270b3f92023-03-03 05:54:13 -050080const mbedtls_error_pair_t psa_to_pk_rsa_errors[] =
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050081{
Andrzej Kurek747ab4e2023-02-28 10:32:47 -050082 { PSA_SUCCESS, 0 },
83 { PSA_ERROR_NOT_PERMITTED, MBEDTLS_ERR_RSA_BAD_INPUT_DATA },
84 { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_RSA_BAD_INPUT_DATA },
85 { PSA_ERROR_INVALID_HANDLE, MBEDTLS_ERR_RSA_BAD_INPUT_DATA },
86 { PSA_ERROR_BUFFER_TOO_SMALL, MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE },
87 { PSA_ERROR_INSUFFICIENT_ENTROPY, MBEDTLS_ERR_RSA_RNG_FAILED },
88 { PSA_ERROR_INVALID_SIGNATURE, MBEDTLS_ERR_RSA_VERIFY_FAILED },
89 { PSA_ERROR_INVALID_PADDING, MBEDTLS_ERR_RSA_INVALID_PADDING }
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050090};
91#endif
92
93#if defined(MBEDTLS_USE_PSA_CRYPTO) && \
94 defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
Andrzej Kurek270b3f92023-03-03 05:54:13 -050095const mbedtls_error_pair_t psa_to_pk_ecdsa_errors[] =
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050096{
Andrzej Kurek747ab4e2023-02-28 10:32:47 -050097 { PSA_SUCCESS, 0 },
98 { PSA_ERROR_NOT_PERMITTED, MBEDTLS_ERR_ECP_BAD_INPUT_DATA },
99 { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_ECP_BAD_INPUT_DATA },
100 { PSA_ERROR_INVALID_HANDLE, MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE },
101 { PSA_ERROR_BUFFER_TOO_SMALL, MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL },
102 { PSA_ERROR_INSUFFICIENT_ENTROPY, MBEDTLS_ERR_ECP_RANDOM_FAILED },
103 { PSA_ERROR_INVALID_SIGNATURE, MBEDTLS_ERR_ECP_VERIFY_FAILED }
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500104};
105#endif
106
107int psa_generic_status_to_mbedtls(psa_status_t status)
108{
109 switch (status) {
110 case PSA_SUCCESS:
111 return 0;
112 case PSA_ERROR_NOT_SUPPORTED:
113 return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;
114 case PSA_ERROR_CORRUPTION_DETECTED:
115 return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
116 case PSA_ERROR_COMMUNICATION_FAILURE:
117 case PSA_ERROR_HARDWARE_FAILURE:
118 return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
119 case PSA_ERROR_NOT_PERMITTED:
120 default:
121 return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
122 }
123}
124
125int psa_status_to_mbedtls(psa_status_t status,
Andrzej Kurek270b3f92023-03-03 05:54:13 -0500126 const mbedtls_error_pair_t *local_translations,
Valerio Settiab9dc662023-03-27 14:02:08 +0200127 size_t local_errors_num,
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500128 int (*fallback_f)(psa_status_t))
129{
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500130 for (size_t i = 0; i < local_errors_num; i++) {
Andrzej Kurek747ab4e2023-02-28 10:32:47 -0500131 if (status == local_translations[i].psa_status) {
132 return local_translations[i].mbedtls_error;
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500133 }
134 }
135 return fallback_f(status);
136}
137
Manuel Pégourié-Gonnardabfe6402023-06-20 09:59:13 +0200138#if defined(MBEDTLS_PK_C)
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500139int psa_pk_status_to_mbedtls(psa_status_t status)
140{
141 switch (status) {
142 case PSA_ERROR_INVALID_HANDLE:
143 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
144 case PSA_ERROR_BUFFER_TOO_SMALL:
145 return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;
146 case PSA_ERROR_NOT_SUPPORTED:
147 return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
148 case PSA_ERROR_INVALID_ARGUMENT:
149 return MBEDTLS_ERR_PK_INVALID_ALG;
Gilles Peskinefc3d8662024-02-09 19:26:37 +0100150 case PSA_ERROR_NOT_PERMITTED:
151 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500152 case PSA_ERROR_INSUFFICIENT_MEMORY:
153 return MBEDTLS_ERR_PK_ALLOC_FAILED;
154 case PSA_ERROR_BAD_STATE:
155 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
156 case PSA_ERROR_DATA_CORRUPT:
157 case PSA_ERROR_DATA_INVALID:
158 case PSA_ERROR_STORAGE_FAILURE:
159 return MBEDTLS_ERR_PK_FILE_IO_ERROR;
160 default:
161 return psa_generic_status_to_mbedtls(status);
162 }
163}
Manuel Pégourié-Gonnardabfe6402023-06-20 09:59:13 +0200164#endif /* MBEDTLS_PK_C */
Joakim Anderssonb3491082023-12-11 21:29:19 +0100165
166/****************************************************************/
167/* Key management */
168/****************************************************************/
169
170#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
171psa_ecc_family_t mbedtls_ecc_group_to_psa(mbedtls_ecp_group_id grpid,
172 size_t *bits)
173{
174 switch (grpid) {
Elena Uziunaitea3632862024-07-04 13:52:43 +0100175#if defined(PSA_WANT_ECC_SECP_R1_192)
Joakim Anderssonb3491082023-12-11 21:29:19 +0100176 case MBEDTLS_ECP_DP_SECP192R1:
177 *bits = 192;
178 return PSA_ECC_FAMILY_SECP_R1;
179#endif
Elena Uziunaiteeaa0cf02024-07-04 17:41:25 +0100180#if defined(PSA_WANT_ECC_SECP_R1_224)
Joakim Anderssonb3491082023-12-11 21:29:19 +0100181 case MBEDTLS_ECP_DP_SECP224R1:
182 *bits = 224;
183 return PSA_ECC_FAMILY_SECP_R1;
184#endif
Elena Uziunaite417d05f2024-07-04 17:46:30 +0100185#if defined(PSA_WANT_ECC_SECP_R1_256)
Joakim Anderssonb3491082023-12-11 21:29:19 +0100186 case MBEDTLS_ECP_DP_SECP256R1:
187 *bits = 256;
188 return PSA_ECC_FAMILY_SECP_R1;
189#endif
Elena Uziunaite6b4cd482024-07-04 17:50:11 +0100190#if defined(PSA_WANT_ECC_SECP_R1_384)
Joakim Anderssonb3491082023-12-11 21:29:19 +0100191 case MBEDTLS_ECP_DP_SECP384R1:
192 *bits = 384;
193 return PSA_ECC_FAMILY_SECP_R1;
194#endif
Elena Uziunaite24e24f22024-07-04 17:53:40 +0100195#if defined(PSA_WANT_ECC_SECP_R1_521)
Joakim Anderssonb3491082023-12-11 21:29:19 +0100196 case MBEDTLS_ECP_DP_SECP521R1:
197 *bits = 521;
198 return PSA_ECC_FAMILY_SECP_R1;
199#endif
Elena Uziunaiteb8d10872024-07-05 10:51:40 +0100200#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256)
Joakim Anderssonb3491082023-12-11 21:29:19 +0100201 case MBEDTLS_ECP_DP_BP256R1:
202 *bits = 256;
203 return PSA_ECC_FAMILY_BRAINPOOL_P_R1;
204#endif
Elena Uziunaiteb8d10872024-07-05 10:51:40 +0100205#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384)
Joakim Anderssonb3491082023-12-11 21:29:19 +0100206 case MBEDTLS_ECP_DP_BP384R1:
207 *bits = 384;
208 return PSA_ECC_FAMILY_BRAINPOOL_P_R1;
209#endif
Elena Uziunaiteb8d10872024-07-05 10:51:40 +0100210#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512)
Joakim Anderssonb3491082023-12-11 21:29:19 +0100211 case MBEDTLS_ECP_DP_BP512R1:
212 *bits = 512;
213 return PSA_ECC_FAMILY_BRAINPOOL_P_R1;
214#endif
Elena Uziunaite0b5d48e2024-07-05 11:48:23 +0100215#if defined(PSA_WANT_ECC_MONTGOMERY_255)
Joakim Anderssonb3491082023-12-11 21:29:19 +0100216 case MBEDTLS_ECP_DP_CURVE25519:
217 *bits = 255;
218 return PSA_ECC_FAMILY_MONTGOMERY;
219#endif
Elena Uziunaite9e85c9f2024-07-04 18:37:34 +0100220#if defined(PSA_WANT_ECC_SECP_K1_192)
Joakim Anderssonb3491082023-12-11 21:29:19 +0100221 case MBEDTLS_ECP_DP_SECP192K1:
222 *bits = 192;
223 return PSA_ECC_FAMILY_SECP_K1;
224#endif
Elena Uziunaite63cb13e2024-09-05 12:43:14 +0100225#if defined(PSA_WANT_ECC_SECP_K1_224)
Valerio Setti78636272024-01-04 13:17:04 +0100226 /* secp224k1 is not and will not be supported in PSA (#3541). */
Joakim Anderssonb3491082023-12-11 21:29:19 +0100227#endif
Elena Uziunaite9e85c9f2024-07-04 18:37:34 +0100228#if defined(PSA_WANT_ECC_SECP_K1_256)
Joakim Anderssonb3491082023-12-11 21:29:19 +0100229 case MBEDTLS_ECP_DP_SECP256K1:
230 *bits = 256;
231 return PSA_ECC_FAMILY_SECP_K1;
232#endif
Elena Uziunaite0b5d48e2024-07-05 11:48:23 +0100233#if defined(PSA_WANT_ECC_MONTGOMERY_448)
Joakim Anderssonb3491082023-12-11 21:29:19 +0100234 case MBEDTLS_ECP_DP_CURVE448:
235 *bits = 448;
236 return PSA_ECC_FAMILY_MONTGOMERY;
237#endif
238 default:
239 *bits = 0;
240 return 0;
241 }
242}
243
Valerio Setti39faa9c2024-01-09 09:11:22 +0100244mbedtls_ecp_group_id mbedtls_ecc_group_from_psa(psa_ecc_family_t family,
Valerio Settid36c3132023-12-21 14:03:51 +0100245 size_t bits)
Joakim Anderssonb3491082023-12-11 21:29:19 +0100246{
Valerio Setti39faa9c2024-01-09 09:11:22 +0100247 switch (family) {
Joakim Anderssonb3491082023-12-11 21:29:19 +0100248 case PSA_ECC_FAMILY_SECP_R1:
249 switch (bits) {
250#if defined(PSA_WANT_ECC_SECP_R1_192)
251 case 192:
252 return MBEDTLS_ECP_DP_SECP192R1;
253#endif
254#if defined(PSA_WANT_ECC_SECP_R1_224)
255 case 224:
256 return MBEDTLS_ECP_DP_SECP224R1;
257#endif
258#if defined(PSA_WANT_ECC_SECP_R1_256)
259 case 256:
260 return MBEDTLS_ECP_DP_SECP256R1;
261#endif
262#if defined(PSA_WANT_ECC_SECP_R1_384)
263 case 384:
264 return MBEDTLS_ECP_DP_SECP384R1;
265#endif
266#if defined(PSA_WANT_ECC_SECP_R1_521)
267 case 521:
Valerio Settid36c3132023-12-21 14:03:51 +0100268 return MBEDTLS_ECP_DP_SECP521R1;
Joakim Anderssonb3491082023-12-11 21:29:19 +0100269#endif
270 }
271 break;
272
273 case PSA_ECC_FAMILY_BRAINPOOL_P_R1:
274 switch (bits) {
275#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256)
276 case 256:
277 return MBEDTLS_ECP_DP_BP256R1;
278#endif
279#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384)
280 case 384:
281 return MBEDTLS_ECP_DP_BP384R1;
282#endif
283#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512)
284 case 512:
285 return MBEDTLS_ECP_DP_BP512R1;
286#endif
287 }
288 break;
289
290 case PSA_ECC_FAMILY_MONTGOMERY:
291 switch (bits) {
292#if defined(PSA_WANT_ECC_MONTGOMERY_255)
293 case 255:
Valerio Settid36c3132023-12-21 14:03:51 +0100294 return MBEDTLS_ECP_DP_CURVE25519;
Joakim Anderssonb3491082023-12-11 21:29:19 +0100295#endif
296#if defined(PSA_WANT_ECC_MONTGOMERY_448)
297 case 448:
298 return MBEDTLS_ECP_DP_CURVE448;
299#endif
300 }
301 break;
302
303 case PSA_ECC_FAMILY_SECP_K1:
304 switch (bits) {
305#if defined(PSA_WANT_ECC_SECP_K1_192)
306 case 192:
307 return MBEDTLS_ECP_DP_SECP192K1;
308#endif
309#if defined(PSA_WANT_ECC_SECP_K1_224)
Valerio Setti78636272024-01-04 13:17:04 +0100310 /* secp224k1 is not and will not be supported in PSA (#3541). */
Joakim Anderssonb3491082023-12-11 21:29:19 +0100311#endif
312#if defined(PSA_WANT_ECC_SECP_K1_256)
313 case 256:
314 return MBEDTLS_ECP_DP_SECP256K1;
315#endif
316 }
317 break;
318 }
319
Joakim Anderssonb3491082023-12-11 21:29:19 +0100320 return MBEDTLS_ECP_DP_NONE;
321}
322#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */
323
Valerio Settibb91bcd2024-02-26 08:41:33 +0100324/* Wrapper function allowing the classic API to use the PSA RNG.
325 *
326 * `mbedtls_psa_get_random(MBEDTLS_PSA_RANDOM_STATE, ...)` calls
327 * `psa_generate_random(...)`. The state parameter is ignored since the
328 * PSA API doesn't support passing an explicit state.
Valerio Settibb91bcd2024-02-26 08:41:33 +0100329 */
Valerio Settibb91bcd2024-02-26 08:41:33 +0100330int mbedtls_psa_get_random(void *p_rng,
331 unsigned char *output,
332 size_t output_size)
333{
334 /* This function takes a pointer to the RNG state because that's what
335 * classic mbedtls functions using an RNG expect. The PSA RNG manages
336 * its own state internally and doesn't let the caller access that state.
337 * So we just ignore the state parameter, and in practice we'll pass
338 * NULL. */
339 (void) p_rng;
340 psa_status_t status = psa_generate_random(output, output_size);
341 if (status == PSA_SUCCESS) {
342 return 0;
343 } else {
344 return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
345 }
346}
Valerio Settibb91bcd2024-02-26 08:41:33 +0100347
Valerio Setti1a58e9a2024-02-29 16:14:29 +0100348#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
Valerio Settic22e3ce2024-01-10 08:46:59 +0100349
Elena Uziunaite87e05502024-07-10 15:45:14 +0300350#if defined(PSA_HAVE_ALG_SOME_ECDSA)
Valerio Settif4d2dc22024-01-16 10:57:48 +0100351
Valerio Setti84890c92024-01-09 14:20:23 +0100352/**
353 * \brief Convert a single raw coordinate to DER ASN.1 format. The output der
354 * buffer is filled backward (i.e. starting from its end).
355 *
356 * \param raw_buf Buffer containing the raw coordinate to be
357 * converted.
Valerio Setti2bd0ecd2024-02-05 15:25:15 +0100358 * \param raw_len Length of raw_buf in bytes. This must be > 0.
Valerio Setti84890c92024-01-09 14:20:23 +0100359 * \param der_buf_start Pointer to the beginning of the buffer which
360 * will be filled with the DER converted data.
361 * \param der_buf_end End of the buffer used to store the DER output.
362 *
363 * \return On success, the amount of data (in bytes) written to
364 * the DER buffer.
365 * \return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if the provided der
366 * buffer is too small to contain all the converted data.
367 * \return MBEDTLS_ERR_ASN1_INVALID_DATA if the input raw
368 * coordinate is null (i.e. all zeros).
369 *
370 * \warning Raw and der buffer must not be overlapping.
Valerio Setti75501f52024-01-08 16:49:17 +0100371 */
372static int convert_raw_to_der_single_int(const unsigned char *raw_buf, size_t raw_len,
373 unsigned char *der_buf_start,
374 unsigned char *der_buf_end)
375{
376 unsigned char *p = der_buf_end;
Valerio Setti954ef4b2024-02-05 12:06:46 +0100377 int len;
Valerio Setti75501f52024-01-08 16:49:17 +0100378 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
379
Valerio Setti954ef4b2024-02-05 12:06:46 +0100380 /* ASN.1 DER encoding requires minimal length, so skip leading 0s.
381 * Provided input MPIs should not be 0, but as a failsafe measure, still
382 * detect that and return error in case. */
383 while (*raw_buf == 0x00) {
384 ++raw_buf;
385 --raw_len;
386 if (raw_len == 0) {
387 return MBEDTLS_ERR_ASN1_INVALID_DATA;
388 }
389 }
390 len = (int) raw_len;
391
Valerio Setti75501f52024-01-08 16:49:17 +0100392 /* Copy the raw coordinate to the end of der_buf. */
393 if ((p - der_buf_start) < len) {
394 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
395 }
396 p -= len;
397 memcpy(p, raw_buf, len);
398
Valerio Setti75501f52024-01-08 16:49:17 +0100399 /* If MSb is 1, ASN.1 requires that we prepend a 0. */
400 if (*p & 0x80) {
401 if ((p - der_buf_start) < 1) {
402 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
403 }
404 --p;
405 *p = 0x00;
406 ++len;
407 }
408
409 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, der_buf_start, len));
410 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, der_buf_start, MBEDTLS_ASN1_INTEGER));
411
412 return len;
413}
414
Valerio Setti315e4af2024-02-05 10:09:15 +0100415int mbedtls_ecdsa_raw_to_der(size_t bits, const unsigned char *raw, size_t raw_len,
416 unsigned char *der, size_t der_size, size_t *der_len)
Valerio Setti75501f52024-01-08 16:49:17 +0100417{
418 unsigned char r[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)];
419 unsigned char s[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)];
420 const size_t coordinate_len = PSA_BITS_TO_BYTES(bits);
421 size_t len = 0;
422 unsigned char *p = der + der_size;
423 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
424
Gilles Peskine1ba7e242024-10-04 18:56:17 +0200425 if (bits == 0) {
426 return MBEDTLS_ERR_ASN1_INVALID_DATA;
427 }
Valerio Setticf81f692024-02-06 16:57:12 +0100428 if (raw_len != (2 * coordinate_len)) {
Valerio Setti75501f52024-01-08 16:49:17 +0100429 return MBEDTLS_ERR_ASN1_INVALID_DATA;
430 }
Minos Galanakis123a6252024-08-08 14:11:53 +0100431 if (coordinate_len > sizeof(r)) {
432 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
433 }
Valerio Setti75501f52024-01-08 16:49:17 +0100434
435 /* Since raw and der buffers might overlap, dump r and s before starting
436 * the conversion. */
Valerio Setti75501f52024-01-08 16:49:17 +0100437 memcpy(r, raw, coordinate_len);
Valerio Setti75501f52024-01-08 16:49:17 +0100438 memcpy(s, raw + coordinate_len, coordinate_len);
439
440 /* der buffer will initially be written starting from its end so we pick s
441 * first and then r. */
442 ret = convert_raw_to_der_single_int(s, coordinate_len, der, p);
443 if (ret < 0) {
444 return ret;
445 }
446 p -= ret;
447 len += ret;
448
449 ret = convert_raw_to_der_single_int(r, coordinate_len, der, p);
450 if (ret < 0) {
451 return ret;
452 }
453 p -= ret;
454 len += ret;
455
456 /* Add ASN.1 header (len + tag). */
457 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, der, len));
458 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, der,
459 MBEDTLS_ASN1_CONSTRUCTED |
460 MBEDTLS_ASN1_SEQUENCE));
461
462 /* memmove the content of der buffer to its beginnig. */
463 memmove(der, p, len);
464 *der_len = len;
465
466 return 0;
467}
Valerio Setti75501f52024-01-08 16:49:17 +0100468
Valerio Setti84890c92024-01-09 14:20:23 +0100469/**
470 * \brief Convert a single integer from ASN.1 DER format to raw.
471 *
472 * \param der Buffer containing the DER integer value to be
473 * converted.
474 * \param der_len Length of the der buffer in bytes.
475 * \param raw Output buffer that will be filled with the
476 * converted data. This should be at least
Valerio Setti78da7462024-01-30 15:08:40 +0100477 * coordinate_size bytes and it must be zeroed before
478 * calling this function.
Valerio Setti84890c92024-01-09 14:20:23 +0100479 * \param coordinate_size Size (in bytes) of a single coordinate in raw
480 * format.
481 *
482 * \return On success, the amount of DER data parsed from the
483 * provided der buffer.
484 * \return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the integer tag
485 * is missing in the der buffer.
486 * \return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the integer
487 * is null (i.e. all zeros) or if the output raw buffer
488 * is too small to contain the converted raw value.
489 *
490 * \warning Der and raw buffers must not be overlapping.
Valerio Setti75501f52024-01-08 16:49:17 +0100491 */
492static int convert_der_to_raw_single_int(unsigned char *der, size_t der_len,
Valerio Setti122c94f2024-01-29 18:02:03 +0100493 unsigned char *raw, size_t coordinate_size)
Valerio Setti75501f52024-01-08 16:49:17 +0100494{
495 unsigned char *p = der;
496 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
497 size_t unpadded_len, padding_len = 0;
498
499 /* Get the length of ASN.1 element (i.e. the integer we need to parse). */
500 ret = mbedtls_asn1_get_tag(&p, p + der_len, &unpadded_len,
501 MBEDTLS_ASN1_INTEGER);
502 if (ret != 0) {
503 return ret;
504 }
505
Valerio Setti19103902024-02-07 16:16:58 +0100506 /* It's invalid to have:
507 * - unpadded_len == 0.
508 * - MSb set without a leading 0x00 (leading 0x00 is checked below). */
509 if (((unpadded_len == 0) || (*p & 0x80) != 0)) {
Valerio Setti091bdc42024-02-05 16:17:44 +0100510 return MBEDTLS_ERR_ASN1_INVALID_DATA;
511 }
512
Valerio Setti86bae522024-01-10 11:12:31 +0100513 /* Skip possible leading zero */
Valerio Setti19103902024-02-07 16:16:58 +0100514 if (*p == 0x00) {
Valerio Setti75501f52024-01-08 16:49:17 +0100515 p++;
516 unpadded_len--;
Valerio Setti19103902024-02-07 16:16:58 +0100517 /* It is not allowed to have more than 1 leading zero.
518 * Ignore the case in which unpadded_len = 0 because that's a 0 encoded
519 * in ASN.1 format (i.e. 020100). */
520 if ((unpadded_len > 0) && (*p == 0x00)) {
Valerio Setti091bdc42024-02-05 16:17:44 +0100521 return MBEDTLS_ERR_ASN1_INVALID_DATA;
522 }
Valerio Setti2d73baf2024-02-01 15:25:17 +0100523 }
Valerio Setti75501f52024-01-08 16:49:17 +0100524
Valerio Setti9b9b5a52024-01-29 16:53:03 +0100525 if (unpadded_len > coordinate_size) {
526 /* Parsed number is longer than the maximum expected value. */
527 return MBEDTLS_ERR_ASN1_INVALID_DATA;
Valerio Setti75501f52024-01-08 16:49:17 +0100528 }
Valerio Setti78da7462024-01-30 15:08:40 +0100529 padding_len = coordinate_size - unpadded_len;
530 /* raw buffer was already zeroed by the calling function so zero-padding
531 * operation is skipped here. */
Valerio Setti75501f52024-01-08 16:49:17 +0100532 memcpy(raw + padding_len, p, unpadded_len);
533 p += unpadded_len;
534
535 return (int) (p - der);
536}
537
Valerio Setti315e4af2024-02-05 10:09:15 +0100538int mbedtls_ecdsa_der_to_raw(size_t bits, const unsigned char *der, size_t der_len,
539 unsigned char *raw, size_t raw_size, size_t *raw_len)
Valerio Setti75501f52024-01-08 16:49:17 +0100540{
541 unsigned char raw_tmp[PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE];
542 unsigned char *p = (unsigned char *) der;
543 size_t data_len;
544 size_t coordinate_size = PSA_BITS_TO_BYTES(bits);
545 int ret;
546
Gilles Peskine1ba7e242024-10-04 18:56:17 +0200547 if (bits == 0) {
548 return MBEDTLS_ERR_ASN1_INVALID_DATA;
549 }
Valerio Setti75501f52024-01-08 16:49:17 +0100550 /* The output raw buffer should be at least twice the size of a raw
551 * coordinate in order to store r and s. */
552 if (raw_size < coordinate_size * 2) {
553 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
554 }
Minos Galanakis123a6252024-08-08 14:11:53 +0100555 if (2 * coordinate_size > sizeof(raw_tmp)) {
556 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
557 }
Valerio Setti75501f52024-01-08 16:49:17 +0100558
559 /* Check that the provided input DER buffer has the right header. */
560 ret = mbedtls_asn1_get_tag(&p, der + der_len, &data_len,
561 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
562 if (ret != 0) {
563 return ret;
564 }
565
Valerio Setti05c256f2024-02-05 16:02:11 +0100566 memset(raw_tmp, 0, 2 * coordinate_size);
Valerio Setti75501f52024-01-08 16:49:17 +0100567
568 /* Extract r */
Valerio Setti122c94f2024-01-29 18:02:03 +0100569 ret = convert_der_to_raw_single_int(p, data_len, raw_tmp, coordinate_size);
Valerio Setti75501f52024-01-08 16:49:17 +0100570 if (ret < 0) {
571 return ret;
572 }
573 p += ret;
574 data_len -= ret;
575
576 /* Extract s */
577 ret = convert_der_to_raw_single_int(p, data_len, raw_tmp + coordinate_size,
Valerio Setti75501f52024-01-08 16:49:17 +0100578 coordinate_size);
579 if (ret < 0) {
580 return ret;
581 }
582 p += ret;
583 data_len -= ret;
584
585 /* Check that we consumed all the input der data. */
Valerio Setti5713c8a2024-01-09 15:48:37 +0100586 if ((size_t) (p - der) != der_len) {
Valerio Setti75501f52024-01-08 16:49:17 +0100587 return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
588 }
589
590 memcpy(raw, raw_tmp, 2 * coordinate_size);
591 *raw_len = 2 * coordinate_size;
592
593 return 0;
594}
Valerio Settif4d2dc22024-01-16 10:57:48 +0100595
Elena Uziunaite87e05502024-07-10 15:45:14 +0300596#endif /* PSA_HAVE_ALG_SOME_ECDSA */