xref: /optee_os/lib/libmbedtls/mbedtls/library/ecdsa.c (revision 817466cb476de705a8e3dabe1ef165fe27a18c2f)
1*817466cbSJens Wiklander /*
2*817466cbSJens Wiklander  *  Elliptic curve DSA
3*817466cbSJens Wiklander  *
4*817466cbSJens Wiklander  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5*817466cbSJens Wiklander  *  SPDX-License-Identifier: Apache-2.0
6*817466cbSJens Wiklander  *
7*817466cbSJens Wiklander  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8*817466cbSJens Wiklander  *  not use this file except in compliance with the License.
9*817466cbSJens Wiklander  *  You may obtain a copy of the License at
10*817466cbSJens Wiklander  *
11*817466cbSJens Wiklander  *  http://www.apache.org/licenses/LICENSE-2.0
12*817466cbSJens Wiklander  *
13*817466cbSJens Wiklander  *  Unless required by applicable law or agreed to in writing, software
14*817466cbSJens Wiklander  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15*817466cbSJens Wiklander  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*817466cbSJens Wiklander  *  See the License for the specific language governing permissions and
17*817466cbSJens Wiklander  *  limitations under the License.
18*817466cbSJens Wiklander  *
19*817466cbSJens Wiklander  *  This file is part of mbed TLS (https://tls.mbed.org)
20*817466cbSJens Wiklander  */
21*817466cbSJens Wiklander 
22*817466cbSJens Wiklander /*
23*817466cbSJens Wiklander  * References:
24*817466cbSJens Wiklander  *
25*817466cbSJens Wiklander  * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
26*817466cbSJens Wiklander  */
27*817466cbSJens Wiklander 
28*817466cbSJens Wiklander #if !defined(MBEDTLS_CONFIG_FILE)
29*817466cbSJens Wiklander #include "mbedtls/config.h"
30*817466cbSJens Wiklander #else
31*817466cbSJens Wiklander #include MBEDTLS_CONFIG_FILE
32*817466cbSJens Wiklander #endif
33*817466cbSJens Wiklander 
34*817466cbSJens Wiklander #if defined(MBEDTLS_ECDSA_C)
35*817466cbSJens Wiklander 
36*817466cbSJens Wiklander #include "mbedtls/ecdsa.h"
37*817466cbSJens Wiklander #include "mbedtls/asn1write.h"
38*817466cbSJens Wiklander 
39*817466cbSJens Wiklander #include <string.h>
40*817466cbSJens Wiklander 
41*817466cbSJens Wiklander #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
42*817466cbSJens Wiklander #include "mbedtls/hmac_drbg.h"
43*817466cbSJens Wiklander #endif
44*817466cbSJens Wiklander 
45*817466cbSJens Wiklander /*
46*817466cbSJens Wiklander  * Derive a suitable integer for group grp from a buffer of length len
47*817466cbSJens Wiklander  * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3
48*817466cbSJens Wiklander  */
49*817466cbSJens Wiklander static int derive_mpi( const mbedtls_ecp_group *grp, mbedtls_mpi *x,
50*817466cbSJens Wiklander                        const unsigned char *buf, size_t blen )
51*817466cbSJens Wiklander {
52*817466cbSJens Wiklander     int ret;
53*817466cbSJens Wiklander     size_t n_size = ( grp->nbits + 7 ) / 8;
54*817466cbSJens Wiklander     size_t use_size = blen > n_size ? n_size : blen;
55*817466cbSJens Wiklander 
56*817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( x, buf, use_size ) );
57*817466cbSJens Wiklander     if( use_size * 8 > grp->nbits )
58*817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( x, use_size * 8 - grp->nbits ) );
59*817466cbSJens Wiklander 
60*817466cbSJens Wiklander     /* While at it, reduce modulo N */
61*817466cbSJens Wiklander     if( mbedtls_mpi_cmp_mpi( x, &grp->N ) >= 0 )
62*817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( x, x, &grp->N ) );
63*817466cbSJens Wiklander 
64*817466cbSJens Wiklander cleanup:
65*817466cbSJens Wiklander     return( ret );
66*817466cbSJens Wiklander }
67*817466cbSJens Wiklander 
68*817466cbSJens Wiklander /*
69*817466cbSJens Wiklander  * Compute ECDSA signature of a hashed message (SEC1 4.1.3)
70*817466cbSJens Wiklander  * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message)
71*817466cbSJens Wiklander  */
72*817466cbSJens Wiklander int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
73*817466cbSJens Wiklander                 const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
74*817466cbSJens Wiklander                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
75*817466cbSJens Wiklander {
76*817466cbSJens Wiklander     int ret, key_tries, sign_tries, blind_tries;
77*817466cbSJens Wiklander     mbedtls_ecp_point R;
78*817466cbSJens Wiklander     mbedtls_mpi k, e, t;
79*817466cbSJens Wiklander 
80*817466cbSJens Wiklander     /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
81*817466cbSJens Wiklander     if( grp->N.p == NULL )
82*817466cbSJens Wiklander         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
83*817466cbSJens Wiklander 
84*817466cbSJens Wiklander     mbedtls_ecp_point_init( &R );
85*817466cbSJens Wiklander     mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t );
86*817466cbSJens Wiklander 
87*817466cbSJens Wiklander     sign_tries = 0;
88*817466cbSJens Wiklander     do
89*817466cbSJens Wiklander     {
90*817466cbSJens Wiklander         /*
91*817466cbSJens Wiklander          * Steps 1-3: generate a suitable ephemeral keypair
92*817466cbSJens Wiklander          * and set r = xR mod n
93*817466cbSJens Wiklander          */
94*817466cbSJens Wiklander         key_tries = 0;
95*817466cbSJens Wiklander         do
96*817466cbSJens Wiklander         {
97*817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair( grp, &k, &R, f_rng, p_rng ) );
98*817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( r, &R.X, &grp->N ) );
99*817466cbSJens Wiklander 
100*817466cbSJens Wiklander             if( key_tries++ > 10 )
101*817466cbSJens Wiklander             {
102*817466cbSJens Wiklander                 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
103*817466cbSJens Wiklander                 goto cleanup;
104*817466cbSJens Wiklander             }
105*817466cbSJens Wiklander         }
106*817466cbSJens Wiklander         while( mbedtls_mpi_cmp_int( r, 0 ) == 0 );
107*817466cbSJens Wiklander 
108*817466cbSJens Wiklander         /*
109*817466cbSJens Wiklander          * Step 5: derive MPI from hashed message
110*817466cbSJens Wiklander          */
111*817466cbSJens Wiklander         MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) );
112*817466cbSJens Wiklander 
113*817466cbSJens Wiklander         /*
114*817466cbSJens Wiklander          * Generate a random value to blind inv_mod in next step,
115*817466cbSJens Wiklander          * avoiding a potential timing leak.
116*817466cbSJens Wiklander          */
117*817466cbSJens Wiklander         blind_tries = 0;
118*817466cbSJens Wiklander         do
119*817466cbSJens Wiklander         {
120*817466cbSJens Wiklander             size_t n_size = ( grp->nbits + 7 ) / 8;
121*817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &t, n_size, f_rng, p_rng ) );
122*817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &t, 8 * n_size - grp->nbits ) );
123*817466cbSJens Wiklander 
124*817466cbSJens Wiklander             /* See mbedtls_ecp_gen_keypair() */
125*817466cbSJens Wiklander             if( ++blind_tries > 30 )
126*817466cbSJens Wiklander                 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
127*817466cbSJens Wiklander         }
128*817466cbSJens Wiklander         while( mbedtls_mpi_cmp_int( &t, 1 ) < 0 ||
129*817466cbSJens Wiklander                mbedtls_mpi_cmp_mpi( &t, &grp->N ) >= 0 );
130*817466cbSJens Wiklander 
131*817466cbSJens Wiklander         /*
132*817466cbSJens Wiklander          * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n
133*817466cbSJens Wiklander          */
134*817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, r, d ) );
135*817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) );
136*817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) );
137*817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &k, &k, &t ) );
138*817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, &k, &grp->N ) );
139*817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) );
140*817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) );
141*817466cbSJens Wiklander 
142*817466cbSJens Wiklander         if( sign_tries++ > 10 )
143*817466cbSJens Wiklander         {
144*817466cbSJens Wiklander             ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
145*817466cbSJens Wiklander             goto cleanup;
146*817466cbSJens Wiklander         }
147*817466cbSJens Wiklander     }
148*817466cbSJens Wiklander     while( mbedtls_mpi_cmp_int( s, 0 ) == 0 );
149*817466cbSJens Wiklander 
150*817466cbSJens Wiklander cleanup:
151*817466cbSJens Wiklander     mbedtls_ecp_point_free( &R );
152*817466cbSJens Wiklander     mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t );
153*817466cbSJens Wiklander 
154*817466cbSJens Wiklander     return( ret );
155*817466cbSJens Wiklander }
156*817466cbSJens Wiklander 
157*817466cbSJens Wiklander #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
158*817466cbSJens Wiklander /*
159*817466cbSJens Wiklander  * Deterministic signature wrapper
160*817466cbSJens Wiklander  */
161*817466cbSJens Wiklander int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
162*817466cbSJens Wiklander                     const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
163*817466cbSJens Wiklander                     mbedtls_md_type_t md_alg )
164*817466cbSJens Wiklander {
165*817466cbSJens Wiklander     int ret;
166*817466cbSJens Wiklander     mbedtls_hmac_drbg_context rng_ctx;
167*817466cbSJens Wiklander     unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES];
168*817466cbSJens Wiklander     size_t grp_len = ( grp->nbits + 7 ) / 8;
169*817466cbSJens Wiklander     const mbedtls_md_info_t *md_info;
170*817466cbSJens Wiklander     mbedtls_mpi h;
171*817466cbSJens Wiklander 
172*817466cbSJens Wiklander     if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL )
173*817466cbSJens Wiklander         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
174*817466cbSJens Wiklander 
175*817466cbSJens Wiklander     mbedtls_mpi_init( &h );
176*817466cbSJens Wiklander     mbedtls_hmac_drbg_init( &rng_ctx );
177*817466cbSJens Wiklander 
178*817466cbSJens Wiklander     /* Use private key and message hash (reduced) to initialize HMAC_DRBG */
179*817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) );
180*817466cbSJens Wiklander     MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) );
181*817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) );
182*817466cbSJens Wiklander     mbedtls_hmac_drbg_seed_buf( &rng_ctx, md_info, data, 2 * grp_len );
183*817466cbSJens Wiklander 
184*817466cbSJens Wiklander     ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen,
185*817466cbSJens Wiklander                       mbedtls_hmac_drbg_random, &rng_ctx );
186*817466cbSJens Wiklander 
187*817466cbSJens Wiklander cleanup:
188*817466cbSJens Wiklander     mbedtls_hmac_drbg_free( &rng_ctx );
189*817466cbSJens Wiklander     mbedtls_mpi_free( &h );
190*817466cbSJens Wiklander 
191*817466cbSJens Wiklander     return( ret );
192*817466cbSJens Wiklander }
193*817466cbSJens Wiklander #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
194*817466cbSJens Wiklander 
195*817466cbSJens Wiklander /*
196*817466cbSJens Wiklander  * Verify ECDSA signature of hashed message (SEC1 4.1.4)
197*817466cbSJens Wiklander  * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message)
198*817466cbSJens Wiklander  */
199*817466cbSJens Wiklander int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
200*817466cbSJens Wiklander                   const unsigned char *buf, size_t blen,
201*817466cbSJens Wiklander                   const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s)
202*817466cbSJens Wiklander {
203*817466cbSJens Wiklander     int ret;
204*817466cbSJens Wiklander     mbedtls_mpi e, s_inv, u1, u2;
205*817466cbSJens Wiklander     mbedtls_ecp_point R;
206*817466cbSJens Wiklander 
207*817466cbSJens Wiklander     mbedtls_ecp_point_init( &R );
208*817466cbSJens Wiklander     mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 );
209*817466cbSJens Wiklander 
210*817466cbSJens Wiklander     /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
211*817466cbSJens Wiklander     if( grp->N.p == NULL )
212*817466cbSJens Wiklander         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
213*817466cbSJens Wiklander 
214*817466cbSJens Wiklander     /*
215*817466cbSJens Wiklander      * Step 1: make sure r and s are in range 1..n-1
216*817466cbSJens Wiklander      */
217*817466cbSJens Wiklander     if( mbedtls_mpi_cmp_int( r, 1 ) < 0 || mbedtls_mpi_cmp_mpi( r, &grp->N ) >= 0 ||
218*817466cbSJens Wiklander         mbedtls_mpi_cmp_int( s, 1 ) < 0 || mbedtls_mpi_cmp_mpi( s, &grp->N ) >= 0 )
219*817466cbSJens Wiklander     {
220*817466cbSJens Wiklander         ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
221*817466cbSJens Wiklander         goto cleanup;
222*817466cbSJens Wiklander     }
223*817466cbSJens Wiklander 
224*817466cbSJens Wiklander     /*
225*817466cbSJens Wiklander      * Additional precaution: make sure Q is valid
226*817466cbSJens Wiklander      */
227*817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) );
228*817466cbSJens Wiklander 
229*817466cbSJens Wiklander     /*
230*817466cbSJens Wiklander      * Step 3: derive MPI from hashed message
231*817466cbSJens Wiklander      */
232*817466cbSJens Wiklander     MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) );
233*817466cbSJens Wiklander 
234*817466cbSJens Wiklander     /*
235*817466cbSJens Wiklander      * Step 4: u1 = e / s mod n, u2 = r / s mod n
236*817466cbSJens Wiklander      */
237*817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) );
238*817466cbSJens Wiklander 
239*817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u1, &e, &s_inv ) );
240*817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u1, &u1, &grp->N ) );
241*817466cbSJens Wiklander 
242*817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u2, r, &s_inv ) );
243*817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u2, &u2, &grp->N ) );
244*817466cbSJens Wiklander 
245*817466cbSJens Wiklander     /*
246*817466cbSJens Wiklander      * Step 5: R = u1 G + u2 Q
247*817466cbSJens Wiklander      *
248*817466cbSJens Wiklander      * Since we're not using any secret data, no need to pass a RNG to
249*817466cbSJens Wiklander      * mbedtls_ecp_mul() for countermesures.
250*817466cbSJens Wiklander      */
251*817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, &R, &u1, &grp->G, &u2, Q ) );
252*817466cbSJens Wiklander 
253*817466cbSJens Wiklander     if( mbedtls_ecp_is_zero( &R ) )
254*817466cbSJens Wiklander     {
255*817466cbSJens Wiklander         ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
256*817466cbSJens Wiklander         goto cleanup;
257*817466cbSJens Wiklander     }
258*817466cbSJens Wiklander 
259*817466cbSJens Wiklander     /*
260*817466cbSJens Wiklander      * Step 6: convert xR to an integer (no-op)
261*817466cbSJens Wiklander      * Step 7: reduce xR mod n (gives v)
262*817466cbSJens Wiklander      */
263*817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &R.X, &R.X, &grp->N ) );
264*817466cbSJens Wiklander 
265*817466cbSJens Wiklander     /*
266*817466cbSJens Wiklander      * Step 8: check if v (that is, R.X) is equal to r
267*817466cbSJens Wiklander      */
268*817466cbSJens Wiklander     if( mbedtls_mpi_cmp_mpi( &R.X, r ) != 0 )
269*817466cbSJens Wiklander     {
270*817466cbSJens Wiklander         ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
271*817466cbSJens Wiklander         goto cleanup;
272*817466cbSJens Wiklander     }
273*817466cbSJens Wiklander 
274*817466cbSJens Wiklander cleanup:
275*817466cbSJens Wiklander     mbedtls_ecp_point_free( &R );
276*817466cbSJens Wiklander     mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv ); mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 );
277*817466cbSJens Wiklander 
278*817466cbSJens Wiklander     return( ret );
279*817466cbSJens Wiklander }
280*817466cbSJens Wiklander 
281*817466cbSJens Wiklander /*
282*817466cbSJens Wiklander  * Convert a signature (given by context) to ASN.1
283*817466cbSJens Wiklander  */
284*817466cbSJens Wiklander static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s,
285*817466cbSJens Wiklander                                     unsigned char *sig, size_t *slen )
286*817466cbSJens Wiklander {
287*817466cbSJens Wiklander     int ret;
288*817466cbSJens Wiklander     unsigned char buf[MBEDTLS_ECDSA_MAX_LEN];
289*817466cbSJens Wiklander     unsigned char *p = buf + sizeof( buf );
290*817466cbSJens Wiklander     size_t len = 0;
291*817466cbSJens Wiklander 
292*817466cbSJens Wiklander     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, s ) );
293*817466cbSJens Wiklander     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, r ) );
294*817466cbSJens Wiklander 
295*817466cbSJens Wiklander     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, buf, len ) );
296*817466cbSJens Wiklander     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, buf,
297*817466cbSJens Wiklander                                        MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
298*817466cbSJens Wiklander 
299*817466cbSJens Wiklander     memcpy( sig, p, len );
300*817466cbSJens Wiklander     *slen = len;
301*817466cbSJens Wiklander 
302*817466cbSJens Wiklander     return( 0 );
303*817466cbSJens Wiklander }
304*817466cbSJens Wiklander 
305*817466cbSJens Wiklander /*
306*817466cbSJens Wiklander  * Compute and write signature
307*817466cbSJens Wiklander  */
308*817466cbSJens Wiklander int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg,
309*817466cbSJens Wiklander                            const unsigned char *hash, size_t hlen,
310*817466cbSJens Wiklander                            unsigned char *sig, size_t *slen,
311*817466cbSJens Wiklander                            int (*f_rng)(void *, unsigned char *, size_t),
312*817466cbSJens Wiklander                            void *p_rng )
313*817466cbSJens Wiklander {
314*817466cbSJens Wiklander     int ret;
315*817466cbSJens Wiklander     mbedtls_mpi r, s;
316*817466cbSJens Wiklander 
317*817466cbSJens Wiklander     mbedtls_mpi_init( &r );
318*817466cbSJens Wiklander     mbedtls_mpi_init( &s );
319*817466cbSJens Wiklander 
320*817466cbSJens Wiklander #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
321*817466cbSJens Wiklander     (void) f_rng;
322*817466cbSJens Wiklander     (void) p_rng;
323*817466cbSJens Wiklander 
324*817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det( &ctx->grp, &r, &s, &ctx->d,
325*817466cbSJens Wiklander                              hash, hlen, md_alg ) );
326*817466cbSJens Wiklander #else
327*817466cbSJens Wiklander     (void) md_alg;
328*817466cbSJens Wiklander 
329*817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d,
330*817466cbSJens Wiklander                          hash, hlen, f_rng, p_rng ) );
331*817466cbSJens Wiklander #endif
332*817466cbSJens Wiklander 
333*817466cbSJens Wiklander     MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) );
334*817466cbSJens Wiklander 
335*817466cbSJens Wiklander cleanup:
336*817466cbSJens Wiklander     mbedtls_mpi_free( &r );
337*817466cbSJens Wiklander     mbedtls_mpi_free( &s );
338*817466cbSJens Wiklander 
339*817466cbSJens Wiklander     return( ret );
340*817466cbSJens Wiklander }
341*817466cbSJens Wiklander 
342*817466cbSJens Wiklander #if ! defined(MBEDTLS_DEPRECATED_REMOVED) && \
343*817466cbSJens Wiklander     defined(MBEDTLS_ECDSA_DETERMINISTIC)
344*817466cbSJens Wiklander int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx,
345*817466cbSJens Wiklander                                const unsigned char *hash, size_t hlen,
346*817466cbSJens Wiklander                                unsigned char *sig, size_t *slen,
347*817466cbSJens Wiklander                                mbedtls_md_type_t md_alg )
348*817466cbSJens Wiklander {
349*817466cbSJens Wiklander     return( mbedtls_ecdsa_write_signature( ctx, md_alg, hash, hlen, sig, slen,
350*817466cbSJens Wiklander                                    NULL, NULL ) );
351*817466cbSJens Wiklander }
352*817466cbSJens Wiklander #endif
353*817466cbSJens Wiklander 
354*817466cbSJens Wiklander /*
355*817466cbSJens Wiklander  * Read and check signature
356*817466cbSJens Wiklander  */
357*817466cbSJens Wiklander int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx,
358*817466cbSJens Wiklander                           const unsigned char *hash, size_t hlen,
359*817466cbSJens Wiklander                           const unsigned char *sig, size_t slen )
360*817466cbSJens Wiklander {
361*817466cbSJens Wiklander     int ret;
362*817466cbSJens Wiklander     unsigned char *p = (unsigned char *) sig;
363*817466cbSJens Wiklander     const unsigned char *end = sig + slen;
364*817466cbSJens Wiklander     size_t len;
365*817466cbSJens Wiklander     mbedtls_mpi r, s;
366*817466cbSJens Wiklander 
367*817466cbSJens Wiklander     mbedtls_mpi_init( &r );
368*817466cbSJens Wiklander     mbedtls_mpi_init( &s );
369*817466cbSJens Wiklander 
370*817466cbSJens Wiklander     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
371*817466cbSJens Wiklander                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
372*817466cbSJens Wiklander     {
373*817466cbSJens Wiklander         ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
374*817466cbSJens Wiklander         goto cleanup;
375*817466cbSJens Wiklander     }
376*817466cbSJens Wiklander 
377*817466cbSJens Wiklander     if( p + len != end )
378*817466cbSJens Wiklander     {
379*817466cbSJens Wiklander         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA +
380*817466cbSJens Wiklander               MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
381*817466cbSJens Wiklander         goto cleanup;
382*817466cbSJens Wiklander     }
383*817466cbSJens Wiklander 
384*817466cbSJens Wiklander     if( ( ret = mbedtls_asn1_get_mpi( &p, end, &r ) ) != 0 ||
385*817466cbSJens Wiklander         ( ret = mbedtls_asn1_get_mpi( &p, end, &s ) ) != 0 )
386*817466cbSJens Wiklander     {
387*817466cbSJens Wiklander         ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
388*817466cbSJens Wiklander         goto cleanup;
389*817466cbSJens Wiklander     }
390*817466cbSJens Wiklander 
391*817466cbSJens Wiklander     if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen,
392*817466cbSJens Wiklander                               &ctx->Q, &r, &s ) ) != 0 )
393*817466cbSJens Wiklander         goto cleanup;
394*817466cbSJens Wiklander 
395*817466cbSJens Wiklander     if( p != end )
396*817466cbSJens Wiklander         ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH;
397*817466cbSJens Wiklander 
398*817466cbSJens Wiklander cleanup:
399*817466cbSJens Wiklander     mbedtls_mpi_free( &r );
400*817466cbSJens Wiklander     mbedtls_mpi_free( &s );
401*817466cbSJens Wiklander 
402*817466cbSJens Wiklander     return( ret );
403*817466cbSJens Wiklander }
404*817466cbSJens Wiklander 
405*817466cbSJens Wiklander /*
406*817466cbSJens Wiklander  * Generate key pair
407*817466cbSJens Wiklander  */
408*817466cbSJens Wiklander int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid,
409*817466cbSJens Wiklander                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
410*817466cbSJens Wiklander {
411*817466cbSJens Wiklander     return( mbedtls_ecp_group_load( &ctx->grp, gid ) ||
412*817466cbSJens Wiklander             mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) );
413*817466cbSJens Wiklander }
414*817466cbSJens Wiklander 
415*817466cbSJens Wiklander /*
416*817466cbSJens Wiklander  * Set context from an mbedtls_ecp_keypair
417*817466cbSJens Wiklander  */
418*817466cbSJens Wiklander int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key )
419*817466cbSJens Wiklander {
420*817466cbSJens Wiklander     int ret;
421*817466cbSJens Wiklander 
422*817466cbSJens Wiklander     if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 ||
423*817466cbSJens Wiklander         ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 ||
424*817466cbSJens Wiklander         ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 )
425*817466cbSJens Wiklander     {
426*817466cbSJens Wiklander         mbedtls_ecdsa_free( ctx );
427*817466cbSJens Wiklander     }
428*817466cbSJens Wiklander 
429*817466cbSJens Wiklander     return( ret );
430*817466cbSJens Wiklander }
431*817466cbSJens Wiklander 
432*817466cbSJens Wiklander /*
433*817466cbSJens Wiklander  * Initialize context
434*817466cbSJens Wiklander  */
435*817466cbSJens Wiklander void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx )
436*817466cbSJens Wiklander {
437*817466cbSJens Wiklander     mbedtls_ecp_keypair_init( ctx );
438*817466cbSJens Wiklander }
439*817466cbSJens Wiklander 
440*817466cbSJens Wiklander /*
441*817466cbSJens Wiklander  * Free context
442*817466cbSJens Wiklander  */
443*817466cbSJens Wiklander void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx )
444*817466cbSJens Wiklander {
445*817466cbSJens Wiklander     mbedtls_ecp_keypair_free( ctx );
446*817466cbSJens Wiklander }
447*817466cbSJens Wiklander 
448*817466cbSJens Wiklander #endif /* MBEDTLS_ECDSA_C */
449