mbed os with nrf51 internal bandgap enabled to read battery level

Dependents:   BLE_file_test BLE_Blink ExternalEncoder

Committer:
elessair
Date:
Sun Oct 23 15:10:02 2016 +0000
Revision:
0:f269e3021894
Initial commit

Who changed what in which revision?

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