bn_gf2m.c 27.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
/* crypto/bn/bn_gf2m.c */
/* ====================================================================
 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
 *
 * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
 * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
 * to the OpenSSL project.
 *
 * The ECC Code is licensed pursuant to the OpenSSL open source
 * license provided below.
 *
 * In addition, Sun covenants to all licensees who provide a reciprocal
 * covenant with respect to their own patents if any, not to sue under
 * current and future patent claims necessarily infringed by the making,
 * using, practicing, selling, offering for sale and/or otherwise
 * disposing of the ECC Code as delivered hereunder (or portions thereof),
 * provided that such covenant shall not apply:
 *  1) for code that a licensee deletes from the ECC Code;
 *  2) separates from the ECC Code; or
 *  3) for infringements caused by:
 *       i) the modification of the ECC Code or
 *      ii) the combination of the ECC Code with other software or
 *          devices where such combination causes the infringement.
 *
 * The software is originally written by Sheueling Chang Shantz and
 * Douglas Stebila of Sun Microsystems Laboratories.
 *
 */

30 31 32 33 34 35 36
/* NOTE: This file is licensed pursuant to the OpenSSL license below
 * and may be modified; but after modifications, the above covenant
 * may no longer apply!  In such cases, the corresponding paragraph
 * ["In addition, Sun covenants ... causes the infringement."] and
 * this note can be edited out; but please keep the Sun copyright
 * notice and attribution. */

37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
/* ====================================================================
 * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. All advertising materials mentioning features or use of this
 *    software must display the following acknowledgment:
 *    "This product includes software developed by the OpenSSL Project
 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
 *
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
 *    endorse or promote products derived from this software without
 *    prior written permission. For written permission, please contact
 *    openssl-core@openssl.org.
 *
 * 5. Products derived from this software may not be called "OpenSSL"
 *    nor may "OpenSSL" appear in their names without prior written
 *    permission of the OpenSSL Project.
 *
 * 6. Redistributions of any form whatsoever must retain the following
 *    acknowledgment:
 *    "This product includes software developed by the OpenSSL Project
 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
 *
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 * ====================================================================
 *
 * This product includes cryptographic software written by Eric Young
 * (eay@cryptsoft.com).  This product includes software written by Tim
 * Hudson (tjh@cryptsoft.com).
 *
 */

91 92
#define OPENSSL_FIPSAPI

93 94 95 96 97 98
#include <assert.h>
#include <limits.h>
#include <stdio.h>
#include "cryptlib.h"
#include "bn_lcl.h"

99 100
#ifndef OPENSSL_NO_EC2M

101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
/* Maximum number of iterations before BN_GF2m_mod_solve_quad_arr should fail. */
#define MAX_ITERATIONS 50

static const BN_ULONG SQR_tb[16] =
  {     0,     1,     4,     5,    16,    17,    20,    21,
       64,    65,    68,    69,    80,    81,    84,    85 };
/* Platform-specific macros to accelerate squaring. */
#if defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG)
#define SQR1(w) \
    SQR_tb[(w) >> 60 & 0xF] << 56 | SQR_tb[(w) >> 56 & 0xF] << 48 | \
    SQR_tb[(w) >> 52 & 0xF] << 40 | SQR_tb[(w) >> 48 & 0xF] << 32 | \
    SQR_tb[(w) >> 44 & 0xF] << 24 | SQR_tb[(w) >> 40 & 0xF] << 16 | \
    SQR_tb[(w) >> 36 & 0xF] <<  8 | SQR_tb[(w) >> 32 & 0xF]
#define SQR0(w) \
    SQR_tb[(w) >> 28 & 0xF] << 56 | SQR_tb[(w) >> 24 & 0xF] << 48 | \
    SQR_tb[(w) >> 20 & 0xF] << 40 | SQR_tb[(w) >> 16 & 0xF] << 32 | \
    SQR_tb[(w) >> 12 & 0xF] << 24 | SQR_tb[(w) >>  8 & 0xF] << 16 | \
    SQR_tb[(w) >>  4 & 0xF] <<  8 | SQR_tb[(w)       & 0xF]
#endif
#ifdef THIRTY_TWO_BIT
#define SQR1(w) \
    SQR_tb[(w) >> 28 & 0xF] << 24 | SQR_tb[(w) >> 24 & 0xF] << 16 | \
    SQR_tb[(w) >> 20 & 0xF] <<  8 | SQR_tb[(w) >> 16 & 0xF]
#define SQR0(w) \
    SQR_tb[(w) >> 12 & 0xF] << 24 | SQR_tb[(w) >>  8 & 0xF] << 16 | \
    SQR_tb[(w) >>  4 & 0xF] <<  8 | SQR_tb[(w)       & 0xF]
#endif

/* Product of two polynomials a, b each with degree < BN_BITS2 - 1,
 * result is a polynomial r with degree < 2 * BN_BITS - 1
 * The caller MUST ensure that the variables have the right amount
 * of space allocated.
 */
