mbed TLS library

Dependents:   HTTPClient-SSL WS_SERVER

Committer:
ansond
Date:
Thu Jun 11 03:27:03 2015 +0000
Revision:
0:137634ff4186
initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ansond 0:137634ff4186 1 /*
ansond 0:137634ff4186 2 * Elliptic curve DSA
ansond 0:137634ff4186 3 *
ansond 0:137634ff4186 4 * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
ansond 0:137634ff4186 5 *
ansond 0:137634ff4186 6 * This file is part of mbed TLS (https://tls.mbed.org)
ansond 0:137634ff4186 7 *
ansond 0:137634ff4186 8 * This program is free software; you can redistribute it and/or modify
ansond 0:137634ff4186 9 * it under the terms of the GNU General Public License as published by
ansond 0:137634ff4186 10 * the Free Software Foundation; either version 2 of the License, or
ansond 0:137634ff4186 11 * (at your option) any later version.
ansond 0:137634ff4186 12 *
ansond 0:137634ff4186 13 * This program is distributed in the hope that it will be useful,
ansond 0:137634ff4186 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ansond 0:137634ff4186 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
ansond 0:137634ff4186 16 * GNU General Public License for more details.
ansond 0:137634ff4186 17 *
ansond 0:137634ff4186 18 * You should have received a copy of the GNU General Public License along
ansond 0:137634ff4186 19 * with this program; if not, write to the Free Software Foundation, Inc.,
ansond 0:137634ff4186 20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ansond 0:137634ff4186 21 */
ansond 0:137634ff4186 22
ansond 0:137634ff4186 23 /*
ansond 0:137634ff4186 24 * References:
ansond 0:137634ff4186 25 *
ansond 0:137634ff4186 26 * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
ansond 0:137634ff4186 27 */
ansond 0:137634ff4186 28
ansond 0:137634ff4186 29 #if !defined(POLARSSL_CONFIG_FILE)
ansond 0:137634ff4186 30 #include "polarssl/config.h"
ansond 0:137634ff4186 31 #else
ansond 0:137634ff4186 32 #include POLARSSL_CONFIG_FILE
ansond 0:137634ff4186 33 #endif
ansond 0:137634ff4186 34
ansond 0:137634ff4186 35 #if defined(POLARSSL_ECDSA_C)
ansond 0:137634ff4186 36
ansond 0:137634ff4186 37 #include "polarssl/ecdsa.h"
ansond 0:137634ff4186 38 #include "polarssl/asn1write.h"
ansond 0:137634ff4186 39
ansond 0:137634ff4186 40 #include <string.h>
ansond 0:137634ff4186 41
ansond 0:137634ff4186 42 #if defined(POLARSSL_ECDSA_DETERMINISTIC)
ansond 0:137634ff4186 43 #include "polarssl/hmac_drbg.h"
ansond 0:137634ff4186 44 #endif
ansond 0:137634ff4186 45
ansond 0:137634ff4186 46 #if defined(POLARSSL_ECDSA_DETERMINISTIC)
ansond 0:137634ff4186 47 /*
ansond 0:137634ff4186 48 * This a hopefully temporary compatibility function.
ansond 0:137634ff4186 49 *
ansond 0:137634ff4186 50 * Since we can't ensure the caller will pass a valid md_alg before the next
ansond 0:137634ff4186 51 * interface change, try to pick up a decent md by size.
ansond 0:137634ff4186 52 *
ansond 0:137634ff4186 53 * Argument is the minimum size in bytes of the MD output.
ansond 0:137634ff4186 54 */
ansond 0:137634ff4186 55 static const md_info_t *md_info_by_size( size_t min_size )
ansond 0:137634ff4186 56 {
ansond 0:137634ff4186 57 const md_info_t *md_cur, *md_picked = NULL;
ansond 0:137634ff4186 58 const int *md_alg;
ansond 0:137634ff4186 59
ansond 0:137634ff4186 60 for( md_alg = md_list(); *md_alg != 0; md_alg++ )
ansond 0:137634ff4186 61 {
ansond 0:137634ff4186 62 if( ( md_cur = md_info_from_type( (md_type_t) *md_alg ) ) == NULL ||
ansond 0:137634ff4186 63 (size_t) md_cur->size < min_size ||
ansond 0:137634ff4186 64 ( md_picked != NULL && md_cur->size > md_picked->size ) )
ansond 0:137634ff4186 65 continue;
ansond 0:137634ff4186 66
ansond 0:137634ff4186 67 md_picked = md_cur;
ansond 0:137634ff4186 68 }
ansond 0:137634ff4186 69
ansond 0:137634ff4186 70 return( md_picked );
ansond 0:137634ff4186 71 }
ansond 0:137634ff4186 72 #endif /* POLARSSL_ECDSA_DETERMINISTIC */
ansond 0:137634ff4186 73
ansond 0:137634ff4186 74 /*
ansond 0:137634ff4186 75 * Derive a suitable integer for group grp from a buffer of length len
ansond 0:137634ff4186 76 * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3
ansond 0:137634ff4186 77 */
ansond 0:137634ff4186 78 static int derive_mpi( const ecp_group *grp, mpi *x,
ansond 0:137634ff4186 79 const unsigned char *buf, size_t blen )
ansond 0:137634ff4186 80 {
ansond 0:137634ff4186 81 int ret;
ansond 0:137634ff4186 82 size_t n_size = ( grp->nbits + 7 ) / 8;
ansond 0:137634ff4186 83 size_t use_size = blen > n_size ? n_size : blen;
ansond 0:137634ff4186 84
ansond 0:137634ff4186 85 MPI_CHK( mpi_read_binary( x, buf, use_size ) );
ansond 0:137634ff4186 86 if( use_size * 8 > grp->nbits )
ansond 0:137634ff4186 87 MPI_CHK( mpi_shift_r( x, use_size * 8 - grp->nbits ) );
ansond 0:137634ff4186 88
ansond 0:137634ff4186 89 /* While at it, reduce modulo N */
ansond 0:137634ff4186 90 if( mpi_cmp_mpi( x, &grp->N ) >= 0 )
ansond 0:137634ff4186 91 MPI_CHK( mpi_sub_mpi( x, x, &grp->N ) );
ansond 0:137634ff4186 92
ansond 0:137634ff4186 93 cleanup:
ansond 0:137634ff4186 94 return( ret );
ansond 0:137634ff4186 95 }
ansond 0:137634ff4186 96
ansond 0:137634ff4186 97 /*
ansond 0:137634ff4186 98 * Compute ECDSA signature of a hashed message (SEC1 4.1.3)
ansond 0:137634ff4186 99 * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message)
ansond 0:137634ff4186 100 */
ansond 0:137634ff4186 101 int ecdsa_sign( ecp_group *grp, mpi *r, mpi *s,
ansond 0:137634ff4186 102 const mpi *d, const unsigned char *buf, size_t blen,
ansond 0:137634ff4186 103 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
ansond 0:137634ff4186 104 {
ansond 0:137634ff4186 105 int ret, key_tries, sign_tries, blind_tries;
ansond 0:137634ff4186 106 ecp_point R;
ansond 0:137634ff4186 107 mpi k, e, t;
ansond 0:137634ff4186 108
ansond 0:137634ff4186 109 /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
ansond 0:137634ff4186 110 if( grp->N.p == NULL )
ansond 0:137634ff4186 111 return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
ansond 0:137634ff4186 112
ansond 0:137634ff4186 113 ecp_point_init( &R );
ansond 0:137634ff4186 114 mpi_init( &k ); mpi_init( &e ); mpi_init( &t );
ansond 0:137634ff4186 115
ansond 0:137634ff4186 116 sign_tries = 0;
ansond 0:137634ff4186 117 do
ansond 0:137634ff4186 118 {
ansond 0:137634ff4186 119 /*
ansond 0:137634ff4186 120 * Steps 1-3: generate a suitable ephemeral keypair
ansond 0:137634ff4186 121 * and set r = xR mod n
ansond 0:137634ff4186 122 */
ansond 0:137634ff4186 123 key_tries = 0;
ansond 0:137634ff4186 124 do
ansond 0:137634ff4186 125 {
ansond 0:137634ff4186 126 MPI_CHK( ecp_gen_keypair( grp, &k, &R, f_rng, p_rng ) );
ansond 0:137634ff4186 127 MPI_CHK( mpi_mod_mpi( r, &R.X, &grp->N ) );
ansond 0:137634ff4186 128
ansond 0:137634ff4186 129 if( key_tries++ > 10 )
ansond 0:137634ff4186 130 {
ansond 0:137634ff4186 131 ret = POLARSSL_ERR_ECP_RANDOM_FAILED;
ansond 0:137634ff4186 132 goto cleanup;
ansond 0:137634ff4186 133 }
ansond 0:137634ff4186 134 }
ansond 0:137634ff4186 135 while( mpi_cmp_int( r, 0 ) == 0 );
ansond 0:137634ff4186 136
ansond 0:137634ff4186 137 /*
ansond 0:137634ff4186 138 * Step 5: derive MPI from hashed message
ansond 0:137634ff4186 139 */
ansond 0:137634ff4186 140 MPI_CHK( derive_mpi( grp, &e, buf, blen ) );
ansond 0:137634ff4186 141
ansond 0:137634ff4186 142 /*
ansond 0:137634ff4186 143 * Generate a random value to blind inv_mod in next step,
ansond 0:137634ff4186 144 * avoiding a potential timing leak.
ansond 0:137634ff4186 145 */
ansond 0:137634ff4186 146 blind_tries = 0;
ansond 0:137634ff4186 147 do
ansond 0:137634ff4186 148 {
ansond 0:137634ff4186 149 size_t n_size = ( grp->nbits + 7 ) / 8;
ansond 0:137634ff4186 150 MPI_CHK( mpi_fill_random( &t, n_size, f_rng, p_rng ) );
ansond 0:137634ff4186 151 MPI_CHK( mpi_shift_r( &t, 8 * n_size - grp->nbits ) );
ansond 0:137634ff4186 152
ansond 0:137634ff4186 153 /* See ecp_gen_keypair() */
ansond 0:137634ff4186 154 if( ++blind_tries > 30 )
ansond 0:137634ff4186 155 return( POLARSSL_ERR_ECP_RANDOM_FAILED );
ansond 0:137634ff4186 156 }
ansond 0:137634ff4186 157 while( mpi_cmp_int( &t, 1 ) < 0 ||
ansond 0:137634ff4186 158 mpi_cmp_mpi( &t, &grp->N ) >= 0 );
ansond 0:137634ff4186 159
ansond 0:137634ff4186 160 /*
ansond 0:137634ff4186 161 * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n
ansond 0:137634ff4186 162 */
ansond 0:137634ff4186 163 MPI_CHK( mpi_mul_mpi( s, r, d ) );
ansond 0:137634ff4186 164 MPI_CHK( mpi_add_mpi( &e, &e, s ) );
ansond 0:137634ff4186 165 MPI_CHK( mpi_mul_mpi( &e, &e, &t ) );
ansond 0:137634ff4186 166 MPI_CHK( mpi_mul_mpi( &k, &k, &t ) );
ansond 0:137634ff4186 167 MPI_CHK( mpi_inv_mod( s, &k, &grp->N ) );
ansond 0:137634ff4186 168 MPI_CHK( mpi_mul_mpi( s, s, &e ) );
ansond 0:137634ff4186 169 MPI_CHK( mpi_mod_mpi( s, s, &grp->N ) );
ansond 0:137634ff4186 170
ansond 0:137634ff4186 171 if( sign_tries++ > 10 )
ansond 0:137634ff4186 172 {
ansond 0:137634ff4186 173 ret = POLARSSL_ERR_ECP_RANDOM_FAILED;
ansond 0:137634ff4186 174 goto cleanup;
ansond 0:137634ff4186 175 }
ansond 0:137634ff4186 176 }
ansond 0:137634ff4186 177 while( mpi_cmp_int( s, 0 ) == 0 );
ansond 0:137634ff4186 178
ansond 0:137634ff4186 179 cleanup:
ansond 0:137634ff4186 180 ecp_point_free( &R );
ansond 0:137634ff4186 181 mpi_free( &k ); mpi_free( &e ); mpi_free( &t );
ansond 0:137634ff4186 182
ansond 0:137634ff4186 183 return( ret );
ansond 0:137634ff4186 184 }
ansond 0:137634ff4186 185
ansond 0:137634ff4186 186 #if defined(POLARSSL_ECDSA_DETERMINISTIC)
ansond 0:137634ff4186 187 /*
ansond 0:137634ff4186 188 * Deterministic signature wrapper
ansond 0:137634ff4186 189 */
ansond 0:137634ff4186 190 int ecdsa_sign_det( ecp_group *grp, mpi *r, mpi *s,
ansond 0:137634ff4186 191 const mpi *d, const unsigned char *buf, size_t blen,
ansond 0:137634ff4186 192 md_type_t md_alg )
ansond 0:137634ff4186 193 {
ansond 0:137634ff4186 194 int ret;
ansond 0:137634ff4186 195 hmac_drbg_context rng_ctx;
ansond 0:137634ff4186 196 unsigned char data[2 * POLARSSL_ECP_MAX_BYTES];
ansond 0:137634ff4186 197 size_t grp_len = ( grp->nbits + 7 ) / 8;
ansond 0:137634ff4186 198 const md_info_t *md_info;
ansond 0:137634ff4186 199 mpi h;
ansond 0:137634ff4186 200
ansond 0:137634ff4186 201 /* Temporary fallback */
ansond 0:137634ff4186 202 if( md_alg == POLARSSL_MD_NONE )
ansond 0:137634ff4186 203 md_info = md_info_by_size( blen );
ansond 0:137634ff4186 204 else
ansond 0:137634ff4186 205 md_info = md_info_from_type( md_alg );
ansond 0:137634ff4186 206
ansond 0:137634ff4186 207 if( md_info == NULL )
ansond 0:137634ff4186 208 return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
ansond 0:137634ff4186 209
ansond 0:137634ff4186 210 mpi_init( &h );
ansond 0:137634ff4186 211 memset( &rng_ctx, 0, sizeof( hmac_drbg_context ) );
ansond 0:137634ff4186 212
ansond 0:137634ff4186 213 /* Use private key and message hash (reduced) to initialize HMAC_DRBG */
ansond 0:137634ff4186 214 MPI_CHK( mpi_write_binary( d, data, grp_len ) );
ansond 0:137634ff4186 215 MPI_CHK( derive_mpi( grp, &h, buf, blen ) );
ansond 0:137634ff4186 216 MPI_CHK( mpi_write_binary( &h, data + grp_len, grp_len ) );
ansond 0:137634ff4186 217 hmac_drbg_init_buf( &rng_ctx, md_info, data, 2 * grp_len );
ansond 0:137634ff4186 218
ansond 0:137634ff4186 219 ret = ecdsa_sign( grp, r, s, d, buf, blen,
ansond 0:137634ff4186 220 hmac_drbg_random, &rng_ctx );
ansond 0:137634ff4186 221
ansond 0:137634ff4186 222 cleanup:
ansond 0:137634ff4186 223 hmac_drbg_free( &rng_ctx );
ansond 0:137634ff4186 224 mpi_free( &h );
ansond 0:137634ff4186 225
ansond 0:137634ff4186 226 return( ret );
ansond 0:137634ff4186 227 }
ansond 0:137634ff4186 228 #endif /* POLARSSL_ECDSA_DETERMINISTIC */
ansond 0:137634ff4186 229
ansond 0:137634ff4186 230 /*
ansond 0:137634ff4186 231 * Verify ECDSA signature of hashed message (SEC1 4.1.4)
ansond 0:137634ff4186 232 * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message)
ansond 0:137634ff4186 233 */
ansond 0:137634ff4186 234 int ecdsa_verify( ecp_group *grp,
ansond 0:137634ff4186 235 const unsigned char *buf, size_t blen,
ansond 0:137634ff4186 236 const ecp_point *Q, const mpi *r, const mpi *s)
ansond 0:137634ff4186 237 {
ansond 0:137634ff4186 238 int ret;
ansond 0:137634ff4186 239 mpi e, s_inv, u1, u2;
ansond 0:137634ff4186 240 ecp_point R, P;
ansond 0:137634ff4186 241
ansond 0:137634ff4186 242 ecp_point_init( &R ); ecp_point_init( &P );
ansond 0:137634ff4186 243 mpi_init( &e ); mpi_init( &s_inv ); mpi_init( &u1 ); mpi_init( &u2 );
ansond 0:137634ff4186 244
ansond 0:137634ff4186 245 /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
ansond 0:137634ff4186 246 if( grp->N.p == NULL )
ansond 0:137634ff4186 247 return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
ansond 0:137634ff4186 248
ansond 0:137634ff4186 249 /*
ansond 0:137634ff4186 250 * Step 1: make sure r and s are in range 1..n-1
ansond 0:137634ff4186 251 */
ansond 0:137634ff4186 252 if( mpi_cmp_int( r, 1 ) < 0 || mpi_cmp_mpi( r, &grp->N ) >= 0 ||
ansond 0:137634ff4186 253 mpi_cmp_int( s, 1 ) < 0 || mpi_cmp_mpi( s, &grp->N ) >= 0 )
ansond 0:137634ff4186 254 {
ansond 0:137634ff4186 255 ret = POLARSSL_ERR_ECP_VERIFY_FAILED;
ansond 0:137634ff4186 256 goto cleanup;
ansond 0:137634ff4186 257 }
ansond 0:137634ff4186 258
ansond 0:137634ff4186 259 /*
ansond 0:137634ff4186 260 * Additional precaution: make sure Q is valid
ansond 0:137634ff4186 261 */
ansond 0:137634ff4186 262 MPI_CHK( ecp_check_pubkey( grp, Q ) );
ansond 0:137634ff4186 263
ansond 0:137634ff4186 264 /*
ansond 0:137634ff4186 265 * Step 3: derive MPI from hashed message
ansond 0:137634ff4186 266 */
ansond 0:137634ff4186 267 MPI_CHK( derive_mpi( grp, &e, buf, blen ) );
ansond 0:137634ff4186 268
ansond 0:137634ff4186 269 /*
ansond 0:137634ff4186 270 * Step 4: u1 = e / s mod n, u2 = r / s mod n
ansond 0:137634ff4186 271 */
ansond 0:137634ff4186 272 MPI_CHK( mpi_inv_mod( &s_inv, s, &grp->N ) );
ansond 0:137634ff4186 273
ansond 0:137634ff4186 274 MPI_CHK( mpi_mul_mpi( &u1, &e, &s_inv ) );
ansond 0:137634ff4186 275 MPI_CHK( mpi_mod_mpi( &u1, &u1, &grp->N ) );
ansond 0:137634ff4186 276
ansond 0:137634ff4186 277 MPI_CHK( mpi_mul_mpi( &u2, r, &s_inv ) );
ansond 0:137634ff4186 278 MPI_CHK( mpi_mod_mpi( &u2, &u2, &grp->N ) );
ansond 0:137634ff4186 279
ansond 0:137634ff4186 280 /*
ansond 0:137634ff4186 281 * Step 5: R = u1 G + u2 Q
ansond 0:137634ff4186 282 *
ansond 0:137634ff4186 283 * Since we're not using any secret data, no need to pass a RNG to
ansond 0:137634ff4186 284 * ecp_mul() for countermesures.
ansond 0:137634ff4186 285 */
ansond 0:137634ff4186 286 MPI_CHK( ecp_mul( grp, &R, &u1, &grp->G, NULL, NULL ) );
ansond 0:137634ff4186 287 MPI_CHK( ecp_mul( grp, &P, &u2, Q, NULL, NULL ) );
ansond 0:137634ff4186 288 MPI_CHK( ecp_add( grp, &R, &R, &P ) );
ansond 0:137634ff4186 289
ansond 0:137634ff4186 290 if( ecp_is_zero( &R ) )
ansond 0:137634ff4186 291 {
ansond 0:137634ff4186 292 ret = POLARSSL_ERR_ECP_VERIFY_FAILED;
ansond 0:137634ff4186 293 goto cleanup;
ansond 0:137634ff4186 294 }
ansond 0:137634ff4186 295
ansond 0:137634ff4186 296 /*
ansond 0:137634ff4186 297 * Step 6: convert xR to an integer (no-op)
ansond 0:137634ff4186 298 * Step 7: reduce xR mod n (gives v)
ansond 0:137634ff4186 299 */
ansond 0:137634ff4186 300 MPI_CHK( mpi_mod_mpi( &R.X, &R.X, &grp->N ) );
ansond 0:137634ff4186 301
ansond 0:137634ff4186 302 /*
ansond 0:137634ff4186 303 * Step 8: check if v (that is, R.X) is equal to r
ansond 0:137634ff4186 304 */
ansond 0:137634ff4186 305 if( mpi_cmp_mpi( &R.X, r ) != 0 )
ansond 0:137634ff4186 306 {
ansond 0:137634ff4186 307 ret = POLARSSL_ERR_ECP_VERIFY_FAILED;
ansond 0:137634ff4186 308 goto cleanup;
ansond 0:137634ff4186 309 }
ansond 0:137634ff4186 310
ansond 0:137634ff4186 311 cleanup:
ansond 0:137634ff4186 312 ecp_point_free( &R ); ecp_point_free( &P );
ansond 0:137634ff4186 313 mpi_free( &e ); mpi_free( &s_inv ); mpi_free( &u1 ); mpi_free( &u2 );
ansond 0:137634ff4186 314
ansond 0:137634ff4186 315 return( ret );
ansond 0:137634ff4186 316 }
ansond 0:137634ff4186 317
ansond 0:137634ff4186 318 /*
ansond 0:137634ff4186 319 * RFC 4492 page 20:
ansond 0:137634ff4186 320 *
ansond 0:137634ff4186 321 * Ecdsa-Sig-Value ::= SEQUENCE {
ansond 0:137634ff4186 322 * r INTEGER,
ansond 0:137634ff4186 323 * s INTEGER
ansond 0:137634ff4186 324 * }
ansond 0:137634ff4186 325 *
ansond 0:137634ff4186 326 * Size is at most
ansond 0:137634ff4186 327 * 1 (tag) + 1 (len) + 1 (initial 0) + ECP_MAX_BYTES for each of r and s,
ansond 0:137634ff4186 328 * twice that + 1 (tag) + 2 (len) for the sequence
ansond 0:137634ff4186 329 * (assuming ECP_MAX_BYTES is less than 126 for r and s,
ansond 0:137634ff4186 330 * and less than 124 (total len <= 255) for the sequence)
ansond 0:137634ff4186 331 */
ansond 0:137634ff4186 332 #if POLARSSL_ECP_MAX_BYTES > 124
ansond 0:137634ff4186 333 #error "POLARSSL_ECP_MAX_BYTES bigger than expected, please fix MAX_SIG_LEN"
ansond 0:137634ff4186 334 #endif
ansond 0:137634ff4186 335 #define MAX_SIG_LEN ( 3 + 2 * ( 3 + POLARSSL_ECP_MAX_BYTES ) )
ansond 0:137634ff4186 336
ansond 0:137634ff4186 337 /*
ansond 0:137634ff4186 338 * Convert a signature (given by context) to ASN.1
ansond 0:137634ff4186 339 */
ansond 0:137634ff4186 340 static int ecdsa_signature_to_asn1( ecdsa_context *ctx,
ansond 0:137634ff4186 341 unsigned char *sig, size_t *slen )
ansond 0:137634ff4186 342 {
ansond 0:137634ff4186 343 int ret;
ansond 0:137634ff4186 344 unsigned char buf[MAX_SIG_LEN];
ansond 0:137634ff4186 345 unsigned char *p = buf + sizeof( buf );
ansond 0:137634ff4186 346 size_t len = 0;
ansond 0:137634ff4186 347
ansond 0:137634ff4186 348 ASN1_CHK_ADD( len, asn1_write_mpi( &p, buf, &ctx->s ) );
ansond 0:137634ff4186 349 ASN1_CHK_ADD( len, asn1_write_mpi( &p, buf, &ctx->r ) );
ansond 0:137634ff4186 350
ansond 0:137634ff4186 351 ASN1_CHK_ADD( len, asn1_write_len( &p, buf, len ) );
ansond 0:137634ff4186 352 ASN1_CHK_ADD( len, asn1_write_tag( &p, buf,
ansond 0:137634ff4186 353 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
ansond 0:137634ff4186 354
ansond 0:137634ff4186 355 memcpy( sig, p, len );
ansond 0:137634ff4186 356 *slen = len;
ansond 0:137634ff4186 357
ansond 0:137634ff4186 358 return( 0 );
ansond 0:137634ff4186 359 }
ansond 0:137634ff4186 360
ansond 0:137634ff4186 361 /*
ansond 0:137634ff4186 362 * Compute and write signature
ansond 0:137634ff4186 363 */
ansond 0:137634ff4186 364 int ecdsa_write_signature( ecdsa_context *ctx,
ansond 0:137634ff4186 365 const unsigned char *hash, size_t hlen,
ansond 0:137634ff4186 366 unsigned char *sig, size_t *slen,
ansond 0:137634ff4186 367 int (*f_rng)(void *, unsigned char *, size_t),
ansond 0:137634ff4186 368 void *p_rng )
ansond 0:137634ff4186 369 {
ansond 0:137634ff4186 370 int ret;
ansond 0:137634ff4186 371
ansond 0:137634ff4186 372 if( ( ret = ecdsa_sign( &ctx->grp, &ctx->r, &ctx->s, &ctx->d,
ansond 0:137634ff4186 373 hash, hlen, f_rng, p_rng ) ) != 0 )
ansond 0:137634ff4186 374 {
ansond 0:137634ff4186 375 return( ret );
ansond 0:137634ff4186 376 }
ansond 0:137634ff4186 377
ansond 0:137634ff4186 378 return( ecdsa_signature_to_asn1( ctx, sig, slen ) );
ansond 0:137634ff4186 379 }
ansond 0:137634ff4186 380
ansond 0:137634ff4186 381 #if defined(POLARSSL_ECDSA_DETERMINISTIC)
ansond 0:137634ff4186 382 /*
ansond 0:137634ff4186 383 * Compute and write signature deterministically
ansond 0:137634ff4186 384 */
ansond 0:137634ff4186 385 int ecdsa_write_signature_det( ecdsa_context *ctx,
ansond 0:137634ff4186 386 const unsigned char *hash, size_t hlen,
ansond 0:137634ff4186 387 unsigned char *sig, size_t *slen,
ansond 0:137634ff4186 388 md_type_t md_alg )
ansond 0:137634ff4186 389 {
ansond 0:137634ff4186 390 int ret;
ansond 0:137634ff4186 391
ansond 0:137634ff4186 392 if( ( ret = ecdsa_sign_det( &ctx->grp, &ctx->r, &ctx->s, &ctx->d,
ansond 0:137634ff4186 393 hash, hlen, md_alg ) ) != 0 )
ansond 0:137634ff4186 394 {
ansond 0:137634ff4186 395 return( ret );
ansond 0:137634ff4186 396 }
ansond 0:137634ff4186 397
ansond 0:137634ff4186 398 return( ecdsa_signature_to_asn1( ctx, sig, slen ) );
ansond 0:137634ff4186 399 }
ansond 0:137634ff4186 400 #endif /* POLARSSL_ECDSA_DETERMINISTIC */
ansond 0:137634ff4186 401
ansond 0:137634ff4186 402 /*
ansond 0:137634ff4186 403 * Read and check signature
ansond 0:137634ff4186 404 */
ansond 0:137634ff4186 405 int ecdsa_read_signature( ecdsa_context *ctx,
ansond 0:137634ff4186 406 const unsigned char *hash, size_t hlen,
ansond 0:137634ff4186 407 const unsigned char *sig, size_t slen )
ansond 0:137634ff4186 408 {
ansond 0:137634ff4186 409 int ret;
ansond 0:137634ff4186 410 unsigned char *p = (unsigned char *) sig;
ansond 0:137634ff4186 411 const unsigned char *end = sig + slen;
ansond 0:137634ff4186 412 size_t len;
ansond 0:137634ff4186 413
ansond 0:137634ff4186 414 if( ( ret = asn1_get_tag( &p, end, &len,
ansond 0:137634ff4186 415 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
ansond 0:137634ff4186 416 {
ansond 0:137634ff4186 417 return( POLARSSL_ERR_ECP_BAD_INPUT_DATA + ret );
ansond 0:137634ff4186 418 }
ansond 0:137634ff4186 419
ansond 0:137634ff4186 420 if( p + len != end )
ansond 0:137634ff4186 421 return( POLARSSL_ERR_ECP_BAD_INPUT_DATA +
ansond 0:137634ff4186 422 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
ansond 0:137634ff4186 423
ansond 0:137634ff4186 424 if( ( ret = asn1_get_mpi( &p, end, &ctx->r ) ) != 0 ||
ansond 0:137634ff4186 425 ( ret = asn1_get_mpi( &p, end, &ctx->s ) ) != 0 )
ansond 0:137634ff4186 426 return( POLARSSL_ERR_ECP_BAD_INPUT_DATA + ret );
ansond 0:137634ff4186 427
ansond 0:137634ff4186 428 if( ( ret = ecdsa_verify( &ctx->grp, hash, hlen,
ansond 0:137634ff4186 429 &ctx->Q, &ctx->r, &ctx->s ) ) != 0 )
ansond 0:137634ff4186 430 return( ret );
ansond 0:137634ff4186 431
ansond 0:137634ff4186 432 if( p != end )
ansond 0:137634ff4186 433 return( POLARSSL_ERR_ECP_SIG_LEN_MISMATCH );
ansond 0:137634ff4186 434
ansond 0:137634ff4186 435 return( 0 );
ansond 0:137634ff4186 436 }
ansond 0:137634ff4186 437
ansond 0:137634ff4186 438 /*
ansond 0:137634ff4186 439 * Generate key pair
ansond 0:137634ff4186 440 */
ansond 0:137634ff4186 441 int ecdsa_genkey( ecdsa_context *ctx, ecp_group_id gid,
ansond 0:137634ff4186 442 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
ansond 0:137634ff4186 443 {
ansond 0:137634ff4186 444 return( ecp_use_known_dp( &ctx->grp, gid ) ||
ansond 0:137634ff4186 445 ecp_gen_keypair( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) );
ansond 0:137634ff4186 446 }
ansond 0:137634ff4186 447
ansond 0:137634ff4186 448 /*
ansond 0:137634ff4186 449 * Set context from an ecp_keypair
ansond 0:137634ff4186 450 */
ansond 0:137634ff4186 451 int ecdsa_from_keypair( ecdsa_context *ctx, const ecp_keypair *key )
ansond 0:137634ff4186 452 {
ansond 0:137634ff4186 453 int ret;
ansond 0:137634ff4186 454
ansond 0:137634ff4186 455 if( ( ret = ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 ||
ansond 0:137634ff4186 456 ( ret = mpi_copy( &ctx->d, &key->d ) ) != 0 ||
ansond 0:137634ff4186 457 ( ret = ecp_copy( &ctx->Q, &key->Q ) ) != 0 )
ansond 0:137634ff4186 458 {
ansond 0:137634ff4186 459 ecdsa_free( ctx );
ansond 0:137634ff4186 460 }
ansond 0:137634ff4186 461
ansond 0:137634ff4186 462 return( ret );
ansond 0:137634ff4186 463 }
ansond 0:137634ff4186 464
ansond 0:137634ff4186 465 /*
ansond 0:137634ff4186 466 * Initialize context
ansond 0:137634ff4186 467 */
ansond 0:137634ff4186 468 void ecdsa_init( ecdsa_context *ctx )
ansond 0:137634ff4186 469 {
ansond 0:137634ff4186 470 ecp_group_init( &ctx->grp );
ansond 0:137634ff4186 471 mpi_init( &ctx->d );
ansond 0:137634ff4186 472 ecp_point_init( &ctx->Q );
ansond 0:137634ff4186 473 mpi_init( &ctx->r );
ansond 0:137634ff4186 474 mpi_init( &ctx->s );
ansond 0:137634ff4186 475 }
ansond 0:137634ff4186 476
ansond 0:137634ff4186 477 /*
ansond 0:137634ff4186 478 * Free context
ansond 0:137634ff4186 479 */
ansond 0:137634ff4186 480 void ecdsa_free( ecdsa_context *ctx )
ansond 0:137634ff4186 481 {
ansond 0:137634ff4186 482 ecp_group_free( &ctx->grp );
ansond 0:137634ff4186 483 mpi_free( &ctx->d );
ansond 0:137634ff4186 484 ecp_point_free( &ctx->Q );
ansond 0:137634ff4186 485 mpi_free( &ctx->r );
ansond 0:137634ff4186 486 mpi_free( &ctx->s );
ansond 0:137634ff4186 487 }
ansond 0:137634ff4186 488
ansond 0:137634ff4186 489 #if defined(POLARSSL_SELF_TEST)
ansond 0:137634ff4186 490
ansond 0:137634ff4186 491 /*
ansond 0:137634ff4186 492 * Checkup routine
ansond 0:137634ff4186 493 */
ansond 0:137634ff4186 494 int ecdsa_self_test( int verbose )
ansond 0:137634ff4186 495 {
ansond 0:137634ff4186 496 ((void) verbose );
ansond 0:137634ff4186 497 return( 0 );
ansond 0:137634ff4186 498 }
ansond 0:137634ff4186 499
ansond 0:137634ff4186 500 #endif /* POLARSSL_SELF_TEST */
ansond 0:137634ff4186 501
ansond 0:137634ff4186 502 #endif /* POLARSSL_ECDSA_C */
ansond 0:137634ff4186 503