| 
									
										
										
										
											2004-02-23 03:32:53 +08:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2019-09-10 20:56:40 +08:00
										 |  |  |  * Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved. | 
					
						
							| 
									
										
										
										
											2002-02-14 02:21:51 +08:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2016-05-18 03:38:09 +08:00
										 |  |  |  * Licensed under the OpenSSL license (the "License").  You may not use | 
					
						
							|  |  |  |  * this file except in compliance with the License.  You can obtain a copy | 
					
						
							|  |  |  |  * in the file LICENSE in the source distribution or at | 
					
						
							|  |  |  |  * https://www.openssl.org/source/license.html
 | 
					
						
							| 
									
										
										
										
											2002-02-14 02:21:51 +08:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2002-07-26 16:41:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-29 00:57:51 +08:00
										 |  |  | #include <string.h>
 | 
					
						
							| 
									
										
										
										
											2002-07-26 16:41:04 +08:00
										 |  |  | #include <openssl/err.h>
 | 
					
						
							| 
									
										
										
										
											2002-08-07 18:49:54 +08:00
										 |  |  | #include <openssl/obj_mac.h>
 | 
					
						
							| 
									
										
										
										
											2013-01-25 05:27:28 +08:00
										 |  |  | #include <openssl/rand.h>
 | 
					
						
							| 
									
										
										
										
											2019-09-28 05:57:58 +08:00
										 |  |  | #include "crypto/bn.h"
 | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  | #include "ec_lcl.h"
 | 
					
						
							| 
									
										
										
										
											2013-07-15 19:42:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-29 00:57:51 +08:00
										 |  |  | int ossl_ecdsa_sign(int type, const unsigned char *dgst, int dlen, | 
					
						
							|  |  |  |                     unsigned char *sig, unsigned int *siglen, | 
					
						
							|  |  |  |                     const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ECDSA_SIG *s; | 
					
						
							| 
									
										
										
										
											2017-08-03 21:23:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-29 00:57:51 +08:00
										 |  |  |     s = ECDSA_do_sign_ex(dgst, dlen, kinv, r, eckey); | 
					
						
							|  |  |  |     if (s == NULL) { | 
					
						
							|  |  |  |         *siglen = 0; | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     *siglen = i2d_ECDSA_SIG(s, &sig); | 
					
						
							|  |  |  |     ECDSA_SIG_free(s); | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-18 01:05:43 +08:00
										 |  |  | static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                             BIGNUM **kinvp, BIGNUM **rp, | 
					
						
							|  |  |  |                             const unsigned char *dgst, int dlen) | 
					
						
							| 
									
										
										
										
											2002-02-14 02:21:51 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     BN_CTX *ctx = NULL; | 
					
						
							| 
									
										
										
										
											2016-02-01 00:34:07 +08:00
										 |  |  |     BIGNUM *k = NULL, *r = NULL, *X = NULL; | 
					
						
							|  |  |  |     const BIGNUM *order; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     EC_POINT *tmp_point = NULL; | 
					
						
							|  |  |  |     const EC_GROUP *group; | 
					
						
							|  |  |  |     int ret = 0; | 
					
						
							| 
									
										
										
										
											2017-11-01 04:58:39 +08:00
										 |  |  |     int order_bits; | 
					
						
							| 
									
										
										
										
											2019-07-26 17:03:12 +08:00
										 |  |  |     const BIGNUM *priv_key; | 
					
						
							| 
									
										
										
										
											2005-05-16 18:11:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL) { | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  |         ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_PASSED_NULL_PARAMETER); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-07-26 17:03:12 +08:00
										 |  |  |     if ((priv_key = EC_KEY_get0_private_key(eckey)) == NULL) { | 
					
						
							|  |  |  |         ECerr(EC_F_ECDSA_SIGN_SETUP, EC_R_MISSING_PRIVATE_KEY); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2003-01-15 22:54:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-23 23:02:34 +08:00
										 |  |  |     if (!EC_KEY_can_sign(eckey)) { | 
					
						
							|  |  |  |         ECerr(EC_F_ECDSA_SIGN_SETUP, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-06 22:13:29 +08:00
										 |  |  |     if ((ctx = ctx_in) == NULL) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         if ((ctx = BN_CTX_new()) == NULL) { | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  |             ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             return 0; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-07-06 22:13:29 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2002-02-14 02:21:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     k = BN_new();               /* this value is later returned in *kinvp */ | 
					
						
							|  |  |  |     r = BN_new();               /* this value is later returned in *rp */ | 
					
						
							|  |  |  |     X = BN_new(); | 
					
						
							| 
									
										
										
										
											2016-02-01 00:34:07 +08:00
										 |  |  |     if (k == NULL || r == NULL || X == NULL) { | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  |         ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         goto err; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ((tmp_point = EC_POINT_new(group)) == NULL) { | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  |         ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         goto err; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-02-01 00:34:07 +08:00
										 |  |  |     order = EC_GROUP_get0_order(group); | 
					
						
							| 
									
										
										
										
											2011-04-24 03:55:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-01 04:58:39 +08:00
										 |  |  |     /* Preallocate space */ | 
					
						
							|  |  |  |     order_bits = BN_num_bits(order); | 
					
						
							|  |  |  |     if (!BN_set_bit(k, order_bits) | 
					
						
							|  |  |  |         || !BN_set_bit(r, order_bits) | 
					
						
							|  |  |  |         || !BN_set_bit(X, order_bits)) | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     do { | 
					
						
							|  |  |  |         /* get random k */ | 
					
						
							| 
									
										
										
										
											2018-07-06 22:13:29 +08:00
										 |  |  |         do { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             if (dgst != NULL) { | 
					
						
							| 
									
										
										
										
											2019-07-26 17:03:12 +08:00
										 |  |  |                 if (!BN_generate_dsa_nonce(k, order, priv_key, | 
					
						
							| 
									
										
										
										
											2018-07-06 22:13:29 +08:00
										 |  |  |                                            dgst, dlen, ctx)) { | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  |                     ECerr(EC_F_ECDSA_SIGN_SETUP, | 
					
						
							| 
									
										
										
										
											2018-07-06 22:13:29 +08:00
										 |  |  |                           EC_R_RANDOM_NUMBER_GENERATION_FAILED); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                     goto err; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2015-01-28 01:34:45 +08:00
										 |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2017-08-03 02:00:52 +08:00
										 |  |  |                 if (!BN_priv_rand_range(k, order)) { | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  |                     ECerr(EC_F_ECDSA_SIGN_SETUP, | 
					
						
							| 
									
										
										
										
											2018-07-06 22:13:29 +08:00
										 |  |  |                           EC_R_RANDOM_NUMBER_GENERATION_FAILED); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                     goto err; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2018-07-06 22:13:29 +08:00
										 |  |  |         } while (BN_is_zero(k)); | 
					
						
							| 
									
										
										
										
											2002-02-14 02:21:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         /* compute r the x-coordinate of generator * k */ | 
					
						
							|  |  |  |         if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) { | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  |             ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             goto err; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-07-30 23:40:18 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (!EC_POINT_get_affine_coordinates(group, tmp_point, X, NULL, ctx)) { | 
					
						
							|  |  |  |             ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); | 
					
						
							|  |  |  |             goto err; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-07-30 23:40:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         if (!BN_nnmod(r, X, order, ctx)) { | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  |             ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             goto err; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-07-06 22:13:29 +08:00
										 |  |  |     } while (BN_is_zero(r)); | 
					
						
							| 
									
										
										
										
											2002-02-14 02:21:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-27 22:45:51 +08:00
										 |  |  |     /* compute the inverse of k */ | 
					
						
							| 
									
										
										
										
											2018-05-08 19:00:30 +08:00
										 |  |  |     if (!ec_group_do_inverse_ord(group, k, k, ctx)) { | 
					
						
							| 
									
										
										
										
											2018-04-27 22:45:51 +08:00
										 |  |  |         ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); | 
					
						
							|  |  |  |         goto err; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-09-12 06:13:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     /* clear old values if necessary */ | 
					
						
							| 
									
										
										
										
											2015-05-01 09:37:06 +08:00
										 |  |  |     BN_clear_free(*rp); | 
					
						
							|  |  |  |     BN_clear_free(*kinvp); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     /* save the pre-computed values  */ | 
					
						
							|  |  |  |     *rp = r; | 
					
						
							|  |  |  |     *kinvp = k; | 
					
						
							|  |  |  |     ret = 1; | 
					
						
							|  |  |  |  err: | 
					
						
							|  |  |  |     if (!ret) { | 
					
						
							| 
									
										
										
										
											2015-05-01 09:37:06 +08:00
										 |  |  |         BN_clear_free(k); | 
					
						
							|  |  |  |         BN_clear_free(r); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-05-01 09:37:06 +08:00
										 |  |  |     if (ctx != ctx_in) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         BN_CTX_free(ctx); | 
					
						
							| 
									
										
										
										
											2015-03-26 06:35:24 +08:00
										 |  |  |     EC_POINT_free(tmp_point); | 
					
						
							| 
									
										
										
										
											2015-05-01 09:37:06 +08:00
										 |  |  |     BN_clear_free(X); | 
					
						
							| 
									
										
										
										
											2017-10-17 22:04:09 +08:00
										 |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2002-02-14 02:21:51 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  | int ossl_ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, | 
					
						
							|  |  |  |                           BIGNUM **rp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return ecdsa_sign_setup(eckey, ctx_in, kinvp, rp, NULL, 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len, | 
					
						
							|  |  |  |                                const BIGNUM *in_kinv, const BIGNUM *in_r, | 
					
						
							|  |  |  |                                EC_KEY *eckey) | 
					
						
							| 
									
										
										
										
											2002-02-14 02:21:51 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     int ok = 0, i; | 
					
						
							| 
									
										
										
										
											2018-07-13 04:27:43 +08:00
										 |  |  |     BIGNUM *kinv = NULL, *s, *m = NULL; | 
					
						
							| 
									
										
										
										
											2016-02-01 00:34:07 +08:00
										 |  |  |     const BIGNUM *order, *ckinv; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     BN_CTX *ctx = NULL; | 
					
						
							|  |  |  |     const EC_GROUP *group; | 
					
						
							|  |  |  |     ECDSA_SIG *ret; | 
					
						
							|  |  |  |     const BIGNUM *priv_key; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     group = EC_KEY_get0_group(eckey); | 
					
						
							|  |  |  |     priv_key = EC_KEY_get0_private_key(eckey); | 
					
						
							| 
									
										
										
										
											2002-08-07 18:49:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-26 17:03:12 +08:00
										 |  |  |     if (group == NULL) { | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  |         ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_PASSED_NULL_PARAMETER); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-07-26 17:03:12 +08:00
										 |  |  |     if (priv_key == NULL) { | 
					
						
							|  |  |  |         ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, EC_R_MISSING_PRIVATE_KEY); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2002-02-14 02:21:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-23 23:02:34 +08:00
										 |  |  |     if (!EC_KEY_can_sign(eckey)) { | 
					
						
							|  |  |  |         ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     ret = ECDSA_SIG_new(); | 
					
						
							| 
									
										
										
										
											2015-10-30 19:12:26 +08:00
										 |  |  |     if (ret == NULL) { | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  |         ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-07-20 01:57:15 +08:00
										 |  |  |     ret->r = BN_new(); | 
					
						
							|  |  |  |     ret->s = BN_new(); | 
					
						
							|  |  |  |     if (ret->r == NULL || ret->s == NULL) { | 
					
						
							|  |  |  |         ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE); | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     s = ret->s; | 
					
						
							| 
									
										
										
										
											2004-02-23 03:32:53 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-13 04:27:43 +08:00
										 |  |  |     if ((ctx = BN_CTX_new()) == NULL | 
					
						
							|  |  |  |         || (m = BN_new()) == NULL) { | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  |         ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         goto err; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2002-02-14 02:21:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-01 00:34:07 +08:00
										 |  |  |     order = EC_GROUP_get0_order(group); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     i = BN_num_bits(order); | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * Need to truncate digest if it is too long: first truncate whole bytes. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if (8 * dgst_len > i) | 
					
						
							|  |  |  |         dgst_len = (i + 7) / 8; | 
					
						
							|  |  |  |     if (!BN_bin2bn(dgst, dgst_len, m)) { | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  |         ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         goto err; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-07-06 22:13:29 +08:00
										 |  |  |     /* If still too long, truncate remaining bits with a shift */ | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) { | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  |         ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         goto err; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     do { | 
					
						
							|  |  |  |         if (in_kinv == NULL || in_r == NULL) { | 
					
						
							|  |  |  |             if (!ecdsa_sign_setup(eckey, ctx, &kinv, &ret->r, dgst, dgst_len)) { | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  |                 ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_ECDSA_LIB); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                 goto err; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             ckinv = kinv; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             ckinv = in_kinv; | 
					
						
							|  |  |  |             if (BN_copy(ret->r, in_r) == NULL) { | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  |                 ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                 goto err; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2002-02-14 02:21:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-13 04:27:43 +08:00
										 |  |  |         /*
 | 
					
						
							|  |  |  |          * With only one multiplicant being in Montgomery domain | 
					
						
							|  |  |  |          * multiplication yields real result without post-conversion. | 
					
						
							|  |  |  |          * Also note that all operations but last are performed with | 
					
						
							|  |  |  |          * zero-padded vectors. Last operation, BN_mod_mul_montgomery | 
					
						
							|  |  |  |          * below, returns user-visible value with removed zero padding. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         if (!bn_to_mont_fixed_top(s, ret->r, group->mont_data, ctx) | 
					
						
							|  |  |  |             || !bn_mul_mont_fixed_top(s, s, priv_key, group->mont_data, ctx)) { | 
					
						
							| 
									
										
										
										
											2018-05-25 19:10:13 +08:00
										 |  |  |             ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB); | 
					
						
							|  |  |  |             goto err; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-07-13 04:27:43 +08:00
										 |  |  |         if (!bn_mod_add_fixed_top(s, s, m, order)) { | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  |             ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             goto err; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-07-13 04:27:43 +08:00
										 |  |  |         /*
 | 
					
						
							|  |  |  |          * |s| can still be larger than modulus, because |m| can be. In | 
					
						
							|  |  |  |          * such case we count on Montgomery reduction to tie it up. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         if (!bn_to_mont_fixed_top(s, s, group->mont_data, ctx) | 
					
						
							|  |  |  |             || !BN_mod_mul_montgomery(s, s, ckinv, group->mont_data, ctx)) { | 
					
						
							| 
									
										
										
										
											2018-05-25 19:10:13 +08:00
										 |  |  |             ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB); | 
					
						
							|  |  |  |             goto err; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-07-13 04:27:43 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         if (BN_is_zero(s)) { | 
					
						
							|  |  |  |             /*
 | 
					
						
							| 
									
										
										
										
											2017-12-18 05:15:15 +08:00
										 |  |  |              * if kinv and r have been supplied by the caller, don't | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |              * generate new kinv and r values | 
					
						
							|  |  |  |              */ | 
					
						
							|  |  |  |             if (in_kinv != NULL && in_r != NULL) { | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  |                 ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, EC_R_NEED_NEW_SETUP_VALUES); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                 goto err; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2018-07-06 22:13:29 +08:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             /* s != 0 => we have a valid signature */ | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2018-07-06 22:13:29 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |     } while (1); | 
					
						
							| 
									
										
										
										
											2002-02-14 02:21:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     ok = 1; | 
					
						
							|  |  |  |  err: | 
					
						
							|  |  |  |     if (!ok) { | 
					
						
							|  |  |  |         ECDSA_SIG_free(ret); | 
					
						
							|  |  |  |         ret = NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-05-01 09:37:06 +08:00
										 |  |  |     BN_CTX_free(ctx); | 
					
						
							| 
									
										
										
										
											2018-07-06 21:55:34 +08:00
										 |  |  |     BN_clear_free(m); | 
					
						
							| 
									
										
										
										
											2015-05-01 09:37:06 +08:00
										 |  |  |     BN_clear_free(kinv); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2002-02-14 02:21:51 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-29 00:57:51 +08:00
										 |  |  | /*-
 | 
					
						
							|  |  |  |  * returns | 
					
						
							|  |  |  |  *      1: correct signature | 
					
						
							|  |  |  |  *      0: incorrect signature | 
					
						
							|  |  |  |  *     -1: error | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int ossl_ecdsa_verify(int type, const unsigned char *dgst, int dgst_len, | 
					
						
							|  |  |  |                       const unsigned char *sigbuf, int sig_len, EC_KEY *eckey) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ECDSA_SIG *s; | 
					
						
							|  |  |  |     const unsigned char *p = sigbuf; | 
					
						
							|  |  |  |     unsigned char *der = NULL; | 
					
						
							|  |  |  |     int derlen = -1; | 
					
						
							|  |  |  |     int ret = -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     s = ECDSA_SIG_new(); | 
					
						
							|  |  |  |     if (s == NULL) | 
					
						
							| 
									
										
										
										
											2017-10-17 22:04:09 +08:00
										 |  |  |         return ret; | 
					
						
							| 
									
										
										
										
											2015-10-29 00:57:51 +08:00
										 |  |  |     if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL) | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  |     /* Ensure signature uses DER and doesn't have trailing garbage */ | 
					
						
							|  |  |  |     derlen = i2d_ECDSA_SIG(s, &der); | 
					
						
							| 
									
										
										
										
											2015-12-09 21:10:36 +08:00
										 |  |  |     if (derlen != sig_len || memcmp(sigbuf, der, derlen) != 0) | 
					
						
							| 
									
										
										
										
											2015-10-29 00:57:51 +08:00
										 |  |  |         goto err; | 
					
						
							|  |  |  |     ret = ECDSA_do_verify(dgst, dgst_len, s, eckey); | 
					
						
							|  |  |  |  err: | 
					
						
							|  |  |  |     OPENSSL_clear_free(der, derlen); | 
					
						
							|  |  |  |     ECDSA_SIG_free(s); | 
					
						
							| 
									
										
										
										
											2017-10-17 22:04:09 +08:00
										 |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2015-10-29 00:57:51 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  | int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len, | 
					
						
							|  |  |  |                           const ECDSA_SIG *sig, EC_KEY *eckey) | 
					
						
							| 
									
										
										
										
											2002-02-14 02:21:51 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     int ret = -1, i; | 
					
						
							|  |  |  |     BN_CTX *ctx; | 
					
						
							| 
									
										
										
										
											2016-02-01 00:34:07 +08:00
										 |  |  |     const BIGNUM *order; | 
					
						
							|  |  |  |     BIGNUM *u1, *u2, *m, *X; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     EC_POINT *point = NULL; | 
					
						
							|  |  |  |     const EC_GROUP *group; | 
					
						
							|  |  |  |     const EC_POINT *pub_key; | 
					
						
							| 
									
										
										
										
											2005-05-16 18:11:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     /* check input values */ | 
					
						
							|  |  |  |     if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL || | 
					
						
							|  |  |  |         (pub_key = EC_KEY_get0_public_key(eckey)) == NULL || sig == NULL) { | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  |         ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, EC_R_MISSING_PARAMETERS); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2002-02-14 02:21:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-23 23:02:34 +08:00
										 |  |  |     if (!EC_KEY_can_sign(eckey)) { | 
					
						
							|  |  |  |         ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     ctx = BN_CTX_new(); | 
					
						
							| 
									
										
										
										
											2015-10-30 19:12:26 +08:00
										 |  |  |     if (ctx == NULL) { | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  |         ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_MALLOC_FAILURE); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     BN_CTX_start(ctx); | 
					
						
							|  |  |  |     u1 = BN_CTX_get(ctx); | 
					
						
							|  |  |  |     u2 = BN_CTX_get(ctx); | 
					
						
							|  |  |  |     m = BN_CTX_get(ctx); | 
					
						
							|  |  |  |     X = BN_CTX_get(ctx); | 
					
						
							| 
									
										
										
										
											2015-12-09 21:10:36 +08:00
										 |  |  |     if (X == NULL) { | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  |         ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         goto err; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2004-02-23 03:32:53 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-01 00:34:07 +08:00
										 |  |  |     order = EC_GROUP_get0_order(group); | 
					
						
							|  |  |  |     if (order == NULL) { | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  |         ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_EC_LIB); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         goto err; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2002-02-14 02:21:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (BN_is_zero(sig->r) || BN_is_negative(sig->r) || | 
					
						
							|  |  |  |         BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s) || | 
					
						
							|  |  |  |         BN_is_negative(sig->s) || BN_ucmp(sig->s, order) >= 0) { | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  |         ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, EC_R_BAD_SIGNATURE); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         ret = 0;                /* signature is invalid */ | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* calculate tmp1 = inv(S) mod order */ | 
					
						
							| 
									
										
										
										
											2018-05-08 19:00:30 +08:00
										 |  |  |     if (!ec_group_do_inverse_ord(group, u2, sig->s, ctx)) { | 
					
						
							| 
									
										
										
										
											2018-04-27 22:45:51 +08:00
										 |  |  |         ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB); | 
					
						
							|  |  |  |         goto err; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     /* digest -> m */ | 
					
						
							|  |  |  |     i = BN_num_bits(order); | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * Need to truncate digest if it is too long: first truncate whole bytes. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if (8 * dgst_len > i) | 
					
						
							|  |  |  |         dgst_len = (i + 7) / 8; | 
					
						
							|  |  |  |     if (!BN_bin2bn(dgst, dgst_len, m)) { | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  |         ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         goto err; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* If still too long truncate remaining bits with a shift */ | 
					
						
							|  |  |  |     if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) { | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  |         ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         goto err; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* u1 = m * tmp mod order */ | 
					
						
							|  |  |  |     if (!BN_mod_mul(u1, m, u2, order, ctx)) { | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  |         ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         goto err; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* u2 = r * w mod q */ | 
					
						
							|  |  |  |     if (!BN_mod_mul(u2, sig->r, u2, order, ctx)) { | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  |         ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         goto err; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((point = EC_POINT_new(group)) == NULL) { | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  |         ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_MALLOC_FAILURE); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         goto err; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx)) { | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  |         ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_EC_LIB); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         goto err; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-30 23:40:18 +08:00
										 |  |  |     if (!EC_POINT_get_affine_coordinates(group, point, X, NULL, ctx)) { | 
					
						
							|  |  |  |         ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_EC_LIB); | 
					
						
							|  |  |  |         goto err; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-07-30 23:40:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (!BN_nnmod(u1, X, order, ctx)) { | 
					
						
							| 
									
										
										
										
											2015-10-28 02:19:32 +08:00
										 |  |  |         ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         goto err; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /*  if the signature is correct u1 is equal to sig->r */ | 
					
						
							|  |  |  |     ret = (BN_ucmp(u1, sig->r) == 0); | 
					
						
							|  |  |  |  err: | 
					
						
							|  |  |  |     BN_CTX_end(ctx); | 
					
						
							|  |  |  |     BN_CTX_free(ctx); | 
					
						
							| 
									
										
										
										
											2015-03-26 06:35:24 +08:00
										 |  |  |     EC_POINT_free(point); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2002-02-14 02:21:51 +08:00
										 |  |  | } |