#ifdef THIRTY_TWO_BIT
static void bn_GF2m_mul_1x1(BN_ULONG *r1, BN_ULONG *r0, const BN_ULONG a, const BN_ULONG b)
	{
	register BN_ULONG h, l, s;
	BN_ULONG tab[8], top2b = a >> 30; 
	register BN_ULONG a1, a2, a4;

	a1 = a & (0x3FFFFFFF); a2 = a1 << 1; a4 = a2 << 1;

	tab[0] =  0; tab[1] = a1;    tab[2] = a2;    tab[3] = a1^a2;
	tab[4] = a4; tab[5] = a1^a4; tab[6] = a2^a4; tab[7] = a1^a2^a4;

	s = tab[b       & 0x7]; l  = s;
	s = tab[b >>  3 & 0x7]; l ^= s <<  3; h  = s >> 29;
	s = tab[b >>  6 & 0x7]; l ^= s <<  6; h ^= s >> 26;
	s = tab[b >>  9 & 0x7]; l ^= s <<  9; h ^= s >> 23;
	s = tab[b >> 12 & 0x7]; l ^= s << 12; h ^= s >> 20;
	s = tab[b >> 15 & 0x7]; l ^= s << 15; h ^= s >> 17;
	s = tab[b >> 18 & 0x7]; l ^= s << 18; h ^= s >> 14;
	s = tab[b >> 21 & 0x7]; l ^= s << 21; h ^= s >> 11;
	s = tab[b >> 24 & 0x7]; l ^= s << 24; h ^= s >>  8;
	s = tab[b >> 27 & 0x7]; l ^= s << 27; h ^= s >>  5;
	s = tab[b >> 30      ]; l ^= s << 30; h ^= s >>  2;

	/* compensate for the top two bits of a */

	if (top2b & 01) { l ^= b << 30; h ^= b >> 2; } 
	if (top2b & 02) { l ^= b << 31; h ^= b >> 1; } 

	*r1 = h; *r0 = l;
	} 
#endif
#if defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG)
static void bn_GF2m_mul_1x1(BN_ULONG *r1, BN_ULONG *r0, const BN_ULONG a, const BN_ULONG b)
	{
	register BN_ULONG h, l, s;
	BN_ULONG tab[16], top3b = a >> 61;
	register BN_ULONG a1, a2, a4, a8;

173
	a1 = a & (0x1FFFFFFFFFFFFFFFULL); a2 = a1 << 1; a4 = a2 << 1; a8 = a4 << 1;
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232

	tab[ 0] = 0;     tab[ 1] = a1;       tab[ 2] = a2;       tab[ 3] = a1^a2;
	tab[ 4] = a4;    tab[ 5] = a1^a4;    tab[ 6] = a2^a4;    tab[ 7] = a1^a2^a4;
	tab[ 8] = a8;    tab[ 9] = a1^a8;    tab[10] = a2^a8;    tab[11] = a1^a2^a8;
	tab[12] = a4^a8; tab[13] = a1^a4^a8; tab[14] = a2^a4^a8; tab[15] = a1^a2^a4^a8;

	s = tab[b       & 0xF]; l  = s;
	s = tab[b >>  4 & 0xF]; l ^= s <<  4; h  = s >> 60;
	s = tab[b >>  8 & 0xF]; l ^= s <<  8; h ^= s >> 56;
	s = tab[b >> 12 & 0xF]; l ^= s << 12; h ^= s >> 52;
	s = tab[b >> 16 & 0xF]; l ^= s << 16; h ^= s >> 48;
	s = tab[b >> 20 & 0xF]; l ^= s << 20; h ^= s >> 44;
	s = tab[b >> 24 & 0xF]; l ^= s << 24; h ^= s >> 40;
	s = tab[b >> 28 & 0xF]; l ^= s << 28; h ^= s >> 36;
	s = tab[b >> 32 & 0xF]; l ^= s << 32; h ^= s >> 32;
	s = tab[b >> 36 & 0xF]; l ^= s << 36; h ^= s >> 28;
	s = tab[b >> 40 & 0xF]; l ^= s << 40; h ^= s >> 24;
	s = tab[b >> 44 & 0xF]; l ^= s << 44; h ^= s >> 20;
	s = tab[b >> 48 & 0xF]; l ^= s << 48; h ^= s >> 16;
	s = tab[b >> 52 & 0xF]; l ^= s << 52; h ^= s >> 12;
	s = tab[b >> 56 & 0xF]; l ^= s << 56; h ^= s >>  8;
	s = tab[b >> 60      ]; l ^= s << 60; h ^= s >>  4;

	/* compensate for the top three bits of a */

	if (top3b & 01) { l ^= b << 61; h ^= b >> 3; } 
	if (top3b & 02) { l ^= b << 62; h ^= b >> 2; } 
	if (top3b & 04) { l ^= b << 63; h ^= b >> 1; } 

	*r1 = h; *r0 = l;
	} 
#endif

/* Product of two polynomials a, b each with degree < 2 * BN_BITS2 - 1,
 * result is a polynomial r with degree < 4 * BN_BITS2 - 1
 * The caller MUST ensure that the variables have the right amount
 * of space allocated.
 */
