xref: /optee_os/lib/libmbedtls/mbedtls/library/pk_wrap.c (revision 7901324d9530594155991c8b283023d567741cc7)
1817466cbSJens Wiklander /*
2817466cbSJens Wiklander  *  Public Key abstraction layer: wrapper functions
3817466cbSJens Wiklander  *
4*7901324dSJerome Forissier  *  Copyright The Mbed TLS Contributors
5*7901324dSJerome 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 
20*7901324dSJerome Forissier #include "common.h"
21817466cbSJens Wiklander 
22817466cbSJens Wiklander #if defined(MBEDTLS_PK_C)
23817466cbSJens Wiklander #include "mbedtls/pk_internal.h"
2411fa71b9SJerome Forissier #include "mbedtls/error.h"
25817466cbSJens Wiklander 
26817466cbSJens Wiklander /* Even if RSA not activated, for the sake of RSA-alt */
27817466cbSJens Wiklander #include "mbedtls/rsa.h"
28817466cbSJens Wiklander 
29817466cbSJens Wiklander #include <string.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 
3911fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO)
4011fa71b9SJerome Forissier #include "mbedtls/asn1write.h"
4111fa71b9SJerome Forissier #endif
4211fa71b9SJerome Forissier 
433d3b0591SJens Wiklander #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
443d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
453d3b0591SJens Wiklander #endif
463d3b0591SJens Wiklander 
4711fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO)
4811fa71b9SJerome Forissier #include "psa/crypto.h"
4911fa71b9SJerome Forissier #include "mbedtls/psa_util.h"
5011fa71b9SJerome Forissier #include "mbedtls/asn1.h"
5111fa71b9SJerome Forissier #endif
5211fa71b9SJerome Forissier 
53817466cbSJens Wiklander #if defined(MBEDTLS_PLATFORM_C)
54817466cbSJens Wiklander #include "mbedtls/platform.h"
55817466cbSJens Wiklander #else
56817466cbSJens Wiklander #include <stdlib.h>
57817466cbSJens Wiklander #define mbedtls_calloc    calloc
58817466cbSJens Wiklander #define mbedtls_free       free
59817466cbSJens Wiklander #endif
60817466cbSJens Wiklander 
61817466cbSJens Wiklander #include <limits.h>
623d3b0591SJens Wiklander #include <stdint.h>
63817466cbSJens Wiklander 
64817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C)
65817466cbSJens Wiklander static int rsa_can_do( mbedtls_pk_type_t type )
66817466cbSJens Wiklander {
67817466cbSJens Wiklander     return( type == MBEDTLS_PK_RSA ||
68817466cbSJens Wiklander             type == MBEDTLS_PK_RSASSA_PSS );
69817466cbSJens Wiklander }
70817466cbSJens Wiklander 
71817466cbSJens Wiklander static size_t rsa_get_bitlen( const void *ctx )
72817466cbSJens Wiklander {
733d3b0591SJens Wiklander     const mbedtls_rsa_context * rsa = (const mbedtls_rsa_context *) ctx;
743d3b0591SJens Wiklander     return( 8 * mbedtls_rsa_get_len( rsa ) );
75817466cbSJens Wiklander }
76817466cbSJens Wiklander 
77817466cbSJens Wiklander static int rsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,
78817466cbSJens Wiklander                    const unsigned char *hash, size_t hash_len,
79817466cbSJens Wiklander                    const unsigned char *sig, size_t sig_len )
80817466cbSJens Wiklander {
8111fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
823d3b0591SJens Wiklander     mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx;
833d3b0591SJens Wiklander     size_t rsa_len = mbedtls_rsa_get_len( rsa );
84817466cbSJens Wiklander 
853d3b0591SJens Wiklander #if SIZE_MAX > UINT_MAX
86817466cbSJens Wiklander     if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len )
87817466cbSJens Wiklander         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
883d3b0591SJens Wiklander #endif /* SIZE_MAX > UINT_MAX */
89817466cbSJens Wiklander 
903d3b0591SJens Wiklander     if( sig_len < rsa_len )
91817466cbSJens Wiklander         return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
92817466cbSJens Wiklander 
933d3b0591SJens Wiklander     if( ( ret = mbedtls_rsa_pkcs1_verify( rsa, NULL, NULL,
94817466cbSJens Wiklander                                   MBEDTLS_RSA_PUBLIC, md_alg,
95817466cbSJens Wiklander                                   (unsigned int) hash_len, hash, sig ) ) != 0 )
96817466cbSJens Wiklander         return( ret );
97817466cbSJens Wiklander 
983d3b0591SJens Wiklander     /* The buffer contains a valid signature followed by extra data.
993d3b0591SJens Wiklander      * We have a special error code for that so that so that callers can
1003d3b0591SJens Wiklander      * use mbedtls_pk_verify() to check "Does the buffer start with a
1013d3b0591SJens Wiklander      * valid signature?" and not just "Does the buffer contain a valid
1023d3b0591SJens Wiklander      * signature?". */
1033d3b0591SJens Wiklander     if( sig_len > rsa_len )
104817466cbSJens Wiklander         return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH );
105817466cbSJens Wiklander 
106817466cbSJens Wiklander     return( 0 );
107817466cbSJens Wiklander }
108817466cbSJens Wiklander 
109817466cbSJens Wiklander static int rsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
110817466cbSJens Wiklander                    const unsigned char *hash, size_t hash_len,
111817466cbSJens Wiklander                    unsigned char *sig, size_t *sig_len,
112817466cbSJens Wiklander                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
113817466cbSJens Wiklander {
1143d3b0591SJens Wiklander     mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx;
1153d3b0591SJens Wiklander 
1163d3b0591SJens Wiklander #if SIZE_MAX > UINT_MAX
117817466cbSJens Wiklander     if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len )
118817466cbSJens Wiklander         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
1193d3b0591SJens Wiklander #endif /* SIZE_MAX > UINT_MAX */
120817466cbSJens Wiklander 
1213d3b0591SJens Wiklander     *sig_len = mbedtls_rsa_get_len( rsa );
122817466cbSJens Wiklander 
1233d3b0591SJens Wiklander     return( mbedtls_rsa_pkcs1_sign( rsa, f_rng, p_rng, MBEDTLS_RSA_PRIVATE,
124817466cbSJens Wiklander                 md_alg, (unsigned int) hash_len, hash, sig ) );
125817466cbSJens Wiklander }
126817466cbSJens Wiklander 
127817466cbSJens Wiklander static int rsa_decrypt_wrap( void *ctx,
128817466cbSJens Wiklander                     const unsigned char *input, size_t ilen,
129817466cbSJens Wiklander                     unsigned char *output, size_t *olen, size_t osize,
130817466cbSJens Wiklander                     int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
131817466cbSJens Wiklander {
1323d3b0591SJens Wiklander     mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx;
1333d3b0591SJens Wiklander 
1343d3b0591SJens Wiklander     if( ilen != mbedtls_rsa_get_len( rsa ) )
135817466cbSJens Wiklander         return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
136817466cbSJens Wiklander 
1373d3b0591SJens Wiklander     return( mbedtls_rsa_pkcs1_decrypt( rsa, f_rng, p_rng,
138817466cbSJens Wiklander                 MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) );
139817466cbSJens Wiklander }
140817466cbSJens Wiklander 
141817466cbSJens Wiklander static int rsa_encrypt_wrap( void *ctx,
142817466cbSJens Wiklander                     const unsigned char *input, size_t ilen,
143817466cbSJens Wiklander                     unsigned char *output, size_t *olen, size_t osize,
144817466cbSJens Wiklander                     int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
145817466cbSJens Wiklander {
1463d3b0591SJens Wiklander     mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx;
1473d3b0591SJens Wiklander     *olen = mbedtls_rsa_get_len( rsa );
148817466cbSJens Wiklander 
149817466cbSJens Wiklander     if( *olen > osize )
150817466cbSJens Wiklander         return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE );
151817466cbSJens Wiklander 
1523d3b0591SJens Wiklander     return( mbedtls_rsa_pkcs1_encrypt( rsa, f_rng, p_rng, MBEDTLS_RSA_PUBLIC,
1533d3b0591SJens Wiklander                                        ilen, input, output ) );
154817466cbSJens Wiklander }
155817466cbSJens Wiklander 
156817466cbSJens Wiklander static int rsa_check_pair_wrap( const void *pub, const void *prv )
157817466cbSJens Wiklander {
158817466cbSJens Wiklander     return( mbedtls_rsa_check_pub_priv( (const mbedtls_rsa_context *) pub,
159817466cbSJens Wiklander                                 (const mbedtls_rsa_context *) prv ) );
160817466cbSJens Wiklander }
161817466cbSJens Wiklander 
162817466cbSJens Wiklander static void *rsa_alloc_wrap( void )
163817466cbSJens Wiklander {
164817466cbSJens Wiklander     void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_context ) );
165817466cbSJens Wiklander 
166817466cbSJens Wiklander     if( ctx != NULL )
167817466cbSJens Wiklander         mbedtls_rsa_init( (mbedtls_rsa_context *) ctx, 0, 0 );
168817466cbSJens Wiklander 
169817466cbSJens Wiklander     return( ctx );
170817466cbSJens Wiklander }
171817466cbSJens Wiklander 
172817466cbSJens Wiklander static void rsa_free_wrap( void *ctx )
173817466cbSJens Wiklander {
174817466cbSJens Wiklander     mbedtls_rsa_free( (mbedtls_rsa_context *) ctx );
175817466cbSJens Wiklander     mbedtls_free( ctx );
176817466cbSJens Wiklander }
177817466cbSJens Wiklander 
178817466cbSJens Wiklander static void rsa_debug( const void *ctx, mbedtls_pk_debug_item *items )
179817466cbSJens Wiklander {
180817466cbSJens Wiklander     items->type = MBEDTLS_PK_DEBUG_MPI;
181817466cbSJens Wiklander     items->name = "rsa.N";
182817466cbSJens Wiklander     items->value = &( ((mbedtls_rsa_context *) ctx)->N );
183817466cbSJens Wiklander 
184817466cbSJens Wiklander     items++;
185817466cbSJens Wiklander 
186817466cbSJens Wiklander     items->type = MBEDTLS_PK_DEBUG_MPI;
187817466cbSJens Wiklander     items->name = "rsa.E";
188817466cbSJens Wiklander     items->value = &( ((mbedtls_rsa_context *) ctx)->E );
189817466cbSJens Wiklander }
190817466cbSJens Wiklander 
191817466cbSJens Wiklander const mbedtls_pk_info_t mbedtls_rsa_info = {
192817466cbSJens Wiklander     MBEDTLS_PK_RSA,
193817466cbSJens Wiklander     "RSA",
194817466cbSJens Wiklander     rsa_get_bitlen,
195817466cbSJens Wiklander     rsa_can_do,
196817466cbSJens Wiklander     rsa_verify_wrap,
197817466cbSJens Wiklander     rsa_sign_wrap,
1983d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
1993d3b0591SJens Wiklander     NULL,
2003d3b0591SJens Wiklander     NULL,
2013d3b0591SJens Wiklander #endif
202817466cbSJens Wiklander     rsa_decrypt_wrap,
203817466cbSJens Wiklander     rsa_encrypt_wrap,
204817466cbSJens Wiklander     rsa_check_pair_wrap,
205817466cbSJens Wiklander     rsa_alloc_wrap,
206817466cbSJens Wiklander     rsa_free_wrap,
2073d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
2083d3b0591SJens Wiklander     NULL,
2093d3b0591SJens Wiklander     NULL,
2103d3b0591SJens Wiklander #endif
211817466cbSJens Wiklander     rsa_debug,
212817466cbSJens Wiklander };
213817466cbSJens Wiklander #endif /* MBEDTLS_RSA_C */
214817466cbSJens Wiklander 
215817466cbSJens Wiklander #if defined(MBEDTLS_ECP_C)
216817466cbSJens Wiklander /*
217817466cbSJens Wiklander  * Generic EC key
218817466cbSJens Wiklander  */
219817466cbSJens Wiklander static int eckey_can_do( mbedtls_pk_type_t type )
220817466cbSJens Wiklander {
221817466cbSJens Wiklander     return( type == MBEDTLS_PK_ECKEY ||
222817466cbSJens Wiklander             type == MBEDTLS_PK_ECKEY_DH ||
223817466cbSJens Wiklander             type == MBEDTLS_PK_ECDSA );
224817466cbSJens Wiklander }
225817466cbSJens Wiklander 
226817466cbSJens Wiklander static size_t eckey_get_bitlen( const void *ctx )
227817466cbSJens Wiklander {
228817466cbSJens Wiklander     return( ((mbedtls_ecp_keypair *) ctx)->grp.pbits );
229817466cbSJens Wiklander }
230817466cbSJens Wiklander 
231817466cbSJens Wiklander #if defined(MBEDTLS_ECDSA_C)
232817466cbSJens Wiklander /* Forward declarations */
233817466cbSJens Wiklander static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,
234817466cbSJens Wiklander                        const unsigned char *hash, size_t hash_len,
235817466cbSJens Wiklander                        const unsigned char *sig, size_t sig_len );
236817466cbSJens Wiklander 
237817466cbSJens Wiklander static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
238817466cbSJens Wiklander                    const unsigned char *hash, size_t hash_len,
239817466cbSJens Wiklander                    unsigned char *sig, size_t *sig_len,
240817466cbSJens Wiklander                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
241817466cbSJens Wiklander 
242817466cbSJens Wiklander static int eckey_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,
243817466cbSJens Wiklander                        const unsigned char *hash, size_t hash_len,
244817466cbSJens Wiklander                        const unsigned char *sig, size_t sig_len )
245817466cbSJens Wiklander {
24611fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
247817466cbSJens Wiklander     mbedtls_ecdsa_context ecdsa;
248817466cbSJens Wiklander 
249817466cbSJens Wiklander     mbedtls_ecdsa_init( &ecdsa );
250817466cbSJens Wiklander 
251817466cbSJens Wiklander     if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 )
252817466cbSJens Wiklander         ret = ecdsa_verify_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len );
253817466cbSJens Wiklander 
254817466cbSJens Wiklander     mbedtls_ecdsa_free( &ecdsa );
255817466cbSJens Wiklander 
256817466cbSJens Wiklander     return( ret );
257817466cbSJens Wiklander }
258817466cbSJens Wiklander 
259817466cbSJens Wiklander static int eckey_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
260817466cbSJens Wiklander                    const unsigned char *hash, size_t hash_len,
261817466cbSJens Wiklander                    unsigned char *sig, size_t *sig_len,
262817466cbSJens Wiklander                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
263817466cbSJens Wiklander {
26411fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
265817466cbSJens Wiklander     mbedtls_ecdsa_context ecdsa;
266817466cbSJens Wiklander 
267817466cbSJens Wiklander     mbedtls_ecdsa_init( &ecdsa );
268817466cbSJens Wiklander 
269817466cbSJens Wiklander     if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 )
270817466cbSJens Wiklander         ret = ecdsa_sign_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len,
271817466cbSJens Wiklander                                f_rng, p_rng );
272817466cbSJens Wiklander 
273817466cbSJens Wiklander     mbedtls_ecdsa_free( &ecdsa );
274817466cbSJens Wiklander 
275817466cbSJens Wiklander     return( ret );
276817466cbSJens Wiklander }
277817466cbSJens Wiklander 
2783d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
2793d3b0591SJens Wiklander /* Forward declarations */
2803d3b0591SJens Wiklander static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
2813d3b0591SJens Wiklander                        const unsigned char *hash, size_t hash_len,
2823d3b0591SJens Wiklander                        const unsigned char *sig, size_t sig_len,
2833d3b0591SJens Wiklander                        void *rs_ctx );
2843d3b0591SJens Wiklander 
2853d3b0591SJens Wiklander static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
2863d3b0591SJens Wiklander                    const unsigned char *hash, size_t hash_len,
2873d3b0591SJens Wiklander                    unsigned char *sig, size_t *sig_len,
2883d3b0591SJens Wiklander                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
2893d3b0591SJens Wiklander                    void *rs_ctx );
2903d3b0591SJens Wiklander 
2913d3b0591SJens Wiklander /*
2923d3b0591SJens Wiklander  * Restart context for ECDSA operations with ECKEY context
2933d3b0591SJens Wiklander  *
2943d3b0591SJens Wiklander  * We need to store an actual ECDSA context, as we need to pass the same to
2953d3b0591SJens Wiklander  * the underlying ecdsa function, so we can't create it on the fly every time.
2963d3b0591SJens Wiklander  */
2973d3b0591SJens Wiklander typedef struct
2983d3b0591SJens Wiklander {
2993d3b0591SJens Wiklander     mbedtls_ecdsa_restart_ctx ecdsa_rs;
3003d3b0591SJens Wiklander     mbedtls_ecdsa_context ecdsa_ctx;
3013d3b0591SJens Wiklander } eckey_restart_ctx;
3023d3b0591SJens Wiklander 
3033d3b0591SJens Wiklander static void *eckey_rs_alloc( void )
3043d3b0591SJens Wiklander {
3053d3b0591SJens Wiklander     eckey_restart_ctx *rs_ctx;
3063d3b0591SJens Wiklander 
3073d3b0591SJens Wiklander     void *ctx = mbedtls_calloc( 1, sizeof( eckey_restart_ctx ) );
3083d3b0591SJens Wiklander 
3093d3b0591SJens Wiklander     if( ctx != NULL )
3103d3b0591SJens Wiklander     {
3113d3b0591SJens Wiklander         rs_ctx = ctx;
3123d3b0591SJens Wiklander         mbedtls_ecdsa_restart_init( &rs_ctx->ecdsa_rs );
3133d3b0591SJens Wiklander         mbedtls_ecdsa_init( &rs_ctx->ecdsa_ctx );
3143d3b0591SJens Wiklander     }
3153d3b0591SJens Wiklander 
3163d3b0591SJens Wiklander     return( ctx );
3173d3b0591SJens Wiklander }
3183d3b0591SJens Wiklander 
3193d3b0591SJens Wiklander static void eckey_rs_free( void *ctx )
3203d3b0591SJens Wiklander {
3213d3b0591SJens Wiklander     eckey_restart_ctx *rs_ctx;
3223d3b0591SJens Wiklander 
3233d3b0591SJens Wiklander     if( ctx == NULL)
3243d3b0591SJens Wiklander         return;
3253d3b0591SJens Wiklander 
3263d3b0591SJens Wiklander     rs_ctx = ctx;
3273d3b0591SJens Wiklander     mbedtls_ecdsa_restart_free( &rs_ctx->ecdsa_rs );
3283d3b0591SJens Wiklander     mbedtls_ecdsa_free( &rs_ctx->ecdsa_ctx );
3293d3b0591SJens Wiklander 
3303d3b0591SJens Wiklander     mbedtls_free( ctx );
3313d3b0591SJens Wiklander }
3323d3b0591SJens Wiklander 
3333d3b0591SJens Wiklander static int eckey_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
3343d3b0591SJens Wiklander                        const unsigned char *hash, size_t hash_len,
3353d3b0591SJens Wiklander                        const unsigned char *sig, size_t sig_len,
3363d3b0591SJens Wiklander                        void *rs_ctx )
3373d3b0591SJens Wiklander {
33811fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
3393d3b0591SJens Wiklander     eckey_restart_ctx *rs = rs_ctx;
3403d3b0591SJens Wiklander 
3413d3b0591SJens Wiklander     /* Should never happen */
3423d3b0591SJens Wiklander     if( rs == NULL )
3433d3b0591SJens Wiklander         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
3443d3b0591SJens Wiklander 
3453d3b0591SJens Wiklander     /* set up our own sub-context if needed (that is, on first run) */
3463d3b0591SJens Wiklander     if( rs->ecdsa_ctx.grp.pbits == 0 )
3473d3b0591SJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) );
3483d3b0591SJens Wiklander 
3493d3b0591SJens Wiklander     MBEDTLS_MPI_CHK( ecdsa_verify_rs_wrap( &rs->ecdsa_ctx,
3503d3b0591SJens Wiklander                                            md_alg, hash, hash_len,
3513d3b0591SJens Wiklander                                            sig, sig_len, &rs->ecdsa_rs ) );
3523d3b0591SJens Wiklander 
3533d3b0591SJens Wiklander cleanup:
3543d3b0591SJens Wiklander     return( ret );
3553d3b0591SJens Wiklander }
3563d3b0591SJens Wiklander 
3573d3b0591SJens Wiklander static int eckey_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
3583d3b0591SJens Wiklander                    const unsigned char *hash, size_t hash_len,
3593d3b0591SJens Wiklander                    unsigned char *sig, size_t *sig_len,
3603d3b0591SJens Wiklander                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
3613d3b0591SJens Wiklander                        void *rs_ctx )
3623d3b0591SJens Wiklander {
36311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
3643d3b0591SJens Wiklander     eckey_restart_ctx *rs = rs_ctx;
3653d3b0591SJens Wiklander 
3663d3b0591SJens Wiklander     /* Should never happen */
3673d3b0591SJens Wiklander     if( rs == NULL )
3683d3b0591SJens Wiklander         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
3693d3b0591SJens Wiklander 
3703d3b0591SJens Wiklander     /* set up our own sub-context if needed (that is, on first run) */
3713d3b0591SJens Wiklander     if( rs->ecdsa_ctx.grp.pbits == 0 )
3723d3b0591SJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) );
3733d3b0591SJens Wiklander 
3743d3b0591SJens Wiklander     MBEDTLS_MPI_CHK( ecdsa_sign_rs_wrap( &rs->ecdsa_ctx, md_alg,
3753d3b0591SJens Wiklander                                          hash, hash_len, sig, sig_len,
3763d3b0591SJens Wiklander                                          f_rng, p_rng, &rs->ecdsa_rs ) );
3773d3b0591SJens Wiklander 
3783d3b0591SJens Wiklander cleanup:
3793d3b0591SJens Wiklander     return( ret );
3803d3b0591SJens Wiklander }
3813d3b0591SJens Wiklander #endif /* MBEDTLS_ECP_RESTARTABLE */
382817466cbSJens Wiklander #endif /* MBEDTLS_ECDSA_C */
383817466cbSJens Wiklander 
384817466cbSJens Wiklander static int eckey_check_pair( const void *pub, const void *prv )
385817466cbSJens Wiklander {
386817466cbSJens Wiklander     return( mbedtls_ecp_check_pub_priv( (const mbedtls_ecp_keypair *) pub,
387817466cbSJens Wiklander                                 (const mbedtls_ecp_keypair *) prv ) );
388817466cbSJens Wiklander }
389817466cbSJens Wiklander 
390817466cbSJens Wiklander static void *eckey_alloc_wrap( void )
391817466cbSJens Wiklander {
392817466cbSJens Wiklander     void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) );
393817466cbSJens Wiklander 
394817466cbSJens Wiklander     if( ctx != NULL )
395817466cbSJens Wiklander         mbedtls_ecp_keypair_init( ctx );
396817466cbSJens Wiklander 
397817466cbSJens Wiklander     return( ctx );
398817466cbSJens Wiklander }
399817466cbSJens Wiklander 
400817466cbSJens Wiklander static void eckey_free_wrap( void *ctx )
401817466cbSJens Wiklander {
402817466cbSJens Wiklander     mbedtls_ecp_keypair_free( (mbedtls_ecp_keypair *) ctx );
403817466cbSJens Wiklander     mbedtls_free( ctx );
404817466cbSJens Wiklander }
405817466cbSJens Wiklander 
406817466cbSJens Wiklander static void eckey_debug( const void *ctx, mbedtls_pk_debug_item *items )
407817466cbSJens Wiklander {
408817466cbSJens Wiklander     items->type = MBEDTLS_PK_DEBUG_ECP;
409817466cbSJens Wiklander     items->name = "eckey.Q";
410817466cbSJens Wiklander     items->value = &( ((mbedtls_ecp_keypair *) ctx)->Q );
411817466cbSJens Wiklander }
412817466cbSJens Wiklander 
413817466cbSJens Wiklander const mbedtls_pk_info_t mbedtls_eckey_info = {
414817466cbSJens Wiklander     MBEDTLS_PK_ECKEY,
415817466cbSJens Wiklander     "EC",
416817466cbSJens Wiklander     eckey_get_bitlen,
417817466cbSJens Wiklander     eckey_can_do,
418817466cbSJens Wiklander #if defined(MBEDTLS_ECDSA_C)
419817466cbSJens Wiklander     eckey_verify_wrap,
420817466cbSJens Wiklander     eckey_sign_wrap,
4213d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
4223d3b0591SJens Wiklander     eckey_verify_rs_wrap,
4233d3b0591SJens Wiklander     eckey_sign_rs_wrap,
424817466cbSJens Wiklander #endif
4253d3b0591SJens Wiklander #else /* MBEDTLS_ECDSA_C */
4263d3b0591SJens Wiklander     NULL,
4273d3b0591SJens Wiklander     NULL,
4283d3b0591SJens Wiklander #endif /* MBEDTLS_ECDSA_C */
429817466cbSJens Wiklander     NULL,
430817466cbSJens Wiklander     NULL,
431817466cbSJens Wiklander     eckey_check_pair,
432817466cbSJens Wiklander     eckey_alloc_wrap,
433817466cbSJens Wiklander     eckey_free_wrap,
4343d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
4353d3b0591SJens Wiklander     eckey_rs_alloc,
4363d3b0591SJens Wiklander     eckey_rs_free,
4373d3b0591SJens Wiklander #endif
438817466cbSJens Wiklander     eckey_debug,
439817466cbSJens Wiklander };
440817466cbSJens Wiklander 
441817466cbSJens Wiklander /*
442817466cbSJens Wiklander  * EC key restricted to ECDH
443817466cbSJens Wiklander  */
444817466cbSJens Wiklander static int eckeydh_can_do( mbedtls_pk_type_t type )
445817466cbSJens Wiklander {
446817466cbSJens Wiklander     return( type == MBEDTLS_PK_ECKEY ||
447817466cbSJens Wiklander             type == MBEDTLS_PK_ECKEY_DH );
448817466cbSJens Wiklander }
449817466cbSJens Wiklander 
450817466cbSJens Wiklander const mbedtls_pk_info_t mbedtls_eckeydh_info = {
451817466cbSJens Wiklander     MBEDTLS_PK_ECKEY_DH,
452817466cbSJens Wiklander     "EC_DH",
453817466cbSJens Wiklander     eckey_get_bitlen,         /* Same underlying key structure */
454817466cbSJens Wiklander     eckeydh_can_do,
455817466cbSJens Wiklander     NULL,
456817466cbSJens Wiklander     NULL,
4573d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
4583d3b0591SJens Wiklander     NULL,
4593d3b0591SJens Wiklander     NULL,
4603d3b0591SJens Wiklander #endif
461817466cbSJens Wiklander     NULL,
462817466cbSJens Wiklander     NULL,
463817466cbSJens Wiklander     eckey_check_pair,
464817466cbSJens Wiklander     eckey_alloc_wrap,       /* Same underlying key structure */
465817466cbSJens Wiklander     eckey_free_wrap,        /* Same underlying key structure */
4663d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
4673d3b0591SJens Wiklander     NULL,
4683d3b0591SJens Wiklander     NULL,
4693d3b0591SJens Wiklander #endif
470817466cbSJens Wiklander     eckey_debug,            /* Same underlying key structure */
471817466cbSJens Wiklander };
472817466cbSJens Wiklander #endif /* MBEDTLS_ECP_C */
473817466cbSJens Wiklander 
474817466cbSJens Wiklander #if defined(MBEDTLS_ECDSA_C)
475817466cbSJens Wiklander static int ecdsa_can_do( mbedtls_pk_type_t type )
476817466cbSJens Wiklander {
477817466cbSJens Wiklander     return( type == MBEDTLS_PK_ECDSA );
478817466cbSJens Wiklander }
479817466cbSJens Wiklander 
48011fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO)
48111fa71b9SJerome Forissier /*
48211fa71b9SJerome Forissier  * An ASN.1 encoded signature is a sequence of two ASN.1 integers. Parse one of
48311fa71b9SJerome Forissier  * those integers and convert it to the fixed-length encoding expected by PSA.
48411fa71b9SJerome Forissier  */
48511fa71b9SJerome Forissier static int extract_ecdsa_sig_int( unsigned char **from, const unsigned char *end,
48611fa71b9SJerome Forissier                                   unsigned char *to, size_t to_len )
48711fa71b9SJerome Forissier {
48811fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
48911fa71b9SJerome Forissier     size_t unpadded_len, padding_len;
49011fa71b9SJerome Forissier 
49111fa71b9SJerome Forissier     if( ( ret = mbedtls_asn1_get_tag( from, end, &unpadded_len,
49211fa71b9SJerome Forissier                                       MBEDTLS_ASN1_INTEGER ) ) != 0 )
49311fa71b9SJerome Forissier     {
49411fa71b9SJerome Forissier         return( ret );
49511fa71b9SJerome Forissier     }
49611fa71b9SJerome Forissier 
49711fa71b9SJerome Forissier     while( unpadded_len > 0 && **from == 0x00 )
49811fa71b9SJerome Forissier     {
49911fa71b9SJerome Forissier         ( *from )++;
50011fa71b9SJerome Forissier         unpadded_len--;
50111fa71b9SJerome Forissier     }
50211fa71b9SJerome Forissier 
50311fa71b9SJerome Forissier     if( unpadded_len > to_len || unpadded_len == 0 )
50411fa71b9SJerome Forissier         return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
50511fa71b9SJerome Forissier 
50611fa71b9SJerome Forissier     padding_len = to_len - unpadded_len;
50711fa71b9SJerome Forissier     memset( to, 0x00, padding_len );
50811fa71b9SJerome Forissier     memcpy( to + padding_len, *from, unpadded_len );
50911fa71b9SJerome Forissier     ( *from ) += unpadded_len;
51011fa71b9SJerome Forissier 
51111fa71b9SJerome Forissier     return( 0 );
51211fa71b9SJerome Forissier }
51311fa71b9SJerome Forissier 
51411fa71b9SJerome Forissier /*
51511fa71b9SJerome Forissier  * Convert a signature from an ASN.1 sequence of two integers
51611fa71b9SJerome Forissier  * to a raw {r,s} buffer. Note: the provided sig buffer must be at least
51711fa71b9SJerome Forissier  * twice as big as int_size.
51811fa71b9SJerome Forissier  */
51911fa71b9SJerome Forissier static int extract_ecdsa_sig( unsigned char **p, const unsigned char *end,
52011fa71b9SJerome Forissier                               unsigned char *sig, size_t int_size )
52111fa71b9SJerome Forissier {
52211fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
52311fa71b9SJerome Forissier     size_t tmp_size;
52411fa71b9SJerome Forissier 
52511fa71b9SJerome Forissier     if( ( ret = mbedtls_asn1_get_tag( p, end, &tmp_size,
52611fa71b9SJerome Forissier                 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
52711fa71b9SJerome Forissier         return( ret );
52811fa71b9SJerome Forissier 
52911fa71b9SJerome Forissier     /* Extract r */
53011fa71b9SJerome Forissier     if( ( ret = extract_ecdsa_sig_int( p, end, sig, int_size ) ) != 0 )
53111fa71b9SJerome Forissier         return( ret );
53211fa71b9SJerome Forissier     /* Extract s */
53311fa71b9SJerome Forissier     if( ( ret = extract_ecdsa_sig_int( p, end, sig + int_size, int_size ) ) != 0 )
53411fa71b9SJerome Forissier         return( ret );
53511fa71b9SJerome Forissier 
53611fa71b9SJerome Forissier     return( 0 );
53711fa71b9SJerome Forissier }
53811fa71b9SJerome Forissier 
53911fa71b9SJerome Forissier static int ecdsa_verify_wrap( void *ctx_arg, mbedtls_md_type_t md_alg,
54011fa71b9SJerome Forissier                        const unsigned char *hash, size_t hash_len,
54111fa71b9SJerome Forissier                        const unsigned char *sig, size_t sig_len )
54211fa71b9SJerome Forissier {
54311fa71b9SJerome Forissier     mbedtls_ecdsa_context *ctx = ctx_arg;
54411fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
54511fa71b9SJerome Forissier     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
546*7901324dSJerome Forissier     psa_key_id_t key_id = 0;
54711fa71b9SJerome Forissier     psa_status_t status;
54811fa71b9SJerome Forissier     mbedtls_pk_context key;
54911fa71b9SJerome Forissier     int key_len;
55011fa71b9SJerome Forissier     /* see ECP_PUB_DER_MAX_BYTES in pkwrite.c */
55111fa71b9SJerome Forissier     unsigned char buf[30 + 2 * MBEDTLS_ECP_MAX_BYTES];
55211fa71b9SJerome Forissier     unsigned char *p;
55311fa71b9SJerome Forissier     mbedtls_pk_info_t pk_info = mbedtls_eckey_info;
554*7901324dSJerome Forissier     psa_algorithm_t psa_sig_md = PSA_ALG_ECDSA_ANY;
55511fa71b9SJerome Forissier     size_t curve_bits;
556*7901324dSJerome Forissier     psa_ecc_family_t curve =
55711fa71b9SJerome Forissier         mbedtls_ecc_group_to_psa( ctx->grp.id, &curve_bits );
55811fa71b9SJerome Forissier     const size_t signature_part_size = ( ctx->grp.nbits + 7 ) / 8;
559*7901324dSJerome Forissier     ((void) md_alg);
56011fa71b9SJerome Forissier 
56111fa71b9SJerome Forissier     if( curve == 0 )
56211fa71b9SJerome Forissier         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
56311fa71b9SJerome Forissier 
56411fa71b9SJerome Forissier     /* mbedtls_pk_write_pubkey() expects a full PK context;
56511fa71b9SJerome Forissier      * re-construct one to make it happy */
56611fa71b9SJerome Forissier     key.pk_info = &pk_info;
56711fa71b9SJerome Forissier     key.pk_ctx = ctx;
56811fa71b9SJerome Forissier     p = buf + sizeof( buf );
56911fa71b9SJerome Forissier     key_len = mbedtls_pk_write_pubkey( &p, buf, &key );
57011fa71b9SJerome Forissier     if( key_len <= 0 )
57111fa71b9SJerome Forissier         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
57211fa71b9SJerome Forissier 
57311fa71b9SJerome Forissier     psa_set_key_type( &attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY( curve ) );
57411fa71b9SJerome Forissier     psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_VERIFY_HASH );
57511fa71b9SJerome Forissier     psa_set_key_algorithm( &attributes, psa_sig_md );
57611fa71b9SJerome Forissier 
57711fa71b9SJerome Forissier     status = psa_import_key( &attributes,
57811fa71b9SJerome Forissier                              buf + sizeof( buf ) - key_len, key_len,
579*7901324dSJerome Forissier                              &key_id );
58011fa71b9SJerome Forissier     if( status != PSA_SUCCESS )
58111fa71b9SJerome Forissier     {
58211fa71b9SJerome Forissier         ret = mbedtls_psa_err_translate_pk( status );
58311fa71b9SJerome Forissier         goto cleanup;
58411fa71b9SJerome Forissier     }
58511fa71b9SJerome Forissier 
58611fa71b9SJerome Forissier     /* We don't need the exported key anymore and can
58711fa71b9SJerome Forissier      * reuse its buffer for signature extraction. */
58811fa71b9SJerome Forissier     if( 2 * signature_part_size > sizeof( buf ) )
58911fa71b9SJerome Forissier     {
59011fa71b9SJerome Forissier         ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA;
59111fa71b9SJerome Forissier         goto cleanup;
59211fa71b9SJerome Forissier     }
59311fa71b9SJerome Forissier 
59411fa71b9SJerome Forissier     p = (unsigned char*) sig;
59511fa71b9SJerome Forissier     if( ( ret = extract_ecdsa_sig( &p, sig + sig_len, buf,
59611fa71b9SJerome Forissier                                    signature_part_size ) ) != 0 )
59711fa71b9SJerome Forissier     {
59811fa71b9SJerome Forissier         goto cleanup;
59911fa71b9SJerome Forissier     }
60011fa71b9SJerome Forissier 
601*7901324dSJerome Forissier     if( psa_verify_hash( key_id, psa_sig_md,
60211fa71b9SJerome Forissier                          hash, hash_len,
60311fa71b9SJerome Forissier                          buf, 2 * signature_part_size )
60411fa71b9SJerome Forissier          != PSA_SUCCESS )
60511fa71b9SJerome Forissier     {
60611fa71b9SJerome Forissier          ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
60711fa71b9SJerome Forissier          goto cleanup;
60811fa71b9SJerome Forissier     }
60911fa71b9SJerome Forissier 
61011fa71b9SJerome Forissier     if( p != sig + sig_len )
61111fa71b9SJerome Forissier     {
61211fa71b9SJerome Forissier         ret = MBEDTLS_ERR_PK_SIG_LEN_MISMATCH;
61311fa71b9SJerome Forissier         goto cleanup;
61411fa71b9SJerome Forissier     }
61511fa71b9SJerome Forissier     ret = 0;
61611fa71b9SJerome Forissier 
61711fa71b9SJerome Forissier cleanup:
618*7901324dSJerome Forissier     psa_destroy_key( key_id );
61911fa71b9SJerome Forissier     return( ret );
62011fa71b9SJerome Forissier }
62111fa71b9SJerome Forissier #else /* MBEDTLS_USE_PSA_CRYPTO */
622817466cbSJens Wiklander static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,
623817466cbSJens Wiklander                        const unsigned char *hash, size_t hash_len,
624817466cbSJens Wiklander                        const unsigned char *sig, size_t sig_len )
625817466cbSJens Wiklander {
62611fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
627817466cbSJens Wiklander     ((void) md_alg);
628817466cbSJens Wiklander 
629817466cbSJens Wiklander     ret = mbedtls_ecdsa_read_signature( (mbedtls_ecdsa_context *) ctx,
630817466cbSJens Wiklander                                 hash, hash_len, sig, sig_len );
631817466cbSJens Wiklander 
632817466cbSJens Wiklander     if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH )
633817466cbSJens Wiklander         return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH );
634817466cbSJens Wiklander 
635817466cbSJens Wiklander     return( ret );
636817466cbSJens Wiklander }
63711fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */
638817466cbSJens Wiklander 
639817466cbSJens Wiklander static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
640817466cbSJens Wiklander                    const unsigned char *hash, size_t hash_len,
641817466cbSJens Wiklander                    unsigned char *sig, size_t *sig_len,
642817466cbSJens Wiklander                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
643817466cbSJens Wiklander {
644817466cbSJens Wiklander     return( mbedtls_ecdsa_write_signature( (mbedtls_ecdsa_context *) ctx,
645817466cbSJens Wiklander                 md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng ) );
646817466cbSJens Wiklander }
647817466cbSJens Wiklander 
6483d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
6493d3b0591SJens Wiklander static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
6503d3b0591SJens Wiklander                        const unsigned char *hash, size_t hash_len,
6513d3b0591SJens Wiklander                        const unsigned char *sig, size_t sig_len,
6523d3b0591SJens Wiklander                        void *rs_ctx )
6533d3b0591SJens Wiklander {
65411fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
6553d3b0591SJens Wiklander     ((void) md_alg);
6563d3b0591SJens Wiklander 
6573d3b0591SJens Wiklander     ret = mbedtls_ecdsa_read_signature_restartable(
6583d3b0591SJens Wiklander             (mbedtls_ecdsa_context *) ctx,
6593d3b0591SJens Wiklander             hash, hash_len, sig, sig_len,
6603d3b0591SJens Wiklander             (mbedtls_ecdsa_restart_ctx *) rs_ctx );
6613d3b0591SJens Wiklander 
6623d3b0591SJens Wiklander     if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH )
6633d3b0591SJens Wiklander         return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH );
6643d3b0591SJens Wiklander 
6653d3b0591SJens Wiklander     return( ret );
6663d3b0591SJens Wiklander }
6673d3b0591SJens Wiklander 
6683d3b0591SJens Wiklander static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
6693d3b0591SJens Wiklander                    const unsigned char *hash, size_t hash_len,
6703d3b0591SJens Wiklander                    unsigned char *sig, size_t *sig_len,
6713d3b0591SJens Wiklander                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
6723d3b0591SJens Wiklander                    void *rs_ctx )
6733d3b0591SJens Wiklander {
6743d3b0591SJens Wiklander     return( mbedtls_ecdsa_write_signature_restartable(
6753d3b0591SJens Wiklander                 (mbedtls_ecdsa_context *) ctx,
6763d3b0591SJens Wiklander                 md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng,
6773d3b0591SJens Wiklander                 (mbedtls_ecdsa_restart_ctx *) rs_ctx ) );
6783d3b0591SJens Wiklander 
6793d3b0591SJens Wiklander }
6803d3b0591SJens Wiklander #endif /* MBEDTLS_ECP_RESTARTABLE */
6813d3b0591SJens Wiklander 
682817466cbSJens Wiklander static void *ecdsa_alloc_wrap( void )
683817466cbSJens Wiklander {
684817466cbSJens Wiklander     void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_context ) );
685817466cbSJens Wiklander 
686817466cbSJens Wiklander     if( ctx != NULL )
687817466cbSJens Wiklander         mbedtls_ecdsa_init( (mbedtls_ecdsa_context *) ctx );
688817466cbSJens Wiklander 
689817466cbSJens Wiklander     return( ctx );
690817466cbSJens Wiklander }
691817466cbSJens Wiklander 
692817466cbSJens Wiklander static void ecdsa_free_wrap( void *ctx )
693817466cbSJens Wiklander {
694817466cbSJens Wiklander     mbedtls_ecdsa_free( (mbedtls_ecdsa_context *) ctx );
695817466cbSJens Wiklander     mbedtls_free( ctx );
696817466cbSJens Wiklander }
697817466cbSJens Wiklander 
6983d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
6993d3b0591SJens Wiklander static void *ecdsa_rs_alloc( void )
7003d3b0591SJens Wiklander {
7013d3b0591SJens Wiklander     void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_restart_ctx ) );
7023d3b0591SJens Wiklander 
7033d3b0591SJens Wiklander     if( ctx != NULL )
7043d3b0591SJens Wiklander         mbedtls_ecdsa_restart_init( ctx );
7053d3b0591SJens Wiklander 
7063d3b0591SJens Wiklander     return( ctx );
7073d3b0591SJens Wiklander }
7083d3b0591SJens Wiklander 
7093d3b0591SJens Wiklander static void ecdsa_rs_free( void *ctx )
7103d3b0591SJens Wiklander {
7113d3b0591SJens Wiklander     mbedtls_ecdsa_restart_free( ctx );
7123d3b0591SJens Wiklander     mbedtls_free( ctx );
7133d3b0591SJens Wiklander }
7143d3b0591SJens Wiklander #endif /* MBEDTLS_ECP_RESTARTABLE */
7153d3b0591SJens Wiklander 
716817466cbSJens Wiklander const mbedtls_pk_info_t mbedtls_ecdsa_info = {
717817466cbSJens Wiklander     MBEDTLS_PK_ECDSA,
718817466cbSJens Wiklander     "ECDSA",
719817466cbSJens Wiklander     eckey_get_bitlen,     /* Compatible key structures */
720817466cbSJens Wiklander     ecdsa_can_do,
721817466cbSJens Wiklander     ecdsa_verify_wrap,
722817466cbSJens Wiklander     ecdsa_sign_wrap,
7233d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
7243d3b0591SJens Wiklander     ecdsa_verify_rs_wrap,
7253d3b0591SJens Wiklander     ecdsa_sign_rs_wrap,
7263d3b0591SJens Wiklander #endif
727817466cbSJens Wiklander     NULL,
728817466cbSJens Wiklander     NULL,
729817466cbSJens Wiklander     eckey_check_pair,   /* Compatible key structures */
730817466cbSJens Wiklander     ecdsa_alloc_wrap,
731817466cbSJens Wiklander     ecdsa_free_wrap,
7323d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
7333d3b0591SJens Wiklander     ecdsa_rs_alloc,
7343d3b0591SJens Wiklander     ecdsa_rs_free,
7353d3b0591SJens Wiklander #endif
736817466cbSJens Wiklander     eckey_debug,        /* Compatible key structures */
737817466cbSJens Wiklander };
738817466cbSJens Wiklander #endif /* MBEDTLS_ECDSA_C */
739817466cbSJens Wiklander 
740817466cbSJens Wiklander #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
741817466cbSJens Wiklander /*
742817466cbSJens Wiklander  * Support for alternative RSA-private implementations
743817466cbSJens Wiklander  */
744817466cbSJens Wiklander 
745817466cbSJens Wiklander static int rsa_alt_can_do( mbedtls_pk_type_t type )
746817466cbSJens Wiklander {
747817466cbSJens Wiklander     return( type == MBEDTLS_PK_RSA );
748817466cbSJens Wiklander }
749817466cbSJens Wiklander 
750817466cbSJens Wiklander static size_t rsa_alt_get_bitlen( const void *ctx )
751817466cbSJens Wiklander {
752817466cbSJens Wiklander     const mbedtls_rsa_alt_context *rsa_alt = (const mbedtls_rsa_alt_context *) ctx;
753817466cbSJens Wiklander 
754817466cbSJens Wiklander     return( 8 * rsa_alt->key_len_func( rsa_alt->key ) );
755817466cbSJens Wiklander }
756817466cbSJens Wiklander 
757817466cbSJens Wiklander static int rsa_alt_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
758817466cbSJens Wiklander                    const unsigned char *hash, size_t hash_len,
759817466cbSJens Wiklander                    unsigned char *sig, size_t *sig_len,
760817466cbSJens Wiklander                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
761817466cbSJens Wiklander {
762817466cbSJens Wiklander     mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx;
763817466cbSJens Wiklander 
7643d3b0591SJens Wiklander #if SIZE_MAX > UINT_MAX
765817466cbSJens Wiklander     if( UINT_MAX < hash_len )
766817466cbSJens Wiklander         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
7673d3b0591SJens Wiklander #endif /* SIZE_MAX > UINT_MAX */
768817466cbSJens Wiklander 
769817466cbSJens Wiklander     *sig_len = rsa_alt->key_len_func( rsa_alt->key );
77011fa71b9SJerome Forissier     if( *sig_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE )
77111fa71b9SJerome Forissier         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
772817466cbSJens Wiklander 
773817466cbSJens Wiklander     return( rsa_alt->sign_func( rsa_alt->key, f_rng, p_rng, MBEDTLS_RSA_PRIVATE,
774817466cbSJens Wiklander                 md_alg, (unsigned int) hash_len, hash, sig ) );
775817466cbSJens Wiklander }
776817466cbSJens Wiklander 
777817466cbSJens Wiklander static int rsa_alt_decrypt_wrap( void *ctx,
778817466cbSJens Wiklander                     const unsigned char *input, size_t ilen,
779817466cbSJens Wiklander                     unsigned char *output, size_t *olen, size_t osize,
780817466cbSJens Wiklander                     int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
781817466cbSJens Wiklander {
782817466cbSJens Wiklander     mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx;
783817466cbSJens Wiklander 
784817466cbSJens Wiklander     ((void) f_rng);
785817466cbSJens Wiklander     ((void) p_rng);
786817466cbSJens Wiklander 
787817466cbSJens Wiklander     if( ilen != rsa_alt->key_len_func( rsa_alt->key ) )
788817466cbSJens Wiklander         return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
789817466cbSJens Wiklander 
790817466cbSJens Wiklander     return( rsa_alt->decrypt_func( rsa_alt->key,
791817466cbSJens Wiklander                 MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) );
792817466cbSJens Wiklander }
793817466cbSJens Wiklander 
794817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C)
795817466cbSJens Wiklander static int rsa_alt_check_pair( const void *pub, const void *prv )
796817466cbSJens Wiklander {
797817466cbSJens Wiklander     unsigned char sig[MBEDTLS_MPI_MAX_SIZE];
798817466cbSJens Wiklander     unsigned char hash[32];
799817466cbSJens Wiklander     size_t sig_len = 0;
80011fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
801817466cbSJens Wiklander 
802817466cbSJens Wiklander     if( rsa_alt_get_bitlen( prv ) != rsa_get_bitlen( pub ) )
803817466cbSJens Wiklander         return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
804817466cbSJens Wiklander 
805817466cbSJens Wiklander     memset( hash, 0x2a, sizeof( hash ) );
806817466cbSJens Wiklander 
807817466cbSJens Wiklander     if( ( ret = rsa_alt_sign_wrap( (void *) prv, MBEDTLS_MD_NONE,
808817466cbSJens Wiklander                                    hash, sizeof( hash ),
809817466cbSJens Wiklander                                    sig, &sig_len, NULL, NULL ) ) != 0 )
810817466cbSJens Wiklander     {
811817466cbSJens Wiklander         return( ret );
812817466cbSJens Wiklander     }
813817466cbSJens Wiklander 
814817466cbSJens Wiklander     if( rsa_verify_wrap( (void *) pub, MBEDTLS_MD_NONE,
815817466cbSJens Wiklander                          hash, sizeof( hash ), sig, sig_len ) != 0 )
816817466cbSJens Wiklander     {
817817466cbSJens Wiklander         return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
818817466cbSJens Wiklander     }
819817466cbSJens Wiklander 
820817466cbSJens Wiklander     return( 0 );
821817466cbSJens Wiklander }
822817466cbSJens Wiklander #endif /* MBEDTLS_RSA_C */
823817466cbSJens Wiklander 
824817466cbSJens Wiklander static void *rsa_alt_alloc_wrap( void )
825817466cbSJens Wiklander {
826817466cbSJens Wiklander     void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_alt_context ) );
827817466cbSJens Wiklander 
828817466cbSJens Wiklander     if( ctx != NULL )
829817466cbSJens Wiklander         memset( ctx, 0, sizeof( mbedtls_rsa_alt_context ) );
830817466cbSJens Wiklander 
831817466cbSJens Wiklander     return( ctx );
832817466cbSJens Wiklander }
833817466cbSJens Wiklander 
834817466cbSJens Wiklander static void rsa_alt_free_wrap( void *ctx )
835817466cbSJens Wiklander {
8363d3b0591SJens Wiklander     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_rsa_alt_context ) );
837817466cbSJens Wiklander     mbedtls_free( ctx );
838817466cbSJens Wiklander }
839817466cbSJens Wiklander 
840817466cbSJens Wiklander const mbedtls_pk_info_t mbedtls_rsa_alt_info = {
841817466cbSJens Wiklander     MBEDTLS_PK_RSA_ALT,
842817466cbSJens Wiklander     "RSA-alt",
843817466cbSJens Wiklander     rsa_alt_get_bitlen,
844817466cbSJens Wiklander     rsa_alt_can_do,
845817466cbSJens Wiklander     NULL,
846817466cbSJens Wiklander     rsa_alt_sign_wrap,
8473d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
8483d3b0591SJens Wiklander     NULL,
8493d3b0591SJens Wiklander     NULL,
8503d3b0591SJens Wiklander #endif
851817466cbSJens Wiklander     rsa_alt_decrypt_wrap,
852817466cbSJens Wiklander     NULL,
853817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C)
854817466cbSJens Wiklander     rsa_alt_check_pair,
855817466cbSJens Wiklander #else
856817466cbSJens Wiklander     NULL,
857817466cbSJens Wiklander #endif
858817466cbSJens Wiklander     rsa_alt_alloc_wrap,
859817466cbSJens Wiklander     rsa_alt_free_wrap,
8603d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
8613d3b0591SJens Wiklander     NULL,
8623d3b0591SJens Wiklander     NULL,
8633d3b0591SJens Wiklander #endif
864817466cbSJens Wiklander     NULL,
865817466cbSJens Wiklander };
866817466cbSJens Wiklander 
867817466cbSJens Wiklander #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */
868817466cbSJens Wiklander 
86911fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO)
87011fa71b9SJerome Forissier 
87111fa71b9SJerome Forissier static void *pk_opaque_alloc_wrap( void )
87211fa71b9SJerome Forissier {
873*7901324dSJerome Forissier     void *ctx = mbedtls_calloc( 1, sizeof( psa_key_id_t ) );
87411fa71b9SJerome Forissier 
87511fa71b9SJerome Forissier     /* no _init() function to call, an calloc() already zeroized */
87611fa71b9SJerome Forissier 
87711fa71b9SJerome Forissier     return( ctx );
87811fa71b9SJerome Forissier }
87911fa71b9SJerome Forissier 
88011fa71b9SJerome Forissier static void pk_opaque_free_wrap( void *ctx )
88111fa71b9SJerome Forissier {
882*7901324dSJerome Forissier     mbedtls_platform_zeroize( ctx, sizeof( psa_key_id_t ) );
88311fa71b9SJerome Forissier     mbedtls_free( ctx );
88411fa71b9SJerome Forissier }
88511fa71b9SJerome Forissier 
88611fa71b9SJerome Forissier static size_t pk_opaque_get_bitlen( const void *ctx )
88711fa71b9SJerome Forissier {
888*7901324dSJerome Forissier     const psa_key_id_t *key = (const psa_key_id_t *) ctx;
88911fa71b9SJerome Forissier     size_t bits;
89011fa71b9SJerome Forissier     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
89111fa71b9SJerome Forissier 
89211fa71b9SJerome Forissier     if( PSA_SUCCESS != psa_get_key_attributes( *key, &attributes ) )
89311fa71b9SJerome Forissier         return( 0 );
89411fa71b9SJerome Forissier 
89511fa71b9SJerome Forissier     bits = psa_get_key_bits( &attributes );
89611fa71b9SJerome Forissier     psa_reset_key_attributes( &attributes );
89711fa71b9SJerome Forissier     return( bits );
89811fa71b9SJerome Forissier }
89911fa71b9SJerome Forissier 
90011fa71b9SJerome Forissier static int pk_opaque_can_do( mbedtls_pk_type_t type )
90111fa71b9SJerome Forissier {
90211fa71b9SJerome Forissier     /* For now opaque PSA keys can only wrap ECC keypairs,
90311fa71b9SJerome Forissier      * as checked by setup_psa().
90411fa71b9SJerome Forissier      * Also, ECKEY_DH does not really make sense with the current API. */
90511fa71b9SJerome Forissier     return( type == MBEDTLS_PK_ECKEY ||
90611fa71b9SJerome Forissier             type == MBEDTLS_PK_ECDSA );
90711fa71b9SJerome Forissier }
90811fa71b9SJerome Forissier 
909*7901324dSJerome Forissier #if defined(MBEDTLS_ECDSA_C)
910*7901324dSJerome Forissier 
91111fa71b9SJerome Forissier /*
91211fa71b9SJerome Forissier  * Simultaneously convert and move raw MPI from the beginning of a buffer
91311fa71b9SJerome Forissier  * to an ASN.1 MPI at the end of the buffer.
91411fa71b9SJerome Forissier  * See also mbedtls_asn1_write_mpi().
91511fa71b9SJerome Forissier  *
91611fa71b9SJerome Forissier  * p: pointer to the end of the output buffer
91711fa71b9SJerome Forissier  * start: start of the output buffer, and also of the mpi to write at the end
91811fa71b9SJerome Forissier  * n_len: length of the mpi to read from start
91911fa71b9SJerome Forissier  */
92011fa71b9SJerome Forissier static int asn1_write_mpibuf( unsigned char **p, unsigned char *start,
92111fa71b9SJerome Forissier                               size_t n_len )
92211fa71b9SJerome Forissier {
92311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
92411fa71b9SJerome Forissier     size_t len = 0;
92511fa71b9SJerome Forissier 
92611fa71b9SJerome Forissier     if( (size_t)( *p - start ) < n_len )
92711fa71b9SJerome Forissier         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
92811fa71b9SJerome Forissier 
92911fa71b9SJerome Forissier     len = n_len;
93011fa71b9SJerome Forissier     *p -= len;
93111fa71b9SJerome Forissier     memmove( *p, start, len );
93211fa71b9SJerome Forissier 
93311fa71b9SJerome Forissier     /* ASN.1 DER encoding requires minimal length, so skip leading 0s.
93411fa71b9SJerome Forissier      * Neither r nor s should be 0, but as a failsafe measure, still detect
93511fa71b9SJerome Forissier      * that rather than overflowing the buffer in case of a PSA error. */
93611fa71b9SJerome Forissier     while( len > 0 && **p == 0x00 )
93711fa71b9SJerome Forissier     {
93811fa71b9SJerome Forissier         ++(*p);
93911fa71b9SJerome Forissier         --len;
94011fa71b9SJerome Forissier     }
94111fa71b9SJerome Forissier 
94211fa71b9SJerome Forissier     /* this is only reached if the signature was invalid */
94311fa71b9SJerome Forissier     if( len == 0 )
94411fa71b9SJerome Forissier         return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED );
94511fa71b9SJerome Forissier 
94611fa71b9SJerome Forissier     /* if the msb is 1, ASN.1 requires that we prepend a 0.
94711fa71b9SJerome Forissier      * Neither r nor s can be 0, so we can assume len > 0 at all times. */
94811fa71b9SJerome Forissier     if( **p & 0x80 )
94911fa71b9SJerome Forissier     {
95011fa71b9SJerome Forissier         if( *p - start < 1 )
95111fa71b9SJerome Forissier             return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
95211fa71b9SJerome Forissier 
95311fa71b9SJerome Forissier         *--(*p) = 0x00;
95411fa71b9SJerome Forissier         len += 1;
95511fa71b9SJerome Forissier     }
95611fa71b9SJerome Forissier 
95711fa71b9SJerome Forissier     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
95811fa71b9SJerome Forissier     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
95911fa71b9SJerome Forissier                                                 MBEDTLS_ASN1_INTEGER ) );
96011fa71b9SJerome Forissier 
96111fa71b9SJerome Forissier     return( (int) len );
96211fa71b9SJerome Forissier }
96311fa71b9SJerome Forissier 
96411fa71b9SJerome Forissier /* Transcode signature from PSA format to ASN.1 sequence.
96511fa71b9SJerome Forissier  * See ecdsa_signature_to_asn1 in ecdsa.c, but with byte buffers instead of
96611fa71b9SJerome Forissier  * MPIs, and in-place.
96711fa71b9SJerome Forissier  *
96811fa71b9SJerome Forissier  * [in/out] sig: the signature pre- and post-transcoding
96911fa71b9SJerome Forissier  * [in/out] sig_len: signature length pre- and post-transcoding
97011fa71b9SJerome Forissier  * [int] buf_len: the available size the in/out buffer
97111fa71b9SJerome Forissier  */
97211fa71b9SJerome Forissier static int pk_ecdsa_sig_asn1_from_psa( unsigned char *sig, size_t *sig_len,
97311fa71b9SJerome Forissier                                        size_t buf_len )
97411fa71b9SJerome Forissier {
97511fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
97611fa71b9SJerome Forissier     size_t len = 0;
97711fa71b9SJerome Forissier     const size_t rs_len = *sig_len / 2;
97811fa71b9SJerome Forissier     unsigned char *p = sig + buf_len;
97911fa71b9SJerome Forissier 
98011fa71b9SJerome Forissier     MBEDTLS_ASN1_CHK_ADD( len, asn1_write_mpibuf( &p, sig + rs_len, rs_len ) );
98111fa71b9SJerome Forissier     MBEDTLS_ASN1_CHK_ADD( len, asn1_write_mpibuf( &p, sig, rs_len ) );
98211fa71b9SJerome Forissier 
98311fa71b9SJerome Forissier     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, sig, len ) );
98411fa71b9SJerome Forissier     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, sig,
98511fa71b9SJerome Forissier                           MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
98611fa71b9SJerome Forissier 
98711fa71b9SJerome Forissier     memmove( sig, p, len );
98811fa71b9SJerome Forissier     *sig_len = len;
98911fa71b9SJerome Forissier 
99011fa71b9SJerome Forissier     return( 0 );
99111fa71b9SJerome Forissier }
99211fa71b9SJerome Forissier 
993*7901324dSJerome Forissier #endif /* MBEDTLS_ECDSA_C */
994*7901324dSJerome Forissier 
99511fa71b9SJerome Forissier static int pk_opaque_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
99611fa71b9SJerome Forissier                    const unsigned char *hash, size_t hash_len,
99711fa71b9SJerome Forissier                    unsigned char *sig, size_t *sig_len,
99811fa71b9SJerome Forissier                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
99911fa71b9SJerome Forissier {
1000*7901324dSJerome Forissier #if !defined(MBEDTLS_ECDSA_C)
1001*7901324dSJerome Forissier     ((void) ctx);
1002*7901324dSJerome Forissier     ((void) md_alg);
1003*7901324dSJerome Forissier     ((void) hash);
1004*7901324dSJerome Forissier     ((void) hash_len);
1005*7901324dSJerome Forissier     ((void) sig);
1006*7901324dSJerome Forissier     ((void) sig_len);
1007*7901324dSJerome Forissier     ((void) f_rng);
1008*7901324dSJerome Forissier     ((void) p_rng);
1009*7901324dSJerome Forissier     return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
1010*7901324dSJerome Forissier #else /* !MBEDTLS_ECDSA_C */
1011*7901324dSJerome Forissier     const psa_key_id_t *key = (const psa_key_id_t *) ctx;
101211fa71b9SJerome Forissier     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
101311fa71b9SJerome Forissier     psa_algorithm_t alg = PSA_ALG_ECDSA( mbedtls_psa_translate_md( md_alg ) );
101411fa71b9SJerome Forissier     size_t buf_len;
101511fa71b9SJerome Forissier     psa_status_t status;
101611fa71b9SJerome Forissier 
101711fa71b9SJerome Forissier     /* PSA has its own RNG */
101811fa71b9SJerome Forissier     (void) f_rng;
101911fa71b9SJerome Forissier     (void) p_rng;
102011fa71b9SJerome Forissier 
102111fa71b9SJerome Forissier     /* PSA needs an output buffer of known size, but our API doesn't provide
102211fa71b9SJerome Forissier      * that information. Assume that the buffer is large enough for a
102311fa71b9SJerome Forissier      * maximal-length signature with that key (otherwise the application is
102411fa71b9SJerome Forissier      * buggy anyway). */
102511fa71b9SJerome Forissier     status = psa_get_key_attributes( *key, &attributes );
102611fa71b9SJerome Forissier     if( status != PSA_SUCCESS )
102711fa71b9SJerome Forissier         return( mbedtls_psa_err_translate_pk( status ) );
102811fa71b9SJerome Forissier     buf_len = MBEDTLS_ECDSA_MAX_SIG_LEN( psa_get_key_bits( &attributes ) );
102911fa71b9SJerome Forissier     psa_reset_key_attributes( &attributes );
103011fa71b9SJerome Forissier     if( buf_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE )
103111fa71b9SJerome Forissier         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
103211fa71b9SJerome Forissier 
103311fa71b9SJerome Forissier     /* make the signature */
103411fa71b9SJerome Forissier     status = psa_sign_hash( *key, alg, hash, hash_len,
103511fa71b9SJerome Forissier                             sig, buf_len, sig_len );
103611fa71b9SJerome Forissier     if( status != PSA_SUCCESS )
103711fa71b9SJerome Forissier         return( mbedtls_psa_err_translate_pk( status ) );
103811fa71b9SJerome Forissier 
103911fa71b9SJerome Forissier     /* transcode it to ASN.1 sequence */
104011fa71b9SJerome Forissier     return( pk_ecdsa_sig_asn1_from_psa( sig, sig_len, buf_len ) );
1041*7901324dSJerome Forissier #endif /* !MBEDTLS_ECDSA_C */
104211fa71b9SJerome Forissier }
104311fa71b9SJerome Forissier 
104411fa71b9SJerome Forissier const mbedtls_pk_info_t mbedtls_pk_opaque_info = {
104511fa71b9SJerome Forissier     MBEDTLS_PK_OPAQUE,
104611fa71b9SJerome Forissier     "Opaque",
104711fa71b9SJerome Forissier     pk_opaque_get_bitlen,
104811fa71b9SJerome Forissier     pk_opaque_can_do,
104911fa71b9SJerome Forissier     NULL, /* verify - will be done later */
105011fa71b9SJerome Forissier     pk_opaque_sign_wrap,
105111fa71b9SJerome Forissier #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
105211fa71b9SJerome Forissier     NULL, /* restartable verify - not relevant */
105311fa71b9SJerome Forissier     NULL, /* restartable sign - not relevant */
105411fa71b9SJerome Forissier #endif
105511fa71b9SJerome Forissier     NULL, /* decrypt - will be done later */
105611fa71b9SJerome Forissier     NULL, /* encrypt - will be done later */
105711fa71b9SJerome Forissier     NULL, /* check_pair - could be done later or left NULL */
105811fa71b9SJerome Forissier     pk_opaque_alloc_wrap,
105911fa71b9SJerome Forissier     pk_opaque_free_wrap,
106011fa71b9SJerome Forissier #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
106111fa71b9SJerome Forissier     NULL, /* restart alloc - not relevant */
106211fa71b9SJerome Forissier     NULL, /* restart free - not relevant */
106311fa71b9SJerome Forissier #endif
106411fa71b9SJerome Forissier     NULL, /* debug - could be done later, or even left NULL */
106511fa71b9SJerome Forissier };
106611fa71b9SJerome Forissier 
106711fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */
106811fa71b9SJerome Forissier 
1069817466cbSJens Wiklander #endif /* MBEDTLS_PK_C */
1070