BBR 1 Ebene

Committer:
borlanic
Date:
Mon May 14 11:29:06 2018 +0000
Revision:
0:fbdae7e6d805
BBR

Who changed what in which revision?

UserRevisionLine numberNew contents of line
borlanic 0:fbdae7e6d805 1 /*
borlanic 0:fbdae7e6d805 2 * Elliptic curve DSA
borlanic 0:fbdae7e6d805 3 *
borlanic 0:fbdae7e6d805 4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
borlanic 0:fbdae7e6d805 5 * SPDX-License-Identifier: Apache-2.0
borlanic 0:fbdae7e6d805 6 *
borlanic 0:fbdae7e6d805 7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
borlanic 0:fbdae7e6d805 8 * not use this file except in compliance with the License.
borlanic 0:fbdae7e6d805 9 * You may obtain a copy of the License at
borlanic 0:fbdae7e6d805 10 *
borlanic 0:fbdae7e6d805 11 * http://www.apache.org/licenses/LICENSE-2.0
borlanic 0:fbdae7e6d805 12 *
borlanic 0:fbdae7e6d805 13 * Unless required by applicable law or agreed to in writing, software
borlanic 0:fbdae7e6d805 14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
borlanic 0:fbdae7e6d805 15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
borlanic 0:fbdae7e6d805 16 * See the License for the specific language governing permissions and
borlanic 0:fbdae7e6d805 17 * limitations under the License.
borlanic 0:fbdae7e6d805 18 *
borlanic 0:fbdae7e6d805 19 * This file is part of mbed TLS (https://tls.mbed.org)
borlanic 0:fbdae7e6d805 20 */
borlanic 0:fbdae7e6d805 21
borlanic 0:fbdae7e6d805 22 /*
borlanic 0:fbdae7e6d805 23 * References:
borlanic 0:fbdae7e6d805 24 *
borlanic 0:fbdae7e6d805 25 * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
borlanic 0:fbdae7e6d805 26 */
borlanic 0:fbdae7e6d805 27
borlanic 0:fbdae7e6d805 28 #if !defined(MBEDTLS_CONFIG_FILE)
borlanic 0:fbdae7e6d805 29 #include "mbedtls/config.h"
borlanic 0:fbdae7e6d805 30 #else
borlanic 0:fbdae7e6d805 31 #include MBEDTLS_CONFIG_FILE
borlanic 0:fbdae7e6d805 32 #endif
borlanic 0:fbdae7e6d805 33
borlanic 0:fbdae7e6d805 34 #if defined(MBEDTLS_ECDSA_C)
borlanic 0:fbdae7e6d805 35
borlanic 0:fbdae7e6d805 36 #include "mbedtls/ecdsa.h"
borlanic 0:fbdae7e6d805 37 #include "mbedtls/asn1write.h"
borlanic 0:fbdae7e6d805 38
borlanic 0:fbdae7e6d805 39 #include <string.h>
borlanic 0:fbdae7e6d805 40
borlanic 0:fbdae7e6d805 41 #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
borlanic 0:fbdae7e6d805 42 #include "mbedtls/hmac_drbg.h"
borlanic 0:fbdae7e6d805 43 #endif
borlanic 0:fbdae7e6d805 44
borlanic 0:fbdae7e6d805 45 /*
borlanic 0:fbdae7e6d805 46 * Derive a suitable integer for group grp from a buffer of length len
borlanic 0:fbdae7e6d805 47 * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3
borlanic 0:fbdae7e6d805 48 */
borlanic 0:fbdae7e6d805 49 static int derive_mpi( const mbedtls_ecp_group *grp, mbedtls_mpi *x,
borlanic 0:fbdae7e6d805 50 const unsigned char *buf, size_t blen )
borlanic 0:fbdae7e6d805 51 {
borlanic 0:fbdae7e6d805 52 int ret;
borlanic 0:fbdae7e6d805 53 size_t n_size = ( grp->nbits + 7 ) / 8;
borlanic 0:fbdae7e6d805 54 size_t use_size = blen > n_size ? n_size : blen;
borlanic 0:fbdae7e6d805 55
borlanic 0:fbdae7e6d805 56 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( x, buf, use_size ) );
borlanic 0:fbdae7e6d805 57 if( use_size * 8 > grp->nbits )
borlanic 0:fbdae7e6d805 58 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( x, use_size * 8 - grp->nbits ) );
borlanic 0:fbdae7e6d805 59
borlanic 0:fbdae7e6d805 60 /* While at it, reduce modulo N */
borlanic 0:fbdae7e6d805 61 if( mbedtls_mpi_cmp_mpi( x, &grp->N ) >= 0 )
borlanic 0:fbdae7e6d805 62 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( x, x, &grp->N ) );
borlanic 0:fbdae7e6d805 63
borlanic 0:fbdae7e6d805 64 cleanup:
borlanic 0:fbdae7e6d805 65 return( ret );
borlanic 0:fbdae7e6d805 66 }
borlanic 0:fbdae7e6d805 67
borlanic 0:fbdae7e6d805 68 #if !defined(MBEDTLS_ECDSA_SIGN_ALT)
borlanic 0:fbdae7e6d805 69 /*
borlanic 0:fbdae7e6d805 70 * Compute ECDSA signature of a hashed message (SEC1 4.1.3)
borlanic 0:fbdae7e6d805 71 * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message)
borlanic 0:fbdae7e6d805 72 */
borlanic 0:fbdae7e6d805 73 int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
borlanic 0:fbdae7e6d805 74 const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
borlanic 0:fbdae7e6d805 75 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
borlanic 0:fbdae7e6d805 76 {
borlanic 0:fbdae7e6d805 77 int ret, key_tries, sign_tries, blind_tries;
borlanic 0:fbdae7e6d805 78 mbedtls_ecp_point R;
borlanic 0:fbdae7e6d805 79 mbedtls_mpi k, e, t;
borlanic 0:fbdae7e6d805 80
borlanic 0:fbdae7e6d805 81 /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
borlanic 0:fbdae7e6d805 82 if( grp->N.p == NULL )
borlanic 0:fbdae7e6d805 83 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
borlanic 0:fbdae7e6d805 84
borlanic 0:fbdae7e6d805 85 /* Make sure d is in range 1..n-1 */
borlanic 0:fbdae7e6d805 86 if( mbedtls_mpi_cmp_int( d, 1 ) < 0 || mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 )
borlanic 0:fbdae7e6d805 87 return( MBEDTLS_ERR_ECP_INVALID_KEY );
borlanic 0:fbdae7e6d805 88
borlanic 0:fbdae7e6d805 89 mbedtls_ecp_point_init( &R );
borlanic 0:fbdae7e6d805 90 mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t );
borlanic 0:fbdae7e6d805 91
borlanic 0:fbdae7e6d805 92 sign_tries = 0;
borlanic 0:fbdae7e6d805 93 do
borlanic 0:fbdae7e6d805 94 {
borlanic 0:fbdae7e6d805 95 /*
borlanic 0:fbdae7e6d805 96 * Steps 1-3: generate a suitable ephemeral keypair
borlanic 0:fbdae7e6d805 97 * and set r = xR mod n
borlanic 0:fbdae7e6d805 98 */
borlanic 0:fbdae7e6d805 99 key_tries = 0;
borlanic 0:fbdae7e6d805 100 do
borlanic 0:fbdae7e6d805 101 {
borlanic 0:fbdae7e6d805 102 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair( grp, &k, &R, f_rng, p_rng ) );
borlanic 0:fbdae7e6d805 103 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( r, &R.X, &grp->N ) );
borlanic 0:fbdae7e6d805 104
borlanic 0:fbdae7e6d805 105 if( key_tries++ > 10 )
borlanic 0:fbdae7e6d805 106 {
borlanic 0:fbdae7e6d805 107 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
borlanic 0:fbdae7e6d805 108 goto cleanup;
borlanic 0:fbdae7e6d805 109 }
borlanic 0:fbdae7e6d805 110 }
borlanic 0:fbdae7e6d805 111 while( mbedtls_mpi_cmp_int( r, 0 ) == 0 );
borlanic 0:fbdae7e6d805 112
borlanic 0:fbdae7e6d805 113 /*
borlanic 0:fbdae7e6d805 114 * Step 5: derive MPI from hashed message
borlanic 0:fbdae7e6d805 115 */
borlanic 0:fbdae7e6d805 116 MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) );
borlanic 0:fbdae7e6d805 117
borlanic 0:fbdae7e6d805 118 /*
borlanic 0:fbdae7e6d805 119 * Generate a random value to blind inv_mod in next step,
borlanic 0:fbdae7e6d805 120 * avoiding a potential timing leak.
borlanic 0:fbdae7e6d805 121 */
borlanic 0:fbdae7e6d805 122 blind_tries = 0;
borlanic 0:fbdae7e6d805 123 do
borlanic 0:fbdae7e6d805 124 {
borlanic 0:fbdae7e6d805 125 size_t n_size = ( grp->nbits + 7 ) / 8;
borlanic 0:fbdae7e6d805 126 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &t, n_size, f_rng, p_rng ) );
borlanic 0:fbdae7e6d805 127 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &t, 8 * n_size - grp->nbits ) );
borlanic 0:fbdae7e6d805 128
borlanic 0:fbdae7e6d805 129 /* See mbedtls_ecp_gen_keypair() */
borlanic 0:fbdae7e6d805 130 if( ++blind_tries > 30 )
borlanic 0:fbdae7e6d805 131 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
borlanic 0:fbdae7e6d805 132 }
borlanic 0:fbdae7e6d805 133 while( mbedtls_mpi_cmp_int( &t, 1 ) < 0 ||
borlanic 0:fbdae7e6d805 134 mbedtls_mpi_cmp_mpi( &t, &grp->N ) >= 0 );
borlanic 0:fbdae7e6d805 135
borlanic 0:fbdae7e6d805 136 /*
borlanic 0:fbdae7e6d805 137 * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n
borlanic 0:fbdae7e6d805 138 */
borlanic 0:fbdae7e6d805 139 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, r, d ) );
borlanic 0:fbdae7e6d805 140 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) );
borlanic 0:fbdae7e6d805 141 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) );
borlanic 0:fbdae7e6d805 142 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &k, &k, &t ) );
borlanic 0:fbdae7e6d805 143 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, &k, &grp->N ) );
borlanic 0:fbdae7e6d805 144 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) );
borlanic 0:fbdae7e6d805 145 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) );
borlanic 0:fbdae7e6d805 146
borlanic 0:fbdae7e6d805 147 if( sign_tries++ > 10 )
borlanic 0:fbdae7e6d805 148 {
borlanic 0:fbdae7e6d805 149 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
borlanic 0:fbdae7e6d805 150 goto cleanup;
borlanic 0:fbdae7e6d805 151 }
borlanic 0:fbdae7e6d805 152 }
borlanic 0:fbdae7e6d805 153 while( mbedtls_mpi_cmp_int( s, 0 ) == 0 );
borlanic 0:fbdae7e6d805 154
borlanic 0:fbdae7e6d805 155 cleanup:
borlanic 0:fbdae7e6d805 156 mbedtls_ecp_point_free( &R );
borlanic 0:fbdae7e6d805 157 mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t );
borlanic 0:fbdae7e6d805 158
borlanic 0:fbdae7e6d805 159 return( ret );
borlanic 0:fbdae7e6d805 160 }
borlanic 0:fbdae7e6d805 161 #endif /* MBEDTLS_ECDSA_SIGN_ALT */
borlanic 0:fbdae7e6d805 162
borlanic 0:fbdae7e6d805 163 #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
borlanic 0:fbdae7e6d805 164 /*
borlanic 0:fbdae7e6d805 165 * Deterministic signature wrapper
borlanic 0:fbdae7e6d805 166 */
borlanic 0:fbdae7e6d805 167 int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
borlanic 0:fbdae7e6d805 168 const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
borlanic 0:fbdae7e6d805 169 mbedtls_md_type_t md_alg )
borlanic 0:fbdae7e6d805 170 {
borlanic 0:fbdae7e6d805 171 int ret;
borlanic 0:fbdae7e6d805 172 mbedtls_hmac_drbg_context rng_ctx;
borlanic 0:fbdae7e6d805 173 unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES];
borlanic 0:fbdae7e6d805 174 size_t grp_len = ( grp->nbits + 7 ) / 8;
borlanic 0:fbdae7e6d805 175 const mbedtls_md_info_t *md_info;
borlanic 0:fbdae7e6d805 176 mbedtls_mpi h;
borlanic 0:fbdae7e6d805 177
borlanic 0:fbdae7e6d805 178 if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL )
borlanic 0:fbdae7e6d805 179 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
borlanic 0:fbdae7e6d805 180
borlanic 0:fbdae7e6d805 181 mbedtls_mpi_init( &h );
borlanic 0:fbdae7e6d805 182 mbedtls_hmac_drbg_init( &rng_ctx );
borlanic 0:fbdae7e6d805 183
borlanic 0:fbdae7e6d805 184 /* Use private key and message hash (reduced) to initialize HMAC_DRBG */
borlanic 0:fbdae7e6d805 185 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) );
borlanic 0:fbdae7e6d805 186 MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) );
borlanic 0:fbdae7e6d805 187 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) );
borlanic 0:fbdae7e6d805 188 mbedtls_hmac_drbg_seed_buf( &rng_ctx, md_info, data, 2 * grp_len );
borlanic 0:fbdae7e6d805 189
borlanic 0:fbdae7e6d805 190 ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen,
borlanic 0:fbdae7e6d805 191 mbedtls_hmac_drbg_random, &rng_ctx );
borlanic 0:fbdae7e6d805 192
borlanic 0:fbdae7e6d805 193 cleanup:
borlanic 0:fbdae7e6d805 194 mbedtls_hmac_drbg_free( &rng_ctx );
borlanic 0:fbdae7e6d805 195 mbedtls_mpi_free( &h );
borlanic 0:fbdae7e6d805 196
borlanic 0:fbdae7e6d805 197 return( ret );
borlanic 0:fbdae7e6d805 198 }
borlanic 0:fbdae7e6d805 199 #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
borlanic 0:fbdae7e6d805 200
borlanic 0:fbdae7e6d805 201 #if !defined(MBEDTLS_ECDSA_VERIFY_ALT)
borlanic 0:fbdae7e6d805 202 /*
borlanic 0:fbdae7e6d805 203 * Verify ECDSA signature of hashed message (SEC1 4.1.4)
borlanic 0:fbdae7e6d805 204 * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message)
borlanic 0:fbdae7e6d805 205 */
borlanic 0:fbdae7e6d805 206 int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
borlanic 0:fbdae7e6d805 207 const unsigned char *buf, size_t blen,
borlanic 0:fbdae7e6d805 208 const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s)
borlanic 0:fbdae7e6d805 209 {
borlanic 0:fbdae7e6d805 210 int ret;
borlanic 0:fbdae7e6d805 211 mbedtls_mpi e, s_inv, u1, u2;
borlanic 0:fbdae7e6d805 212 mbedtls_ecp_point R;
borlanic 0:fbdae7e6d805 213
borlanic 0:fbdae7e6d805 214 mbedtls_ecp_point_init( &R );
borlanic 0:fbdae7e6d805 215 mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 );
borlanic 0:fbdae7e6d805 216
borlanic 0:fbdae7e6d805 217 /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
borlanic 0:fbdae7e6d805 218 if( grp->N.p == NULL )
borlanic 0:fbdae7e6d805 219 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
borlanic 0:fbdae7e6d805 220
borlanic 0:fbdae7e6d805 221 /*
borlanic 0:fbdae7e6d805 222 * Step 1: make sure r and s are in range 1..n-1
borlanic 0:fbdae7e6d805 223 */
borlanic 0:fbdae7e6d805 224 if( mbedtls_mpi_cmp_int( r, 1 ) < 0 || mbedtls_mpi_cmp_mpi( r, &grp->N ) >= 0 ||
borlanic 0:fbdae7e6d805 225 mbedtls_mpi_cmp_int( s, 1 ) < 0 || mbedtls_mpi_cmp_mpi( s, &grp->N ) >= 0 )
borlanic 0:fbdae7e6d805 226 {
borlanic 0:fbdae7e6d805 227 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
borlanic 0:fbdae7e6d805 228 goto cleanup;
borlanic 0:fbdae7e6d805 229 }
borlanic 0:fbdae7e6d805 230
borlanic 0:fbdae7e6d805 231 /*
borlanic 0:fbdae7e6d805 232 * Additional precaution: make sure Q is valid
borlanic 0:fbdae7e6d805 233 */
borlanic 0:fbdae7e6d805 234 MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) );
borlanic 0:fbdae7e6d805 235
borlanic 0:fbdae7e6d805 236 /*
borlanic 0:fbdae7e6d805 237 * Step 3: derive MPI from hashed message
borlanic 0:fbdae7e6d805 238 */
borlanic 0:fbdae7e6d805 239 MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) );
borlanic 0:fbdae7e6d805 240
borlanic 0:fbdae7e6d805 241 /*
borlanic 0:fbdae7e6d805 242 * Step 4: u1 = e / s mod n, u2 = r / s mod n
borlanic 0:fbdae7e6d805 243 */
borlanic 0:fbdae7e6d805 244 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) );
borlanic 0:fbdae7e6d805 245
borlanic 0:fbdae7e6d805 246 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u1, &e, &s_inv ) );
borlanic 0:fbdae7e6d805 247 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u1, &u1, &grp->N ) );
borlanic 0:fbdae7e6d805 248
borlanic 0:fbdae7e6d805 249 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u2, r, &s_inv ) );
borlanic 0:fbdae7e6d805 250 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u2, &u2, &grp->N ) );
borlanic 0:fbdae7e6d805 251
borlanic 0:fbdae7e6d805 252 /*
borlanic 0:fbdae7e6d805 253 * Step 5: R = u1 G + u2 Q
borlanic 0:fbdae7e6d805 254 *
borlanic 0:fbdae7e6d805 255 * Since we're not using any secret data, no need to pass a RNG to
borlanic 0:fbdae7e6d805 256 * mbedtls_ecp_mul() for countermesures.
borlanic 0:fbdae7e6d805 257 */
borlanic 0:fbdae7e6d805 258 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, &R, &u1, &grp->G, &u2, Q ) );
borlanic 0:fbdae7e6d805 259
borlanic 0:fbdae7e6d805 260 if( mbedtls_ecp_is_zero( &R ) )
borlanic 0:fbdae7e6d805 261 {
borlanic 0:fbdae7e6d805 262 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
borlanic 0:fbdae7e6d805 263 goto cleanup;
borlanic 0:fbdae7e6d805 264 }
borlanic 0:fbdae7e6d805 265
borlanic 0:fbdae7e6d805 266 /*
borlanic 0:fbdae7e6d805 267 * Step 6: convert xR to an integer (no-op)
borlanic 0:fbdae7e6d805 268 * Step 7: reduce xR mod n (gives v)
borlanic 0:fbdae7e6d805 269 */
borlanic 0:fbdae7e6d805 270 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &R.X, &R.X, &grp->N ) );
borlanic 0:fbdae7e6d805 271
borlanic 0:fbdae7e6d805 272 /*
borlanic 0:fbdae7e6d805 273 * Step 8: check if v (that is, R.X) is equal to r
borlanic 0:fbdae7e6d805 274 */
borlanic 0:fbdae7e6d805 275 if( mbedtls_mpi_cmp_mpi( &R.X, r ) != 0 )
borlanic 0:fbdae7e6d805 276 {
borlanic 0:fbdae7e6d805 277 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
borlanic 0:fbdae7e6d805 278 goto cleanup;
borlanic 0:fbdae7e6d805 279 }
borlanic 0:fbdae7e6d805 280
borlanic 0:fbdae7e6d805 281 cleanup:
borlanic 0:fbdae7e6d805 282 mbedtls_ecp_point_free( &R );
borlanic 0:fbdae7e6d805 283 mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv ); mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 );
borlanic 0:fbdae7e6d805 284
borlanic 0:fbdae7e6d805 285 return( ret );
borlanic 0:fbdae7e6d805 286 }
borlanic 0:fbdae7e6d805 287 #endif /* MBEDTLS_ECDSA_VERIFY_ALT */
borlanic 0:fbdae7e6d805 288
borlanic 0:fbdae7e6d805 289 /*
borlanic 0:fbdae7e6d805 290 * Convert a signature (given by context) to ASN.1
borlanic 0:fbdae7e6d805 291 */
borlanic 0:fbdae7e6d805 292 static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s,
borlanic 0:fbdae7e6d805 293 unsigned char *sig, size_t *slen )
borlanic 0:fbdae7e6d805 294 {
borlanic 0:fbdae7e6d805 295 int ret;
borlanic 0:fbdae7e6d805 296 unsigned char buf[MBEDTLS_ECDSA_MAX_LEN];
borlanic 0:fbdae7e6d805 297 unsigned char *p = buf + sizeof( buf );
borlanic 0:fbdae7e6d805 298 size_t len = 0;
borlanic 0:fbdae7e6d805 299
borlanic 0:fbdae7e6d805 300 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, s ) );
borlanic 0:fbdae7e6d805 301 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, r ) );
borlanic 0:fbdae7e6d805 302
borlanic 0:fbdae7e6d805 303 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, buf, len ) );
borlanic 0:fbdae7e6d805 304 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, buf,
borlanic 0:fbdae7e6d805 305 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
borlanic 0:fbdae7e6d805 306
borlanic 0:fbdae7e6d805 307 memcpy( sig, p, len );
borlanic 0:fbdae7e6d805 308 *slen = len;
borlanic 0:fbdae7e6d805 309
borlanic 0:fbdae7e6d805 310 return( 0 );
borlanic 0:fbdae7e6d805 311 }
borlanic 0:fbdae7e6d805 312
borlanic 0:fbdae7e6d805 313 /*
borlanic 0:fbdae7e6d805 314 * Compute and write signature
borlanic 0:fbdae7e6d805 315 */
borlanic 0:fbdae7e6d805 316 int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg,
borlanic 0:fbdae7e6d805 317 const unsigned char *hash, size_t hlen,
borlanic 0:fbdae7e6d805 318 unsigned char *sig, size_t *slen,
borlanic 0:fbdae7e6d805 319 int (*f_rng)(void *, unsigned char *, size_t),
borlanic 0:fbdae7e6d805 320 void *p_rng )
borlanic 0:fbdae7e6d805 321 {
borlanic 0:fbdae7e6d805 322 int ret;
borlanic 0:fbdae7e6d805 323 mbedtls_mpi r, s;
borlanic 0:fbdae7e6d805 324
borlanic 0:fbdae7e6d805 325 mbedtls_mpi_init( &r );
borlanic 0:fbdae7e6d805 326 mbedtls_mpi_init( &s );
borlanic 0:fbdae7e6d805 327
borlanic 0:fbdae7e6d805 328 #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
borlanic 0:fbdae7e6d805 329 (void) f_rng;
borlanic 0:fbdae7e6d805 330 (void) p_rng;
borlanic 0:fbdae7e6d805 331
borlanic 0:fbdae7e6d805 332 MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det( &ctx->grp, &r, &s, &ctx->d,
borlanic 0:fbdae7e6d805 333 hash, hlen, md_alg ) );
borlanic 0:fbdae7e6d805 334 #else
borlanic 0:fbdae7e6d805 335 (void) md_alg;
borlanic 0:fbdae7e6d805 336
borlanic 0:fbdae7e6d805 337 MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d,
borlanic 0:fbdae7e6d805 338 hash, hlen, f_rng, p_rng ) );
borlanic 0:fbdae7e6d805 339 #endif
borlanic 0:fbdae7e6d805 340
borlanic 0:fbdae7e6d805 341 MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) );
borlanic 0:fbdae7e6d805 342
borlanic 0:fbdae7e6d805 343 cleanup:
borlanic 0:fbdae7e6d805 344 mbedtls_mpi_free( &r );
borlanic 0:fbdae7e6d805 345 mbedtls_mpi_free( &s );
borlanic 0:fbdae7e6d805 346
borlanic 0:fbdae7e6d805 347 return( ret );
borlanic 0:fbdae7e6d805 348 }
borlanic 0:fbdae7e6d805 349
borlanic 0:fbdae7e6d805 350 #if ! defined(MBEDTLS_DEPRECATED_REMOVED) && \
borlanic 0:fbdae7e6d805 351 defined(MBEDTLS_ECDSA_DETERMINISTIC)
borlanic 0:fbdae7e6d805 352 int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx,
borlanic 0:fbdae7e6d805 353 const unsigned char *hash, size_t hlen,
borlanic 0:fbdae7e6d805 354 unsigned char *sig, size_t *slen,
borlanic 0:fbdae7e6d805 355 mbedtls_md_type_t md_alg )
borlanic 0:fbdae7e6d805 356 {
borlanic 0:fbdae7e6d805 357 return( mbedtls_ecdsa_write_signature( ctx, md_alg, hash, hlen, sig, slen,
borlanic 0:fbdae7e6d805 358 NULL, NULL ) );
borlanic 0:fbdae7e6d805 359 }
borlanic 0:fbdae7e6d805 360 #endif
borlanic 0:fbdae7e6d805 361
borlanic 0:fbdae7e6d805 362 /*
borlanic 0:fbdae7e6d805 363 * Read and check signature
borlanic 0:fbdae7e6d805 364 */
borlanic 0:fbdae7e6d805 365 int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx,
borlanic 0:fbdae7e6d805 366 const unsigned char *hash, size_t hlen,
borlanic 0:fbdae7e6d805 367 const unsigned char *sig, size_t slen )
borlanic 0:fbdae7e6d805 368 {
borlanic 0:fbdae7e6d805 369 int ret;
borlanic 0:fbdae7e6d805 370 unsigned char *p = (unsigned char *) sig;
borlanic 0:fbdae7e6d805 371 const unsigned char *end = sig + slen;
borlanic 0:fbdae7e6d805 372 size_t len;
borlanic 0:fbdae7e6d805 373 mbedtls_mpi r, s;
borlanic 0:fbdae7e6d805 374
borlanic 0:fbdae7e6d805 375 mbedtls_mpi_init( &r );
borlanic 0:fbdae7e6d805 376 mbedtls_mpi_init( &s );
borlanic 0:fbdae7e6d805 377
borlanic 0:fbdae7e6d805 378 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
borlanic 0:fbdae7e6d805 379 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
borlanic 0:fbdae7e6d805 380 {
borlanic 0:fbdae7e6d805 381 ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
borlanic 0:fbdae7e6d805 382 goto cleanup;
borlanic 0:fbdae7e6d805 383 }
borlanic 0:fbdae7e6d805 384
borlanic 0:fbdae7e6d805 385 if( p + len != end )
borlanic 0:fbdae7e6d805 386 {
borlanic 0:fbdae7e6d805 387 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA +
borlanic 0:fbdae7e6d805 388 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
borlanic 0:fbdae7e6d805 389 goto cleanup;
borlanic 0:fbdae7e6d805 390 }
borlanic 0:fbdae7e6d805 391
borlanic 0:fbdae7e6d805 392 if( ( ret = mbedtls_asn1_get_mpi( &p, end, &r ) ) != 0 ||
borlanic 0:fbdae7e6d805 393 ( ret = mbedtls_asn1_get_mpi( &p, end, &s ) ) != 0 )
borlanic 0:fbdae7e6d805 394 {
borlanic 0:fbdae7e6d805 395 ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
borlanic 0:fbdae7e6d805 396 goto cleanup;
borlanic 0:fbdae7e6d805 397 }
borlanic 0:fbdae7e6d805 398
borlanic 0:fbdae7e6d805 399 if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen,
borlanic 0:fbdae7e6d805 400 &ctx->Q, &r, &s ) ) != 0 )
borlanic 0:fbdae7e6d805 401 goto cleanup;
borlanic 0:fbdae7e6d805 402
borlanic 0:fbdae7e6d805 403 if( p != end )
borlanic 0:fbdae7e6d805 404 ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH;
borlanic 0:fbdae7e6d805 405
borlanic 0:fbdae7e6d805 406 cleanup:
borlanic 0:fbdae7e6d805 407 mbedtls_mpi_free( &r );
borlanic 0:fbdae7e6d805 408 mbedtls_mpi_free( &s );
borlanic 0:fbdae7e6d805 409
borlanic 0:fbdae7e6d805 410 return( ret );
borlanic 0:fbdae7e6d805 411 }
borlanic 0:fbdae7e6d805 412
borlanic 0:fbdae7e6d805 413 #if !defined(MBEDTLS_ECDSA_GENKEY_ALT)
borlanic 0:fbdae7e6d805 414 /*
borlanic 0:fbdae7e6d805 415 * Generate key pair
borlanic 0:fbdae7e6d805 416 */
borlanic 0:fbdae7e6d805 417 int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid,
borlanic 0:fbdae7e6d805 418 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
borlanic 0:fbdae7e6d805 419 {
borlanic 0:fbdae7e6d805 420 return( mbedtls_ecp_group_load( &ctx->grp, gid ) ||
borlanic 0:fbdae7e6d805 421 mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) );
borlanic 0:fbdae7e6d805 422 }
borlanic 0:fbdae7e6d805 423 #endif /* MBEDTLS_ECDSA_GENKEY_ALT */
borlanic 0:fbdae7e6d805 424
borlanic 0:fbdae7e6d805 425 /*
borlanic 0:fbdae7e6d805 426 * Set context from an mbedtls_ecp_keypair
borlanic 0:fbdae7e6d805 427 */
borlanic 0:fbdae7e6d805 428 int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key )
borlanic 0:fbdae7e6d805 429 {
borlanic 0:fbdae7e6d805 430 int ret;
borlanic 0:fbdae7e6d805 431
borlanic 0:fbdae7e6d805 432 if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 ||
borlanic 0:fbdae7e6d805 433 ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 ||
borlanic 0:fbdae7e6d805 434 ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 )
borlanic 0:fbdae7e6d805 435 {
borlanic 0:fbdae7e6d805 436 mbedtls_ecdsa_free( ctx );
borlanic 0:fbdae7e6d805 437 }
borlanic 0:fbdae7e6d805 438
borlanic 0:fbdae7e6d805 439 return( ret );
borlanic 0:fbdae7e6d805 440 }
borlanic 0:fbdae7e6d805 441
borlanic 0:fbdae7e6d805 442 /*
borlanic 0:fbdae7e6d805 443 * Initialize context
borlanic 0:fbdae7e6d805 444 */
borlanic 0:fbdae7e6d805 445 void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx )
borlanic 0:fbdae7e6d805 446 {
borlanic 0:fbdae7e6d805 447 mbedtls_ecp_keypair_init( ctx );
borlanic 0:fbdae7e6d805 448 }
borlanic 0:fbdae7e6d805 449
borlanic 0:fbdae7e6d805 450 /*
borlanic 0:fbdae7e6d805 451 * Free context
borlanic 0:fbdae7e6d805 452 */
borlanic 0:fbdae7e6d805 453 void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx )
borlanic 0:fbdae7e6d805 454 {
borlanic 0:fbdae7e6d805 455 mbedtls_ecp_keypair_free( ctx );
borlanic 0:fbdae7e6d805 456 }
borlanic 0:fbdae7e6d805 457
borlanic 0:fbdae7e6d805 458 #endif /* MBEDTLS_ECDSA_C */