static void bn_GF2m_mul_2x2(BN_ULONG *r, const BN_ULONG a1, const BN_ULONG a0, const BN_ULONG b1, const BN_ULONG b0)
	{
	BN_ULONG m1, m0;
	/* r[3] = h1, r[2] = h0; r[1] = l1; r[0] = l0 */
	bn_GF2m_mul_1x1(r+3, r+2, a1, b1);
	bn_GF2m_mul_1x1(r+1, r, a0, b0);
	bn_GF2m_mul_1x1(&m1, &m0, a0 ^ a1, b0 ^ b1);
	/* Correction on m1 ^= l1 ^ h1; m0 ^= l0 ^ h0; */
	r[2] ^= m1 ^ r[1] ^ r[3];  /* h0 ^= m1 ^ l1 ^ h1; */
	r[1] = r[3] ^ r[2] ^ r[0] ^ m1 ^ m0;  /* l1 ^= l0 ^ h0 ^ m0; */
	}


/* Add polynomials a and b and store result in r; r could be a or b, a and b 
 * could be equal; r is the bitwise XOR of a and b.
 */
int	BN_GF2m_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
	{
	int i;
	const BIGNUM *at, *bt;

233 234 235
	bn_check_top(a);
	bn_check_top(b);

236 237 238
	if (a->top < b->top) { at = b; bt = a; }
	else { at = a; bt = b; }

239 240
	if(bn_wexpand(r, at->top) == NULL)
		return 0;
241 242 243 244 245 246 247 248 249 250 251

	for (i = 0; i < bt->top; i++)
		{
		r->d[i] = at->d[i] ^ bt->d[i];
		}
	for (; i < at->top; i++)
		{
		r->d[i] = at->d[i];
		}
	
	r->top = at->top;
252
	bn_correct_top(r);
253 254 255 256 257 258 259 260 261 262 263 264 265
	
	return 1;
	}


/* Some functions allow for representation of the irreducible polynomials
 * as an int[], say p.  The irreducible f(t) is then of the form:
 *     t^p[0] + t^p[1] + ... + t^p[k]
 * where m = p[0] > p[1] > ... > p[k] = 0.
 */


/* Performs modular reduction of a and store result in r.  r could be a. */
266
int BN_GF2m_mod_arr(BIGNUM *r, const BIGNUM *a, const int p[])
267 268 269 270
	{
	int j, k;
	int n, dN, d0, d1;
	BN_ULONG zz, *z;
271 272 273

	bn_check_top(a);

274
	if (!p[0])
275
		{
276
		/* reduction mod 1 => return 0 */
277 278 279
		BN_zero(r);
		return 1;
		}
280 281 282

	/* Since the algorithm does reduction in the r value, if a != r, copy
	 * the contents of a into r so we can do reduction in r. 
283
	 */
B
Bodo Möller 已提交
284
	if (a != r)
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
		{
		if (!bn_wexpand(r, a->top)) return 0;
		for (j = 0; j < a->top; j++)
			{
			r->d[j] = a->d[j];
			}
		r->top = a->top;
		}
	z = r->d;

	/* start reduction */
	dN = p[0] / BN_BITS2;  
	for (j = r->top - 1; j > dN;)
		{
		zz = z[j];
		if (z[j] == 0) { j--; continue; }
		z[j] = 0;

303
		for (k = 1; p[k] != 0; k++)
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
			{
			/* reducing component t^p[k] */
			n = p[0] - p[k];
			d0 = n % BN_BITS2;  d1 = BN_BITS2 - d0;
			n /= BN_BITS2; 
			z[j-n] ^= (zz>>d0);
			if (d0) z[j-n-1] ^= (zz<<d1);
			}

		/* reducing component t^0 */
		n = dN;  
		d0 = p[0] % BN_BITS2;
		d1 = BN_BITS2 - d0;
		z[j-n] ^= (zz >> d0);
		if (d0) z[j-n-1] ^= (zz << d1);
		}

	/* final round of reduction */
	while (j == dN)
		{

		d0 = p[0] % BN_BITS2;
		zz = z[dN] >> d0;
		if (zz == 0) break;
		d1 = BN_BITS2 - d0;
		
330 331 332 333 334
		/* clear up the top d1 bits */
		if (d0)
			z[dN] = (z[dN] << d1) >> d1;
		else
			z[dN] = 0;
335 336
		z[0] ^= zz; /* reduction t^0 component */

337
		for (k = 1; p[k] != 0; k++)
338
			{
B
Bodo Möller 已提交
339 340
			BN_ULONG tmp_ulong;

341 342 343 344 345
			/* reducing component t^p[k]*/
			n = p[k] / BN_BITS2;   
			d0 = p[k] % BN_BITS2;
			d1 = BN_BITS2 - d0;
			z[n] ^= (zz << d0);
B
Bodo Möller 已提交
346 347 348
			tmp_ulong = zz >> d1;
                        if (d0 && tmp_ulong)
                                z[n+1] ^= tmp_ulong;
349 350 351 352 353
			}

		
		}

354
	bn_correct_top(r);
355 356 357 358 359 360 361 362 363 364 365
	return 1;
	}

