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@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@cryptsoft.com).  This product includes software written by Tim
55 * Hudson (tjh@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
65static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dlen,
66		const BIGNUM *, const BIGNUM *, EC_KEY *eckey);
67static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
68			    BIGNUM **kinvp, BIGNUM **rp,
69			    const unsigned char *dgst, int dlen);
70static int ecdsa_do_verify(const unsigned char *dgst, int dgst_len,
71		const ECDSA_SIG *sig, EC_KEY *eckey);
72
73static 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
86const ECDSA_METHOD *ECDSA_OpenSSL(void)
87{
88	return &openssl_ecdsa_meth;
89}
90
91static 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;
224err:
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
242static 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;
354err:
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
373static 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);
497err:
498	BN_CTX_end(ctx);
499	BN_CTX_free(ctx);
500	if (point)
501		EC_POINT_free(point);
502	return ret;
503}
504