Dependents:   blinky_max32630fthr

Committer:
switches
Date:
Fri Dec 16 16:27:57 2016 +0000
Revision:
3:1198227e6421
Parent:
0:5c4d7b2438d3
Changed ADC scale for MAX32625 platforms to 1.2V full scale to match MAX32630 platforms

Who changed what in which revision?

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