Home | History | Annotate | Download | only in ecdsa
      1 /* crypto/ecdsa/ecs_ossl.c */
      2 /*
      3  * Written by Nils Larsch for the OpenSSL project
      4  */
      5 /* ====================================================================
      6  * Copyright (c) 1998-2004 The OpenSSL Project.  All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  *
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  *
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in
     17  *    the documentation and/or other materials provided with the
     18  *    distribution.
     19  *
     20  * 3. All advertising materials mentioning features or use of this
     21  *    software must display the following acknowledgment:
     22  *    "This product includes software developed by the OpenSSL Project
     23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
     24  *
     25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
     26  *    endorse or promote products derived from this software without
     27  *    prior written permission. For written permission, please contact
     28  *    openssl-core (at) OpenSSL.org.
     29  *
     30  * 5. Products derived from this software may not be called "OpenSSL"
     31  *    nor may "OpenSSL" appear in their names without prior written
     32  *    permission of the OpenSSL Project.
     33  *
     34  * 6. Redistributions of any form whatsoever must retain the following
     35  *    acknowledgment:
     36  *    "This product includes software developed by the OpenSSL Project
     37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
     38  *
     39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
     40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
     43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     50  * OF THE POSSIBILITY OF SUCH DAMAGE.
     51  * ====================================================================
     52  *
     53  * This product includes cryptographic software written by Eric Young
     54  * (eay (at) cryptsoft.com).  This product includes software written by Tim
     55  * Hudson (tjh (at) cryptsoft.com).
     56  *
     57  */
     58 
     59 #include "ecs_locl.h"
     60 #include <openssl/err.h>
     61 #include <openssl/obj_mac.h>
     62 #include <openssl/bn.h>
     63 #include <openssl/rand.h>
     64 
     65 static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dlen,
     66 		const BIGNUM *, const BIGNUM *, EC_KEY *eckey);
     67 static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
     68 			    BIGNUM **kinvp, BIGNUM **rp,
     69 			    const unsigned char *dgst, int dlen);
     70 static int ecdsa_do_verify(const unsigned char *dgst, int dgst_len,
     71 		const ECDSA_SIG *sig, EC_KEY *eckey);
     72 
     73 static ECDSA_METHOD openssl_ecdsa_meth = {
     74 	"OpenSSL ECDSA method",
     75 	ecdsa_do_sign,
     76 	ecdsa_sign_setup,
     77 	ecdsa_do_verify,
     78 #if 0
     79 	NULL, /* init     */
     80 	NULL, /* finish   */
     81 #endif
     82 	0,    /* flags    */
     83 	NULL  /* app_data */
     84 };
     85 
     86 const ECDSA_METHOD *ECDSA_OpenSSL(void)
     87 {
     88 	return &openssl_ecdsa_meth;
     89 }
     90 
     91 static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
     92 			    BIGNUM **kinvp, BIGNUM **rp,
     93 			    const unsigned char *dgst, int dlen)
     94 {
     95 	BN_CTX   *ctx = NULL;
     96 	BIGNUM	 *k = NULL, *r = NULL, *order = NULL, *X = NULL;
     97 	EC_POINT *tmp_point=NULL;
     98 	const EC_GROUP *group;
     99 	int 	 ret = 0;
    100 
    101 	if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL)
    102 	{
    103 		ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_PASSED_NULL_PARAMETER);
    104 		return 0;
    105 	}
    106 
    107 	if (ctx_in == NULL)
    108 	{
    109 		if ((ctx = BN_CTX_new()) == NULL)
    110 		{
    111 			ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,ERR_R_MALLOC_FAILURE);
    112 			return 0;
    113 		}
    114 	}
    115 	else
    116 		ctx = ctx_in;
    117 
    118 	k     = BN_new();	/* this value is later returned in *kinvp */
    119 	r     = BN_new();	/* this value is later returned in *rp    */
    120 	order = BN_new();
    121 	X     = BN_new();
    122 	if (!k || !r || !order || !X)
    123 	{
    124 		ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE);
    125 		goto err;
    126 	}
    127 	if ((tmp_point = EC_POINT_new(group)) == NULL)
    128 	{
    129 		ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
    130 		goto err;
    131 	}
    132 	if (!EC_GROUP_get_order(group, order, ctx))
    133 	{
    134 		ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
    135 		goto err;
    136 	}
    137 
    138 	do
    139 	{
    140 		/* get random k */
    141 		do
    142 #ifndef OPENSSL_NO_SHA512
    143 			if (EC_KEY_get_nonce_from_hash(eckey))
    144 			{
    145 				if (!BN_generate_dsa_nonce(
    146 					k, order,
    147 					EC_KEY_get0_private_key(eckey),
    148 					dgst, dlen, ctx))
    149 					{
    150 					ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,
    151 						 ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED);
    152 					goto err;
    153 					}
    154 			}
    155 			else
    156 #endif
    157 			{
    158 				if (!BN_rand_range(k, order))
    159 				{
    160 					ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,
    161 					 ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED);
    162 					goto err;
    163 				}
    164 			}
    165 		while (BN_is_zero(k));
    166 
    167 		/* We do not want timing information to leak the length of k,
    168 		 * so we compute G*k using an equivalent scalar of fixed
    169 		 * bit-length. */
    170 
    171 		if (!BN_add(k, k, order)) goto err;
    172 		if (BN_num_bits(k) <= BN_num_bits(order))
    173 			if (!BN_add(k, k, order)) goto err;
    174 
    175 		/* compute r the x-coordinate of generator * k */
    176 		if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx))
    177 		{
    178 			ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
    179 			goto err;
    180 		}
    181 		if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field)
    182 		{
    183 			if (!EC_POINT_get_affine_coordinates_GFp(group,
    184 				tmp_point, X, NULL, ctx))
    185 			{
    186 				ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,ERR_R_EC_LIB);
    187 				goto err;
    188 			}
    189 		}
    190 #ifndef OPENSSL_NO_EC2M
    191 		else /* NID_X9_62_characteristic_two_field */
    192 		{
    193 			if (!EC_POINT_get_affine_coordinates_GF2m(group,
    194 				tmp_point, X, NULL, ctx))
    195 			{
    196 				ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,ERR_R_EC_LIB);
    197 				goto err;
    198 			}
    199 		}
    200 #endif
    201 		if (!BN_nnmod(r, X, order, ctx))
    202 		{
    203 			ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
    204 			goto err;
    205 		}
    206 	}
    207 	while (BN_is_zero(r));
    208 
    209 	/* compute the inverse of k */
    210 	if (!BN_mod_inverse(k, k, order, ctx))
    211 	{
    212 		ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
    213 		goto err;
    214 	}
    215 	/* clear old values if necessary */
    216 	if (*rp != NULL)
    217 		BN_clear_free(*rp);
    218 	if (*kinvp != NULL)
    219 		BN_clear_free(*kinvp);
    220 	/* save the pre-computed values  */
    221 	*rp    = r;
    222 	*kinvp = k;
    223 	ret = 1;
    224 err:
    225 	if (!ret)
    226 	{
    227 		if (k != NULL) BN_clear_free(k);
    228 		if (r != NULL) BN_clear_free(r);
    229 	}
    230 	if (ctx_in == NULL)
    231 		BN_CTX_free(ctx);
    232 	if (order != NULL)
    233 		BN_free(order);
    234 	if (tmp_point != NULL)
    235 		EC_POINT_free(tmp_point);
    236 	if (X)
    237 		BN_clear_free(X);
    238 	return(ret);
    239 }
    240 
    241 
    242 static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dgst_len,
    243 		const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey)
    244 {
    245 	int     ok = 0, i;
    246 	BIGNUM *kinv=NULL, *s, *m=NULL,*tmp=NULL,*order=NULL;
    247 	const BIGNUM *ckinv;
    248 	BN_CTX     *ctx = NULL;
    249 	const EC_GROUP   *group;
    250 	ECDSA_SIG  *ret;
    251 	ECDSA_DATA *ecdsa;
    252 	const BIGNUM *priv_key;
    253 
    254 	ecdsa    = ecdsa_check(eckey);
    255 	group    = EC_KEY_get0_group(eckey);
    256 	priv_key = EC_KEY_get0_private_key(eckey);
    257 
    258 	if (group == NULL || priv_key == NULL || ecdsa == NULL)
    259 	{
    260 		ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_PASSED_NULL_PARAMETER);
    261 		return NULL;
    262 	}
    263 
    264 	ret = ECDSA_SIG_new();
    265 	if (!ret)
    266 	{
    267 		ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
    268 		return NULL;
    269 	}
    270 	s = ret->s;
    271 
    272 	if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL ||
    273 		(tmp = BN_new()) == NULL || (m = BN_new()) == NULL)
    274 	{
    275 		ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
    276 		goto err;
    277 	}
    278 
    279 	if (!EC_GROUP_get_order(group, order, ctx))
    280 	{
    281 		ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB);
    282 		goto err;
    283 	}
    284 	i = BN_num_bits(order);
    285 	/* Need to truncate digest if it is too long: first truncate whole
    286 	 * bytes.
    287 	 */
    288 	if (8 * dgst_len > i)
    289 		dgst_len = (i + 7)/8;
    290 	if (!BN_bin2bn(dgst, dgst_len, m))
    291 	{
    292 		ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
    293 		goto err;
    294 	}
    295 	/* If still too long truncate remaining bits with a shift */
    296 	if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7)))
    297 	{
    298 		ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
    299 		goto err;
    300 	}
    301 	do
    302 	{
    303 		if (in_kinv == NULL || in_r == NULL)
    304 		{
    305 			if (!ecdsa->meth->ecdsa_sign_setup(eckey, ctx, &kinv, &ret->r, dgst, dgst_len))
    306 			{
    307 				ECDSAerr(ECDSA_F_ECDSA_DO_SIGN,ERR_R_ECDSA_LIB);
    308 				goto err;
    309 			}
    310 			ckinv = kinv;
    311 		}
    312 		else
    313 		{
    314 			ckinv  = in_kinv;
    315 			if (BN_copy(ret->r, in_r) == NULL)
    316 			{
    317 				ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
    318 				goto err;
    319 			}
    320 		}
    321 
    322 		if (!BN_mod_mul(tmp, priv_key, ret->r, order, ctx))
    323 		{
    324 			ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
    325 			goto err;
    326 		}
    327 		if (!BN_mod_add_quick(s, tmp, m, order))
    328 		{
    329 			ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
    330 			goto err;
    331 		}
    332 		if (!BN_mod_mul(s, s, ckinv, order, ctx))
    333 		{
    334 			ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
    335 			goto err;
    336 		}
    337 		if (BN_is_zero(s))
    338 		{
    339 			/* if kinv and r have been supplied by the caller
    340 			 * don't to generate new kinv and r values */
    341 			if (in_kinv != NULL && in_r != NULL)
    342 			{
    343 				ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ECDSA_R_NEED_NEW_SETUP_VALUES);
    344 				goto err;
    345 			}
    346 		}
    347 		else
    348 			/* s != 0 => we have a valid signature */
    349 			break;
    350 	}
    351 	while (1);
    352 
    353 	ok = 1;
    354 err:
    355 	if (!ok)
    356 	{
    357 		ECDSA_SIG_free(ret);
    358 		ret = NULL;
    359 	}
    360 	if (ctx)
    361 		BN_CTX_free(ctx);
    362 	if (m)
    363 		BN_clear_free(m);
    364 	if (tmp)
    365 		BN_clear_free(tmp);
    366 	if (order)
    367 		BN_free(order);
    368 	if (kinv)
    369 		BN_clear_free(kinv);
    370 	return ret;
    371 }
    372 
    373 static int ecdsa_do_verify(const unsigned char *dgst, int dgst_len,
    374 		const ECDSA_SIG *sig, EC_KEY *eckey)
    375 {
    376 	int ret = -1, i;
    377 	BN_CTX   *ctx;
    378 	BIGNUM   *order, *u1, *u2, *m, *X;
    379 	EC_POINT *point = NULL;
    380 	const EC_GROUP *group;
    381 	const EC_POINT *pub_key;
    382 
    383 	/* check input values */
    384 	if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL ||
    385 	    (pub_key = EC_KEY_get0_public_key(eckey)) == NULL || sig == NULL)
    386 	{
    387 		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_MISSING_PARAMETERS);
    388 		return -1;
    389 	}
    390 
    391 	ctx = BN_CTX_new();
    392 	if (!ctx)
    393 	{
    394 		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
    395 		return -1;
    396 	}
    397 	BN_CTX_start(ctx);
    398 	order = BN_CTX_get(ctx);
    399 	u1    = BN_CTX_get(ctx);
    400 	u2    = BN_CTX_get(ctx);
    401 	m     = BN_CTX_get(ctx);
    402 	X     = BN_CTX_get(ctx);
    403 	if (!X)
    404 	{
    405 		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
    406 		goto err;
    407 	}
    408 
    409 	if (!EC_GROUP_get_order(group, order, ctx))
    410 	{
    411 		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
    412 		goto err;
    413 	}
    414 
    415 	if (BN_is_zero(sig->r)          || BN_is_negative(sig->r) ||
    416 	    BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s)  ||
    417 	    BN_is_negative(sig->s)      || BN_ucmp(sig->s, order) >= 0)
    418 	{
    419 		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_BAD_SIGNATURE);
    420 		ret = 0;	/* signature is invalid */
    421 		goto err;
    422 	}
    423 	/* calculate tmp1 = inv(S) mod order */
    424 	if (!BN_mod_inverse(u2, sig->s, order, ctx))
    425 	{
    426 		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
    427 		goto err;
    428 	}
    429 	/* digest -> m */
    430 	i = BN_num_bits(order);
    431 	/* Need to truncate digest if it is too long: first truncate whole
    432 	 * bytes.
    433 	 */
    434 	if (8 * dgst_len > i)
    435 		dgst_len = (i + 7)/8;
    436 	if (!BN_bin2bn(dgst, dgst_len, m))
    437 	{
    438 		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
    439 		goto err;
    440 	}
    441 	/* If still too long truncate remaining bits with a shift */
    442 	if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7)))
    443 	{
    444 		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
    445 		goto err;
    446 	}
    447 	/* u1 = m * tmp mod order */
    448 	if (!BN_mod_mul(u1, m, u2, order, ctx))
    449 	{
    450 		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
    451 		goto err;
    452 	}
    453 	/* u2 = r * w mod q */
    454 	if (!BN_mod_mul(u2, sig->r, u2, order, ctx))
    455 	{
    456 		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
    457 		goto err;
    458 	}
    459 
    460 	if ((point = EC_POINT_new(group)) == NULL)
    461 	{
    462 		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
    463 		goto err;
    464 	}
    465 	if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx))
    466 	{
    467 		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
    468 		goto err;
    469 	}
    470 	if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field)
    471 	{
    472 		if (!EC_POINT_get_affine_coordinates_GFp(group,
    473 			point, X, NULL, ctx))
    474 		{
    475 			ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
    476 			goto err;
    477 		}
    478 	}
    479 #ifndef OPENSSL_NO_EC2M
    480 	else /* NID_X9_62_characteristic_two_field */
    481 	{
    482 		if (!EC_POINT_get_affine_coordinates_GF2m(group,
    483 			point, X, NULL, ctx))
    484 		{
    485 			ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
    486 			goto err;
    487 		}
    488 	}
    489 #endif
    490 	if (!BN_nnmod(u1, X, order, ctx))
    491 	{
    492 		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
    493 		goto err;
    494 	}
    495 	/*  if the signature is correct u1 is equal to sig->r */
    496 	ret = (BN_ucmp(u1, sig->r) == 0);
    497 err:
    498 	BN_CTX_end(ctx);
    499 	BN_CTX_free(ctx);
    500 	if (point)
    501 		EC_POINT_free(point);
    502 	return ret;
    503 }
    504