xref: /optee_os/lib/libmbedtls/mbedtls/library/pk_wrap.c (revision 32b3180828fa15a49ccc86ecb4be9d274c140c89)
1817466cbSJens Wiklander /*
2817466cbSJens Wiklander  *  Public Key abstraction layer: wrapper functions
3817466cbSJens Wiklander  *
47901324dSJerome Forissier  *  Copyright The Mbed TLS Contributors
57901324dSJerome Forissier  *  SPDX-License-Identifier: Apache-2.0
6817466cbSJens Wiklander  *
7817466cbSJens Wiklander  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8817466cbSJens Wiklander  *  not use this file except in compliance with the License.
9817466cbSJens Wiklander  *  You may obtain a copy of the License at
10817466cbSJens Wiklander  *
11817466cbSJens Wiklander  *  http://www.apache.org/licenses/LICENSE-2.0
12817466cbSJens Wiklander  *
13817466cbSJens Wiklander  *  Unless required by applicable law or agreed to in writing, software
14817466cbSJens Wiklander  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15817466cbSJens Wiklander  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16817466cbSJens Wiklander  *  See the License for the specific language governing permissions and
17817466cbSJens Wiklander  *  limitations under the License.
18817466cbSJens Wiklander  */
19817466cbSJens Wiklander 
207901324dSJerome Forissier #include "common.h"
21817466cbSJens Wiklander 
22*32b31808SJens Wiklander #include "mbedtls/platform_util.h"
23*32b31808SJens Wiklander 
24817466cbSJens Wiklander #if defined(MBEDTLS_PK_C)
25*32b31808SJens Wiklander #include "pk_wrap.h"
2611fa71b9SJerome Forissier #include "mbedtls/error.h"
27817466cbSJens Wiklander 
28817466cbSJens Wiklander /* Even if RSA not activated, for the sake of RSA-alt */
29817466cbSJens Wiklander #include "mbedtls/rsa.h"
30817466cbSJens Wiklander 
31817466cbSJens Wiklander #if defined(MBEDTLS_ECP_C)
32817466cbSJens Wiklander #include "mbedtls/ecp.h"
33817466cbSJens Wiklander #endif
34817466cbSJens Wiklander 
35817466cbSJens Wiklander #if defined(MBEDTLS_ECDSA_C)
36817466cbSJens Wiklander #include "mbedtls/ecdsa.h"
37817466cbSJens Wiklander #endif
38817466cbSJens Wiklander 
39*32b31808SJens Wiklander #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PSA_CRYPTO_C)
40*32b31808SJens Wiklander #include "pkwrite.h"
4111fa71b9SJerome Forissier #endif
4211fa71b9SJerome Forissier 
43*32b31808SJens Wiklander #if defined(MBEDTLS_PSA_CRYPTO_C)
44*32b31808SJens Wiklander #include "mbedtls/psa_util.h"
45*32b31808SJens Wiklander #define PSA_PK_TO_MBEDTLS_ERR(status) psa_pk_status_to_mbedtls(status)
46*32b31808SJens Wiklander #define PSA_PK_RSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,     \
47*32b31808SJens Wiklander                                                                   psa_to_pk_rsa_errors,            \
48*32b31808SJens Wiklander                                                                   psa_pk_status_to_mbedtls)
49*32b31808SJens Wiklander #define PSA_PK_ECDSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
50*32b31808SJens Wiklander                                                                     psa_to_pk_ecdsa_errors,        \
51*32b31808SJens Wiklander                                                                     psa_pk_status_to_mbedtls)
523d3b0591SJens Wiklander #endif
533d3b0591SJens Wiklander 
5411fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO)
5511fa71b9SJerome Forissier #include "psa/crypto.h"
56*32b31808SJens Wiklander #include "hash_info.h"
57*32b31808SJens Wiklander 
58*32b31808SJens Wiklander #if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
59*32b31808SJens Wiklander #include "mbedtls/asn1write.h"
6011fa71b9SJerome Forissier #include "mbedtls/asn1.h"
6111fa71b9SJerome Forissier #endif
62*32b31808SJens Wiklander #endif  /* MBEDTLS_USE_PSA_CRYPTO */
6311fa71b9SJerome Forissier 
64817466cbSJens Wiklander #include "mbedtls/platform.h"
65817466cbSJens Wiklander 
66817466cbSJens Wiklander #include <limits.h>
673d3b0591SJens Wiklander #include <stdint.h>
68*32b31808SJens Wiklander #include <string.h>
69*32b31808SJens Wiklander 
70*32b31808SJens Wiklander #if !defined(MBEDTLS_DEPRECATED_REMOVED)
71*32b31808SJens Wiklander #if defined(MBEDTLS_PSA_CRYPTO_C)
72*32b31808SJens Wiklander int mbedtls_pk_error_from_psa(psa_status_t status)
73*32b31808SJens Wiklander {
74*32b31808SJens Wiklander     switch (status) {
75*32b31808SJens Wiklander         case PSA_SUCCESS:
76*32b31808SJens Wiklander             return 0;
77*32b31808SJens Wiklander         case PSA_ERROR_INVALID_HANDLE:
78*32b31808SJens Wiklander             return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
79*32b31808SJens Wiklander         case PSA_ERROR_NOT_PERMITTED:
80*32b31808SJens Wiklander             return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
81*32b31808SJens Wiklander         case PSA_ERROR_BUFFER_TOO_SMALL:
82*32b31808SJens Wiklander             return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;
83*32b31808SJens Wiklander         case PSA_ERROR_NOT_SUPPORTED:
84*32b31808SJens Wiklander             return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
85*32b31808SJens Wiklander         case PSA_ERROR_INVALID_ARGUMENT:
86*32b31808SJens Wiklander             return MBEDTLS_ERR_PK_INVALID_ALG;
87*32b31808SJens Wiklander         case PSA_ERROR_INSUFFICIENT_MEMORY:
88*32b31808SJens Wiklander             return MBEDTLS_ERR_PK_ALLOC_FAILED;
89*32b31808SJens Wiklander         case PSA_ERROR_BAD_STATE:
90*32b31808SJens Wiklander             return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
91*32b31808SJens Wiklander         case PSA_ERROR_COMMUNICATION_FAILURE:
92*32b31808SJens Wiklander         case PSA_ERROR_HARDWARE_FAILURE:
93*32b31808SJens Wiklander             return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
94*32b31808SJens Wiklander         case PSA_ERROR_DATA_CORRUPT:
95*32b31808SJens Wiklander         case PSA_ERROR_DATA_INVALID:
96*32b31808SJens Wiklander         case PSA_ERROR_STORAGE_FAILURE:
97*32b31808SJens Wiklander             return MBEDTLS_ERR_PK_FILE_IO_ERROR;
98*32b31808SJens Wiklander         case PSA_ERROR_CORRUPTION_DETECTED:
99*32b31808SJens Wiklander             return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
100*32b31808SJens Wiklander         default:
101*32b31808SJens Wiklander             return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
102*32b31808SJens Wiklander     }
103*32b31808SJens Wiklander }
104*32b31808SJens Wiklander 
105*32b31808SJens Wiklander #if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) ||    \
106*32b31808SJens Wiklander     defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)
107*32b31808SJens Wiklander int mbedtls_pk_error_from_psa_rsa(psa_status_t status)
108*32b31808SJens Wiklander {
109*32b31808SJens Wiklander     switch (status) {
110*32b31808SJens Wiklander         case PSA_ERROR_NOT_PERMITTED:
111*32b31808SJens Wiklander         case PSA_ERROR_INVALID_ARGUMENT:
112*32b31808SJens Wiklander         case PSA_ERROR_INVALID_HANDLE:
113*32b31808SJens Wiklander             return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
114*32b31808SJens Wiklander         case PSA_ERROR_BUFFER_TOO_SMALL:
115*32b31808SJens Wiklander             return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE;
116*32b31808SJens Wiklander         case PSA_ERROR_INSUFFICIENT_ENTROPY:
117*32b31808SJens Wiklander             return MBEDTLS_ERR_RSA_RNG_FAILED;
118*32b31808SJens Wiklander         case PSA_ERROR_INVALID_SIGNATURE:
119*32b31808SJens Wiklander             return MBEDTLS_ERR_RSA_VERIFY_FAILED;
120*32b31808SJens Wiklander         case PSA_ERROR_INVALID_PADDING:
121*32b31808SJens Wiklander             return MBEDTLS_ERR_RSA_INVALID_PADDING;
122*32b31808SJens Wiklander         case PSA_SUCCESS:
123*32b31808SJens Wiklander             return 0;
124*32b31808SJens Wiklander         case PSA_ERROR_NOT_SUPPORTED:
125*32b31808SJens Wiklander             return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
126*32b31808SJens Wiklander         case PSA_ERROR_INSUFFICIENT_MEMORY:
127*32b31808SJens Wiklander             return MBEDTLS_ERR_PK_ALLOC_FAILED;
128*32b31808SJens Wiklander         case PSA_ERROR_BAD_STATE:
129*32b31808SJens Wiklander             return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
130*32b31808SJens Wiklander         case PSA_ERROR_COMMUNICATION_FAILURE:
131*32b31808SJens Wiklander         case PSA_ERROR_HARDWARE_FAILURE:
132*32b31808SJens Wiklander             return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
133*32b31808SJens Wiklander         case PSA_ERROR_DATA_CORRUPT:
134*32b31808SJens Wiklander         case PSA_ERROR_DATA_INVALID:
135*32b31808SJens Wiklander         case PSA_ERROR_STORAGE_FAILURE:
136*32b31808SJens Wiklander             return MBEDTLS_ERR_PK_FILE_IO_ERROR;
137*32b31808SJens Wiklander         case PSA_ERROR_CORRUPTION_DETECTED:
138*32b31808SJens Wiklander             return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
139*32b31808SJens Wiklander         default:
140*32b31808SJens Wiklander             return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
141*32b31808SJens Wiklander     }
142*32b31808SJens Wiklander }
143*32b31808SJens Wiklander #endif /* PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY || PSA_WANT_KEY_TYPE_RSA_KEY_PAIR */
144*32b31808SJens Wiklander #endif /* MBEDTLS_PSA_CRYPTO_C */
145*32b31808SJens Wiklander 
146*32b31808SJens Wiklander #if defined(MBEDTLS_USE_PSA_CRYPTO)
147*32b31808SJens Wiklander #if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
148*32b31808SJens Wiklander int mbedtls_pk_error_from_psa_ecdsa(psa_status_t status)
149*32b31808SJens Wiklander {
150*32b31808SJens Wiklander     switch (status) {
151*32b31808SJens Wiklander         case PSA_ERROR_NOT_PERMITTED:
152*32b31808SJens Wiklander         case PSA_ERROR_INVALID_ARGUMENT:
153*32b31808SJens Wiklander             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
154*32b31808SJens Wiklander         case PSA_ERROR_INVALID_HANDLE:
155*32b31808SJens Wiklander             return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
156*32b31808SJens Wiklander         case PSA_ERROR_BUFFER_TOO_SMALL:
157*32b31808SJens Wiklander             return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
158*32b31808SJens Wiklander         case PSA_ERROR_INSUFFICIENT_ENTROPY:
159*32b31808SJens Wiklander             return MBEDTLS_ERR_ECP_RANDOM_FAILED;
160*32b31808SJens Wiklander         case PSA_ERROR_INVALID_SIGNATURE:
161*32b31808SJens Wiklander             return MBEDTLS_ERR_ECP_VERIFY_FAILED;
162*32b31808SJens Wiklander         case PSA_SUCCESS:
163*32b31808SJens Wiklander             return 0;
164*32b31808SJens Wiklander         case PSA_ERROR_NOT_SUPPORTED:
165*32b31808SJens Wiklander             return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
166*32b31808SJens Wiklander         case PSA_ERROR_INSUFFICIENT_MEMORY:
167*32b31808SJens Wiklander             return MBEDTLS_ERR_PK_ALLOC_FAILED;
168*32b31808SJens Wiklander         case PSA_ERROR_BAD_STATE:
169*32b31808SJens Wiklander             return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
170*32b31808SJens Wiklander         case PSA_ERROR_COMMUNICATION_FAILURE:
171*32b31808SJens Wiklander         case PSA_ERROR_HARDWARE_FAILURE:
172*32b31808SJens Wiklander             return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
173*32b31808SJens Wiklander         case PSA_ERROR_DATA_CORRUPT:
174*32b31808SJens Wiklander         case PSA_ERROR_DATA_INVALID:
175*32b31808SJens Wiklander         case PSA_ERROR_STORAGE_FAILURE:
176*32b31808SJens Wiklander             return MBEDTLS_ERR_PK_FILE_IO_ERROR;
177*32b31808SJens Wiklander         case PSA_ERROR_CORRUPTION_DETECTED:
178*32b31808SJens Wiklander             return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
179*32b31808SJens Wiklander         default:
180*32b31808SJens Wiklander             return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
181*32b31808SJens Wiklander     }
182*32b31808SJens Wiklander }
183*32b31808SJens Wiklander #endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */
184*32b31808SJens Wiklander #endif /* MBEDTLS_USE_PSA_CRYPTO */
185*32b31808SJens Wiklander #endif /* !MBEDTLS_DEPRECATED_REMOVED */
186817466cbSJens Wiklander 
187817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C)
188817466cbSJens Wiklander static int rsa_can_do(mbedtls_pk_type_t type)
189817466cbSJens Wiklander {
190*32b31808SJens Wiklander     return type == MBEDTLS_PK_RSA ||
191*32b31808SJens Wiklander            type == MBEDTLS_PK_RSASSA_PSS;
192817466cbSJens Wiklander }
193817466cbSJens Wiklander 
194817466cbSJens Wiklander static size_t rsa_get_bitlen(const void *ctx)
195817466cbSJens Wiklander {
1963d3b0591SJens Wiklander     const mbedtls_rsa_context *rsa = (const mbedtls_rsa_context *) ctx;
197*32b31808SJens Wiklander     return 8 * mbedtls_rsa_get_len(rsa);
198817466cbSJens Wiklander }
199817466cbSJens Wiklander 
200*32b31808SJens Wiklander #if defined(MBEDTLS_USE_PSA_CRYPTO)
201*32b31808SJens Wiklander static int rsa_verify_wrap(void *ctx, mbedtls_md_type_t md_alg,
202*32b31808SJens Wiklander                            const unsigned char *hash, size_t hash_len,
203*32b31808SJens Wiklander                            const unsigned char *sig, size_t sig_len)
204*32b31808SJens Wiklander {
205*32b31808SJens Wiklander     mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx;
206*32b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
207*32b31808SJens Wiklander     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
208*32b31808SJens Wiklander     mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
209*32b31808SJens Wiklander     psa_status_t status;
210*32b31808SJens Wiklander     mbedtls_pk_context key;
211*32b31808SJens Wiklander     int key_len;
212*32b31808SJens Wiklander     unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES];
213*32b31808SJens Wiklander     psa_algorithm_t psa_alg_md =
214*32b31808SJens Wiklander         PSA_ALG_RSA_PKCS1V15_SIGN(mbedtls_hash_info_psa_from_md(md_alg));
215*32b31808SJens Wiklander     size_t rsa_len = mbedtls_rsa_get_len(rsa);
216*32b31808SJens Wiklander 
217*32b31808SJens Wiklander     if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) {
218*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
219*32b31808SJens Wiklander     }
220*32b31808SJens Wiklander 
221*32b31808SJens Wiklander     if (sig_len < rsa_len) {
222*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_VERIFY_FAILED;
223*32b31808SJens Wiklander     }
224*32b31808SJens Wiklander 
225*32b31808SJens Wiklander     /* mbedtls_pk_write_pubkey_der() expects a full PK context;
226*32b31808SJens Wiklander      * re-construct one to make it happy */
227*32b31808SJens Wiklander     key.pk_info = &mbedtls_rsa_info;
228*32b31808SJens Wiklander     key.pk_ctx = ctx;
229*32b31808SJens Wiklander     key_len = mbedtls_pk_write_pubkey_der(&key, buf, sizeof(buf));
230*32b31808SJens Wiklander     if (key_len <= 0) {
231*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
232*32b31808SJens Wiklander     }
233*32b31808SJens Wiklander 
234*32b31808SJens Wiklander     psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);
235*32b31808SJens Wiklander     psa_set_key_algorithm(&attributes, psa_alg_md);
236*32b31808SJens Wiklander     psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY);
237*32b31808SJens Wiklander 
238*32b31808SJens Wiklander     status = psa_import_key(&attributes,
239*32b31808SJens Wiklander                             buf + sizeof(buf) - key_len, key_len,
240*32b31808SJens Wiklander                             &key_id);
241*32b31808SJens Wiklander     if (status != PSA_SUCCESS) {
242*32b31808SJens Wiklander         ret = PSA_PK_TO_MBEDTLS_ERR(status);
243*32b31808SJens Wiklander         goto cleanup;
244*32b31808SJens Wiklander     }
245*32b31808SJens Wiklander 
246*32b31808SJens Wiklander     status = psa_verify_hash(key_id, psa_alg_md, hash, hash_len,
247*32b31808SJens Wiklander                              sig, sig_len);
248*32b31808SJens Wiklander     if (status != PSA_SUCCESS) {
249*32b31808SJens Wiklander         ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status);
250*32b31808SJens Wiklander         goto cleanup;
251*32b31808SJens Wiklander     }
252*32b31808SJens Wiklander     ret = 0;
253*32b31808SJens Wiklander 
254*32b31808SJens Wiklander cleanup:
255*32b31808SJens Wiklander     status = psa_destroy_key(key_id);
256*32b31808SJens Wiklander     if (ret == 0 && status != PSA_SUCCESS) {
257*32b31808SJens Wiklander         ret = PSA_PK_TO_MBEDTLS_ERR(status);
258*32b31808SJens Wiklander     }
259*32b31808SJens Wiklander 
260*32b31808SJens Wiklander     return ret;
261*32b31808SJens Wiklander }
262*32b31808SJens Wiklander #else
263817466cbSJens Wiklander static int rsa_verify_wrap(void *ctx, mbedtls_md_type_t md_alg,
264817466cbSJens Wiklander                            const unsigned char *hash, size_t hash_len,
265817466cbSJens Wiklander                            const unsigned char *sig, size_t sig_len)
266817466cbSJens Wiklander {
26711fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2683d3b0591SJens Wiklander     mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx;
2693d3b0591SJens Wiklander     size_t rsa_len = mbedtls_rsa_get_len(rsa);
270817466cbSJens Wiklander 
271*32b31808SJens Wiklander     if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) {
272*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
273*32b31808SJens Wiklander     }
274817466cbSJens Wiklander 
275*32b31808SJens Wiklander     if (sig_len < rsa_len) {
276*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_VERIFY_FAILED;
277*32b31808SJens Wiklander     }
278817466cbSJens Wiklander 
279*32b31808SJens Wiklander     if ((ret = mbedtls_rsa_pkcs1_verify(rsa, md_alg,
280*32b31808SJens Wiklander                                         (unsigned int) hash_len,
281*32b31808SJens Wiklander                                         hash, sig)) != 0) {
282*32b31808SJens Wiklander         return ret;
283*32b31808SJens Wiklander     }
284817466cbSJens Wiklander 
2853d3b0591SJens Wiklander     /* The buffer contains a valid signature followed by extra data.
2863d3b0591SJens Wiklander      * We have a special error code for that so that so that callers can
2873d3b0591SJens Wiklander      * use mbedtls_pk_verify() to check "Does the buffer start with a
2883d3b0591SJens Wiklander      * valid signature?" and not just "Does the buffer contain a valid
2893d3b0591SJens Wiklander      * signature?". */
290*32b31808SJens Wiklander     if (sig_len > rsa_len) {
291*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH;
292817466cbSJens Wiklander     }
293817466cbSJens Wiklander 
294*32b31808SJens Wiklander     return 0;
295*32b31808SJens Wiklander }
296*32b31808SJens Wiklander #endif
297*32b31808SJens Wiklander 
298*32b31808SJens Wiklander #if defined(MBEDTLS_PSA_CRYPTO_C)
299*32b31808SJens Wiklander int  mbedtls_pk_psa_rsa_sign_ext(psa_algorithm_t alg,
300*32b31808SJens Wiklander                                  mbedtls_rsa_context *rsa_ctx,
301*32b31808SJens Wiklander                                  const unsigned char *hash, size_t hash_len,
302*32b31808SJens Wiklander                                  unsigned char *sig, size_t sig_size,
303*32b31808SJens Wiklander                                  size_t *sig_len)
304*32b31808SJens Wiklander {
305*32b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
306*32b31808SJens Wiklander     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
307*32b31808SJens Wiklander     mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
308*32b31808SJens Wiklander     psa_status_t status;
309*32b31808SJens Wiklander     mbedtls_pk_context key;
310*32b31808SJens Wiklander     int key_len;
311*32b31808SJens Wiklander     unsigned char buf[MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES];
312*32b31808SJens Wiklander     mbedtls_pk_info_t pk_info = mbedtls_rsa_info;
313*32b31808SJens Wiklander 
314*32b31808SJens Wiklander     *sig_len = mbedtls_rsa_get_len(rsa_ctx);
315*32b31808SJens Wiklander     if (sig_size < *sig_len) {
316*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;
317*32b31808SJens Wiklander     }
318*32b31808SJens Wiklander 
319*32b31808SJens Wiklander     /* mbedtls_pk_write_key_der() expects a full PK context;
320*32b31808SJens Wiklander      * re-construct one to make it happy */
321*32b31808SJens Wiklander     key.pk_info = &pk_info;
322*32b31808SJens Wiklander     key.pk_ctx = rsa_ctx;
323*32b31808SJens Wiklander     key_len = mbedtls_pk_write_key_der(&key, buf, sizeof(buf));
324*32b31808SJens Wiklander     if (key_len <= 0) {
325*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
326*32b31808SJens Wiklander     }
327*32b31808SJens Wiklander     psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
328*32b31808SJens Wiklander     psa_set_key_algorithm(&attributes, alg);
329*32b31808SJens Wiklander     psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
330*32b31808SJens Wiklander 
331*32b31808SJens Wiklander     status = psa_import_key(&attributes,
332*32b31808SJens Wiklander                             buf + sizeof(buf) - key_len, key_len,
333*32b31808SJens Wiklander                             &key_id);
334*32b31808SJens Wiklander     if (status != PSA_SUCCESS) {
335*32b31808SJens Wiklander         ret = PSA_PK_TO_MBEDTLS_ERR(status);
336*32b31808SJens Wiklander         goto cleanup;
337*32b31808SJens Wiklander     }
338*32b31808SJens Wiklander     status = psa_sign_hash(key_id, alg, hash, hash_len,
339*32b31808SJens Wiklander                            sig, sig_size, sig_len);
340*32b31808SJens Wiklander     if (status != PSA_SUCCESS) {
341*32b31808SJens Wiklander         ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status);
342*32b31808SJens Wiklander         goto cleanup;
343*32b31808SJens Wiklander     }
344*32b31808SJens Wiklander 
345*32b31808SJens Wiklander     ret = 0;
346*32b31808SJens Wiklander 
347*32b31808SJens Wiklander cleanup:
348*32b31808SJens Wiklander     status = psa_destroy_key(key_id);
349*32b31808SJens Wiklander     if (ret == 0 && status != PSA_SUCCESS) {
350*32b31808SJens Wiklander         ret = PSA_PK_TO_MBEDTLS_ERR(status);
351*32b31808SJens Wiklander     }
352*32b31808SJens Wiklander     return ret;
353*32b31808SJens Wiklander }
354*32b31808SJens Wiklander #endif /* MBEDTLS_PSA_CRYPTO_C */
355*32b31808SJens Wiklander 
356*32b31808SJens Wiklander #if defined(MBEDTLS_USE_PSA_CRYPTO)
357817466cbSJens Wiklander static int rsa_sign_wrap(void *ctx, mbedtls_md_type_t md_alg,
358817466cbSJens Wiklander                          const unsigned char *hash, size_t hash_len,
359*32b31808SJens Wiklander                          unsigned char *sig, size_t sig_size, size_t *sig_len,
360*32b31808SJens Wiklander                          int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
361*32b31808SJens Wiklander {
362*32b31808SJens Wiklander     ((void) f_rng);
363*32b31808SJens Wiklander     ((void) p_rng);
364*32b31808SJens Wiklander 
365*32b31808SJens Wiklander     psa_algorithm_t psa_md_alg;
366*32b31808SJens Wiklander     psa_md_alg = mbedtls_hash_info_psa_from_md(md_alg);
367*32b31808SJens Wiklander     if (psa_md_alg == 0) {
368*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
369*32b31808SJens Wiklander     }
370*32b31808SJens Wiklander 
371*32b31808SJens Wiklander     return mbedtls_pk_psa_rsa_sign_ext(PSA_ALG_RSA_PKCS1V15_SIGN(
372*32b31808SJens Wiklander                                            psa_md_alg),
373*32b31808SJens Wiklander                                        ctx, hash, hash_len,
374*32b31808SJens Wiklander                                        sig, sig_size, sig_len);
375*32b31808SJens Wiklander }
376*32b31808SJens Wiklander #else
377*32b31808SJens Wiklander static int rsa_sign_wrap(void *ctx, mbedtls_md_type_t md_alg,
378*32b31808SJens Wiklander                          const unsigned char *hash, size_t hash_len,
379*32b31808SJens Wiklander                          unsigned char *sig, size_t sig_size, size_t *sig_len,
380817466cbSJens Wiklander                          int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
381817466cbSJens Wiklander {
3823d3b0591SJens Wiklander     mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx;
3833d3b0591SJens Wiklander 
384*32b31808SJens Wiklander     if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) {
385*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
386817466cbSJens Wiklander     }
387817466cbSJens Wiklander 
388*32b31808SJens Wiklander     *sig_len = mbedtls_rsa_get_len(rsa);
389*32b31808SJens Wiklander     if (sig_size < *sig_len) {
390*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;
391*32b31808SJens Wiklander     }
392*32b31808SJens Wiklander 
393*32b31808SJens Wiklander     return mbedtls_rsa_pkcs1_sign(rsa, f_rng, p_rng,
394*32b31808SJens Wiklander                                   md_alg, (unsigned int) hash_len,
395*32b31808SJens Wiklander                                   hash, sig);
396*32b31808SJens Wiklander }
397*32b31808SJens Wiklander #endif
398*32b31808SJens Wiklander 
399*32b31808SJens Wiklander #if defined(MBEDTLS_USE_PSA_CRYPTO)
400*32b31808SJens Wiklander static int rsa_decrypt_wrap(void *ctx,
401*32b31808SJens Wiklander                             const unsigned char *input, size_t ilen,
402*32b31808SJens Wiklander                             unsigned char *output, size_t *olen, size_t osize,
403*32b31808SJens Wiklander                             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
404*32b31808SJens Wiklander {
405*32b31808SJens Wiklander     mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx;
406*32b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
407*32b31808SJens Wiklander     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
408*32b31808SJens Wiklander     mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
409*32b31808SJens Wiklander     psa_status_t status;
410*32b31808SJens Wiklander     mbedtls_pk_context key;
411*32b31808SJens Wiklander     int key_len;
412*32b31808SJens Wiklander     unsigned char buf[MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES];
413*32b31808SJens Wiklander 
414*32b31808SJens Wiklander     ((void) f_rng);
415*32b31808SJens Wiklander     ((void) p_rng);
416*32b31808SJens Wiklander 
417*32b31808SJens Wiklander #if !defined(MBEDTLS_RSA_ALT)
418*32b31808SJens Wiklander     if (rsa->padding != MBEDTLS_RSA_PKCS_V15) {
419*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_INVALID_PADDING;
420*32b31808SJens Wiklander     }
421*32b31808SJens Wiklander #endif /* !MBEDTLS_RSA_ALT */
422*32b31808SJens Wiklander 
423*32b31808SJens Wiklander     if (ilen != mbedtls_rsa_get_len(rsa)) {
424*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
425*32b31808SJens Wiklander     }
426*32b31808SJens Wiklander 
427*32b31808SJens Wiklander     /* mbedtls_pk_write_key_der() expects a full PK context;
428*32b31808SJens Wiklander      * re-construct one to make it happy */
429*32b31808SJens Wiklander     key.pk_info = &mbedtls_rsa_info;
430*32b31808SJens Wiklander     key.pk_ctx = ctx;
431*32b31808SJens Wiklander     key_len = mbedtls_pk_write_key_der(&key, buf, sizeof(buf));
432*32b31808SJens Wiklander     if (key_len <= 0) {
433*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
434*32b31808SJens Wiklander     }
435*32b31808SJens Wiklander 
436*32b31808SJens Wiklander     psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
437*32b31808SJens Wiklander     psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
438*32b31808SJens Wiklander     psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT);
439*32b31808SJens Wiklander 
440*32b31808SJens Wiklander     status = psa_import_key(&attributes,
441*32b31808SJens Wiklander                             buf + sizeof(buf) - key_len, key_len,
442*32b31808SJens Wiklander                             &key_id);
443*32b31808SJens Wiklander     if (status != PSA_SUCCESS) {
444*32b31808SJens Wiklander         ret = PSA_PK_TO_MBEDTLS_ERR(status);
445*32b31808SJens Wiklander         goto cleanup;
446*32b31808SJens Wiklander     }
447*32b31808SJens Wiklander 
448*32b31808SJens Wiklander     status = psa_asymmetric_decrypt(key_id, PSA_ALG_RSA_PKCS1V15_CRYPT,
449*32b31808SJens Wiklander                                     input, ilen,
450*32b31808SJens Wiklander                                     NULL, 0,
451*32b31808SJens Wiklander                                     output, osize, olen);
452*32b31808SJens Wiklander     if (status != PSA_SUCCESS) {
453*32b31808SJens Wiklander         ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status);
454*32b31808SJens Wiklander         goto cleanup;
455*32b31808SJens Wiklander     }
456*32b31808SJens Wiklander 
457*32b31808SJens Wiklander     ret = 0;
458*32b31808SJens Wiklander 
459*32b31808SJens Wiklander cleanup:
460*32b31808SJens Wiklander     mbedtls_platform_zeroize(buf, sizeof(buf));
461*32b31808SJens Wiklander     status = psa_destroy_key(key_id);
462*32b31808SJens Wiklander     if (ret == 0 && status != PSA_SUCCESS) {
463*32b31808SJens Wiklander         ret = PSA_PK_TO_MBEDTLS_ERR(status);
464*32b31808SJens Wiklander     }
465*32b31808SJens Wiklander 
466*32b31808SJens Wiklander     return ret;
467*32b31808SJens Wiklander }
468*32b31808SJens Wiklander #else
469817466cbSJens Wiklander static int rsa_decrypt_wrap(void *ctx,
470817466cbSJens Wiklander                             const unsigned char *input, size_t ilen,
471817466cbSJens Wiklander                             unsigned char *output, size_t *olen, size_t osize,
472817466cbSJens Wiklander                             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
473817466cbSJens Wiklander {
4743d3b0591SJens Wiklander     mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx;
4753d3b0591SJens Wiklander 
476*32b31808SJens Wiklander     if (ilen != mbedtls_rsa_get_len(rsa)) {
477*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
478817466cbSJens Wiklander     }
479817466cbSJens Wiklander 
480*32b31808SJens Wiklander     return mbedtls_rsa_pkcs1_decrypt(rsa, f_rng, p_rng,
481*32b31808SJens Wiklander                                      olen, input, output, osize);
482*32b31808SJens Wiklander }
483*32b31808SJens Wiklander #endif
484*32b31808SJens Wiklander 
485*32b31808SJens Wiklander #if defined(MBEDTLS_USE_PSA_CRYPTO)
486*32b31808SJens Wiklander static int rsa_encrypt_wrap(void *ctx,
487*32b31808SJens Wiklander                             const unsigned char *input, size_t ilen,
488*32b31808SJens Wiklander                             unsigned char *output, size_t *olen, size_t osize,
489*32b31808SJens Wiklander                             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
490*32b31808SJens Wiklander {
491*32b31808SJens Wiklander     mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx;
492*32b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
493*32b31808SJens Wiklander     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
494*32b31808SJens Wiklander     mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
495*32b31808SJens Wiklander     psa_status_t status;
496*32b31808SJens Wiklander     mbedtls_pk_context key;
497*32b31808SJens Wiklander     int key_len;
498*32b31808SJens Wiklander     unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES];
499*32b31808SJens Wiklander 
500*32b31808SJens Wiklander     ((void) f_rng);
501*32b31808SJens Wiklander     ((void) p_rng);
502*32b31808SJens Wiklander 
503*32b31808SJens Wiklander #if !defined(MBEDTLS_RSA_ALT)
504*32b31808SJens Wiklander     if (rsa->padding != MBEDTLS_RSA_PKCS_V15) {
505*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_INVALID_PADDING;
506*32b31808SJens Wiklander     }
507*32b31808SJens Wiklander #endif
508*32b31808SJens Wiklander 
509*32b31808SJens Wiklander     if (mbedtls_rsa_get_len(rsa) > osize) {
510*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE;
511*32b31808SJens Wiklander     }
512*32b31808SJens Wiklander 
513*32b31808SJens Wiklander     /* mbedtls_pk_write_pubkey_der() expects a full PK context;
514*32b31808SJens Wiklander      * re-construct one to make it happy */
515*32b31808SJens Wiklander     key.pk_info = &mbedtls_rsa_info;
516*32b31808SJens Wiklander     key.pk_ctx = ctx;
517*32b31808SJens Wiklander     key_len = mbedtls_pk_write_pubkey_der(&key, buf, sizeof(buf));
518*32b31808SJens Wiklander     if (key_len <= 0) {
519*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
520*32b31808SJens Wiklander     }
521*32b31808SJens Wiklander 
522*32b31808SJens Wiklander     psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
523*32b31808SJens Wiklander     psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT);
524*32b31808SJens Wiklander     psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY);
525*32b31808SJens Wiklander 
526*32b31808SJens Wiklander     status = psa_import_key(&attributes,
527*32b31808SJens Wiklander                             buf + sizeof(buf) - key_len, key_len,
528*32b31808SJens Wiklander                             &key_id);
529*32b31808SJens Wiklander     if (status != PSA_SUCCESS) {
530*32b31808SJens Wiklander         ret = PSA_PK_TO_MBEDTLS_ERR(status);
531*32b31808SJens Wiklander         goto cleanup;
532*32b31808SJens Wiklander     }
533*32b31808SJens Wiklander 
534*32b31808SJens Wiklander     status = psa_asymmetric_encrypt(key_id, PSA_ALG_RSA_PKCS1V15_CRYPT,
535*32b31808SJens Wiklander                                     input, ilen,
536*32b31808SJens Wiklander                                     NULL, 0,
537*32b31808SJens Wiklander                                     output, osize, olen);
538*32b31808SJens Wiklander     if (status != PSA_SUCCESS) {
539*32b31808SJens Wiklander         ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status);
540*32b31808SJens Wiklander         goto cleanup;
541*32b31808SJens Wiklander     }
542*32b31808SJens Wiklander 
543*32b31808SJens Wiklander     ret = 0;
544*32b31808SJens Wiklander 
545*32b31808SJens Wiklander cleanup:
546*32b31808SJens Wiklander     status = psa_destroy_key(key_id);
547*32b31808SJens Wiklander     if (ret == 0 && status != PSA_SUCCESS) {
548*32b31808SJens Wiklander         ret = PSA_PK_TO_MBEDTLS_ERR(status);
549*32b31808SJens Wiklander     }
550*32b31808SJens Wiklander 
551*32b31808SJens Wiklander     return ret;
552*32b31808SJens Wiklander }
553*32b31808SJens Wiklander #else
554817466cbSJens Wiklander static int rsa_encrypt_wrap(void *ctx,
555817466cbSJens Wiklander                             const unsigned char *input, size_t ilen,
556817466cbSJens Wiklander                             unsigned char *output, size_t *olen, size_t osize,
557817466cbSJens Wiklander                             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
558817466cbSJens Wiklander {
5593d3b0591SJens Wiklander     mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx;
5603d3b0591SJens Wiklander     *olen = mbedtls_rsa_get_len(rsa);
561817466cbSJens Wiklander 
562*32b31808SJens Wiklander     if (*olen > osize) {
563*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE;
564817466cbSJens Wiklander     }
565817466cbSJens Wiklander 
566*32b31808SJens Wiklander     return mbedtls_rsa_pkcs1_encrypt(rsa, f_rng, p_rng,
567*32b31808SJens Wiklander                                      ilen, input, output);
568*32b31808SJens Wiklander }
569*32b31808SJens Wiklander #endif
570*32b31808SJens Wiklander 
571*32b31808SJens Wiklander static int rsa_check_pair_wrap(const void *pub, const void *prv,
572*32b31808SJens Wiklander                                int (*f_rng)(void *, unsigned char *, size_t),
573*32b31808SJens Wiklander                                void *p_rng)
574817466cbSJens Wiklander {
575*32b31808SJens Wiklander     (void) f_rng;
576*32b31808SJens Wiklander     (void) p_rng;
577*32b31808SJens Wiklander     return mbedtls_rsa_check_pub_priv((const mbedtls_rsa_context *) pub,
578*32b31808SJens Wiklander                                       (const mbedtls_rsa_context *) prv);
579817466cbSJens Wiklander }
580817466cbSJens Wiklander 
581817466cbSJens Wiklander static void *rsa_alloc_wrap(void)
582817466cbSJens Wiklander {
583817466cbSJens Wiklander     void *ctx = mbedtls_calloc(1, sizeof(mbedtls_rsa_context));
584817466cbSJens Wiklander 
585*32b31808SJens Wiklander     if (ctx != NULL) {
586*32b31808SJens Wiklander         mbedtls_rsa_init((mbedtls_rsa_context *) ctx);
587*32b31808SJens Wiklander     }
588817466cbSJens Wiklander 
589*32b31808SJens Wiklander     return ctx;
590817466cbSJens Wiklander }
591817466cbSJens Wiklander 
592817466cbSJens Wiklander static void rsa_free_wrap(void *ctx)
593817466cbSJens Wiklander {
594817466cbSJens Wiklander     mbedtls_rsa_free((mbedtls_rsa_context *) ctx);
595817466cbSJens Wiklander     mbedtls_free(ctx);
596817466cbSJens Wiklander }
597817466cbSJens Wiklander 
598817466cbSJens Wiklander static void rsa_debug(const void *ctx, mbedtls_pk_debug_item *items)
599817466cbSJens Wiklander {
600*32b31808SJens Wiklander #if defined(MBEDTLS_RSA_ALT)
601*32b31808SJens Wiklander     /* Not supported */
602*32b31808SJens Wiklander     (void) ctx;
603*32b31808SJens Wiklander     (void) items;
604*32b31808SJens Wiklander #else
605817466cbSJens Wiklander     items->type = MBEDTLS_PK_DEBUG_MPI;
606817466cbSJens Wiklander     items->name = "rsa.N";
607817466cbSJens Wiklander     items->value = &(((mbedtls_rsa_context *) ctx)->N);
608817466cbSJens Wiklander 
609817466cbSJens Wiklander     items++;
610817466cbSJens Wiklander 
611817466cbSJens Wiklander     items->type = MBEDTLS_PK_DEBUG_MPI;
612817466cbSJens Wiklander     items->name = "rsa.E";
613817466cbSJens Wiklander     items->value = &(((mbedtls_rsa_context *) ctx)->E);
614*32b31808SJens Wiklander #endif
615817466cbSJens Wiklander }
616817466cbSJens Wiklander 
617817466cbSJens Wiklander const mbedtls_pk_info_t mbedtls_rsa_info = {
618817466cbSJens Wiklander     MBEDTLS_PK_RSA,
619817466cbSJens Wiklander     "RSA",
620817466cbSJens Wiklander     rsa_get_bitlen,
621817466cbSJens Wiklander     rsa_can_do,
622817466cbSJens Wiklander     rsa_verify_wrap,
623817466cbSJens Wiklander     rsa_sign_wrap,
6243d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
6253d3b0591SJens Wiklander     NULL,
6263d3b0591SJens Wiklander     NULL,
6273d3b0591SJens Wiklander #endif
628817466cbSJens Wiklander     rsa_decrypt_wrap,
629817466cbSJens Wiklander     rsa_encrypt_wrap,
630817466cbSJens Wiklander     rsa_check_pair_wrap,
631817466cbSJens Wiklander     rsa_alloc_wrap,
632817466cbSJens Wiklander     rsa_free_wrap,
6333d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
6343d3b0591SJens Wiklander     NULL,
6353d3b0591SJens Wiklander     NULL,
6363d3b0591SJens Wiklander #endif
637817466cbSJens Wiklander     rsa_debug,
638817466cbSJens Wiklander };
639817466cbSJens Wiklander #endif /* MBEDTLS_RSA_C */
640817466cbSJens Wiklander 
641817466cbSJens Wiklander #if defined(MBEDTLS_ECP_C)
642817466cbSJens Wiklander /*
643817466cbSJens Wiklander  * Generic EC key
644817466cbSJens Wiklander  */
645817466cbSJens Wiklander static int eckey_can_do(mbedtls_pk_type_t type)
646817466cbSJens Wiklander {
647*32b31808SJens Wiklander     return type == MBEDTLS_PK_ECKEY ||
648817466cbSJens Wiklander            type == MBEDTLS_PK_ECKEY_DH ||
649*32b31808SJens Wiklander            type == MBEDTLS_PK_ECDSA;
650817466cbSJens Wiklander }
651817466cbSJens Wiklander 
652817466cbSJens Wiklander static size_t eckey_get_bitlen(const void *ctx)
653817466cbSJens Wiklander {
654*32b31808SJens Wiklander     return ((mbedtls_ecp_keypair *) ctx)->grp.pbits;
655817466cbSJens Wiklander }
656817466cbSJens Wiklander 
657*32b31808SJens Wiklander #if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY)
658*32b31808SJens Wiklander #if defined(MBEDTLS_USE_PSA_CRYPTO)
659*32b31808SJens Wiklander /*
660*32b31808SJens Wiklander  * An ASN.1 encoded signature is a sequence of two ASN.1 integers. Parse one of
661*32b31808SJens Wiklander  * those integers and convert it to the fixed-length encoding expected by PSA.
662*32b31808SJens Wiklander  */
663*32b31808SJens Wiklander static int extract_ecdsa_sig_int(unsigned char **from, const unsigned char *end,
664*32b31808SJens Wiklander                                  unsigned char *to, size_t to_len)
665*32b31808SJens Wiklander {
666*32b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
667*32b31808SJens Wiklander     size_t unpadded_len, padding_len;
668*32b31808SJens Wiklander 
669*32b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(from, end, &unpadded_len,
670*32b31808SJens Wiklander                                     MBEDTLS_ASN1_INTEGER)) != 0) {
671*32b31808SJens Wiklander         return ret;
672*32b31808SJens Wiklander     }
673*32b31808SJens Wiklander 
674*32b31808SJens Wiklander     while (unpadded_len > 0 && **from == 0x00) {
675*32b31808SJens Wiklander         (*from)++;
676*32b31808SJens Wiklander         unpadded_len--;
677*32b31808SJens Wiklander     }
678*32b31808SJens Wiklander 
679*32b31808SJens Wiklander     if (unpadded_len > to_len || unpadded_len == 0) {
680*32b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
681*32b31808SJens Wiklander     }
682*32b31808SJens Wiklander 
683*32b31808SJens Wiklander     padding_len = to_len - unpadded_len;
684*32b31808SJens Wiklander     memset(to, 0x00, padding_len);
685*32b31808SJens Wiklander     memcpy(to + padding_len, *from, unpadded_len);
686*32b31808SJens Wiklander     (*from) += unpadded_len;
687*32b31808SJens Wiklander 
688*32b31808SJens Wiklander     return 0;
689*32b31808SJens Wiklander }
690*32b31808SJens Wiklander 
691*32b31808SJens Wiklander /*
692*32b31808SJens Wiklander  * Convert a signature from an ASN.1 sequence of two integers
693*32b31808SJens Wiklander  * to a raw {r,s} buffer. Note: the provided sig buffer must be at least
694*32b31808SJens Wiklander  * twice as big as int_size.
695*32b31808SJens Wiklander  */
696*32b31808SJens Wiklander static int extract_ecdsa_sig(unsigned char **p, const unsigned char *end,
697*32b31808SJens Wiklander                              unsigned char *sig, size_t int_size)
698*32b31808SJens Wiklander {
699*32b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
700*32b31808SJens Wiklander     size_t tmp_size;
701*32b31808SJens Wiklander 
702*32b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(p, end, &tmp_size,
703*32b31808SJens Wiklander                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
704*32b31808SJens Wiklander         return ret;
705*32b31808SJens Wiklander     }
706*32b31808SJens Wiklander 
707*32b31808SJens Wiklander     /* Extract r */
708*32b31808SJens Wiklander     if ((ret = extract_ecdsa_sig_int(p, end, sig, int_size)) != 0) {
709*32b31808SJens Wiklander         return ret;
710*32b31808SJens Wiklander     }
711*32b31808SJens Wiklander     /* Extract s */
712*32b31808SJens Wiklander     if ((ret = extract_ecdsa_sig_int(p, end, sig + int_size, int_size)) != 0) {
713*32b31808SJens Wiklander         return ret;
714*32b31808SJens Wiklander     }
715*32b31808SJens Wiklander 
716*32b31808SJens Wiklander     return 0;
717*32b31808SJens Wiklander }
718*32b31808SJens Wiklander 
719*32b31808SJens Wiklander static int ecdsa_verify_wrap(void *ctx_arg, mbedtls_md_type_t md_alg,
720*32b31808SJens Wiklander                              const unsigned char *hash, size_t hash_len,
721*32b31808SJens Wiklander                              const unsigned char *sig, size_t sig_len)
722*32b31808SJens Wiklander {
723*32b31808SJens Wiklander     mbedtls_ecp_keypair *ctx = ctx_arg;
724*32b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
725*32b31808SJens Wiklander     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
726*32b31808SJens Wiklander     mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
727*32b31808SJens Wiklander     psa_status_t status;
728*32b31808SJens Wiklander     size_t key_len;
729*32b31808SJens Wiklander     /* This buffer will initially contain the public key and then the signature
730*32b31808SJens Wiklander      * but at different points in time. For all curves except secp224k1, which
731*32b31808SJens Wiklander      * is not currently supported in PSA, the public key is one byte longer
732*32b31808SJens Wiklander      * (header byte + 2 numbers, while the signature is only 2 numbers),
733*32b31808SJens Wiklander      * so use that as the buffer size. */
734*32b31808SJens Wiklander     unsigned char buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];
735*32b31808SJens Wiklander     unsigned char *p;
736*32b31808SJens Wiklander     psa_algorithm_t psa_sig_md = PSA_ALG_ECDSA_ANY;
737*32b31808SJens Wiklander     size_t curve_bits;
738*32b31808SJens Wiklander     psa_ecc_family_t curve =
739*32b31808SJens Wiklander         mbedtls_ecc_group_to_psa(ctx->grp.id, &curve_bits);
740*32b31808SJens Wiklander     const size_t signature_part_size = (ctx->grp.nbits + 7) / 8;
741*32b31808SJens Wiklander     ((void) md_alg);
742*32b31808SJens Wiklander 
743*32b31808SJens Wiklander     if (curve == 0) {
744*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
745*32b31808SJens Wiklander     }
746*32b31808SJens Wiklander 
747*32b31808SJens Wiklander     psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve));
748*32b31808SJens Wiklander     psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);
749*32b31808SJens Wiklander     psa_set_key_algorithm(&attributes, psa_sig_md);
750*32b31808SJens Wiklander 
751*32b31808SJens Wiklander     ret = mbedtls_ecp_point_write_binary(&ctx->grp, &ctx->Q,
752*32b31808SJens Wiklander                                          MBEDTLS_ECP_PF_UNCOMPRESSED,
753*32b31808SJens Wiklander                                          &key_len, buf, sizeof(buf));
754*32b31808SJens Wiklander     if (ret != 0) {
755*32b31808SJens Wiklander         goto cleanup;
756*32b31808SJens Wiklander     }
757*32b31808SJens Wiklander 
758*32b31808SJens Wiklander     status = psa_import_key(&attributes,
759*32b31808SJens Wiklander                             buf, key_len,
760*32b31808SJens Wiklander                             &key_id);
761*32b31808SJens Wiklander     if (status != PSA_SUCCESS) {
762*32b31808SJens Wiklander         ret = PSA_PK_TO_MBEDTLS_ERR(status);
763*32b31808SJens Wiklander         goto cleanup;
764*32b31808SJens Wiklander     }
765*32b31808SJens Wiklander 
766*32b31808SJens Wiklander     /* We don't need the exported key anymore and can
767*32b31808SJens Wiklander      * reuse its buffer for signature extraction. */
768*32b31808SJens Wiklander     if (2 * signature_part_size > sizeof(buf)) {
769*32b31808SJens Wiklander         ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA;
770*32b31808SJens Wiklander         goto cleanup;
771*32b31808SJens Wiklander     }
772*32b31808SJens Wiklander 
773*32b31808SJens Wiklander     p = (unsigned char *) sig;
774*32b31808SJens Wiklander     if ((ret = extract_ecdsa_sig(&p, sig + sig_len, buf,
775*32b31808SJens Wiklander                                  signature_part_size)) != 0) {
776*32b31808SJens Wiklander         goto cleanup;
777*32b31808SJens Wiklander     }
778*32b31808SJens Wiklander 
779*32b31808SJens Wiklander     status = psa_verify_hash(key_id, psa_sig_md,
780*32b31808SJens Wiklander                              hash, hash_len,
781*32b31808SJens Wiklander                              buf, 2 * signature_part_size);
782*32b31808SJens Wiklander     if (status != PSA_SUCCESS) {
783*32b31808SJens Wiklander         ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
784*32b31808SJens Wiklander         goto cleanup;
785*32b31808SJens Wiklander     }
786*32b31808SJens Wiklander 
787*32b31808SJens Wiklander     if (p != sig + sig_len) {
788*32b31808SJens Wiklander         ret = MBEDTLS_ERR_PK_SIG_LEN_MISMATCH;
789*32b31808SJens Wiklander         goto cleanup;
790*32b31808SJens Wiklander     }
791*32b31808SJens Wiklander     ret = 0;
792*32b31808SJens Wiklander 
793*32b31808SJens Wiklander cleanup:
794*32b31808SJens Wiklander     status = psa_destroy_key(key_id);
795*32b31808SJens Wiklander     if (ret == 0 && status != PSA_SUCCESS) {
796*32b31808SJens Wiklander         ret = PSA_PK_TO_MBEDTLS_ERR(status);
797*32b31808SJens Wiklander     }
798*32b31808SJens Wiklander 
799*32b31808SJens Wiklander     return ret;
800*32b31808SJens Wiklander }
801*32b31808SJens Wiklander #else /* MBEDTLS_USE_PSA_CRYPTO */
802817466cbSJens Wiklander static int ecdsa_verify_wrap(void *ctx, mbedtls_md_type_t md_alg,
803817466cbSJens Wiklander                              const unsigned char *hash, size_t hash_len,
804817466cbSJens Wiklander                              const unsigned char *sig, size_t sig_len)
805817466cbSJens Wiklander {
80611fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
807*32b31808SJens Wiklander     ((void) md_alg);
808817466cbSJens Wiklander 
809*32b31808SJens Wiklander     ret = mbedtls_ecdsa_read_signature((mbedtls_ecdsa_context *) ctx,
810*32b31808SJens Wiklander                                        hash, hash_len, sig, sig_len);
811817466cbSJens Wiklander 
812*32b31808SJens Wiklander     if (ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) {
813*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH;
814817466cbSJens Wiklander     }
815817466cbSJens Wiklander 
816*32b31808SJens Wiklander     return ret;
817*32b31808SJens Wiklander }
818*32b31808SJens Wiklander #endif /* MBEDTLS_USE_PSA_CRYPTO */
819*32b31808SJens Wiklander #endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */
820*32b31808SJens Wiklander 
821*32b31808SJens Wiklander #if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
822*32b31808SJens Wiklander #if defined(MBEDTLS_USE_PSA_CRYPTO)
823*32b31808SJens Wiklander /*
824*32b31808SJens Wiklander  * Simultaneously convert and move raw MPI from the beginning of a buffer
825*32b31808SJens Wiklander  * to an ASN.1 MPI at the end of the buffer.
826*32b31808SJens Wiklander  * See also mbedtls_asn1_write_mpi().
827*32b31808SJens Wiklander  *
828*32b31808SJens Wiklander  * p: pointer to the end of the output buffer
829*32b31808SJens Wiklander  * start: start of the output buffer, and also of the mpi to write at the end
830*32b31808SJens Wiklander  * n_len: length of the mpi to read from start
831*32b31808SJens Wiklander  */
832*32b31808SJens Wiklander static int asn1_write_mpibuf(unsigned char **p, unsigned char *start,
833*32b31808SJens Wiklander                              size_t n_len)
834817466cbSJens Wiklander {
83511fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
836*32b31808SJens Wiklander     size_t len = 0;
837817466cbSJens Wiklander 
838*32b31808SJens Wiklander     if ((size_t) (*p - start) < n_len) {
839*32b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
840817466cbSJens Wiklander     }
841817466cbSJens Wiklander 
842*32b31808SJens Wiklander     len = n_len;
843*32b31808SJens Wiklander     *p -= len;
844*32b31808SJens Wiklander     memmove(*p, start, len);
845*32b31808SJens Wiklander 
846*32b31808SJens Wiklander     /* ASN.1 DER encoding requires minimal length, so skip leading 0s.
847*32b31808SJens Wiklander      * Neither r nor s should be 0, but as a failsafe measure, still detect
848*32b31808SJens Wiklander      * that rather than overflowing the buffer in case of a PSA error. */
849*32b31808SJens Wiklander     while (len > 0 && **p == 0x00) {
850*32b31808SJens Wiklander         ++(*p);
851*32b31808SJens Wiklander         --len;
852*32b31808SJens Wiklander     }
853*32b31808SJens Wiklander 
854*32b31808SJens Wiklander     /* this is only reached if the signature was invalid */
855*32b31808SJens Wiklander     if (len == 0) {
856*32b31808SJens Wiklander         return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
857*32b31808SJens Wiklander     }
858*32b31808SJens Wiklander 
859*32b31808SJens Wiklander     /* if the msb is 1, ASN.1 requires that we prepend a 0.
860*32b31808SJens Wiklander      * Neither r nor s can be 0, so we can assume len > 0 at all times. */
861*32b31808SJens Wiklander     if (**p & 0x80) {
862*32b31808SJens Wiklander         if (*p - start < 1) {
863*32b31808SJens Wiklander             return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
864*32b31808SJens Wiklander         }
865*32b31808SJens Wiklander 
866*32b31808SJens Wiklander         *--(*p) = 0x00;
867*32b31808SJens Wiklander         len += 1;
868*32b31808SJens Wiklander     }
869*32b31808SJens Wiklander 
870*32b31808SJens Wiklander     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
871*32b31808SJens Wiklander     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start,
872*32b31808SJens Wiklander                                                      MBEDTLS_ASN1_INTEGER));
873*32b31808SJens Wiklander 
874*32b31808SJens Wiklander     return (int) len;
875*32b31808SJens Wiklander }
876*32b31808SJens Wiklander 
877*32b31808SJens Wiklander /* Transcode signature from PSA format to ASN.1 sequence.
878*32b31808SJens Wiklander  * See ecdsa_signature_to_asn1 in ecdsa.c, but with byte buffers instead of
879*32b31808SJens Wiklander  * MPIs, and in-place.
880*32b31808SJens Wiklander  *
881*32b31808SJens Wiklander  * [in/out] sig: the signature pre- and post-transcoding
882*32b31808SJens Wiklander  * [in/out] sig_len: signature length pre- and post-transcoding
883*32b31808SJens Wiklander  * [int] buf_len: the available size the in/out buffer
884*32b31808SJens Wiklander  */
885*32b31808SJens Wiklander static int pk_ecdsa_sig_asn1_from_psa(unsigned char *sig, size_t *sig_len,
886*32b31808SJens Wiklander                                       size_t buf_len)
887*32b31808SJens Wiklander {
888*32b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
889*32b31808SJens Wiklander     size_t len = 0;
890*32b31808SJens Wiklander     const size_t rs_len = *sig_len / 2;
891*32b31808SJens Wiklander     unsigned char *p = sig + buf_len;
892*32b31808SJens Wiklander 
893*32b31808SJens Wiklander     MBEDTLS_ASN1_CHK_ADD(len, asn1_write_mpibuf(&p, sig + rs_len, rs_len));
894*32b31808SJens Wiklander     MBEDTLS_ASN1_CHK_ADD(len, asn1_write_mpibuf(&p, sig, rs_len));
895*32b31808SJens Wiklander 
896*32b31808SJens Wiklander     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, sig, len));
897*32b31808SJens Wiklander     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, sig,
898*32b31808SJens Wiklander                                                      MBEDTLS_ASN1_CONSTRUCTED |
899*32b31808SJens Wiklander                                                      MBEDTLS_ASN1_SEQUENCE));
900*32b31808SJens Wiklander 
901*32b31808SJens Wiklander     memmove(sig, p, len);
902*32b31808SJens Wiklander     *sig_len = len;
903*32b31808SJens Wiklander 
904*32b31808SJens Wiklander     return 0;
905*32b31808SJens Wiklander }
906*32b31808SJens Wiklander 
907*32b31808SJens Wiklander static int ecdsa_sign_wrap(void *ctx_arg, mbedtls_md_type_t md_alg,
908*32b31808SJens Wiklander                            const unsigned char *hash, size_t hash_len,
909*32b31808SJens Wiklander                            unsigned char *sig, size_t sig_size, size_t *sig_len,
910*32b31808SJens Wiklander                            int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
911*32b31808SJens Wiklander {
912*32b31808SJens Wiklander     mbedtls_ecp_keypair *ctx = ctx_arg;
913*32b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
914*32b31808SJens Wiklander     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
915*32b31808SJens Wiklander     mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
916*32b31808SJens Wiklander     psa_status_t status;
917*32b31808SJens Wiklander     unsigned char buf[MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH];
918*32b31808SJens Wiklander #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
919*32b31808SJens Wiklander     psa_algorithm_t psa_sig_md =
920*32b31808SJens Wiklander         PSA_ALG_DETERMINISTIC_ECDSA(mbedtls_hash_info_psa_from_md(md_alg));
921*32b31808SJens Wiklander #else
922*32b31808SJens Wiklander     psa_algorithm_t psa_sig_md =
923*32b31808SJens Wiklander         PSA_ALG_ECDSA(mbedtls_hash_info_psa_from_md(md_alg));
924*32b31808SJens Wiklander #endif
925*32b31808SJens Wiklander     size_t curve_bits;
926*32b31808SJens Wiklander     psa_ecc_family_t curve =
927*32b31808SJens Wiklander         mbedtls_ecc_group_to_psa(ctx->grp.id, &curve_bits);
928*32b31808SJens Wiklander     size_t key_len = PSA_BITS_TO_BYTES(curve_bits);
929*32b31808SJens Wiklander 
930*32b31808SJens Wiklander     /* PSA has its own RNG */
931*32b31808SJens Wiklander     ((void) f_rng);
932*32b31808SJens Wiklander     ((void) p_rng);
933*32b31808SJens Wiklander 
934*32b31808SJens Wiklander     if (curve == 0) {
935*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
936*32b31808SJens Wiklander     }
937*32b31808SJens Wiklander 
938*32b31808SJens Wiklander     if (key_len > sizeof(buf)) {
939*32b31808SJens Wiklander         return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
940*32b31808SJens Wiklander     }
941*32b31808SJens Wiklander     ret = mbedtls_mpi_write_binary(&ctx->d, buf, key_len);
942*32b31808SJens Wiklander     if (ret != 0) {
943*32b31808SJens Wiklander         goto cleanup;
944*32b31808SJens Wiklander     }
945*32b31808SJens Wiklander 
946*32b31808SJens Wiklander     psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(curve));
947*32b31808SJens Wiklander     psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
948*32b31808SJens Wiklander     psa_set_key_algorithm(&attributes, psa_sig_md);
949*32b31808SJens Wiklander 
950*32b31808SJens Wiklander     status = psa_import_key(&attributes,
951*32b31808SJens Wiklander                             buf, key_len,
952*32b31808SJens Wiklander                             &key_id);
953*32b31808SJens Wiklander     if (status != PSA_SUCCESS) {
954*32b31808SJens Wiklander         ret = PSA_PK_TO_MBEDTLS_ERR(status);
955*32b31808SJens Wiklander         goto cleanup;
956*32b31808SJens Wiklander     }
957*32b31808SJens Wiklander 
958*32b31808SJens Wiklander     status = psa_sign_hash(key_id, psa_sig_md, hash, hash_len,
959*32b31808SJens Wiklander                            sig, sig_size, sig_len);
960*32b31808SJens Wiklander     if (status != PSA_SUCCESS) {
961*32b31808SJens Wiklander         ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
962*32b31808SJens Wiklander         goto cleanup;
963*32b31808SJens Wiklander     }
964*32b31808SJens Wiklander 
965*32b31808SJens Wiklander     ret = pk_ecdsa_sig_asn1_from_psa(sig, sig_len, sig_size);
966*32b31808SJens Wiklander 
967*32b31808SJens Wiklander cleanup:
968*32b31808SJens Wiklander     mbedtls_platform_zeroize(buf, sizeof(buf));
969*32b31808SJens Wiklander     status = psa_destroy_key(key_id);
970*32b31808SJens Wiklander     if (ret == 0 && status != PSA_SUCCESS) {
971*32b31808SJens Wiklander         ret = PSA_PK_TO_MBEDTLS_ERR(status);
972*32b31808SJens Wiklander     }
973*32b31808SJens Wiklander 
974*32b31808SJens Wiklander     return ret;
975*32b31808SJens Wiklander }
976*32b31808SJens Wiklander #else /* MBEDTLS_USE_PSA_CRYPTO */
977*32b31808SJens Wiklander static int ecdsa_sign_wrap(void *ctx, mbedtls_md_type_t md_alg,
978*32b31808SJens Wiklander                            const unsigned char *hash, size_t hash_len,
979*32b31808SJens Wiklander                            unsigned char *sig, size_t sig_size, size_t *sig_len,
980*32b31808SJens Wiklander                            int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
981*32b31808SJens Wiklander {
982*32b31808SJens Wiklander     return mbedtls_ecdsa_write_signature((mbedtls_ecdsa_context *) ctx,
983*32b31808SJens Wiklander                                          md_alg, hash, hash_len,
984*32b31808SJens Wiklander                                          sig, sig_size, sig_len,
985*32b31808SJens Wiklander                                          f_rng, p_rng);
986*32b31808SJens Wiklander }
987*32b31808SJens Wiklander #endif /* MBEDTLS_USE_PSA_CRYPTO */
988*32b31808SJens Wiklander #endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */
989*32b31808SJens Wiklander 
990*32b31808SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
9913d3b0591SJens Wiklander /* Forward declarations */
9923d3b0591SJens Wiklander static int ecdsa_verify_rs_wrap(void *ctx, mbedtls_md_type_t md_alg,
9933d3b0591SJens Wiklander                                 const unsigned char *hash, size_t hash_len,
9943d3b0591SJens Wiklander                                 const unsigned char *sig, size_t sig_len,
9953d3b0591SJens Wiklander                                 void *rs_ctx);
9963d3b0591SJens Wiklander 
9973d3b0591SJens Wiklander static int ecdsa_sign_rs_wrap(void *ctx, mbedtls_md_type_t md_alg,
9983d3b0591SJens Wiklander                               const unsigned char *hash, size_t hash_len,
999*32b31808SJens Wiklander                               unsigned char *sig, size_t sig_size, size_t *sig_len,
10003d3b0591SJens Wiklander                               int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
10013d3b0591SJens Wiklander                               void *rs_ctx);
10023d3b0591SJens Wiklander 
10033d3b0591SJens Wiklander /*
10043d3b0591SJens Wiklander  * Restart context for ECDSA operations with ECKEY context
10053d3b0591SJens Wiklander  *
10063d3b0591SJens Wiklander  * We need to store an actual ECDSA context, as we need to pass the same to
10073d3b0591SJens Wiklander  * the underlying ecdsa function, so we can't create it on the fly every time.
10083d3b0591SJens Wiklander  */
1009*32b31808SJens Wiklander typedef struct {
10103d3b0591SJens Wiklander     mbedtls_ecdsa_restart_ctx ecdsa_rs;
10113d3b0591SJens Wiklander     mbedtls_ecdsa_context ecdsa_ctx;
10123d3b0591SJens Wiklander } eckey_restart_ctx;
10133d3b0591SJens Wiklander 
10143d3b0591SJens Wiklander static void *eckey_rs_alloc(void)
10153d3b0591SJens Wiklander {
10163d3b0591SJens Wiklander     eckey_restart_ctx *rs_ctx;
10173d3b0591SJens Wiklander 
10183d3b0591SJens Wiklander     void *ctx = mbedtls_calloc(1, sizeof(eckey_restart_ctx));
10193d3b0591SJens Wiklander 
1020*32b31808SJens Wiklander     if (ctx != NULL) {
10213d3b0591SJens Wiklander         rs_ctx = ctx;
10223d3b0591SJens Wiklander         mbedtls_ecdsa_restart_init(&rs_ctx->ecdsa_rs);
10233d3b0591SJens Wiklander         mbedtls_ecdsa_init(&rs_ctx->ecdsa_ctx);
10243d3b0591SJens Wiklander     }
10253d3b0591SJens Wiklander 
1026*32b31808SJens Wiklander     return ctx;
10273d3b0591SJens Wiklander }
10283d3b0591SJens Wiklander 
10293d3b0591SJens Wiklander static void eckey_rs_free(void *ctx)
10303d3b0591SJens Wiklander {
10313d3b0591SJens Wiklander     eckey_restart_ctx *rs_ctx;
10323d3b0591SJens Wiklander 
1033*32b31808SJens Wiklander     if (ctx == NULL) {
10343d3b0591SJens Wiklander         return;
1035*32b31808SJens Wiklander     }
10363d3b0591SJens Wiklander 
10373d3b0591SJens Wiklander     rs_ctx = ctx;
10383d3b0591SJens Wiklander     mbedtls_ecdsa_restart_free(&rs_ctx->ecdsa_rs);
10393d3b0591SJens Wiklander     mbedtls_ecdsa_free(&rs_ctx->ecdsa_ctx);
10403d3b0591SJens Wiklander 
10413d3b0591SJens Wiklander     mbedtls_free(ctx);
10423d3b0591SJens Wiklander }
10433d3b0591SJens Wiklander 
10443d3b0591SJens Wiklander static int eckey_verify_rs_wrap(void *ctx, mbedtls_md_type_t md_alg,
10453d3b0591SJens Wiklander                                 const unsigned char *hash, size_t hash_len,
10463d3b0591SJens Wiklander                                 const unsigned char *sig, size_t sig_len,
10473d3b0591SJens Wiklander                                 void *rs_ctx)
10483d3b0591SJens Wiklander {
104911fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
10503d3b0591SJens Wiklander     eckey_restart_ctx *rs = rs_ctx;
10513d3b0591SJens Wiklander 
10523d3b0591SJens Wiklander     /* Should never happen */
1053*32b31808SJens Wiklander     if (rs == NULL) {
1054*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
1055*32b31808SJens Wiklander     }
10563d3b0591SJens Wiklander 
10573d3b0591SJens Wiklander     /* set up our own sub-context if needed (that is, on first run) */
1058*32b31808SJens Wiklander     if (rs->ecdsa_ctx.grp.pbits == 0) {
10593d3b0591SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_ecdsa_from_keypair(&rs->ecdsa_ctx, ctx));
1060*32b31808SJens Wiklander     }
10613d3b0591SJens Wiklander 
10623d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(ecdsa_verify_rs_wrap(&rs->ecdsa_ctx,
10633d3b0591SJens Wiklander                                          md_alg, hash, hash_len,
10643d3b0591SJens Wiklander                                          sig, sig_len, &rs->ecdsa_rs));
10653d3b0591SJens Wiklander 
10663d3b0591SJens Wiklander cleanup:
1067*32b31808SJens Wiklander     return ret;
10683d3b0591SJens Wiklander }
10693d3b0591SJens Wiklander 
10703d3b0591SJens Wiklander static int eckey_sign_rs_wrap(void *ctx, mbedtls_md_type_t md_alg,
10713d3b0591SJens Wiklander                               const unsigned char *hash, size_t hash_len,
1072*32b31808SJens Wiklander                               unsigned char *sig, size_t sig_size, size_t *sig_len,
10733d3b0591SJens Wiklander                               int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
10743d3b0591SJens Wiklander                               void *rs_ctx)
10753d3b0591SJens Wiklander {
107611fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
10773d3b0591SJens Wiklander     eckey_restart_ctx *rs = rs_ctx;
10783d3b0591SJens Wiklander 
10793d3b0591SJens Wiklander     /* Should never happen */
1080*32b31808SJens Wiklander     if (rs == NULL) {
1081*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
1082*32b31808SJens Wiklander     }
10833d3b0591SJens Wiklander 
10843d3b0591SJens Wiklander     /* set up our own sub-context if needed (that is, on first run) */
1085*32b31808SJens Wiklander     if (rs->ecdsa_ctx.grp.pbits == 0) {
10863d3b0591SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_ecdsa_from_keypair(&rs->ecdsa_ctx, ctx));
1087*32b31808SJens Wiklander     }
10883d3b0591SJens Wiklander 
10893d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(ecdsa_sign_rs_wrap(&rs->ecdsa_ctx, md_alg,
1090*32b31808SJens Wiklander                                        hash, hash_len, sig, sig_size, sig_len,
10913d3b0591SJens Wiklander                                        f_rng, p_rng, &rs->ecdsa_rs));
10923d3b0591SJens Wiklander 
10933d3b0591SJens Wiklander cleanup:
1094*32b31808SJens Wiklander     return ret;
10953d3b0591SJens Wiklander }
1096*32b31808SJens Wiklander #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
1097817466cbSJens Wiklander 
1098*32b31808SJens Wiklander static int eckey_check_pair(const void *pub, const void *prv,
1099*32b31808SJens Wiklander                             int (*f_rng)(void *, unsigned char *, size_t),
1100*32b31808SJens Wiklander                             void *p_rng)
1101817466cbSJens Wiklander {
1102*32b31808SJens Wiklander     return mbedtls_ecp_check_pub_priv((const mbedtls_ecp_keypair *) pub,
1103*32b31808SJens Wiklander                                       (const mbedtls_ecp_keypair *) prv,
1104*32b31808SJens Wiklander                                       f_rng, p_rng);
1105817466cbSJens Wiklander }
1106817466cbSJens Wiklander 
1107817466cbSJens Wiklander static void *eckey_alloc_wrap(void)
1108817466cbSJens Wiklander {
1109817466cbSJens Wiklander     void *ctx = mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair));
1110817466cbSJens Wiklander 
1111*32b31808SJens Wiklander     if (ctx != NULL) {
1112817466cbSJens Wiklander         mbedtls_ecp_keypair_init(ctx);
1113*32b31808SJens Wiklander     }
1114817466cbSJens Wiklander 
1115*32b31808SJens Wiklander     return ctx;
1116817466cbSJens Wiklander }
1117817466cbSJens Wiklander 
1118817466cbSJens Wiklander static void eckey_free_wrap(void *ctx)
1119817466cbSJens Wiklander {
1120817466cbSJens Wiklander     mbedtls_ecp_keypair_free((mbedtls_ecp_keypair *) ctx);
1121817466cbSJens Wiklander     mbedtls_free(ctx);
1122817466cbSJens Wiklander }
1123817466cbSJens Wiklander 
1124817466cbSJens Wiklander static void eckey_debug(const void *ctx, mbedtls_pk_debug_item *items)
1125817466cbSJens Wiklander {
1126817466cbSJens Wiklander     items->type = MBEDTLS_PK_DEBUG_ECP;
1127817466cbSJens Wiklander     items->name = "eckey.Q";
1128817466cbSJens Wiklander     items->value = &(((mbedtls_ecp_keypair *) ctx)->Q);
1129817466cbSJens Wiklander }
1130817466cbSJens Wiklander 
1131817466cbSJens Wiklander const mbedtls_pk_info_t mbedtls_eckey_info = {
1132817466cbSJens Wiklander     MBEDTLS_PK_ECKEY,
1133817466cbSJens Wiklander     "EC",
1134817466cbSJens Wiklander     eckey_get_bitlen,
1135817466cbSJens Wiklander     eckey_can_do,
1136*32b31808SJens Wiklander #if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY)
1137*32b31808SJens Wiklander     ecdsa_verify_wrap,   /* Compatible key structures */
1138*32b31808SJens Wiklander #else
1139*32b31808SJens Wiklander     NULL,
1140*32b31808SJens Wiklander #endif
1141*32b31808SJens Wiklander #if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
1142*32b31808SJens Wiklander     ecdsa_sign_wrap,   /* Compatible key structures */
1143*32b31808SJens Wiklander #else
1144*32b31808SJens Wiklander     NULL,
1145*32b31808SJens Wiklander #endif
1146*32b31808SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
11473d3b0591SJens Wiklander     eckey_verify_rs_wrap,
11483d3b0591SJens Wiklander     eckey_sign_rs_wrap,
1149817466cbSJens Wiklander #endif
1150817466cbSJens Wiklander     NULL,
1151817466cbSJens Wiklander     NULL,
1152817466cbSJens Wiklander     eckey_check_pair,
1153817466cbSJens Wiklander     eckey_alloc_wrap,
1154817466cbSJens Wiklander     eckey_free_wrap,
11553d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
11563d3b0591SJens Wiklander     eckey_rs_alloc,
11573d3b0591SJens Wiklander     eckey_rs_free,
11583d3b0591SJens Wiklander #endif
1159817466cbSJens Wiklander     eckey_debug,
1160817466cbSJens Wiklander };
1161817466cbSJens Wiklander 
1162817466cbSJens Wiklander /*
1163817466cbSJens Wiklander  * EC key restricted to ECDH
1164817466cbSJens Wiklander  */
1165817466cbSJens Wiklander static int eckeydh_can_do(mbedtls_pk_type_t type)
1166817466cbSJens Wiklander {
1167*32b31808SJens Wiklander     return type == MBEDTLS_PK_ECKEY ||
1168*32b31808SJens Wiklander            type == MBEDTLS_PK_ECKEY_DH;
1169817466cbSJens Wiklander }
1170817466cbSJens Wiklander 
1171817466cbSJens Wiklander const mbedtls_pk_info_t mbedtls_eckeydh_info = {
1172817466cbSJens Wiklander     MBEDTLS_PK_ECKEY_DH,
1173817466cbSJens Wiklander     "EC_DH",
1174817466cbSJens Wiklander     eckey_get_bitlen,         /* Same underlying key structure */
1175817466cbSJens Wiklander     eckeydh_can_do,
1176817466cbSJens Wiklander     NULL,
1177817466cbSJens Wiklander     NULL,
11783d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
11793d3b0591SJens Wiklander     NULL,
11803d3b0591SJens Wiklander     NULL,
11813d3b0591SJens Wiklander #endif
1182817466cbSJens Wiklander     NULL,
1183817466cbSJens Wiklander     NULL,
1184817466cbSJens Wiklander     eckey_check_pair,
1185817466cbSJens Wiklander     eckey_alloc_wrap,       /* Same underlying key structure */
1186817466cbSJens Wiklander     eckey_free_wrap,        /* Same underlying key structure */
11873d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
11883d3b0591SJens Wiklander     NULL,
11893d3b0591SJens Wiklander     NULL,
11903d3b0591SJens Wiklander #endif
1191817466cbSJens Wiklander     eckey_debug,            /* Same underlying key structure */
1192817466cbSJens Wiklander };
1193817466cbSJens Wiklander #endif /* MBEDTLS_ECP_C */
1194817466cbSJens Wiklander 
1195*32b31808SJens Wiklander #if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
1196817466cbSJens Wiklander static int ecdsa_can_do(mbedtls_pk_type_t type)
1197817466cbSJens Wiklander {
1198*32b31808SJens Wiklander     return type == MBEDTLS_PK_ECDSA;
1199817466cbSJens Wiklander }
1200817466cbSJens Wiklander 
1201*32b31808SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
12023d3b0591SJens Wiklander static int ecdsa_verify_rs_wrap(void *ctx, mbedtls_md_type_t md_alg,
12033d3b0591SJens Wiklander                                 const unsigned char *hash, size_t hash_len,
12043d3b0591SJens Wiklander                                 const unsigned char *sig, size_t sig_len,
12053d3b0591SJens Wiklander                                 void *rs_ctx)
12063d3b0591SJens Wiklander {
120711fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
12083d3b0591SJens Wiklander     ((void) md_alg);
12093d3b0591SJens Wiklander 
12103d3b0591SJens Wiklander     ret = mbedtls_ecdsa_read_signature_restartable(
12113d3b0591SJens Wiklander         (mbedtls_ecdsa_context *) ctx,
12123d3b0591SJens Wiklander         hash, hash_len, sig, sig_len,
12133d3b0591SJens Wiklander         (mbedtls_ecdsa_restart_ctx *) rs_ctx);
12143d3b0591SJens Wiklander 
1215*32b31808SJens Wiklander     if (ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) {
1216*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH;
1217*32b31808SJens Wiklander     }
12183d3b0591SJens Wiklander 
1219*32b31808SJens Wiklander     return ret;
12203d3b0591SJens Wiklander }
12213d3b0591SJens Wiklander 
12223d3b0591SJens Wiklander static int ecdsa_sign_rs_wrap(void *ctx, mbedtls_md_type_t md_alg,
12233d3b0591SJens Wiklander                               const unsigned char *hash, size_t hash_len,
1224*32b31808SJens Wiklander                               unsigned char *sig, size_t sig_size, size_t *sig_len,
12253d3b0591SJens Wiklander                               int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
12263d3b0591SJens Wiklander                               void *rs_ctx)
12273d3b0591SJens Wiklander {
1228*32b31808SJens Wiklander     return mbedtls_ecdsa_write_signature_restartable(
12293d3b0591SJens Wiklander         (mbedtls_ecdsa_context *) ctx,
1230*32b31808SJens Wiklander         md_alg, hash, hash_len, sig, sig_size, sig_len, f_rng, p_rng,
1231*32b31808SJens Wiklander         (mbedtls_ecdsa_restart_ctx *) rs_ctx);
12323d3b0591SJens Wiklander 
12333d3b0591SJens Wiklander }
12343d3b0591SJens Wiklander 
12353d3b0591SJens Wiklander static void *ecdsa_rs_alloc(void)
12363d3b0591SJens Wiklander {
12373d3b0591SJens Wiklander     void *ctx = mbedtls_calloc(1, sizeof(mbedtls_ecdsa_restart_ctx));
12383d3b0591SJens Wiklander 
1239*32b31808SJens Wiklander     if (ctx != NULL) {
12403d3b0591SJens Wiklander         mbedtls_ecdsa_restart_init(ctx);
1241*32b31808SJens Wiklander     }
12423d3b0591SJens Wiklander 
1243*32b31808SJens Wiklander     return ctx;
12443d3b0591SJens Wiklander }
12453d3b0591SJens Wiklander 
12463d3b0591SJens Wiklander static void ecdsa_rs_free(void *ctx)
12473d3b0591SJens Wiklander {
12483d3b0591SJens Wiklander     mbedtls_ecdsa_restart_free(ctx);
12493d3b0591SJens Wiklander     mbedtls_free(ctx);
12503d3b0591SJens Wiklander }
1251*32b31808SJens Wiklander #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
12523d3b0591SJens Wiklander 
1253817466cbSJens Wiklander const mbedtls_pk_info_t mbedtls_ecdsa_info = {
1254817466cbSJens Wiklander     MBEDTLS_PK_ECDSA,
1255817466cbSJens Wiklander     "ECDSA",
1256817466cbSJens Wiklander     eckey_get_bitlen,     /* Compatible key structures */
1257817466cbSJens Wiklander     ecdsa_can_do,
1258*32b31808SJens Wiklander #if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY)
1259*32b31808SJens Wiklander     ecdsa_verify_wrap,   /* Compatible key structures */
1260*32b31808SJens Wiklander #else
1261*32b31808SJens Wiklander     NULL,
1262*32b31808SJens Wiklander #endif
1263*32b31808SJens Wiklander #if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
1264*32b31808SJens Wiklander     ecdsa_sign_wrap,   /* Compatible key structures */
1265*32b31808SJens Wiklander #else
1266*32b31808SJens Wiklander     NULL,
1267*32b31808SJens Wiklander #endif
1268*32b31808SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
12693d3b0591SJens Wiklander     ecdsa_verify_rs_wrap,
12703d3b0591SJens Wiklander     ecdsa_sign_rs_wrap,
12713d3b0591SJens Wiklander #endif
1272817466cbSJens Wiklander     NULL,
1273817466cbSJens Wiklander     NULL,
1274817466cbSJens Wiklander     eckey_check_pair,   /* Compatible key structures */
1275*32b31808SJens Wiklander     eckey_alloc_wrap,   /* Compatible key structures */
1276*32b31808SJens Wiklander     eckey_free_wrap,   /* Compatible key structures */
1277*32b31808SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
12783d3b0591SJens Wiklander     ecdsa_rs_alloc,
12793d3b0591SJens Wiklander     ecdsa_rs_free,
12803d3b0591SJens Wiklander #endif
1281817466cbSJens Wiklander     eckey_debug,        /* Compatible key structures */
1282817466cbSJens Wiklander };
1283*32b31808SJens Wiklander #endif /* MBEDTLS_PK_CAN_ECDSA_SOME */
1284817466cbSJens Wiklander 
1285817466cbSJens Wiklander #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
1286817466cbSJens Wiklander /*
1287817466cbSJens Wiklander  * Support for alternative RSA-private implementations
1288817466cbSJens Wiklander  */
1289817466cbSJens Wiklander 
1290817466cbSJens Wiklander static int rsa_alt_can_do(mbedtls_pk_type_t type)
1291817466cbSJens Wiklander {
1292*32b31808SJens Wiklander     return type == MBEDTLS_PK_RSA;
1293817466cbSJens Wiklander }
1294817466cbSJens Wiklander 
1295817466cbSJens Wiklander static size_t rsa_alt_get_bitlen(const void *ctx)
1296817466cbSJens Wiklander {
1297817466cbSJens Wiklander     const mbedtls_rsa_alt_context *rsa_alt = (const mbedtls_rsa_alt_context *) ctx;
1298817466cbSJens Wiklander 
1299*32b31808SJens Wiklander     return 8 * rsa_alt->key_len_func(rsa_alt->key);
1300817466cbSJens Wiklander }
1301817466cbSJens Wiklander 
1302817466cbSJens Wiklander static int rsa_alt_sign_wrap(void *ctx, mbedtls_md_type_t md_alg,
1303817466cbSJens Wiklander                              const unsigned char *hash, size_t hash_len,
1304*32b31808SJens Wiklander                              unsigned char *sig, size_t sig_size, size_t *sig_len,
1305817466cbSJens Wiklander                              int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
1306817466cbSJens Wiklander {
1307817466cbSJens Wiklander     mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx;
1308817466cbSJens Wiklander 
1309*32b31808SJens Wiklander     if (UINT_MAX < hash_len) {
1310*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
1311*32b31808SJens Wiklander     }
1312817466cbSJens Wiklander 
1313817466cbSJens Wiklander     *sig_len = rsa_alt->key_len_func(rsa_alt->key);
1314*32b31808SJens Wiklander     if (*sig_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE) {
1315*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
1316*32b31808SJens Wiklander     }
1317*32b31808SJens Wiklander     if (*sig_len > sig_size) {
1318*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;
1319*32b31808SJens Wiklander     }
1320817466cbSJens Wiklander 
1321*32b31808SJens Wiklander     return rsa_alt->sign_func(rsa_alt->key, f_rng, p_rng,
1322*32b31808SJens Wiklander                               md_alg, (unsigned int) hash_len, hash, sig);
1323817466cbSJens Wiklander }
1324817466cbSJens Wiklander 
1325817466cbSJens Wiklander static int rsa_alt_decrypt_wrap(void *ctx,
1326817466cbSJens Wiklander                                 const unsigned char *input, size_t ilen,
1327817466cbSJens Wiklander                                 unsigned char *output, size_t *olen, size_t osize,
1328817466cbSJens Wiklander                                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
1329817466cbSJens Wiklander {
1330817466cbSJens Wiklander     mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx;
1331817466cbSJens Wiklander 
1332817466cbSJens Wiklander     ((void) f_rng);
1333817466cbSJens Wiklander     ((void) p_rng);
1334817466cbSJens Wiklander 
1335*32b31808SJens Wiklander     if (ilen != rsa_alt->key_len_func(rsa_alt->key)) {
1336*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1337*32b31808SJens Wiklander     }
1338817466cbSJens Wiklander 
1339*32b31808SJens Wiklander     return rsa_alt->decrypt_func(rsa_alt->key,
1340*32b31808SJens Wiklander                                  olen, input, output, osize);
1341817466cbSJens Wiklander }
1342817466cbSJens Wiklander 
1343817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C)
1344*32b31808SJens Wiklander static int rsa_alt_check_pair(const void *pub, const void *prv,
1345*32b31808SJens Wiklander                               int (*f_rng)(void *, unsigned char *, size_t),
1346*32b31808SJens Wiklander                               void *p_rng)
1347817466cbSJens Wiklander {
1348817466cbSJens Wiklander     unsigned char sig[MBEDTLS_MPI_MAX_SIZE];
1349817466cbSJens Wiklander     unsigned char hash[32];
1350817466cbSJens Wiklander     size_t sig_len = 0;
135111fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1352817466cbSJens Wiklander 
1353*32b31808SJens Wiklander     if (rsa_alt_get_bitlen(prv) != rsa_get_bitlen(pub)) {
1354*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
1355*32b31808SJens Wiklander     }
1356817466cbSJens Wiklander 
1357817466cbSJens Wiklander     memset(hash, 0x2a, sizeof(hash));
1358817466cbSJens Wiklander 
1359817466cbSJens Wiklander     if ((ret = rsa_alt_sign_wrap((void *) prv, MBEDTLS_MD_NONE,
1360817466cbSJens Wiklander                                  hash, sizeof(hash),
1361*32b31808SJens Wiklander                                  sig, sizeof(sig), &sig_len,
1362*32b31808SJens Wiklander                                  f_rng, p_rng)) != 0) {
1363*32b31808SJens Wiklander         return ret;
1364817466cbSJens Wiklander     }
1365817466cbSJens Wiklander 
1366817466cbSJens Wiklander     if (rsa_verify_wrap((void *) pub, MBEDTLS_MD_NONE,
1367*32b31808SJens Wiklander                         hash, sizeof(hash), sig, sig_len) != 0) {
1368*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
1369817466cbSJens Wiklander     }
1370817466cbSJens Wiklander 
1371*32b31808SJens Wiklander     return 0;
1372817466cbSJens Wiklander }
1373817466cbSJens Wiklander #endif /* MBEDTLS_RSA_C */
1374817466cbSJens Wiklander 
1375817466cbSJens Wiklander static void *rsa_alt_alloc_wrap(void)
1376817466cbSJens Wiklander {
1377817466cbSJens Wiklander     void *ctx = mbedtls_calloc(1, sizeof(mbedtls_rsa_alt_context));
1378817466cbSJens Wiklander 
1379*32b31808SJens Wiklander     if (ctx != NULL) {
1380817466cbSJens Wiklander         memset(ctx, 0, sizeof(mbedtls_rsa_alt_context));
1381*32b31808SJens Wiklander     }
1382817466cbSJens Wiklander 
1383*32b31808SJens Wiklander     return ctx;
1384817466cbSJens Wiklander }
1385817466cbSJens Wiklander 
1386817466cbSJens Wiklander static void rsa_alt_free_wrap(void *ctx)
1387817466cbSJens Wiklander {
13883d3b0591SJens Wiklander     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_rsa_alt_context));
1389817466cbSJens Wiklander     mbedtls_free(ctx);
1390817466cbSJens Wiklander }
1391817466cbSJens Wiklander 
1392817466cbSJens Wiklander const mbedtls_pk_info_t mbedtls_rsa_alt_info = {
1393817466cbSJens Wiklander     MBEDTLS_PK_RSA_ALT,
1394817466cbSJens Wiklander     "RSA-alt",
1395817466cbSJens Wiklander     rsa_alt_get_bitlen,
1396817466cbSJens Wiklander     rsa_alt_can_do,
1397817466cbSJens Wiklander     NULL,
1398817466cbSJens Wiklander     rsa_alt_sign_wrap,
13993d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
14003d3b0591SJens Wiklander     NULL,
14013d3b0591SJens Wiklander     NULL,
14023d3b0591SJens Wiklander #endif
1403817466cbSJens Wiklander     rsa_alt_decrypt_wrap,
1404817466cbSJens Wiklander     NULL,
1405817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C)
1406817466cbSJens Wiklander     rsa_alt_check_pair,
1407817466cbSJens Wiklander #else
1408817466cbSJens Wiklander     NULL,
1409817466cbSJens Wiklander #endif
1410817466cbSJens Wiklander     rsa_alt_alloc_wrap,
1411817466cbSJens Wiklander     rsa_alt_free_wrap,
14123d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
14133d3b0591SJens Wiklander     NULL,
14143d3b0591SJens Wiklander     NULL,
14153d3b0591SJens Wiklander #endif
1416817466cbSJens Wiklander     NULL,
1417817466cbSJens Wiklander };
1418817466cbSJens Wiklander 
1419817466cbSJens Wiklander #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */
1420817466cbSJens Wiklander 
142111fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO)
142211fa71b9SJerome Forissier 
142311fa71b9SJerome Forissier static void *pk_opaque_alloc_wrap(void)
142411fa71b9SJerome Forissier {
1425*32b31808SJens Wiklander     void *ctx = mbedtls_calloc(1, sizeof(mbedtls_svc_key_id_t));
142611fa71b9SJerome Forissier 
1427*32b31808SJens Wiklander     /* no _init() function to call, as calloc() already zeroized */
142811fa71b9SJerome Forissier 
1429*32b31808SJens Wiklander     return ctx;
143011fa71b9SJerome Forissier }
143111fa71b9SJerome Forissier 
143211fa71b9SJerome Forissier static void pk_opaque_free_wrap(void *ctx)
143311fa71b9SJerome Forissier {
1434*32b31808SJens Wiklander     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_svc_key_id_t));
143511fa71b9SJerome Forissier     mbedtls_free(ctx);
143611fa71b9SJerome Forissier }
143711fa71b9SJerome Forissier 
143811fa71b9SJerome Forissier static size_t pk_opaque_get_bitlen(const void *ctx)
143911fa71b9SJerome Forissier {
1440*32b31808SJens Wiklander     const mbedtls_svc_key_id_t *key = (const mbedtls_svc_key_id_t *) ctx;
144111fa71b9SJerome Forissier     size_t bits;
144211fa71b9SJerome Forissier     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
144311fa71b9SJerome Forissier 
1444*32b31808SJens Wiklander     if (PSA_SUCCESS != psa_get_key_attributes(*key, &attributes)) {
1445*32b31808SJens Wiklander         return 0;
1446*32b31808SJens Wiklander     }
144711fa71b9SJerome Forissier 
144811fa71b9SJerome Forissier     bits = psa_get_key_bits(&attributes);
144911fa71b9SJerome Forissier     psa_reset_key_attributes(&attributes);
1450*32b31808SJens Wiklander     return bits;
145111fa71b9SJerome Forissier }
145211fa71b9SJerome Forissier 
1453*32b31808SJens Wiklander static int pk_opaque_ecdsa_can_do(mbedtls_pk_type_t type)
145411fa71b9SJerome Forissier {
1455*32b31808SJens Wiklander     return type == MBEDTLS_PK_ECKEY ||
1456*32b31808SJens Wiklander            type == MBEDTLS_PK_ECDSA;
145711fa71b9SJerome Forissier }
145811fa71b9SJerome Forissier 
1459*32b31808SJens Wiklander static int pk_opaque_rsa_can_do(mbedtls_pk_type_t type)
146011fa71b9SJerome Forissier {
1461*32b31808SJens Wiklander     return type == MBEDTLS_PK_RSA ||
1462*32b31808SJens Wiklander            type == MBEDTLS_PK_RSASSA_PSS;
146311fa71b9SJerome Forissier }
146411fa71b9SJerome Forissier 
146511fa71b9SJerome Forissier static int pk_opaque_sign_wrap(void *ctx, mbedtls_md_type_t md_alg,
146611fa71b9SJerome Forissier                                const unsigned char *hash, size_t hash_len,
1467*32b31808SJens Wiklander                                unsigned char *sig, size_t sig_size, size_t *sig_len,
146811fa71b9SJerome Forissier                                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
146911fa71b9SJerome Forissier {
1470*32b31808SJens Wiklander #if !defined(MBEDTLS_PK_CAN_ECDSA_SIGN) && !defined(MBEDTLS_RSA_C)
14717901324dSJerome Forissier     ((void) ctx);
14727901324dSJerome Forissier     ((void) md_alg);
14737901324dSJerome Forissier     ((void) hash);
14747901324dSJerome Forissier     ((void) hash_len);
14757901324dSJerome Forissier     ((void) sig);
1476*32b31808SJens Wiklander     ((void) sig_size);
14777901324dSJerome Forissier     ((void) sig_len);
14787901324dSJerome Forissier     ((void) f_rng);
14797901324dSJerome Forissier     ((void) p_rng);
1480*32b31808SJens Wiklander     return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
1481*32b31808SJens Wiklander #else /* !MBEDTLS_PK_CAN_ECDSA_SIGN && !MBEDTLS_RSA_C */
1482*32b31808SJens Wiklander     const mbedtls_svc_key_id_t *key = (const mbedtls_svc_key_id_t *) ctx;
148311fa71b9SJerome Forissier     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
1484*32b31808SJens Wiklander     psa_algorithm_t alg;
1485*32b31808SJens Wiklander     psa_key_type_t type;
148611fa71b9SJerome Forissier     psa_status_t status;
148711fa71b9SJerome Forissier 
148811fa71b9SJerome Forissier     /* PSA has its own RNG */
148911fa71b9SJerome Forissier     (void) f_rng;
149011fa71b9SJerome Forissier     (void) p_rng;
149111fa71b9SJerome Forissier 
149211fa71b9SJerome Forissier     status = psa_get_key_attributes(*key, &attributes);
1493*32b31808SJens Wiklander     if (status != PSA_SUCCESS) {
1494*32b31808SJens Wiklander         return PSA_PK_TO_MBEDTLS_ERR(status);
1495*32b31808SJens Wiklander     }
1496*32b31808SJens Wiklander 
1497*32b31808SJens Wiklander     type = psa_get_key_type(&attributes);
149811fa71b9SJerome Forissier     psa_reset_key_attributes(&attributes);
1499*32b31808SJens Wiklander 
1500*32b31808SJens Wiklander #if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
1501*32b31808SJens Wiklander     if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) {
1502*32b31808SJens Wiklander         alg = PSA_ALG_ECDSA(mbedtls_hash_info_psa_from_md(md_alg));
1503*32b31808SJens Wiklander     } else
1504*32b31808SJens Wiklander #endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */
1505*32b31808SJens Wiklander #if defined(MBEDTLS_RSA_C)
1506*32b31808SJens Wiklander     if (PSA_KEY_TYPE_IS_RSA(type)) {
1507*32b31808SJens Wiklander         alg = PSA_ALG_RSA_PKCS1V15_SIGN(mbedtls_hash_info_psa_from_md(md_alg));
1508*32b31808SJens Wiklander     } else
1509*32b31808SJens Wiklander #endif /* MBEDTLS_RSA_C */
1510*32b31808SJens Wiklander     return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
151111fa71b9SJerome Forissier 
151211fa71b9SJerome Forissier     /* make the signature */
151311fa71b9SJerome Forissier     status = psa_sign_hash(*key, alg, hash, hash_len,
1514*32b31808SJens Wiklander                            sig, sig_size, sig_len);
1515*32b31808SJens Wiklander     if (status != PSA_SUCCESS) {
1516*32b31808SJens Wiklander #if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
1517*32b31808SJens Wiklander         if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) {
1518*32b31808SJens Wiklander             return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
1519*32b31808SJens Wiklander         } else
1520*32b31808SJens Wiklander #endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */
1521*32b31808SJens Wiklander #if defined(MBEDTLS_RSA_C)
1522*32b31808SJens Wiklander         if (PSA_KEY_TYPE_IS_RSA(type)) {
1523*32b31808SJens Wiklander             return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
1524*32b31808SJens Wiklander         } else
1525*32b31808SJens Wiklander #endif /* MBEDTLS_RSA_C */
1526*32b31808SJens Wiklander         return PSA_PK_TO_MBEDTLS_ERR(status);
152711fa71b9SJerome Forissier     }
152811fa71b9SJerome Forissier 
1529*32b31808SJens Wiklander #if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
1530*32b31808SJens Wiklander     if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) {
1531*32b31808SJens Wiklander         /* transcode it to ASN.1 sequence */
1532*32b31808SJens Wiklander         return pk_ecdsa_sig_asn1_from_psa(sig, sig_len, sig_size);
1533*32b31808SJens Wiklander     }
1534*32b31808SJens Wiklander #endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */
1535*32b31808SJens Wiklander 
1536*32b31808SJens Wiklander     return 0;
1537*32b31808SJens Wiklander #endif /* !MBEDTLS_PK_CAN_ECDSA_SIGN && !MBEDTLS_RSA_C */
1538*32b31808SJens Wiklander }
1539*32b31808SJens Wiklander 
1540*32b31808SJens Wiklander const mbedtls_pk_info_t mbedtls_pk_ecdsa_opaque_info = {
154111fa71b9SJerome Forissier     MBEDTLS_PK_OPAQUE,
154211fa71b9SJerome Forissier     "Opaque",
154311fa71b9SJerome Forissier     pk_opaque_get_bitlen,
1544*32b31808SJens Wiklander     pk_opaque_ecdsa_can_do,
154511fa71b9SJerome Forissier     NULL, /* verify - will be done later */
154611fa71b9SJerome Forissier     pk_opaque_sign_wrap,
154711fa71b9SJerome Forissier #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
154811fa71b9SJerome Forissier     NULL, /* restartable verify - not relevant */
154911fa71b9SJerome Forissier     NULL, /* restartable sign - not relevant */
155011fa71b9SJerome Forissier #endif
1551*32b31808SJens Wiklander     NULL, /* decrypt - not relevant */
1552*32b31808SJens Wiklander     NULL, /* encrypt - not relevant */
1553*32b31808SJens Wiklander     NULL, /* check_pair - could be done later or left NULL */
1554*32b31808SJens Wiklander     pk_opaque_alloc_wrap,
1555*32b31808SJens Wiklander     pk_opaque_free_wrap,
1556*32b31808SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
1557*32b31808SJens Wiklander     NULL, /* restart alloc - not relevant */
1558*32b31808SJens Wiklander     NULL, /* restart free - not relevant */
1559*32b31808SJens Wiklander #endif
1560*32b31808SJens Wiklander     NULL, /* debug - could be done later, or even left NULL */
1561*32b31808SJens Wiklander };
1562*32b31808SJens Wiklander 
1563*32b31808SJens Wiklander #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)
1564*32b31808SJens Wiklander static int pk_opaque_rsa_decrypt(void *ctx,
1565*32b31808SJens Wiklander                                  const unsigned char *input, size_t ilen,
1566*32b31808SJens Wiklander                                  unsigned char *output, size_t *olen, size_t osize,
1567*32b31808SJens Wiklander                                  int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
1568*32b31808SJens Wiklander {
1569*32b31808SJens Wiklander     const mbedtls_svc_key_id_t *key = (const mbedtls_svc_key_id_t *) ctx;
1570*32b31808SJens Wiklander     psa_status_t status;
1571*32b31808SJens Wiklander 
1572*32b31808SJens Wiklander     /* PSA has its own RNG */
1573*32b31808SJens Wiklander     (void) f_rng;
1574*32b31808SJens Wiklander     (void) p_rng;
1575*32b31808SJens Wiklander 
1576*32b31808SJens Wiklander     status = psa_asymmetric_decrypt(*key, PSA_ALG_RSA_PKCS1V15_CRYPT,
1577*32b31808SJens Wiklander                                     input, ilen,
1578*32b31808SJens Wiklander                                     NULL, 0,
1579*32b31808SJens Wiklander                                     output, osize, olen);
1580*32b31808SJens Wiklander     if (status != PSA_SUCCESS) {
1581*32b31808SJens Wiklander         return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
1582*32b31808SJens Wiklander     }
1583*32b31808SJens Wiklander 
1584*32b31808SJens Wiklander     return 0;
1585*32b31808SJens Wiklander }
1586*32b31808SJens Wiklander #endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR */
1587*32b31808SJens Wiklander 
1588*32b31808SJens Wiklander const mbedtls_pk_info_t mbedtls_pk_rsa_opaque_info = {
1589*32b31808SJens Wiklander     MBEDTLS_PK_OPAQUE,
1590*32b31808SJens Wiklander     "Opaque",
1591*32b31808SJens Wiklander     pk_opaque_get_bitlen,
1592*32b31808SJens Wiklander     pk_opaque_rsa_can_do,
1593*32b31808SJens Wiklander     NULL, /* verify - will be done later */
1594*32b31808SJens Wiklander     pk_opaque_sign_wrap,
1595*32b31808SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
1596*32b31808SJens Wiklander     NULL, /* restartable verify - not relevant */
1597*32b31808SJens Wiklander     NULL, /* restartable sign - not relevant */
1598*32b31808SJens Wiklander #endif
1599*32b31808SJens Wiklander #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)
1600*32b31808SJens Wiklander     pk_opaque_rsa_decrypt,
1601*32b31808SJens Wiklander #else
1602*32b31808SJens Wiklander     NULL, /* decrypt - not available */
1603*32b31808SJens Wiklander #endif /* PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY */
160411fa71b9SJerome Forissier     NULL, /* encrypt - will be done later */
160511fa71b9SJerome Forissier     NULL, /* check_pair - could be done later or left NULL */
160611fa71b9SJerome Forissier     pk_opaque_alloc_wrap,
160711fa71b9SJerome Forissier     pk_opaque_free_wrap,
160811fa71b9SJerome Forissier #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
160911fa71b9SJerome Forissier     NULL, /* restart alloc - not relevant */
161011fa71b9SJerome Forissier     NULL, /* restart free - not relevant */
161111fa71b9SJerome Forissier #endif
161211fa71b9SJerome Forissier     NULL, /* debug - could be done later, or even left NULL */
161311fa71b9SJerome Forissier };
161411fa71b9SJerome Forissier 
161511fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */
161611fa71b9SJerome Forissier 
1617817466cbSJens Wiklander #endif /* MBEDTLS_PK_C */
1618