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