/* Performs modular reduction of a by p and store result in r.  r could be a.
 *
 * This function calls down to the BN_GF2m_mod_arr implementation; this wrapper
 * function is only provided for convenience; for best performance, use the 
 * BN_GF2m_mod_arr function.
 */
int	BN_GF2m_mod(BIGNUM *r, const BIGNUM *a, const BIGNUM *p)
	{
366
	int ret = 0;
367 368
	const int max = BN_num_bits(p) + 1;
	int *arr=NULL;
369 370
	bn_check_top(a);
	bn_check_top(p);
371
	if ((arr = (int *)OPENSSL_malloc(sizeof(int) * max)) == NULL) goto err;
372 373
	ret = BN_GF2m_poly2arr(p, arr, max);
	if (!ret || ret > max)
374 375 376 377 378
		{
		BNerr(BN_F_BN_GF2M_MOD,BN_R_INVALID_LENGTH);
		goto err;
		}
	ret = BN_GF2m_mod_arr(r, a, arr);
379
	bn_check_top(r);
380
err:
381 382 383 384 385 386 387 388
	if (arr) OPENSSL_free(arr);
	return ret;
	}


/* Compute the product of two polynomials a and b, reduce modulo p, and store
 * the result in r.  r could be a or b; a could be b.
 */
389
int	BN_GF2m_mod_mul_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const int p[], BN_CTX *ctx)
390 391 392 393
	{
	int zlen, i, j, k, ret = 0;
	BIGNUM *s;
	BN_ULONG x1, x0, y1, y0, zz[4];
394 395 396 397

	bn_check_top(a);
	bn_check_top(b);

398 399 400 401 402 403 404 405
	if (a == b)
		{
		return BN_GF2m_mod_sqr_arr(r, a, p, ctx);
		}

	BN_CTX_start(ctx);
	if ((s = BN_CTX_get(ctx)) == NULL) goto err;
	
B
Bodo Möller 已提交
406
	zlen = a->top + b->top + 4;
407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
	if (!bn_wexpand(s, zlen)) goto err;
	s->top = zlen;

	for (i = 0; i < zlen; i++) s->d[i] = 0;

	for (j = 0; j < b->top; j += 2)
		{
		y0 = b->d[j];
		y1 = ((j+1) == b->top) ? 0 : b->d[j+1];
		for (i = 0; i < a->top; i += 2)
			{
			x0 = a->d[i];
			x1 = ((i+1) == a->top) ? 0 : a->d[i+1];
			bn_GF2m_mul_2x2(zz, x1, x0, y1, y0);
			for (k = 0; k < 4; k++) s->d[i+j+k] ^= zz[k];
			}
		}

425
	bn_correct_top(s);
426 427
	if (BN_GF2m_mod_arr(r, s, p))
		ret = 1;
428
	bn_check_top(r);
429

430
err:
431 432 433 434 435 436 437 438 439 440 441 442 443
	BN_CTX_end(ctx);
	return ret;
	}

/* Compute the product of two polynomials a and b, reduce modulo p, and store
 * the result in r.  r could be a or b; a could equal b.
 *
 * This function calls down to the BN_GF2m_mod_mul_arr implementation; this wrapper
 * function is only provided for convenience; for best performance, use the 
 * BN_GF2m_mod_mul_arr function.
 */
int	BN_GF2m_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *p, BN_CTX *ctx)
	{
444
	int ret = 0;
445 446
	const int max = BN_num_bits(p) + 1;
	int *arr=NULL;
447 448 449
	bn_check_top(a);
	bn_check_top(b);
	bn_check_top(p);
450
	if ((arr = (int *)OPENSSL_malloc(sizeof(int) * max)) == NULL) goto err;
451 452
	ret = BN_GF2m_poly2arr(p, arr, max);
	if (!ret || ret > max)
453 454 455 456 457
		{
		BNerr(BN_F_BN_GF2M_MOD_MUL,BN_R_INVALID_LENGTH);
		goto err;
		}
	ret = BN_GF2m_mod_mul_arr(r, a, b, arr, ctx);
458
	bn_check_top(r);
459
err:
460 461 462 463 464 465
	if (arr) OPENSSL_free(arr);
	return ret;
	}


/* Square a, reduce the result mod p, and store it in a.  r could be a. */
466
int	BN_GF2m_mod_sqr_arr(BIGNUM *r, const BIGNUM *a, const int p[], BN_CTX *ctx)
467 468 469
	{
	int i, ret = 0;
	BIGNUM *s;
470 471

	bn_check_top(a);
472 473 474 475 476 477 478 479 480 481 482
	BN_CTX_start(ctx);
	if ((s = BN_CTX_get(ctx)) == NULL) return 0;
	if (!bn_wexpand(s, 2 * a->top)) goto err;

	for (i = a->top - 1; i >= 0; i--)
		{
		s->d[2*i+1] = SQR1(a->d[i]);
		s->d[2*i  ] = SQR0(a->d[i]);
		}

	s->top = 2 * a->top;
483
	bn_correct_top(s);
484
	if (!BN_GF2m_mod_arr(r, s, p)) goto err;
485
	bn_check_top(r);
486
	ret = 1;
487
err:
488 489 490 491 492 493 494 495 496 497 498 499
	BN_CTX_end(ctx);
	return ret;
	}

