mbedtls ported to mbed-classic
Fork of mbedtls by
Embed:
(wiki syntax)
Show/hide line numbers
ecdsa.c
00001 /* 00002 * Elliptic curve DSA 00003 * 00004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 00005 * SPDX-License-Identifier: Apache-2.0 00006 * 00007 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00008 * not use this file except in compliance with the License. 00009 * You may obtain a copy of the License at 00010 * 00011 * http://www.apache.org/licenses/LICENSE-2.0 00012 * 00013 * Unless required by applicable law or agreed to in writing, software 00014 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00015 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00016 * See the License for the specific language governing permissions and 00017 * limitations under the License. 00018 * 00019 * This file is part of mbed TLS (https://tls.mbed.org) 00020 */ 00021 00022 /* 00023 * References: 00024 * 00025 * SEC1 http://www.secg.org/index.php?action=secg,docs_secg 00026 */ 00027 00028 #if !defined(MBEDTLS_CONFIG_FILE) 00029 #include "mbedtls/config.h" 00030 #else 00031 #include MBEDTLS_CONFIG_FILE 00032 #endif 00033 00034 #if defined(MBEDTLS_ECDSA_C) 00035 00036 #include "mbedtls/ecdsa.h" 00037 #include "mbedtls/asn1write.h" 00038 00039 #include <string.h> 00040 00041 #if defined(MBEDTLS_ECDSA_DETERMINISTIC) 00042 #include "mbedtls/hmac_drbg.h" 00043 #endif 00044 00045 /* 00046 * Derive a suitable integer for group grp from a buffer of length len 00047 * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3 00048 */ 00049 static int derive_mpi( const mbedtls_ecp_group *grp, mbedtls_mpi *x, 00050 const unsigned char *buf, size_t blen ) 00051 { 00052 int ret; 00053 size_t n_size = ( grp->nbits + 7 ) / 8; 00054 size_t use_size = blen > n_size ? n_size : blen; 00055 00056 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( x, buf, use_size ) ); 00057 if( use_size * 8 > grp->nbits ) 00058 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( x, use_size * 8 - grp->nbits ) ); 00059 00060 /* While at it, reduce modulo N */ 00061 if( mbedtls_mpi_cmp_mpi( x, &grp->N ) >= 0 ) 00062 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( x, x, &grp->N ) ); 00063 00064 cleanup: 00065 return( ret ); 00066 } 00067 00068 /* 00069 * Compute ECDSA signature of a hashed message (SEC1 4.1.3) 00070 * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message) 00071 */ 00072 int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, 00073 const mbedtls_mpi *d, const unsigned char *buf, size_t blen, 00074 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) 00075 { 00076 int ret, key_tries, sign_tries, blind_tries; 00077 mbedtls_ecp_point R; 00078 mbedtls_mpi k, e, t; 00079 00080 /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ 00081 if( grp->N .p == NULL ) 00082 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 00083 00084 mbedtls_ecp_point_init( &R ); 00085 mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t ); 00086 00087 sign_tries = 0; 00088 do 00089 { 00090 /* 00091 * Steps 1-3: generate a suitable ephemeral keypair 00092 * and set r = xR mod n 00093 */ 00094 key_tries = 0; 00095 do 00096 { 00097 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair( grp, &k, &R, f_rng, p_rng ) ); 00098 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( r, &R.X , &grp->N ) ); 00099 00100 if( key_tries++ > 10 ) 00101 { 00102 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; 00103 goto cleanup; 00104 } 00105 } 00106 while( mbedtls_mpi_cmp_int( r, 0 ) == 0 ); 00107 00108 /* 00109 * Step 5: derive MPI from hashed message 00110 */ 00111 MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); 00112 00113 /* 00114 * Generate a random value to blind inv_mod in next step, 00115 * avoiding a potential timing leak. 00116 */ 00117 blind_tries = 0; 00118 do 00119 { 00120 size_t n_size = ( grp->nbits + 7 ) / 8; 00121 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &t, n_size, f_rng, p_rng ) ); 00122 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &t, 8 * n_size - grp->nbits ) ); 00123 00124 /* See mbedtls_ecp_gen_keypair() */ 00125 if( ++blind_tries > 30 ) 00126 return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); 00127 } 00128 while( mbedtls_mpi_cmp_int( &t, 1 ) < 0 || 00129 mbedtls_mpi_cmp_mpi( &t, &grp->N ) >= 0 ); 00130 00131 /* 00132 * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n 00133 */ 00134 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, r, d ) ); 00135 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) ); 00136 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) ); 00137 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &k, &k, &t ) ); 00138 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, &k, &grp->N ) ); 00139 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) ); 00140 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) ); 00141 00142 if( sign_tries++ > 10 ) 00143 { 00144 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; 00145 goto cleanup; 00146 } 00147 } 00148 while( mbedtls_mpi_cmp_int( s, 0 ) == 0 ); 00149 00150 cleanup: 00151 mbedtls_ecp_point_free( &R ); 00152 mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t ); 00153 00154 return( ret ); 00155 } 00156 00157 #if defined(MBEDTLS_ECDSA_DETERMINISTIC) 00158 /* 00159 * Deterministic signature wrapper 00160 */ 00161 int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, 00162 const mbedtls_mpi *d, const unsigned char *buf, size_t blen, 00163 mbedtls_md_type_t md_alg ) 00164 { 00165 int ret; 00166 mbedtls_hmac_drbg_context rng_ctx; 00167 unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES]; 00168 size_t grp_len = ( grp->nbits + 7 ) / 8; 00169 const mbedtls_md_info_t *md_info; 00170 mbedtls_mpi h; 00171 00172 if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) 00173 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 00174 00175 mbedtls_mpi_init( &h ); 00176 mbedtls_hmac_drbg_init( &rng_ctx ); 00177 00178 /* Use private key and message hash (reduced) to initialize HMAC_DRBG */ 00179 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) ); 00180 MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) ); 00181 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) ); 00182 mbedtls_hmac_drbg_seed_buf( &rng_ctx, md_info, data, 2 * grp_len ); 00183 00184 ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen, 00185 mbedtls_hmac_drbg_random, &rng_ctx ); 00186 00187 cleanup: 00188 mbedtls_hmac_drbg_free( &rng_ctx ); 00189 mbedtls_mpi_free( &h ); 00190 00191 return( ret ); 00192 } 00193 #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ 00194 00195 /* 00196 * Verify ECDSA signature of hashed message (SEC1 4.1.4) 00197 * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message) 00198 */ 00199 int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, 00200 const unsigned char *buf, size_t blen, 00201 const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s) 00202 { 00203 int ret; 00204 mbedtls_mpi e, s_inv, u1, u2; 00205 mbedtls_ecp_point R; 00206 00207 mbedtls_ecp_point_init( &R ); 00208 mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 ); 00209 00210 /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ 00211 if( grp->N .p == NULL ) 00212 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 00213 00214 /* 00215 * Step 1: make sure r and s are in range 1..n-1 00216 */ 00217 if( mbedtls_mpi_cmp_int( r, 1 ) < 0 || mbedtls_mpi_cmp_mpi( r, &grp->N ) >= 0 || 00218 mbedtls_mpi_cmp_int( s, 1 ) < 0 || mbedtls_mpi_cmp_mpi( s, &grp->N ) >= 0 ) 00219 { 00220 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; 00221 goto cleanup; 00222 } 00223 00224 /* 00225 * Additional precaution: make sure Q is valid 00226 */ 00227 MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) ); 00228 00229 /* 00230 * Step 3: derive MPI from hashed message 00231 */ 00232 MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); 00233 00234 /* 00235 * Step 4: u1 = e / s mod n, u2 = r / s mod n 00236 */ 00237 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) ); 00238 00239 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u1, &e, &s_inv ) ); 00240 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u1, &u1, &grp->N ) ); 00241 00242 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u2, r, &s_inv ) ); 00243 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u2, &u2, &grp->N ) ); 00244 00245 /* 00246 * Step 5: R = u1 G + u2 Q 00247 * 00248 * Since we're not using any secret data, no need to pass a RNG to 00249 * mbedtls_ecp_mul() for countermesures. 00250 */ 00251 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, &R, &u1, &grp->G , &u2, Q ) ); 00252 00253 if( mbedtls_ecp_is_zero( &R ) ) 00254 { 00255 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; 00256 goto cleanup; 00257 } 00258 00259 /* 00260 * Step 6: convert xR to an integer (no-op) 00261 * Step 7: reduce xR mod n (gives v) 00262 */ 00263 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &R.X , &R.X , &grp->N ) ); 00264 00265 /* 00266 * Step 8: check if v (that is, R.X) is equal to r 00267 */ 00268 if( mbedtls_mpi_cmp_mpi( &R.X , r ) != 0 ) 00269 { 00270 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; 00271 goto cleanup; 00272 } 00273 00274 cleanup: 00275 mbedtls_ecp_point_free( &R ); 00276 mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv ); mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 ); 00277 00278 return( ret ); 00279 } 00280 00281 /* 00282 * Convert a signature (given by context) to ASN.1 00283 */ 00284 static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s, 00285 unsigned char *sig, size_t *slen ) 00286 { 00287 int ret; 00288 unsigned char buf[MBEDTLS_ECDSA_MAX_LEN]; 00289 unsigned char *p = buf + sizeof( buf ); 00290 size_t len = 0; 00291 00292 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, s ) ); 00293 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, r ) ); 00294 00295 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, buf, len ) ); 00296 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, buf, 00297 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); 00298 00299 memcpy( sig, p, len ); 00300 *slen = len; 00301 00302 return( 0 ); 00303 } 00304 00305 /* 00306 * Compute and write signature 00307 */ 00308 int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, 00309 const unsigned char *hash, size_t hlen, 00310 unsigned char *sig, size_t *slen, 00311 int (*f_rng)(void *, unsigned char *, size_t), 00312 void *p_rng ) 00313 { 00314 int ret; 00315 mbedtls_mpi r, s; 00316 00317 mbedtls_mpi_init( &r ); 00318 mbedtls_mpi_init( &s ); 00319 00320 #if defined(MBEDTLS_ECDSA_DETERMINISTIC) 00321 (void) f_rng; 00322 (void) p_rng; 00323 00324 MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det( &ctx->grp , &r, &s, &ctx->d , 00325 hash, hlen, md_alg ) ); 00326 #else 00327 (void) md_alg; 00328 00329 MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp , &r, &s, &ctx->d , 00330 hash, hlen, f_rng, p_rng ) ); 00331 #endif 00332 00333 MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) ); 00334 00335 cleanup: 00336 mbedtls_mpi_free( &r ); 00337 mbedtls_mpi_free( &s ); 00338 00339 return( ret ); 00340 } 00341 00342 #if ! defined(MBEDTLS_DEPRECATED_REMOVED) && \ 00343 defined(MBEDTLS_ECDSA_DETERMINISTIC) 00344 int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, 00345 const unsigned char *hash, size_t hlen, 00346 unsigned char *sig, size_t *slen, 00347 mbedtls_md_type_t md_alg ) 00348 { 00349 return( mbedtls_ecdsa_write_signature( ctx, md_alg, hash, hlen, sig, slen, 00350 NULL, NULL ) ); 00351 } 00352 #endif 00353 00354 /* 00355 * Read and check signature 00356 */ 00357 int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, 00358 const unsigned char *hash, size_t hlen, 00359 const unsigned char *sig, size_t slen ) 00360 { 00361 int ret; 00362 unsigned char *p = (unsigned char *) sig; 00363 const unsigned char *end = sig + slen; 00364 size_t len; 00365 mbedtls_mpi r, s; 00366 00367 mbedtls_mpi_init( &r ); 00368 mbedtls_mpi_init( &s ); 00369 00370 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, 00371 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) 00372 { 00373 ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 00374 goto cleanup; 00375 } 00376 00377 if( p + len != end ) 00378 { 00379 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA + 00380 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; 00381 goto cleanup; 00382 } 00383 00384 if( ( ret = mbedtls_asn1_get_mpi( &p, end, &r ) ) != 0 || 00385 ( ret = mbedtls_asn1_get_mpi( &p, end, &s ) ) != 0 ) 00386 { 00387 ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 00388 goto cleanup; 00389 } 00390 00391 if( ( ret = mbedtls_ecdsa_verify( &ctx->grp , hash, hlen, 00392 &ctx->Q , &r, &s ) ) != 0 ) 00393 goto cleanup; 00394 00395 if( p != end ) 00396 ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH; 00397 00398 cleanup: 00399 mbedtls_mpi_free( &r ); 00400 mbedtls_mpi_free( &s ); 00401 00402 return( ret ); 00403 } 00404 00405 /* 00406 * Generate key pair 00407 */ 00408 int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, 00409 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) 00410 { 00411 return( mbedtls_ecp_group_load( &ctx->grp , gid ) || 00412 mbedtls_ecp_gen_keypair( &ctx->grp , &ctx->d , &ctx->Q , f_rng, p_rng ) ); 00413 } 00414 00415 /* 00416 * Set context from an mbedtls_ecp_keypair 00417 */ 00418 int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key ) 00419 { 00420 int ret; 00421 00422 if( ( ret = mbedtls_ecp_group_copy( &ctx->grp , &key->grp ) ) != 0 || 00423 ( ret = mbedtls_mpi_copy( &ctx->d , &key->d ) ) != 0 || 00424 ( ret = mbedtls_ecp_copy( &ctx->Q , &key->Q ) ) != 0 ) 00425 { 00426 mbedtls_ecdsa_free( ctx ); 00427 } 00428 00429 return( ret ); 00430 } 00431 00432 /* 00433 * Initialize context 00434 */ 00435 void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ) 00436 { 00437 mbedtls_ecp_keypair_init( ctx ); 00438 } 00439 00440 /* 00441 * Free context 00442 */ 00443 void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ) 00444 { 00445 mbedtls_ecp_keypair_free( ctx ); 00446 } 00447 00448 #endif /* MBEDTLS_ECDSA_C */
Generated on Tue Jul 12 2022 12:52:43 by 1.7.2