xref: /reactos/dll/3rdparty/mbedtls/ecdsa.c (revision ede7a20a)
1 /*
2  *  Elliptic curve DSA
3  *
4  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6  *
7  *  This file is provided under the Apache License 2.0, or the
8  *  GNU General Public License v2.0 or later.
9  *
10  *  **********
11  *  Apache License 2.0:
12  *
13  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
14  *  not use this file except in compliance with the License.
15  *  You may obtain a copy of the License at
16  *
17  *  http://www.apache.org/licenses/LICENSE-2.0
18  *
19  *  Unless required by applicable law or agreed to in writing, software
20  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22  *  See the License for the specific language governing permissions and
23  *  limitations under the License.
24  *
25  *  **********
26  *
27  *  **********
28  *  GNU General Public License v2.0 or later:
29  *
30  *  This program is free software; you can redistribute it and/or modify
31  *  it under the terms of the GNU General Public License as published by
32  *  the Free Software Foundation; either version 2 of the License, or
33  *  (at your option) any later version.
34  *
35  *  This program is distributed in the hope that it will be useful,
36  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
37  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
38  *  GNU General Public License for more details.
39  *
40  *  You should have received a copy of the GNU General Public License along
41  *  with this program; if not, write to the Free Software Foundation, Inc.,
42  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43  *
44  *  **********
45  *
46  *  This file is part of mbed TLS (https://tls.mbed.org)
47  */
48 
49 /*
50  * References:
51  *
52  * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
53  */
54 
55 #if !defined(MBEDTLS_CONFIG_FILE)
56 #include "mbedtls/config.h"
57 #else
58 #include MBEDTLS_CONFIG_FILE
59 #endif
60 
61 #if defined(MBEDTLS_ECDSA_C)
62 
63 #include "mbedtls/ecdsa.h"
64 #include "mbedtls/asn1write.h"
65 
66 #include <string.h>
67 
68 #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
69 #include "mbedtls/hmac_drbg.h"
70 #endif
71 
72 /*
73  * Derive a suitable integer for group grp from a buffer of length len
74  * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3
75  */
76 static int derive_mpi( const mbedtls_ecp_group *grp, mbedtls_mpi *x,
77                        const unsigned char *buf, size_t blen )
78 {
79     int ret;
80     size_t n_size = ( grp->nbits + 7 ) / 8;
81     size_t use_size = blen > n_size ? n_size : blen;
82 
83     MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( x, buf, use_size ) );
84     if( use_size * 8 > grp->nbits )
85         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( x, use_size * 8 - grp->nbits ) );
86 
87     /* While at it, reduce modulo N */
88     if( mbedtls_mpi_cmp_mpi( x, &grp->N ) >= 0 )
89         MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( x, x, &grp->N ) );
90 
91 cleanup:
92     return( ret );
93 }
94 
95 #if !defined(MBEDTLS_ECDSA_SIGN_ALT)
96 /*
97  * Compute ECDSA signature of a hashed message (SEC1 4.1.3)
98  * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message)
99  */
100 static int ecdsa_sign_internal( mbedtls_ecp_group *grp, mbedtls_mpi *r,
101                                 mbedtls_mpi *s, const mbedtls_mpi *d,
102                                 const unsigned char *buf, size_t blen,
103                                 int (*f_rng)(void *, unsigned char *, size_t),
104                                 void *p_rng,
105                                 int (*f_rng_blind)(void *, unsigned char *,
106                                                    size_t),
107                                 void *p_rng_blind )
108 {
109     int ret, key_tries, sign_tries, blind_tries;
110     mbedtls_ecp_point R;
111     mbedtls_mpi k, e, t;
112 
113     /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
114     if( grp->N.p == NULL )
115         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
116 
117     /* Make sure d is in range 1..n-1 */
118     if( mbedtls_mpi_cmp_int( d, 1 ) < 0 || mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 )
119         return( MBEDTLS_ERR_ECP_INVALID_KEY );
120 
121     mbedtls_ecp_point_init( &R );
122     mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t );
123 
124     sign_tries = 0;
125     do
126     {
127         /*
128          * Steps 1-3: generate a suitable ephemeral keypair
129          * and set r = xR mod n
130          */
131         key_tries = 0;
132         do
133         {
134             MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, &k, f_rng, p_rng ) );
135 
136             MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, &R, &k, &grp->G,
137                                               f_rng_blind, p_rng_blind ) );
138             MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( r, &R.X, &grp->N ) );
139 
140             if( key_tries++ > 10 )
141             {
142                 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
143                 goto cleanup;
144             }
145         }
146         while( mbedtls_mpi_cmp_int( r, 0 ) == 0 );
147 
148         /*
149          * Step 5: derive MPI from hashed message
150          */
151         MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) );
152 
153         /*
154          * Generate a random value to blind inv_mod in next step,
155          * avoiding a potential timing leak.
156          *
157          * This loop does the same job as mbedtls_ecp_gen_privkey() and it is
158          * replaced by a call to it in the mainline. This change is not
159          * necessary to backport the fix separating the blinding and ephemeral
160          * key generating RNGs, therefore the original code is kept.
161          */
162         blind_tries = 0;
163         do
164         {
165             size_t n_size = ( grp->nbits + 7 ) / 8;
166             MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &t, n_size, f_rng_blind,
167                                                       p_rng_blind ) );
168             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &t, 8 * n_size - grp->nbits ) );
169 
170             if( ++blind_tries > 30 )
171                 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
172         }
173         while( mbedtls_mpi_cmp_int( &t, 1 ) < 0 ||
174                mbedtls_mpi_cmp_mpi( &t, &grp->N ) >= 0 );
175 
176         /*
177          * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n
178          */
179         MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, r, d ) );
180         MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) );
181         MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) );
182         MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &k, &k, &t ) );
183         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &k, &k, &grp->N ) );
184         MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, &k, &grp->N ) );
185         MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) );
186         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) );
187 
188         if( sign_tries++ > 10 )
189         {
190             ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
191             goto cleanup;
192         }
193     }
194     while( mbedtls_mpi_cmp_int( s, 0 ) == 0 );
195 
196 cleanup:
197     mbedtls_ecp_point_free( &R );
198     mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t );
199 
200     return( ret );
201 }
202 
203 int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
204                         const mbedtls_mpi *d, const unsigned char *buf,
205                         size_t blen,
206                         int (*f_rng)(void *, unsigned char *, size_t),
207                         void *p_rng )
208 {
209     /* Use the same RNG for both blinding and ephemeral key generation */
210     return( ecdsa_sign_internal( grp, r, s, d, buf, blen, f_rng, p_rng,
211                                  f_rng, p_rng ) );
212 }
213 #endif /* MBEDTLS_ECDSA_SIGN_ALT */
214 
215 #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
216 static int ecdsa_sign_det_internal( mbedtls_ecp_group *grp, mbedtls_mpi *r,
217                                     mbedtls_mpi *s, const mbedtls_mpi *d,
218                                     const unsigned char *buf, size_t blen,
219                                     mbedtls_md_type_t md_alg,
220                                     int (*f_rng_blind)(void *, unsigned char *,
221                                                        size_t),
222                                     void *p_rng_blind )
223 {
224     int ret;
225     mbedtls_hmac_drbg_context rng_ctx;
226     unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES];
227     size_t grp_len = ( grp->nbits + 7 ) / 8;
228     const mbedtls_md_info_t *md_info;
229     mbedtls_mpi h;
230     /* Variables for deterministic blinding fallback */
231     const char* blind_label = "BLINDING CONTEXT";
232     mbedtls_hmac_drbg_context rng_ctx_blind;
233 
234     if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL )
235         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
236 
237     mbedtls_mpi_init( &h );
238     mbedtls_hmac_drbg_init( &rng_ctx );
239     mbedtls_hmac_drbg_init( &rng_ctx_blind );
240 
241     /* Use private key and message hash (reduced) to initialize HMAC_DRBG */
242     MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) );
243     MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) );
244     MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) );
245     mbedtls_hmac_drbg_seed_buf( &rng_ctx, md_info, data, 2 * grp_len );
246 
247     if( f_rng_blind != NULL )
248         ret = ecdsa_sign_internal( grp, r, s, d, buf, blen,
249                                    mbedtls_hmac_drbg_random, &rng_ctx,
250                                    f_rng_blind, p_rng_blind );
251     else
252     {
253         /*
254          * To avoid reusing rng_ctx and risking incorrect behavior we seed a
255          * second HMAC-DRBG with the same seed. We also apply a label to avoid
256          * reusing the bits of the ephemeral key for blinding and eliminate the
257          * risk that they leak this way.
258          */
259 
260         mbedtls_hmac_drbg_seed_buf( &rng_ctx_blind, md_info,
261                                     data, 2 * grp_len );
262         ret = mbedtls_hmac_drbg_update_ret( &rng_ctx_blind,
263                                             (const unsigned char*) blind_label,
264                                             strlen( blind_label ) );
265         if( ret != 0 )
266             goto cleanup;
267 
268         /*
269          * Since the output of the RNGs is always the same for the same key and
270          * message, this limits the efficiency of blinding and leaks information
271          * through side channels. After mbedtls_ecdsa_sign_det() is removed NULL
272          * won't be a valid value for f_rng_blind anymore. Therefore it should
273          * be checked by the caller and this branch and check can be removed.
274          */
275         ret = ecdsa_sign_internal( grp, r, s, d, buf, blen,
276                                    mbedtls_hmac_drbg_random, &rng_ctx,
277                                    mbedtls_hmac_drbg_random, &rng_ctx_blind );
278 
279     }
280 
281 cleanup:
282     mbedtls_hmac_drbg_free( &rng_ctx );
283     mbedtls_hmac_drbg_free( &rng_ctx_blind );
284     mbedtls_mpi_free( &h );
285 
286     return( ret );
287 }
288 
289 /*
290  * Deterministic signature wrappers
291  */
292 int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r,
293                             mbedtls_mpi *s, const mbedtls_mpi *d,
294                             const unsigned char *buf, size_t blen,
295                             mbedtls_md_type_t md_alg )
296 {
297     return( ecdsa_sign_det_internal( grp, r, s, d, buf, blen, md_alg,
298                                      NULL, NULL ) );
299 }
300 
301 int mbedtls_ecdsa_sign_det_ext( mbedtls_ecp_group *grp, mbedtls_mpi *r,
302                                 mbedtls_mpi *s, const mbedtls_mpi *d,
303                                 const unsigned char *buf, size_t blen,
304                                 mbedtls_md_type_t md_alg,
305                                 int (*f_rng_blind)(void *, unsigned char *,
306                                                    size_t),
307                                 void *p_rng_blind )
308 {
309     return( ecdsa_sign_det_internal( grp, r, s, d, buf, blen, md_alg,
310                                      f_rng_blind, p_rng_blind ) );
311 }
312 #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
313 
314 #if !defined(MBEDTLS_ECDSA_VERIFY_ALT)
315 /*
316  * Verify ECDSA signature of hashed message (SEC1 4.1.4)
317  * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message)
318  */
319 int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
320                   const unsigned char *buf, size_t blen,
321                   const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s)
322 {
323     int ret;
324     mbedtls_mpi e, s_inv, u1, u2;
325     mbedtls_ecp_point R;
326 
327     mbedtls_ecp_point_init( &R );
328     mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 );
329 
330     /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
331     if( grp->N.p == NULL )
332         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
333 
334     /*
335      * Step 1: make sure r and s are in range 1..n-1
336      */
337     if( mbedtls_mpi_cmp_int( r, 1 ) < 0 || mbedtls_mpi_cmp_mpi( r, &grp->N ) >= 0 ||
338         mbedtls_mpi_cmp_int( s, 1 ) < 0 || mbedtls_mpi_cmp_mpi( s, &grp->N ) >= 0 )
339     {
340         ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
341         goto cleanup;
342     }
343 
344     /*
345      * Additional precaution: make sure Q is valid
346      */
347     MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) );
348 
349     /*
350      * Step 3: derive MPI from hashed message
351      */
352     MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) );
353 
354     /*
355      * Step 4: u1 = e / s mod n, u2 = r / s mod n
356      */
357     MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) );
358 
359     MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u1, &e, &s_inv ) );
360     MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u1, &u1, &grp->N ) );
361 
362     MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u2, r, &s_inv ) );
363     MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u2, &u2, &grp->N ) );
364 
365     /*
366      * Step 5: R = u1 G + u2 Q
367      *
368      * Since we're not using any secret data, no need to pass a RNG to
369      * mbedtls_ecp_mul() for countermesures.
370      */
371     MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, &R, &u1, &grp->G, &u2, Q ) );
372 
373     if( mbedtls_ecp_is_zero( &R ) )
374     {
375         ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
376         goto cleanup;
377     }
378 
379     /*
380      * Step 6: convert xR to an integer (no-op)
381      * Step 7: reduce xR mod n (gives v)
382      */
383     MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &R.X, &R.X, &grp->N ) );
384 
385     /*
386      * Step 8: check if v (that is, R.X) is equal to r
387      */
388     if( mbedtls_mpi_cmp_mpi( &R.X, r ) != 0 )
389     {
390         ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
391         goto cleanup;
392     }
393 
394 cleanup:
395     mbedtls_ecp_point_free( &R );
396     mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv ); mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 );
397 
398     return( ret );
399 }
400 #endif /* MBEDTLS_ECDSA_VERIFY_ALT */
401 
402 /*
403  * Convert a signature (given by context) to ASN.1
404  */
405 static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s,
406                                     unsigned char *sig, size_t *slen )
407 {
408     int ret;
409     unsigned char buf[MBEDTLS_ECDSA_MAX_LEN];
410     unsigned char *p = buf + sizeof( buf );
411     size_t len = 0;
412 
413     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, s ) );
414     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, r ) );
415 
416     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, buf, len ) );
417     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, buf,
418                                        MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
419 
420     memcpy( sig, p, len );
421     *slen = len;
422 
423     return( 0 );
424 }
425 
426 /*
427  * Compute and write signature
428  */
429 int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg,
430                            const unsigned char *hash, size_t hlen,
431                            unsigned char *sig, size_t *slen,
432                            int (*f_rng)(void *, unsigned char *, size_t),
433                            void *p_rng )
434 {
435     int ret;
436     mbedtls_mpi r, s;
437 
438     mbedtls_mpi_init( &r );
439     mbedtls_mpi_init( &s );
440 
441 #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
442     MBEDTLS_MPI_CHK( ecdsa_sign_det_internal( &ctx->grp, &r, &s, &ctx->d,
443                                               hash, hlen, md_alg,
444                                               f_rng, p_rng ) );
445 #else
446     (void) md_alg;
447 
448     MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d,
449                          hash, hlen, f_rng, p_rng ) );
450 #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
451 
452     MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) );
453 
454 cleanup:
455     mbedtls_mpi_free( &r );
456     mbedtls_mpi_free( &s );
457 
458     return( ret );
459 }
460 
461 #if ! defined(MBEDTLS_DEPRECATED_REMOVED) && \
462     defined(MBEDTLS_ECDSA_DETERMINISTIC)
463 int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx,
464                                const unsigned char *hash, size_t hlen,
465                                unsigned char *sig, size_t *slen,
466                                mbedtls_md_type_t md_alg )
467 {
468     return( mbedtls_ecdsa_write_signature( ctx, md_alg, hash, hlen, sig, slen,
469                                    NULL, NULL ) );
470 }
471 #endif
472 
473 /*
474  * Read and check signature
475  */
476 int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx,
477                           const unsigned char *hash, size_t hlen,
478                           const unsigned char *sig, size_t slen )
479 {
480     int ret;
481     unsigned char *p = (unsigned char *) sig;
482     const unsigned char *end = sig + slen;
483     size_t len;
484     mbedtls_mpi r, s;
485 
486     mbedtls_mpi_init( &r );
487     mbedtls_mpi_init( &s );
488 
489     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
490                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
491     {
492         ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
493         goto cleanup;
494     }
495 
496     if( p + len != end )
497     {
498         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA +
499               MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
500         goto cleanup;
501     }
502 
503     if( ( ret = mbedtls_asn1_get_mpi( &p, end, &r ) ) != 0 ||
504         ( ret = mbedtls_asn1_get_mpi( &p, end, &s ) ) != 0 )
505     {
506         ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
507         goto cleanup;
508     }
509 
510     if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen,
511                               &ctx->Q, &r, &s ) ) != 0 )
512         goto cleanup;
513 
514     /* At this point we know that the buffer starts with a valid signature.
515      * Return 0 if the buffer just contains the signature, and a specific
516      * error code if the valid signature is followed by more data. */
517     if( p != end )
518         ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH;
519 
520 cleanup:
521     mbedtls_mpi_free( &r );
522     mbedtls_mpi_free( &s );
523 
524     return( ret );
525 }
526 
527 #if !defined(MBEDTLS_ECDSA_GENKEY_ALT)
528 /*
529  * Generate key pair
530  */
531 int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid,
532                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
533 {
534     int ret = 0;
535     ret = mbedtls_ecp_group_load( &ctx->grp, gid );
536     if( ret != 0 )
537         return( ret );
538 
539    return( mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d,
540                                     &ctx->Q, f_rng, p_rng ) );
541 }
542 #endif /* MBEDTLS_ECDSA_GENKEY_ALT */
543 
544 /*
545  * Set context from an mbedtls_ecp_keypair
546  */
547 int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key )
548 {
549     int ret;
550 
551     if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 ||
552         ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 ||
553         ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 )
554     {
555         mbedtls_ecdsa_free( ctx );
556     }
557 
558     return( ret );
559 }
560 
561 /*
562  * Initialize context
563  */
564 void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx )
565 {
566     mbedtls_ecp_keypair_init( ctx );
567 }
568 
569 /*
570  * Free context
571  */
572 void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx )
573 {
574     mbedtls_ecp_keypair_free( ctx );
575 }
576 
577 #endif /* MBEDTLS_ECDSA_C */
578