/* Square a, reduce the result mod p, and store it in a.  r could be a.
 *
 * This function calls down to the BN_GF2m_mod_sqr_arr implementation; this wrapper
 * function is only provided for convenience; for best performance, use the 
 * BN_GF2m_mod_sqr_arr function.
 */
int	BN_GF2m_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
	{
500
	int ret = 0;
501 502
	const int max = BN_num_bits(p) + 1;
	int *arr=NULL;
503 504 505

	bn_check_top(a);
	bn_check_top(p);
506
	if ((arr = (int *)OPENSSL_malloc(sizeof(int) * max)) == NULL) goto err;
507 508
	ret = BN_GF2m_poly2arr(p, arr, max);
	if (!ret || ret > max)
509 510 511 512 513
		{
		BNerr(BN_F_BN_GF2M_MOD_SQR,BN_R_INVALID_LENGTH);
		goto err;
		}
	ret = BN_GF2m_mod_sqr_arr(r, a, arr, ctx);
514
	bn_check_top(r);
515
err:
516 517 518 519 520 521 522 523 524 525 526 527 528 529 530
	if (arr) OPENSSL_free(arr);
	return ret;
	}


/* Invert a, reduce modulo p, and store the result in r. r could be a. 
 * Uses Modified Almost Inverse Algorithm (Algorithm 10) from
 *     Hankerson, D., Hernandez, J.L., and Menezes, A.  "Software Implementation
 *     of Elliptic Curve Cryptography Over Binary Fields".
 */
