1*c6672fdcSEdison Ai // SPDX-License-Identifier: Apache-2.0 2817466cbSJens Wiklander /* 3817466cbSJens Wiklander * Elliptic curve DSA 4817466cbSJens Wiklander * 5817466cbSJens Wiklander * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 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 * This file is part of mbed TLS (https://tls.mbed.org) 20817466cbSJens Wiklander */ 21817466cbSJens Wiklander 22817466cbSJens Wiklander /* 23817466cbSJens Wiklander * References: 24817466cbSJens Wiklander * 25817466cbSJens Wiklander * SEC1 http://www.secg.org/index.php?action=secg,docs_secg 26817466cbSJens Wiklander */ 27817466cbSJens Wiklander 28817466cbSJens Wiklander #if !defined(MBEDTLS_CONFIG_FILE) 29817466cbSJens Wiklander #include "mbedtls/config.h" 30817466cbSJens Wiklander #else 31817466cbSJens Wiklander #include MBEDTLS_CONFIG_FILE 32817466cbSJens Wiklander #endif 33817466cbSJens Wiklander 34817466cbSJens Wiklander #if defined(MBEDTLS_ECDSA_C) 35817466cbSJens Wiklander 36817466cbSJens Wiklander #include "mbedtls/ecdsa.h" 37817466cbSJens Wiklander #include "mbedtls/asn1write.h" 38817466cbSJens Wiklander 39817466cbSJens Wiklander #include <string.h> 40817466cbSJens Wiklander 41817466cbSJens Wiklander #if defined(MBEDTLS_ECDSA_DETERMINISTIC) 42817466cbSJens Wiklander #include "mbedtls/hmac_drbg.h" 43817466cbSJens Wiklander #endif 44817466cbSJens Wiklander 45817466cbSJens Wiklander /* 46817466cbSJens Wiklander * Derive a suitable integer for group grp from a buffer of length len 47817466cbSJens Wiklander * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3 48817466cbSJens Wiklander */ 49817466cbSJens Wiklander static int derive_mpi( const mbedtls_ecp_group *grp, mbedtls_mpi *x, 50817466cbSJens Wiklander const unsigned char *buf, size_t blen ) 51817466cbSJens Wiklander { 52817466cbSJens Wiklander int ret; 53817466cbSJens Wiklander size_t n_size = ( grp->nbits + 7 ) / 8; 54817466cbSJens Wiklander size_t use_size = blen > n_size ? n_size : blen; 55817466cbSJens Wiklander 56817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( x, buf, use_size ) ); 57817466cbSJens Wiklander if( use_size * 8 > grp->nbits ) 58817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( x, use_size * 8 - grp->nbits ) ); 59817466cbSJens Wiklander 60817466cbSJens Wiklander /* While at it, reduce modulo N */ 61817466cbSJens Wiklander if( mbedtls_mpi_cmp_mpi( x, &grp->N ) >= 0 ) 62817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( x, x, &grp->N ) ); 63817466cbSJens Wiklander 64817466cbSJens Wiklander cleanup: 65817466cbSJens Wiklander return( ret ); 66817466cbSJens Wiklander } 67817466cbSJens Wiklander 68817466cbSJens Wiklander /* 69817466cbSJens Wiklander * Compute ECDSA signature of a hashed message (SEC1 4.1.3) 70817466cbSJens Wiklander * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message) 71817466cbSJens Wiklander */ 72817466cbSJens Wiklander int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, 73817466cbSJens Wiklander const mbedtls_mpi *d, const unsigned char *buf, size_t blen, 74817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) 75817466cbSJens Wiklander { 76817466cbSJens Wiklander int ret, key_tries, sign_tries, blind_tries; 77817466cbSJens Wiklander mbedtls_ecp_point R; 78817466cbSJens Wiklander mbedtls_mpi k, e, t; 79817466cbSJens Wiklander 80817466cbSJens Wiklander /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ 81817466cbSJens Wiklander if( grp->N.p == NULL ) 82817466cbSJens Wiklander return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 83817466cbSJens Wiklander 84817466cbSJens Wiklander mbedtls_ecp_point_init( &R ); 85817466cbSJens Wiklander mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t ); 86817466cbSJens Wiklander 87817466cbSJens Wiklander sign_tries = 0; 88817466cbSJens Wiklander do 89817466cbSJens Wiklander { 90817466cbSJens Wiklander /* 91817466cbSJens Wiklander * Steps 1-3: generate a suitable ephemeral keypair 92817466cbSJens Wiklander * and set r = xR mod n 93817466cbSJens Wiklander */ 94817466cbSJens Wiklander key_tries = 0; 95817466cbSJens Wiklander do 96817466cbSJens Wiklander { 97817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair( grp, &k, &R, f_rng, p_rng ) ); 98817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( r, &R.X, &grp->N ) ); 99817466cbSJens Wiklander 100817466cbSJens Wiklander if( key_tries++ > 10 ) 101817466cbSJens Wiklander { 102817466cbSJens Wiklander ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; 103817466cbSJens Wiklander goto cleanup; 104817466cbSJens Wiklander } 105817466cbSJens Wiklander } 106817466cbSJens Wiklander while( mbedtls_mpi_cmp_int( r, 0 ) == 0 ); 107817466cbSJens Wiklander 108817466cbSJens Wiklander /* 109817466cbSJens Wiklander * Step 5: derive MPI from hashed message 110817466cbSJens Wiklander */ 111817466cbSJens Wiklander MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); 112817466cbSJens Wiklander 113817466cbSJens Wiklander /* 114817466cbSJens Wiklander * Generate a random value to blind inv_mod in next step, 115817466cbSJens Wiklander * avoiding a potential timing leak. 116817466cbSJens Wiklander */ 117817466cbSJens Wiklander blind_tries = 0; 118817466cbSJens Wiklander do 119817466cbSJens Wiklander { 120817466cbSJens Wiklander size_t n_size = ( grp->nbits + 7 ) / 8; 121817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &t, n_size, f_rng, p_rng ) ); 122817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &t, 8 * n_size - grp->nbits ) ); 123817466cbSJens Wiklander 124817466cbSJens Wiklander /* See mbedtls_ecp_gen_keypair() */ 125817466cbSJens Wiklander if( ++blind_tries > 30 ) 126817466cbSJens Wiklander return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); 127817466cbSJens Wiklander } 128817466cbSJens Wiklander while( mbedtls_mpi_cmp_int( &t, 1 ) < 0 || 129817466cbSJens Wiklander mbedtls_mpi_cmp_mpi( &t, &grp->N ) >= 0 ); 130817466cbSJens Wiklander 131817466cbSJens Wiklander /* 132817466cbSJens Wiklander * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n 133817466cbSJens Wiklander */ 134817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, r, d ) ); 135817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) ); 136817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) ); 137817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &k, &k, &t ) ); 138817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, &k, &grp->N ) ); 139817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) ); 140817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) ); 141817466cbSJens Wiklander 142817466cbSJens Wiklander if( sign_tries++ > 10 ) 143817466cbSJens Wiklander { 144817466cbSJens Wiklander ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; 145817466cbSJens Wiklander goto cleanup; 146817466cbSJens Wiklander } 147817466cbSJens Wiklander } 148817466cbSJens Wiklander while( mbedtls_mpi_cmp_int( s, 0 ) == 0 ); 149817466cbSJens Wiklander 150817466cbSJens Wiklander cleanup: 151817466cbSJens Wiklander mbedtls_ecp_point_free( &R ); 152817466cbSJens Wiklander mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t ); 153817466cbSJens Wiklander 154817466cbSJens Wiklander return( ret ); 155817466cbSJens Wiklander } 156817466cbSJens Wiklander 157817466cbSJens Wiklander #if defined(MBEDTLS_ECDSA_DETERMINISTIC) 158817466cbSJens Wiklander /* 159817466cbSJens Wiklander * Deterministic signature wrapper 160817466cbSJens Wiklander */ 161817466cbSJens Wiklander int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, 162817466cbSJens Wiklander const mbedtls_mpi *d, const unsigned char *buf, size_t blen, 163817466cbSJens Wiklander mbedtls_md_type_t md_alg ) 164817466cbSJens Wiklander { 165817466cbSJens Wiklander int ret; 166817466cbSJens Wiklander mbedtls_hmac_drbg_context rng_ctx; 167817466cbSJens Wiklander unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES]; 168817466cbSJens Wiklander size_t grp_len = ( grp->nbits + 7 ) / 8; 169817466cbSJens Wiklander const mbedtls_md_info_t *md_info; 170817466cbSJens Wiklander mbedtls_mpi h; 171817466cbSJens Wiklander 172817466cbSJens Wiklander if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) 173817466cbSJens Wiklander return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 174817466cbSJens Wiklander 175817466cbSJens Wiklander mbedtls_mpi_init( &h ); 176817466cbSJens Wiklander mbedtls_hmac_drbg_init( &rng_ctx ); 177817466cbSJens Wiklander 178817466cbSJens Wiklander /* Use private key and message hash (reduced) to initialize HMAC_DRBG */ 179817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) ); 180817466cbSJens Wiklander MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) ); 181817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) ); 182817466cbSJens Wiklander mbedtls_hmac_drbg_seed_buf( &rng_ctx, md_info, data, 2 * grp_len ); 183817466cbSJens Wiklander 184817466cbSJens Wiklander ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen, 185817466cbSJens Wiklander mbedtls_hmac_drbg_random, &rng_ctx ); 186817466cbSJens Wiklander 187817466cbSJens Wiklander cleanup: 188817466cbSJens Wiklander mbedtls_hmac_drbg_free( &rng_ctx ); 189817466cbSJens Wiklander mbedtls_mpi_free( &h ); 190817466cbSJens Wiklander 191817466cbSJens Wiklander return( ret ); 192817466cbSJens Wiklander } 193817466cbSJens Wiklander #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ 194817466cbSJens Wiklander 195817466cbSJens Wiklander /* 196817466cbSJens Wiklander * Verify ECDSA signature of hashed message (SEC1 4.1.4) 197817466cbSJens Wiklander * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message) 198817466cbSJens Wiklander */ 199817466cbSJens Wiklander int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, 200817466cbSJens Wiklander const unsigned char *buf, size_t blen, 201817466cbSJens Wiklander const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s) 202817466cbSJens Wiklander { 203817466cbSJens Wiklander int ret; 204817466cbSJens Wiklander mbedtls_mpi e, s_inv, u1, u2; 205817466cbSJens Wiklander mbedtls_ecp_point R; 206817466cbSJens Wiklander 207817466cbSJens Wiklander mbedtls_ecp_point_init( &R ); 208817466cbSJens Wiklander mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 ); 209817466cbSJens Wiklander 210817466cbSJens Wiklander /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ 211817466cbSJens Wiklander if( grp->N.p == NULL ) 212817466cbSJens Wiklander return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 213817466cbSJens Wiklander 214817466cbSJens Wiklander /* 215817466cbSJens Wiklander * Step 1: make sure r and s are in range 1..n-1 216817466cbSJens Wiklander */ 217817466cbSJens Wiklander if( mbedtls_mpi_cmp_int( r, 1 ) < 0 || mbedtls_mpi_cmp_mpi( r, &grp->N ) >= 0 || 218817466cbSJens Wiklander mbedtls_mpi_cmp_int( s, 1 ) < 0 || mbedtls_mpi_cmp_mpi( s, &grp->N ) >= 0 ) 219817466cbSJens Wiklander { 220817466cbSJens Wiklander ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; 221817466cbSJens Wiklander goto cleanup; 222817466cbSJens Wiklander } 223817466cbSJens Wiklander 224817466cbSJens Wiklander /* 225817466cbSJens Wiklander * Additional precaution: make sure Q is valid 226817466cbSJens Wiklander */ 227817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) ); 228817466cbSJens Wiklander 229817466cbSJens Wiklander /* 230817466cbSJens Wiklander * Step 3: derive MPI from hashed message 231817466cbSJens Wiklander */ 232817466cbSJens Wiklander MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); 233817466cbSJens Wiklander 234817466cbSJens Wiklander /* 235817466cbSJens Wiklander * Step 4: u1 = e / s mod n, u2 = r / s mod n 236817466cbSJens Wiklander */ 237817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) ); 238817466cbSJens Wiklander 239817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u1, &e, &s_inv ) ); 240817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u1, &u1, &grp->N ) ); 241817466cbSJens Wiklander 242817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u2, r, &s_inv ) ); 243817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u2, &u2, &grp->N ) ); 244817466cbSJens Wiklander 245817466cbSJens Wiklander /* 246817466cbSJens Wiklander * Step 5: R = u1 G + u2 Q 247817466cbSJens Wiklander * 248817466cbSJens Wiklander * Since we're not using any secret data, no need to pass a RNG to 249817466cbSJens Wiklander * mbedtls_ecp_mul() for countermesures. 250817466cbSJens Wiklander */ 251817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, &R, &u1, &grp->G, &u2, Q ) ); 252817466cbSJens Wiklander 253817466cbSJens Wiklander if( mbedtls_ecp_is_zero( &R ) ) 254817466cbSJens Wiklander { 255817466cbSJens Wiklander ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; 256817466cbSJens Wiklander goto cleanup; 257817466cbSJens Wiklander } 258817466cbSJens Wiklander 259817466cbSJens Wiklander /* 260817466cbSJens Wiklander * Step 6: convert xR to an integer (no-op) 261817466cbSJens Wiklander * Step 7: reduce xR mod n (gives v) 262817466cbSJens Wiklander */ 263817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &R.X, &R.X, &grp->N ) ); 264817466cbSJens Wiklander 265817466cbSJens Wiklander /* 266817466cbSJens Wiklander * Step 8: check if v (that is, R.X) is equal to r 267817466cbSJens Wiklander */ 268817466cbSJens Wiklander if( mbedtls_mpi_cmp_mpi( &R.X, r ) != 0 ) 269817466cbSJens Wiklander { 270817466cbSJens Wiklander ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; 271817466cbSJens Wiklander goto cleanup; 272817466cbSJens Wiklander } 273817466cbSJens Wiklander 274817466cbSJens Wiklander cleanup: 275817466cbSJens Wiklander mbedtls_ecp_point_free( &R ); 276817466cbSJens Wiklander mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv ); mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 ); 277817466cbSJens Wiklander 278817466cbSJens Wiklander return( ret ); 279817466cbSJens Wiklander } 280817466cbSJens Wiklander 281817466cbSJens Wiklander /* 282817466cbSJens Wiklander * Convert a signature (given by context) to ASN.1 283817466cbSJens Wiklander */ 284817466cbSJens Wiklander static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s, 285817466cbSJens Wiklander unsigned char *sig, size_t *slen ) 286817466cbSJens Wiklander { 287817466cbSJens Wiklander int ret; 288817466cbSJens Wiklander unsigned char buf[MBEDTLS_ECDSA_MAX_LEN]; 289817466cbSJens Wiklander unsigned char *p = buf + sizeof( buf ); 290817466cbSJens Wiklander size_t len = 0; 291817466cbSJens Wiklander 292817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, s ) ); 293817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, r ) ); 294817466cbSJens Wiklander 295817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, buf, len ) ); 296817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, buf, 297817466cbSJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); 298817466cbSJens Wiklander 299817466cbSJens Wiklander memcpy( sig, p, len ); 300817466cbSJens Wiklander *slen = len; 301817466cbSJens Wiklander 302817466cbSJens Wiklander return( 0 ); 303817466cbSJens Wiklander } 304817466cbSJens Wiklander 305817466cbSJens Wiklander /* 306817466cbSJens Wiklander * Compute and write signature 307817466cbSJens Wiklander */ 308817466cbSJens Wiklander int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, 309817466cbSJens Wiklander const unsigned char *hash, size_t hlen, 310817466cbSJens Wiklander unsigned char *sig, size_t *slen, 311817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 312817466cbSJens Wiklander void *p_rng ) 313817466cbSJens Wiklander { 314817466cbSJens Wiklander int ret; 315817466cbSJens Wiklander mbedtls_mpi r, s; 316817466cbSJens Wiklander 317817466cbSJens Wiklander mbedtls_mpi_init( &r ); 318817466cbSJens Wiklander mbedtls_mpi_init( &s ); 319817466cbSJens Wiklander 320817466cbSJens Wiklander #if defined(MBEDTLS_ECDSA_DETERMINISTIC) 321817466cbSJens Wiklander (void) f_rng; 322817466cbSJens Wiklander (void) p_rng; 323817466cbSJens Wiklander 324817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det( &ctx->grp, &r, &s, &ctx->d, 325817466cbSJens Wiklander hash, hlen, md_alg ) ); 326817466cbSJens Wiklander #else 327817466cbSJens Wiklander (void) md_alg; 328817466cbSJens Wiklander 329817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d, 330817466cbSJens Wiklander hash, hlen, f_rng, p_rng ) ); 331817466cbSJens Wiklander #endif 332817466cbSJens Wiklander 333817466cbSJens Wiklander MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) ); 334817466cbSJens Wiklander 335817466cbSJens Wiklander cleanup: 336817466cbSJens Wiklander mbedtls_mpi_free( &r ); 337817466cbSJens Wiklander mbedtls_mpi_free( &s ); 338817466cbSJens Wiklander 339817466cbSJens Wiklander return( ret ); 340817466cbSJens Wiklander } 341817466cbSJens Wiklander 342817466cbSJens Wiklander #if ! defined(MBEDTLS_DEPRECATED_REMOVED) && \ 343817466cbSJens Wiklander defined(MBEDTLS_ECDSA_DETERMINISTIC) 344817466cbSJens Wiklander int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, 345817466cbSJens Wiklander const unsigned char *hash, size_t hlen, 346817466cbSJens Wiklander unsigned char *sig, size_t *slen, 347817466cbSJens Wiklander mbedtls_md_type_t md_alg ) 348817466cbSJens Wiklander { 349817466cbSJens Wiklander return( mbedtls_ecdsa_write_signature( ctx, md_alg, hash, hlen, sig, slen, 350817466cbSJens Wiklander NULL, NULL ) ); 351817466cbSJens Wiklander } 352817466cbSJens Wiklander #endif 353817466cbSJens Wiklander 354817466cbSJens Wiklander /* 355817466cbSJens Wiklander * Read and check signature 356817466cbSJens Wiklander */ 357817466cbSJens Wiklander int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, 358817466cbSJens Wiklander const unsigned char *hash, size_t hlen, 359817466cbSJens Wiklander const unsigned char *sig, size_t slen ) 360817466cbSJens Wiklander { 361817466cbSJens Wiklander int ret; 362817466cbSJens Wiklander unsigned char *p = (unsigned char *) sig; 363817466cbSJens Wiklander const unsigned char *end = sig + slen; 364817466cbSJens Wiklander size_t len; 365817466cbSJens Wiklander mbedtls_mpi r, s; 366817466cbSJens Wiklander 367817466cbSJens Wiklander mbedtls_mpi_init( &r ); 368817466cbSJens Wiklander mbedtls_mpi_init( &s ); 369817466cbSJens Wiklander 370817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, 371817466cbSJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) 372817466cbSJens Wiklander { 373817466cbSJens Wiklander ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 374817466cbSJens Wiklander goto cleanup; 375817466cbSJens Wiklander } 376817466cbSJens Wiklander 377817466cbSJens Wiklander if( p + len != end ) 378817466cbSJens Wiklander { 379817466cbSJens Wiklander ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA + 380817466cbSJens Wiklander MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; 381817466cbSJens Wiklander goto cleanup; 382817466cbSJens Wiklander } 383817466cbSJens Wiklander 384817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_mpi( &p, end, &r ) ) != 0 || 385817466cbSJens Wiklander ( ret = mbedtls_asn1_get_mpi( &p, end, &s ) ) != 0 ) 386817466cbSJens Wiklander { 387817466cbSJens Wiklander ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 388817466cbSJens Wiklander goto cleanup; 389817466cbSJens Wiklander } 390817466cbSJens Wiklander 391817466cbSJens Wiklander if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen, 392817466cbSJens Wiklander &ctx->Q, &r, &s ) ) != 0 ) 393817466cbSJens Wiklander goto cleanup; 394817466cbSJens Wiklander 395817466cbSJens Wiklander if( p != end ) 396817466cbSJens Wiklander ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH; 397817466cbSJens Wiklander 398817466cbSJens Wiklander cleanup: 399817466cbSJens Wiklander mbedtls_mpi_free( &r ); 400817466cbSJens Wiklander mbedtls_mpi_free( &s ); 401817466cbSJens Wiklander 402817466cbSJens Wiklander return( ret ); 403817466cbSJens Wiklander } 404817466cbSJens Wiklander 405817466cbSJens Wiklander /* 406817466cbSJens Wiklander * Generate key pair 407817466cbSJens Wiklander */ 408817466cbSJens Wiklander int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, 409817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) 410817466cbSJens Wiklander { 411817466cbSJens Wiklander return( mbedtls_ecp_group_load( &ctx->grp, gid ) || 412817466cbSJens Wiklander mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ); 413817466cbSJens Wiklander } 414817466cbSJens Wiklander 415817466cbSJens Wiklander /* 416817466cbSJens Wiklander * Set context from an mbedtls_ecp_keypair 417817466cbSJens Wiklander */ 418817466cbSJens Wiklander int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key ) 419817466cbSJens Wiklander { 420817466cbSJens Wiklander int ret; 421817466cbSJens Wiklander 422817466cbSJens Wiklander if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 || 423817466cbSJens Wiklander ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 || 424817466cbSJens Wiklander ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 ) 425817466cbSJens Wiklander { 426817466cbSJens Wiklander mbedtls_ecdsa_free( ctx ); 427817466cbSJens Wiklander } 428817466cbSJens Wiklander 429817466cbSJens Wiklander return( ret ); 430817466cbSJens Wiklander } 431817466cbSJens Wiklander 432817466cbSJens Wiklander /* 433817466cbSJens Wiklander * Initialize context 434817466cbSJens Wiklander */ 435817466cbSJens Wiklander void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ) 436817466cbSJens Wiklander { 437817466cbSJens Wiklander mbedtls_ecp_keypair_init( ctx ); 438817466cbSJens Wiklander } 439817466cbSJens Wiklander 440817466cbSJens Wiklander /* 441817466cbSJens Wiklander * Free context 442817466cbSJens Wiklander */ 443817466cbSJens Wiklander void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ) 444817466cbSJens Wiklander { 445817466cbSJens Wiklander mbedtls_ecp_keypair_free( ctx ); 446817466cbSJens Wiklander } 447817466cbSJens Wiklander 448817466cbSJens Wiklander #endif /* MBEDTLS_ECDSA_C */ 449