int BN_GF2m_mod_inv(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
	{
	BIGNUM *b, *c, *u, *v, *tmp;
	int ret = 0;

531 532 533
	bn_check_top(a);
	bn_check_top(p);

534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559
	BN_CTX_start(ctx);
	
	b = BN_CTX_get(ctx);
	c = BN_CTX_get(ctx);
	u = BN_CTX_get(ctx);
	v = BN_CTX_get(ctx);
	if (v == NULL) goto err;

	if (!BN_one(b)) goto err;
	if (!BN_GF2m_mod(u, a, p)) goto err;
	if (!BN_copy(v, p)) goto err;

	if (BN_is_zero(u)) goto err;

	while (1)
		{
		while (!BN_is_odd(u))
			{
			if (!BN_rshift1(u, u)) goto err;
			if (BN_is_odd(b))
				{
				if (!BN_GF2m_add(b, b, p)) goto err;
				}
			if (!BN_rshift1(b, b)) goto err;
			}

560
		if (BN_abs_is_word(u, 1)) break;
561 562 563 564 565 566 567 568 569 570 571 572 573

		if (BN_num_bits(u) < BN_num_bits(v))
			{
			tmp = u; u = v; v = tmp;
			tmp = b; b = c; c = tmp;
			}
		
		if (!BN_GF2m_add(u, u, v)) goto err;
		if (!BN_GF2m_add(b, b, c)) goto err;
		}


	if (!BN_copy(r, b)) goto err;
574
	bn_check_top(r);
575 576
	ret = 1;

577
err:
578 579 580 581 582 583 584 585 586 587
  	BN_CTX_end(ctx);
	return ret;
	}

/* Invert xx, reduce modulo p, and store the result in r. r could be xx. 
 *
 * This function calls down to the BN_GF2m_mod_inv implementation; this wrapper
 * function is only provided for convenience; for best performance, use the 
 * BN_GF2m_mod_inv function.
 */
588
int BN_GF2m_mod_inv_arr(BIGNUM *r, const BIGNUM *xx, const int p[], BN_CTX *ctx)
589 590 591 592
	{
	BIGNUM *field;
	int ret = 0;

593
	bn_check_top(xx);
594 595 596 597 598
	BN_CTX_start(ctx);
	if ((field = BN_CTX_get(ctx)) == NULL) goto err;
	if (!BN_GF2m_arr2poly(p, field)) goto err;
	
	ret = BN_GF2m_mod_inv(r, xx, field, ctx);
599
	bn_check_top(r);
600

601
err:
602 603 604 605 606
	BN_CTX_end(ctx);
	return ret;
	}


607
#ifndef OPENSSL_SUN_GF2M_DIV
608 609 610 611 612 613 614
/* Divide y by x, reduce modulo p, and store the result in r. r could be x 
 * or y, x could equal y.
 */
int BN_GF2m_mod_div(BIGNUM *r, const BIGNUM *y, const BIGNUM *x, const BIGNUM *p, BN_CTX *ctx)
	{
	BIGNUM *xinv = NULL;
	int ret = 0;
615 616 617 618 619

	bn_check_top(y);
	bn_check_top(x);
	bn_check_top(p);

620 621 622 623 624 625
	BN_CTX_start(ctx);
	xinv = BN_CTX_get(ctx);
	if (xinv == NULL) goto err;
	
	if (!BN_GF2m_mod_inv(xinv, x, p, ctx)) goto err;
	if (!BN_GF2m_mod_mul(r, y, xinv, p, ctx)) goto err;
626
	bn_check_top(r);
627 628
	ret = 1;

629
err:
630 631 632 633 634 635 636 637 638 639 640 641 642 643 644
	BN_CTX_end(ctx);
	return ret;
	}
#else
/* Divide y by x, reduce modulo p, and store the result in r. r could be x 
 * or y, x could equal y.
 * Uses algorithm Modular_Division_GF(2^m) from 
 *     Chang-Shantz, S.  "From Euclid's GCD to Montgomery Multiplication to 
 *     the Great Divide".
 */
int BN_GF2m_mod_div(BIGNUM *r, const BIGNUM *y, const BIGNUM *x, const BIGNUM *p, BN_CTX *ctx)
	{
	BIGNUM *a, *b, *u, *v;
	int ret = 0;

645 646 647 648
	bn_check_top(y);
	bn_check_top(x);
	bn_check_top(p);

649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681
	BN_CTX_start(ctx);
	
	a = BN_CTX_get(ctx);
	b = BN_CTX_get(ctx);
	u = BN_CTX_get(ctx);
	v = BN_CTX_get(ctx);
	if (v == NULL) goto err;

	/* reduce x and y mod p */
	if (!BN_GF2m_mod(u, y, p)) goto err;
	if (!BN_GF2m_mod(a, x, p)) goto err;
	if (!BN_copy(b, p)) goto err;
	
	while (!BN_is_odd(a))
		{
		if (!BN_rshift1(a, a)) goto err;
		if (BN_is_odd(u)) if (!BN_GF2m_add(u, u, p)) goto err;
		if (!BN_rshift1(u, u)) goto err;
		}

	do
		{
		if (BN_GF2m_cmp(b, a) > 0)
			{
			if (!BN_GF2m_add(b, b, a)) goto err;
			if (!BN_GF2m_add(v, v, u)) goto err;
			do
				{
				if (!BN_rshift1(b, b)) goto err;
				if (BN_is_odd(v)) if (!BN_GF2m_add(v, v, p)) goto err;
				if (!BN_rshift1(v, v)) goto err;
				} while (!BN_is_odd(b));
			}
682
		else if (BN_abs_is_word(a, 1))
683 684 685 686 687 688 689 690 691 692 693 694 695 696 697
			break;
		else
			{
			if (!BN_GF2m_add(a, a, b)) goto err;
			if (!BN_GF2m_add(u, u, v)) goto err;
			do
				{
				if (!BN_rshift1(a, a)) goto err;
				if (BN_is_odd(u)) if (!BN_GF2m_add(u, u, p)) goto err;
				if (!BN_rshift1(u, u)) goto err;
				} while (!BN_is_odd(a));
			}
		} while (1);

	if (!BN_copy(r, u)) goto err;
698
	bn_check_top(r);
699 700
	ret = 1;

701
err:
702 703 704 705 706 707 708 709 710 711 712 713
  	BN_CTX_end(ctx);
	return ret;
	}
#endif

/* Divide yy by xx, reduce modulo p, and store the result in r. r could be xx 
 * or yy, xx could equal yy.
 *
 * This function calls down to the BN_GF2m_mod_div implementation; this wrapper
 * function is only provided for convenience; for best performance, use the 
 * BN_GF2m_mod_div function.
 */
714
int BN_GF2m_mod_div_arr(BIGNUM *r, const BIGNUM *yy, const BIGNUM *xx, const int p[], BN_CTX *ctx)
715 716 717 718
	{
	BIGNUM *field;
	int ret = 0;

719 720 721
	bn_check_top(yy);
	bn_check_top(xx);

722 723 724 725 726
	BN_CTX_start(ctx);
	if ((field = BN_CTX_get(ctx)) == NULL) goto err;
	if (!BN_GF2m_arr2poly(p, field)) goto err;
	
	ret = BN_GF2m_mod_div(r, yy, xx, field, ctx);
727
	bn_check_top(r);
728

729
err:
730 731 732 733 734 735 736 737 738
	BN_CTX_end(ctx);
	return ret;
	}


/* Compute the bth power of a, reduce modulo p, and store
 * the result in r.  r could be a.
 * Uses simple square-and-multiply algorithm A.5.1 from IEEE P1363.
 */
739
int	BN_GF2m_mod_exp_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const int p[], BN_CTX *ctx)
740 741 742
	{
	int ret = 0, i, n;
	BIGNUM *u;
743 744 745 746

	bn_check_top(a);
	bn_check_top(b);

747 748
	if (BN_is_zero(b))
		return(BN_one(r));
749 750 751

	if (BN_abs_is_word(b, 1))
		return (BN_copy(r, a) != NULL);
752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767

	BN_CTX_start(ctx);
	if ((u = BN_CTX_get(ctx)) == NULL) goto err;
	
	if (!BN_GF2m_mod_arr(u, a, p)) goto err;
	
	n = BN_num_bits(b) - 1;
	for (i = n - 1; i >= 0; i--)
		{
		if (!BN_GF2m_mod_sqr_arr(u, u, p, ctx)) goto err;
		if (BN_is_bit_set(b, i))
			{
			if (!BN_GF2m_mod_mul_arr(u, u, a, p, ctx)) goto err;
			}
		}
	if (!BN_copy(r, u)) goto err;
768
	bn_check_top(r);
769
	ret = 1;
770
err:
771 772 773 774 775 776 777 778 779 780 781 782 783
	BN_CTX_end(ctx);
	return ret;
	}

/* Compute the bth power of a, reduce modulo p, and store
 * the result in r.  r could be a.
 *
 * This function calls down to the BN_GF2m_mod_exp_arr implementation; this wrapper
 * function is only provided for convenience; for best performance, use the 
 * BN_GF2m_mod_exp_arr function.
 */
int BN_GF2m_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *p, BN_CTX *ctx)
	{
784
	int ret = 0;
785 786
	const int max = BN_num_bits(p) + 1;
	int *arr=NULL;
787 788 789
	bn_check_top(a);
	bn_check_top(b);
	bn_check_top(p);
790
	if ((arr = (int *)OPENSSL_malloc(sizeof(int) * max)) == NULL) goto err;
791 792
	ret = BN_GF2m_poly2arr(p, arr, max);
	if (!ret || ret > max)
793 794 795 796 797
		{
		BNerr(BN_F_BN_GF2M_MOD_EXP,BN_R_INVALID_LENGTH);
		goto err;
		}
	ret = BN_GF2m_mod_exp_arr(r, a, b, arr, ctx);
798
	bn_check_top(r);
799
err:
800 801 802 803 804 805 806 807
	if (arr) OPENSSL_free(arr);
	return ret;
	}

/* Compute the square root of a, reduce modulo p, and store
 * the result in r.  r could be a.
 * Uses exponentiation as in algorithm A.4.1 from IEEE P1363.
 */
808
int	BN_GF2m_mod_sqrt_arr(BIGNUM *r, const BIGNUM *a, const int p[], BN_CTX *ctx)
809 810 811
	{
	int ret = 0;
	BIGNUM *u;
812

813 814
	bn_check_top(a);

815
	if (!p[0])
816
		{
817
		/* reduction mod 1 => return 0 */
818 819 820
		BN_zero(r);
		return 1;
		}
821

822 823 824 825 826
	BN_CTX_start(ctx);
	if ((u = BN_CTX_get(ctx)) == NULL) goto err;
	
	if (!BN_set_bit(u, p[0] - 1)) goto err;
	ret = BN_GF2m_mod_exp_arr(r, a, u, p, ctx);
827
	bn_check_top(r);
828

829
err:
830 831 832 833 834 835 836 837 838 839 840 841 842
	BN_CTX_end(ctx);
	return ret;
	}

/* Compute the square root of a, reduce modulo p, and store
 * the result in r.  r could be a.
 *
 * This function calls down to the BN_GF2m_mod_sqrt_arr implementation; this wrapper
 * function is only provided for convenience; for best performance, use the 
 * BN_GF2m_mod_sqrt_arr function.
 */
int BN_GF2m_mod_sqrt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
	{
843
	int ret = 0;
844 845
	const int max = BN_num_bits(p) + 1;
	int *arr=NULL;
846 847
	bn_check_top(a);
	bn_check_top(p);
848
	if ((arr = (int *)OPENSSL_malloc(sizeof(int) * max)) == NULL) goto err;
849 850
	ret = BN_GF2m_poly2arr(p, arr, max);
	if (!ret || ret > max)
851
		{
852
		BNerr(BN_F_BN_GF2M_MOD_SQRT,BN_R_INVALID_LENGTH);
853 854 855
		goto err;
		}
	ret = BN_GF2m_mod_sqrt_arr(r, a, arr, ctx);
856
	bn_check_top(r);
857
err:
858 859 860 861 862 863 864
	if (arr) OPENSSL_free(arr);
	return ret;
	}

/* Find r such that r^2 + r = a mod p.  r could be a. If no r exists returns 0.
 * Uses algorithms A.4.7 and A.4.6 from IEEE P1363.
 */
865
int BN_GF2m_mod_solve_quad_arr(BIGNUM *r, const BIGNUM *a_, const int p[], BN_CTX *ctx)
866
	{
867
	int ret = 0, count = 0, j;
868
	BIGNUM *a, *z, *rho, *w, *w2, *tmp;
869

870 871
	bn_check_top(a_);

872
	if (!p[0])
873
		{
874
		/* reduction mod 1 => return 0 */
875 876 877
		BN_zero(r);
		return 1;
		}
878

879 880 881 882 883 884 885 886 887 888
	BN_CTX_start(ctx);
	a = BN_CTX_get(ctx);
	z = BN_CTX_get(ctx);
	w = BN_CTX_get(ctx);
	if (w == NULL) goto err;

	if (!BN_GF2m_mod_arr(a, a_, p)) goto err;
	
	if (BN_is_zero(a))
		{
889 890
		BN_zero(r);
		ret = 1;
891 892 893 894 895 896 897
		goto err;
		}

	if (p[0] & 0x1) /* m is odd */
		{
		/* compute half-trace of a */
		if (!BN_copy(z, a)) goto err;
R
Richard Levitte 已提交
898
		for (j = 1; j <= (p[0] - 1) / 2; j++)
899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915
			{
			if (!BN_GF2m_mod_sqr_arr(z, z, p, ctx)) goto err;
			if (!BN_GF2m_mod_sqr_arr(z, z, p, ctx)) goto err;
			if (!BN_GF2m_add(z, z, a)) goto err;
			}
		
		}
	else /* m is even */
		{
		rho = BN_CTX_get(ctx);
		w2 = BN_CTX_get(ctx);
		tmp = BN_CTX_get(ctx);
		if (tmp == NULL) goto err;
		do
			{
			if (!BN_rand(rho, p[0], 0, 0)) goto err;
			if (!BN_GF2m_mod_arr(rho, rho, p)) goto err;
916
			BN_zero(z);
917
			if (!BN_copy(w, rho)) goto err;
R
Richard Levitte 已提交
918
			for (j = 1; j <= p[0] - 1; j++)
919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936
				{
				if (!BN_GF2m_mod_sqr_arr(z, z, p, ctx)) goto err;
				if (!BN_GF2m_mod_sqr_arr(w2, w, p, ctx)) goto err;
				if (!BN_GF2m_mod_mul_arr(tmp, w2, a, p, ctx)) goto err;
				if (!BN_GF2m_add(z, z, tmp)) goto err;
				if (!BN_GF2m_add(w, w2, rho)) goto err;
				}
			count++;
			} while (BN_is_zero(w) && (count < MAX_ITERATIONS));
		if (BN_is_zero(w))
			{
			BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR,BN_R_TOO_MANY_ITERATIONS);
			goto err;
			}
		}
	
	if (!BN_GF2m_mod_sqr_arr(w, z, p, ctx)) goto err;
	if (!BN_GF2m_add(w, z, w)) goto err;
937 938 939 940 941
	if (BN_GF2m_cmp(w, a))
		{
		BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR, BN_R_NO_SOLUTION);
		goto err;
		}
942 943

	if (!BN_copy(r, z)) goto err;
944
	bn_check_top(r);
945 946 947

	ret = 1;

948
err:
949 950 951 952 953 954 955 956 957 958 959 960
	BN_CTX_end(ctx);
	return ret;
	}

/* Find r such that r^2 + r = a mod p.  r could be a. If no r exists returns 0.
 *
 * This function calls down to the BN_GF2m_mod_solve_quad_arr implementation; this wrapper
 * function is only provided for convenience; for best performance, use the 
 * BN_GF2m_mod_solve_quad_arr function.
 */
int BN_GF2m_mod_solve_quad(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
	{
961
	int ret = 0;
962 963
	const int max = BN_num_bits(p) + 1;
	int *arr=NULL;
964 965
	bn_check_top(a);
	bn_check_top(p);
966
	if ((arr = (int *)OPENSSL_malloc(sizeof(int) *
967
						max)) == NULL) goto err;
968 969
	ret = BN_GF2m_poly2arr(p, arr, max);
	if (!ret || ret > max)
970 971 972 973 974
		{
		BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD,BN_R_INVALID_LENGTH);
		goto err;
		}
	ret = BN_GF2m_mod_solve_quad_arr(r, a, arr, ctx);
975
	bn_check_top(r);
976
err:
977 978 979 980
	if (arr) OPENSSL_free(arr);
	return ret;
	}

981
/* Convert the bit-string representation of a polynomial
982 983
 * ( \sum_{i=0}^n a_i * x^i) into an array of integers corresponding 
 * to the bits with non-zero coefficient.  Array is terminated with -1.
984
 * Up to max elements of the array will be filled.  Return value is total
985
 * number of array elements that would be filled if array was large enough.
986
 */
987
int BN_GF2m_poly2arr(const BIGNUM *a, int p[], int max)
988
	{
989
	int i, j, k = 0;
990 991
	BN_ULONG mask;

992
	if (BN_is_zero(a))
993
		return 0;
994 995 996

	for (i = a->top - 1; i >= 0; i--)
		{
997 998 999
		if (!a->d[i])
			/* skip word if a->d[i] == 0 */
			continue;
1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011
		mask = BN_TBIT;
		for (j = BN_BITS2 - 1; j >= 0; j--)
			{
			if (a->d[i] & mask) 
				{
				if (k < max) p[k] = BN_BITS2 * i + j;
				k++;
				}
			mask >>= 1;
			}
		}

1012 1013 1014 1015 1016
	if (k < max) {
		p[k] = -1;
		k++;
	}

1017 1018 1019 1020
	return k;
	}

/* Convert the coefficient array representation of a polynomial to a 
1021
 * bit-string.  The array must be terminated by -1.
1022
 */
1023
int BN_GF2m_arr2poly(const int p[], BIGNUM *a)
1024 1025 1026
	{
	int i;

1027
	bn_check_top(a);
1028
	BN_zero(a);
1029
	for (i = 0; p[i] != -1; i++)
1030
		{
N
Nils Larsch 已提交
1031 1032
		if (BN_set_bit(a, p[i]) == 0)
			return 0;
1033
		}
1034
	bn_check_top(a);
1035

1036 1037 1038
	return 1;
	}

1039
#endif