os/ossrv/ssl/libcrypto/src/crypto/bn/bn_gf2m.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/* crypto/bn/bn_gf2m.c */
sl@0
     2
/* ====================================================================
sl@0
     3
 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
sl@0
     4
 *
sl@0
     5
 * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
sl@0
     6
 * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
sl@0
     7
 * to the OpenSSL project.
sl@0
     8
 *
sl@0
     9
 * The ECC Code is licensed pursuant to the OpenSSL open source
sl@0
    10
 * license provided below.
sl@0
    11
 *
sl@0
    12
 * In addition, Sun covenants to all licensees who provide a reciprocal
sl@0
    13
 * covenant with respect to their own patents if any, not to sue under
sl@0
    14
 * current and future patent claims necessarily infringed by the making,
sl@0
    15
 * using, practicing, selling, offering for sale and/or otherwise
sl@0
    16
 * disposing of the ECC Code as delivered hereunder (or portions thereof),
sl@0
    17
 * provided that such covenant shall not apply:
sl@0
    18
 *  1) for code that a licensee deletes from the ECC Code;
sl@0
    19
 *  2) separates from the ECC Code; or
sl@0
    20
 *  3) for infringements caused by:
sl@0
    21
 *       i) the modification of the ECC Code or
sl@0
    22
 *      ii) the combination of the ECC Code with other software or
sl@0
    23
 *          devices where such combination causes the infringement.
sl@0
    24
 *
sl@0
    25
 * The software is originally written by Sheueling Chang Shantz and
sl@0
    26
 * Douglas Stebila of Sun Microsystems Laboratories.
sl@0
    27
 *
sl@0
    28
 */
sl@0
    29
sl@0
    30
/* NOTE: This file is licensed pursuant to the OpenSSL license below
sl@0
    31
 * and may be modified; but after modifications, the above covenant
sl@0
    32
 * may no longer apply!  In such cases, the corresponding paragraph
sl@0
    33
 * ["In addition, Sun covenants ... causes the infringement."] and
sl@0
    34
 * this note can be edited out; but please keep the Sun copyright
sl@0
    35
 * notice and attribution. */
sl@0
    36
sl@0
    37
/* ====================================================================
sl@0
    38
 * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
sl@0
    39
 *
sl@0
    40
 * Redistribution and use in source and binary forms, with or without
sl@0
    41
 * modification, are permitted provided that the following conditions
sl@0
    42
 * are met:
sl@0
    43
 *
sl@0
    44
 * 1. Redistributions of source code must retain the above copyright
sl@0
    45
 *    notice, this list of conditions and the following disclaimer. 
sl@0
    46
 *
sl@0
    47
 * 2. Redistributions in binary form must reproduce the above copyright
sl@0
    48
 *    notice, this list of conditions and the following disclaimer in
sl@0
    49
 *    the documentation and/or other materials provided with the
sl@0
    50
 *    distribution.
sl@0
    51
 *
sl@0
    52
 * 3. All advertising materials mentioning features or use of this
sl@0
    53
 *    software must display the following acknowledgment:
sl@0
    54
 *    "This product includes software developed by the OpenSSL Project
sl@0
    55
 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
sl@0
    56
 *
sl@0
    57
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
sl@0
    58
 *    endorse or promote products derived from this software without
sl@0
    59
 *    prior written permission. For written permission, please contact
sl@0
    60
 *    openssl-core@openssl.org.
sl@0
    61
 *
sl@0
    62
 * 5. Products derived from this software may not be called "OpenSSL"
sl@0
    63
 *    nor may "OpenSSL" appear in their names without prior written
sl@0
    64
 *    permission of the OpenSSL Project.
sl@0
    65
 *
sl@0
    66
 * 6. Redistributions of any form whatsoever must retain the following
sl@0
    67
 *    acknowledgment:
sl@0
    68
 *    "This product includes software developed by the OpenSSL Project
sl@0
    69
 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
sl@0
    70
 *
sl@0
    71
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
sl@0
    72
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
sl@0
    73
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
sl@0
    74
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
sl@0
    75
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
sl@0
    76
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
sl@0
    77
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
sl@0
    78
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
sl@0
    79
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
sl@0
    80
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
sl@0
    81
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
sl@0
    82
 * OF THE POSSIBILITY OF SUCH DAMAGE.
sl@0
    83
 * ====================================================================
sl@0
    84
 *
sl@0
    85
 * This product includes cryptographic software written by Eric Young
sl@0
    86
 * (eay@cryptsoft.com).  This product includes software written by Tim
sl@0
    87
 * Hudson (tjh@cryptsoft.com).
sl@0
    88
 *
sl@0
    89
 */
sl@0
    90
sl@0
    91
#include <assert.h>
sl@0
    92
#include <limits.h>
sl@0
    93
#include <stdio.h>
sl@0
    94
#include "cryptlib.h"
sl@0
    95
#include "bn_lcl.h"
sl@0
    96
sl@0
    97
/* Maximum number of iterations before BN_GF2m_mod_solve_quad_arr should fail. */
sl@0
    98
#define MAX_ITERATIONS 50
sl@0
    99
sl@0
   100
static const BN_ULONG SQR_tb[16] =
sl@0
   101
  {     0,     1,     4,     5,    16,    17,    20,    21,
sl@0
   102
       64,    65,    68,    69,    80,    81,    84,    85 };
sl@0
   103
/* Platform-specific macros to accelerate squaring. */
sl@0
   104
#if defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG)
sl@0
   105
#define SQR1(w) \
sl@0
   106
    SQR_tb[(w) >> 60 & 0xF] << 56 | SQR_tb[(w) >> 56 & 0xF] << 48 | \
sl@0
   107
    SQR_tb[(w) >> 52 & 0xF] << 40 | SQR_tb[(w) >> 48 & 0xF] << 32 | \
sl@0
   108
    SQR_tb[(w) >> 44 & 0xF] << 24 | SQR_tb[(w) >> 40 & 0xF] << 16 | \
sl@0
   109
    SQR_tb[(w) >> 36 & 0xF] <<  8 | SQR_tb[(w) >> 32 & 0xF]
sl@0
   110
#define SQR0(w) \
sl@0
   111
    SQR_tb[(w) >> 28 & 0xF] << 56 | SQR_tb[(w) >> 24 & 0xF] << 48 | \
sl@0
   112
    SQR_tb[(w) >> 20 & 0xF] << 40 | SQR_tb[(w) >> 16 & 0xF] << 32 | \
sl@0
   113
    SQR_tb[(w) >> 12 & 0xF] << 24 | SQR_tb[(w) >>  8 & 0xF] << 16 | \
sl@0
   114
    SQR_tb[(w) >>  4 & 0xF] <<  8 | SQR_tb[(w)       & 0xF]
sl@0
   115
#endif
sl@0
   116
#ifdef THIRTY_TWO_BIT
sl@0
   117
#define SQR1(w) \
sl@0
   118
    SQR_tb[(w) >> 28 & 0xF] << 24 | SQR_tb[(w) >> 24 & 0xF] << 16 | \
sl@0
   119
    SQR_tb[(w) >> 20 & 0xF] <<  8 | SQR_tb[(w) >> 16 & 0xF]
sl@0
   120
#define SQR0(w) \
sl@0
   121
    SQR_tb[(w) >> 12 & 0xF] << 24 | SQR_tb[(w) >>  8 & 0xF] << 16 | \
sl@0
   122
    SQR_tb[(w) >>  4 & 0xF] <<  8 | SQR_tb[(w)       & 0xF]
sl@0
   123
#endif
sl@0
   124
#ifdef SIXTEEN_BIT
sl@0
   125
#define SQR1(w) \
sl@0
   126
    SQR_tb[(w) >> 12 & 0xF] <<  8 | SQR_tb[(w) >>  8 & 0xF]
sl@0
   127
#define SQR0(w) \
sl@0
   128
    SQR_tb[(w) >>  4 & 0xF] <<  8 | SQR_tb[(w)       & 0xF]
sl@0
   129
#endif
sl@0
   130
#ifdef EIGHT_BIT
sl@0
   131
#define SQR1(w) \
sl@0
   132
    SQR_tb[(w) >>  4 & 0xF]
sl@0
   133
#define SQR0(w) \
sl@0
   134
    SQR_tb[(w)       & 15]
sl@0
   135
#endif
sl@0
   136
sl@0
   137
/* Product of two polynomials a, b each with degree < BN_BITS2 - 1,
sl@0
   138
 * result is a polynomial r with degree < 2 * BN_BITS - 1
sl@0
   139
 * The caller MUST ensure that the variables have the right amount
sl@0
   140
 * of space allocated.
sl@0
   141
 */
sl@0
   142
#ifdef EIGHT_BIT
sl@0
   143
static void bn_GF2m_mul_1x1(BN_ULONG *r1, BN_ULONG *r0, const BN_ULONG a, const BN_ULONG b)
sl@0
   144
	{
sl@0
   145
	register BN_ULONG h, l, s;
sl@0
   146
	BN_ULONG tab[4], top1b = a >> 7;
sl@0
   147
	register BN_ULONG a1, a2;
sl@0
   148
sl@0
   149
	a1 = a & (0x7F); a2 = a1 << 1;
sl@0
   150
sl@0
   151
	tab[0] = 0; tab[1] = a1; tab[2] = a2; tab[3] = a1^a2;
sl@0
   152
sl@0
   153
	s = tab[b      & 0x3]; l  = s;
sl@0
   154
	s = tab[b >> 2 & 0x3]; l ^= s << 2; h  = s >> 6;
sl@0
   155
	s = tab[b >> 4 & 0x3]; l ^= s << 4; h ^= s >> 4;
sl@0
   156
	s = tab[b >> 6      ]; l ^= s << 6; h ^= s >> 2;
sl@0
   157
	
sl@0
   158
	/* compensate for the top bit of a */
sl@0
   159
sl@0
   160
	if (top1b & 01) { l ^= b << 7; h ^= b >> 1; } 
sl@0
   161
sl@0
   162
	*r1 = h; *r0 = l;
sl@0
   163
	} 
sl@0
   164
#endif
sl@0
   165
#ifdef SIXTEEN_BIT
sl@0
   166
static void bn_GF2m_mul_1x1(BN_ULONG *r1, BN_ULONG *r0, const BN_ULONG a, const BN_ULONG b)
sl@0
   167
	{
sl@0
   168
	register BN_ULONG h, l, s;
sl@0
   169
	BN_ULONG tab[4], top1b = a >> 15; 
sl@0
   170
	register BN_ULONG a1, a2;
sl@0
   171
sl@0
   172
	a1 = a & (0x7FFF); a2 = a1 << 1;
sl@0
   173
sl@0
   174
	tab[0] = 0; tab[1] = a1; tab[2] = a2; tab[3] = a1^a2;
sl@0
   175
sl@0
   176
	s = tab[b      & 0x3]; l  = s;
sl@0
   177
	s = tab[b >> 2 & 0x3]; l ^= s <<  2; h  = s >> 14;
sl@0
   178
	s = tab[b >> 4 & 0x3]; l ^= s <<  4; h ^= s >> 12;
sl@0
   179
	s = tab[b >> 6 & 0x3]; l ^= s <<  6; h ^= s >> 10;
sl@0
   180
	s = tab[b >> 8 & 0x3]; l ^= s <<  8; h ^= s >>  8;
sl@0
   181
	s = tab[b >>10 & 0x3]; l ^= s << 10; h ^= s >>  6;
sl@0
   182
	s = tab[b >>12 & 0x3]; l ^= s << 12; h ^= s >>  4;
sl@0
   183
	s = tab[b >>14      ]; l ^= s << 14; h ^= s >>  2;
sl@0
   184
sl@0
   185
	/* compensate for the top bit of a */
sl@0
   186
sl@0
   187
	if (top1b & 01) { l ^= b << 15; h ^= b >> 1; } 
sl@0
   188
sl@0
   189
	*r1 = h; *r0 = l;
sl@0
   190
	} 
sl@0
   191
#endif
sl@0
   192
#ifdef THIRTY_TWO_BIT
sl@0
   193
static void bn_GF2m_mul_1x1(BN_ULONG *r1, BN_ULONG *r0, const BN_ULONG a, const BN_ULONG b)
sl@0
   194
	{
sl@0
   195
	register BN_ULONG h, l, s;
sl@0
   196
	BN_ULONG tab[8], top2b = a >> 30; 
sl@0
   197
	register BN_ULONG a1, a2, a4;
sl@0
   198
sl@0
   199
	a1 = a & (0x3FFFFFFF); a2 = a1 << 1; a4 = a2 << 1;
sl@0
   200
sl@0
   201
	tab[0] =  0; tab[1] = a1;    tab[2] = a2;    tab[3] = a1^a2;
sl@0
   202
	tab[4] = a4; tab[5] = a1^a4; tab[6] = a2^a4; tab[7] = a1^a2^a4;
sl@0
   203
sl@0
   204
	s = tab[b       & 0x7]; l  = s;
sl@0
   205
	s = tab[b >>  3 & 0x7]; l ^= s <<  3; h  = s >> 29;
sl@0
   206
	s = tab[b >>  6 & 0x7]; l ^= s <<  6; h ^= s >> 26;
sl@0
   207
	s = tab[b >>  9 & 0x7]; l ^= s <<  9; h ^= s >> 23;
sl@0
   208
	s = tab[b >> 12 & 0x7]; l ^= s << 12; h ^= s >> 20;
sl@0
   209
	s = tab[b >> 15 & 0x7]; l ^= s << 15; h ^= s >> 17;
sl@0
   210
	s = tab[b >> 18 & 0x7]; l ^= s << 18; h ^= s >> 14;
sl@0
   211
	s = tab[b >> 21 & 0x7]; l ^= s << 21; h ^= s >> 11;
sl@0
   212
	s = tab[b >> 24 & 0x7]; l ^= s << 24; h ^= s >>  8;
sl@0
   213
	s = tab[b >> 27 & 0x7]; l ^= s << 27; h ^= s >>  5;
sl@0
   214
	s = tab[b >> 30      ]; l ^= s << 30; h ^= s >>  2;
sl@0
   215
sl@0
   216
	/* compensate for the top two bits of a */
sl@0
   217
sl@0
   218
	if (top2b & 01) { l ^= b << 30; h ^= b >> 2; } 
sl@0
   219
	if (top2b & 02) { l ^= b << 31; h ^= b >> 1; } 
sl@0
   220
sl@0
   221
	*r1 = h; *r0 = l;
sl@0
   222
	} 
sl@0
   223
#endif
sl@0
   224
#if defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG)
sl@0
   225
static void bn_GF2m_mul_1x1(BN_ULONG *r1, BN_ULONG *r0, const BN_ULONG a, const BN_ULONG b)
sl@0
   226
	{
sl@0
   227
	register BN_ULONG h, l, s;
sl@0
   228
	BN_ULONG tab[16], top3b = a >> 61;
sl@0
   229
	register BN_ULONG a1, a2, a4, a8;
sl@0
   230
sl@0
   231
	a1 = a & (0x1FFFFFFFFFFFFFFFULL); a2 = a1 << 1; a4 = a2 << 1; a8 = a4 << 1;
sl@0
   232
sl@0
   233
	tab[ 0] = 0;     tab[ 1] = a1;       tab[ 2] = a2;       tab[ 3] = a1^a2;
sl@0
   234
	tab[ 4] = a4;    tab[ 5] = a1^a4;    tab[ 6] = a2^a4;    tab[ 7] = a1^a2^a4;
sl@0
   235
	tab[ 8] = a8;    tab[ 9] = a1^a8;    tab[10] = a2^a8;    tab[11] = a1^a2^a8;
sl@0
   236
	tab[12] = a4^a8; tab[13] = a1^a4^a8; tab[14] = a2^a4^a8; tab[15] = a1^a2^a4^a8;
sl@0
   237
sl@0
   238
	s = tab[b       & 0xF]; l  = s;
sl@0
   239
	s = tab[b >>  4 & 0xF]; l ^= s <<  4; h  = s >> 60;
sl@0
   240
	s = tab[b >>  8 & 0xF]; l ^= s <<  8; h ^= s >> 56;
sl@0
   241
	s = tab[b >> 12 & 0xF]; l ^= s << 12; h ^= s >> 52;
sl@0
   242
	s = tab[b >> 16 & 0xF]; l ^= s << 16; h ^= s >> 48;
sl@0
   243
	s = tab[b >> 20 & 0xF]; l ^= s << 20; h ^= s >> 44;
sl@0
   244
	s = tab[b >> 24 & 0xF]; l ^= s << 24; h ^= s >> 40;
sl@0
   245
	s = tab[b >> 28 & 0xF]; l ^= s << 28; h ^= s >> 36;
sl@0
   246
	s = tab[b >> 32 & 0xF]; l ^= s << 32; h ^= s >> 32;
sl@0
   247
	s = tab[b >> 36 & 0xF]; l ^= s << 36; h ^= s >> 28;
sl@0
   248
	s = tab[b >> 40 & 0xF]; l ^= s << 40; h ^= s >> 24;
sl@0
   249
	s = tab[b >> 44 & 0xF]; l ^= s << 44; h ^= s >> 20;
sl@0
   250
	s = tab[b >> 48 & 0xF]; l ^= s << 48; h ^= s >> 16;
sl@0
   251
	s = tab[b >> 52 & 0xF]; l ^= s << 52; h ^= s >> 12;
sl@0
   252
	s = tab[b >> 56 & 0xF]; l ^= s << 56; h ^= s >>  8;
sl@0
   253
	s = tab[b >> 60      ]; l ^= s << 60; h ^= s >>  4;
sl@0
   254
sl@0
   255
	/* compensate for the top three bits of a */
sl@0
   256
sl@0
   257
	if (top3b & 01) { l ^= b << 61; h ^= b >> 3; } 
sl@0
   258
	if (top3b & 02) { l ^= b << 62; h ^= b >> 2; } 
sl@0
   259
	if (top3b & 04) { l ^= b << 63; h ^= b >> 1; } 
sl@0
   260
sl@0
   261
	*r1 = h; *r0 = l;
sl@0
   262
	} 
sl@0
   263
#endif
sl@0
   264
sl@0
   265
/* Product of two polynomials a, b each with degree < 2 * BN_BITS2 - 1,
sl@0
   266
 * result is a polynomial r with degree < 4 * BN_BITS2 - 1
sl@0
   267
 * The caller MUST ensure that the variables have the right amount
sl@0
   268
 * of space allocated.
sl@0
   269
 */
sl@0
   270
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)
sl@0
   271
	{
sl@0
   272
	BN_ULONG m1, m0;
sl@0
   273
	/* r[3] = h1, r[2] = h0; r[1] = l1; r[0] = l0 */
sl@0
   274
	bn_GF2m_mul_1x1(r+3, r+2, a1, b1);
sl@0
   275
	bn_GF2m_mul_1x1(r+1, r, a0, b0);
sl@0
   276
	bn_GF2m_mul_1x1(&m1, &m0, a0 ^ a1, b0 ^ b1);
sl@0
   277
	/* Correction on m1 ^= l1 ^ h1; m0 ^= l0 ^ h0; */
sl@0
   278
	r[2] ^= m1 ^ r[1] ^ r[3];  /* h0 ^= m1 ^ l1 ^ h1; */
sl@0
   279
	r[1] = r[3] ^ r[2] ^ r[0] ^ m1 ^ m0;  /* l1 ^= l0 ^ h0 ^ m0; */
sl@0
   280
	}
sl@0
   281
sl@0
   282
sl@0
   283
/* Add polynomials a and b and store result in r; r could be a or b, a and b 
sl@0
   284
 * could be equal; r is the bitwise XOR of a and b.
sl@0
   285
 */
sl@0
   286
EXPORT_C int	BN_GF2m_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
sl@0
   287
	{
sl@0
   288
	int i;
sl@0
   289
	const BIGNUM *at, *bt;
sl@0
   290
sl@0
   291
	bn_check_top(a);
sl@0
   292
	bn_check_top(b);
sl@0
   293
sl@0
   294
	if (a->top < b->top) { at = b; bt = a; }
sl@0
   295
	else { at = a; bt = b; }
sl@0
   296
sl@0
   297
	bn_wexpand(r, at->top);
sl@0
   298
sl@0
   299
	for (i = 0; i < bt->top; i++)
sl@0
   300
		{
sl@0
   301
		r->d[i] = at->d[i] ^ bt->d[i];
sl@0
   302
		}
sl@0
   303
	for (; i < at->top; i++)
sl@0
   304
		{
sl@0
   305
		r->d[i] = at->d[i];
sl@0
   306
		}
sl@0
   307
	
sl@0
   308
	r->top = at->top;
sl@0
   309
	bn_correct_top(r);
sl@0
   310
	
sl@0
   311
	return 1;
sl@0
   312
	}
sl@0
   313
sl@0
   314
sl@0
   315
/* Some functions allow for representation of the irreducible polynomials
sl@0
   316
 * as an int[], say p.  The irreducible f(t) is then of the form:
sl@0
   317
 *     t^p[0] + t^p[1] + ... + t^p[k]
sl@0
   318
 * where m = p[0] > p[1] > ... > p[k] = 0.
sl@0
   319
 */
sl@0
   320
sl@0
   321
sl@0
   322
/* Performs modular reduction of a and store result in r.  r could be a. */
sl@0
   323
EXPORT_C int BN_GF2m_mod_arr(BIGNUM *r, const BIGNUM *a, const unsigned int p[])
sl@0
   324
	{
sl@0
   325
	int j, k;
sl@0
   326
	int n, dN, d0, d1;
sl@0
   327
	BN_ULONG zz, *z;
sl@0
   328
sl@0
   329
	bn_check_top(a);
sl@0
   330
sl@0
   331
	if (!p[0])
sl@0
   332
		{
sl@0
   333
		/* reduction mod 1 => return 0 */
sl@0
   334
		BN_zero(r);
sl@0
   335
		return 1;
sl@0
   336
		}
sl@0
   337
sl@0
   338
	/* Since the algorithm does reduction in the r value, if a != r, copy
sl@0
   339
	 * the contents of a into r so we can do reduction in r. 
sl@0
   340
	 */
sl@0
   341
	if (a != r)
sl@0
   342
		{
sl@0
   343
		if (!bn_wexpand(r, a->top)) return 0;
sl@0
   344
		for (j = 0; j < a->top; j++)
sl@0
   345
			{
sl@0
   346
			r->d[j] = a->d[j];
sl@0
   347
			}
sl@0
   348
		r->top = a->top;
sl@0
   349
		}
sl@0
   350
	z = r->d;
sl@0
   351
sl@0
   352
	/* start reduction */
sl@0
   353
	dN = p[0] / BN_BITS2;  
sl@0
   354
	for (j = r->top - 1; j > dN;)
sl@0
   355
		{
sl@0
   356
		zz = z[j];
sl@0
   357
		if (z[j] == 0) { j--; continue; }
sl@0
   358
		z[j] = 0;
sl@0
   359
sl@0
   360
		for (k = 1; p[k] != 0; k++)
sl@0
   361
			{
sl@0
   362
			/* reducing component t^p[k] */
sl@0
   363
			n = p[0] - p[k];
sl@0
   364
			d0 = n % BN_BITS2;  d1 = BN_BITS2 - d0;
sl@0
   365
			n /= BN_BITS2; 
sl@0
   366
			z[j-n] ^= (zz>>d0);
sl@0
   367
			if (d0) z[j-n-1] ^= (zz<<d1);
sl@0
   368
			}
sl@0
   369
sl@0
   370
		/* reducing component t^0 */
sl@0
   371
		n = dN;  
sl@0
   372
		d0 = p[0] % BN_BITS2;
sl@0
   373
		d1 = BN_BITS2 - d0;
sl@0
   374
		z[j-n] ^= (zz >> d0);
sl@0
   375
		if (d0) z[j-n-1] ^= (zz << d1);
sl@0
   376
		}
sl@0
   377
sl@0
   378
	/* final round of reduction */
sl@0
   379
	while (j == dN)
sl@0
   380
		{
sl@0
   381
sl@0
   382
		d0 = p[0] % BN_BITS2;
sl@0
   383
		zz = z[dN] >> d0;
sl@0
   384
		if (zz == 0) break;
sl@0
   385
		d1 = BN_BITS2 - d0;
sl@0
   386
		
sl@0
   387
		if (d0) z[dN] = (z[dN] << d1) >> d1; /* clear up the top d1 bits */
sl@0
   388
		z[0] ^= zz; /* reduction t^0 component */
sl@0
   389
sl@0
   390
		for (k = 1; p[k] != 0; k++)
sl@0
   391
			{
sl@0
   392
			BN_ULONG tmp_ulong;
sl@0
   393
sl@0
   394
			/* reducing component t^p[k]*/
sl@0
   395
			n = p[k] / BN_BITS2;   
sl@0
   396
			d0 = p[k] % BN_BITS2;
sl@0
   397
			d1 = BN_BITS2 - d0;
sl@0
   398
			z[n] ^= (zz << d0);
sl@0
   399
			tmp_ulong = zz >> d1;
sl@0
   400
                        if (d0 && tmp_ulong)
sl@0
   401
                                z[n+1] ^= tmp_ulong;
sl@0
   402
			}
sl@0
   403
sl@0
   404
		
sl@0
   405
		}
sl@0
   406
sl@0
   407
	bn_correct_top(r);
sl@0
   408
	return 1;
sl@0
   409
	}
sl@0
   410
sl@0
   411
/* Performs modular reduction of a by p and store result in r.  r could be a.
sl@0
   412
 *
sl@0
   413
 * This function calls down to the BN_GF2m_mod_arr implementation; this wrapper
sl@0
   414
 * function is only provided for convenience; for best performance, use the 
sl@0
   415
 * BN_GF2m_mod_arr function.
sl@0
   416
 */
sl@0
   417
EXPORT_C int	BN_GF2m_mod(BIGNUM *r, const BIGNUM *a, const BIGNUM *p)
sl@0
   418
	{
sl@0
   419
	int ret = 0;
sl@0
   420
	const int max = BN_num_bits(p);
sl@0
   421
	unsigned int *arr=NULL;
sl@0
   422
	bn_check_top(a);
sl@0
   423
	bn_check_top(p);
sl@0
   424
	if ((arr = (unsigned int *)OPENSSL_malloc(sizeof(unsigned int) * max)) == NULL) goto err;
sl@0
   425
	ret = BN_GF2m_poly2arr(p, arr, max);
sl@0
   426
	if (!ret || ret > max)
sl@0
   427
		{
sl@0
   428
		BNerr(BN_F_BN_GF2M_MOD,BN_R_INVALID_LENGTH);
sl@0
   429
		goto err;
sl@0
   430
		}
sl@0
   431
	ret = BN_GF2m_mod_arr(r, a, arr);
sl@0
   432
	bn_check_top(r);
sl@0
   433
err:
sl@0
   434
	if (arr) OPENSSL_free(arr);
sl@0
   435
	return ret;
sl@0
   436
	}
sl@0
   437
sl@0
   438
sl@0
   439
/* Compute the product of two polynomials a and b, reduce modulo p, and store
sl@0
   440
 * the result in r.  r could be a or b; a could be b.
sl@0
   441
 */
sl@0
   442
EXPORT_C int	BN_GF2m_mod_mul_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const unsigned int p[], BN_CTX *ctx)
sl@0
   443
	{
sl@0
   444
	int zlen, i, j, k, ret = 0;
sl@0
   445
	BIGNUM *s;
sl@0
   446
	BN_ULONG x1, x0, y1, y0, zz[4];
sl@0
   447
sl@0
   448
	bn_check_top(a);
sl@0
   449
	bn_check_top(b);
sl@0
   450
sl@0
   451
	if (a == b)
sl@0
   452
		{
sl@0
   453
		return BN_GF2m_mod_sqr_arr(r, a, p, ctx);
sl@0
   454
		}
sl@0
   455
sl@0
   456
	BN_CTX_start(ctx);
sl@0
   457
	if ((s = BN_CTX_get(ctx)) == NULL) goto err;
sl@0
   458
	
sl@0
   459
	zlen = a->top + b->top + 4;
sl@0
   460
	if (!bn_wexpand(s, zlen)) goto err;
sl@0
   461
	s->top = zlen;
sl@0
   462
sl@0
   463
	for (i = 0; i < zlen; i++) s->d[i] = 0;
sl@0
   464
sl@0
   465
	for (j = 0; j < b->top; j += 2)
sl@0
   466
		{
sl@0
   467
		y0 = b->d[j];
sl@0
   468
		y1 = ((j+1) == b->top) ? 0 : b->d[j+1];
sl@0
   469
		for (i = 0; i < a->top; i += 2)
sl@0
   470
			{
sl@0
   471
			x0 = a->d[i];
sl@0
   472
			x1 = ((i+1) == a->top) ? 0 : a->d[i+1];
sl@0
   473
			bn_GF2m_mul_2x2(zz, x1, x0, y1, y0);
sl@0
   474
			for (k = 0; k < 4; k++) s->d[i+j+k] ^= zz[k];
sl@0
   475
			}
sl@0
   476
		}
sl@0
   477
sl@0
   478
	bn_correct_top(s);
sl@0
   479
	if (BN_GF2m_mod_arr(r, s, p))
sl@0
   480
		ret = 1;
sl@0
   481
	bn_check_top(r);
sl@0
   482
sl@0
   483
err:
sl@0
   484
	BN_CTX_end(ctx);
sl@0
   485
	return ret;
sl@0
   486
	}
sl@0
   487
sl@0
   488
/* Compute the product of two polynomials a and b, reduce modulo p, and store
sl@0
   489
 * the result in r.  r could be a or b; a could equal b.
sl@0
   490
 *
sl@0
   491
 * This function calls down to the BN_GF2m_mod_mul_arr implementation; this wrapper
sl@0
   492
 * function is only provided for convenience; for best performance, use the 
sl@0
   493
 * BN_GF2m_mod_mul_arr function.
sl@0
   494
 */
sl@0
   495
EXPORT_C int	BN_GF2m_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *p, BN_CTX *ctx)
sl@0
   496
	{
sl@0
   497
	int ret = 0;
sl@0
   498
	const int max = BN_num_bits(p);
sl@0
   499
	unsigned int *arr=NULL;
sl@0
   500
	bn_check_top(a);
sl@0
   501
	bn_check_top(b);
sl@0
   502
	bn_check_top(p);
sl@0
   503
	if ((arr = (unsigned int *)OPENSSL_malloc(sizeof(unsigned int) * max)) == NULL) goto err;
sl@0
   504
	ret = BN_GF2m_poly2arr(p, arr, max);
sl@0
   505
	if (!ret || ret > max)
sl@0
   506
		{
sl@0
   507
		BNerr(BN_F_BN_GF2M_MOD_MUL,BN_R_INVALID_LENGTH);
sl@0
   508
		goto err;
sl@0
   509
		}
sl@0
   510
	ret = BN_GF2m_mod_mul_arr(r, a, b, arr, ctx);
sl@0
   511
	bn_check_top(r);
sl@0
   512
err:
sl@0
   513
	if (arr) OPENSSL_free(arr);
sl@0
   514
	return ret;
sl@0
   515
	}
sl@0
   516
sl@0
   517
sl@0
   518
/* Square a, reduce the result mod p, and store it in a.  r could be a. */
sl@0
   519
EXPORT_C int	BN_GF2m_mod_sqr_arr(BIGNUM *r, const BIGNUM *a, const unsigned int p[], BN_CTX *ctx)
sl@0
   520
	{
sl@0
   521
	int i, ret = 0;
sl@0
   522
	BIGNUM *s;
sl@0
   523
sl@0
   524
	bn_check_top(a);
sl@0
   525
	BN_CTX_start(ctx);
sl@0
   526
	if ((s = BN_CTX_get(ctx)) == NULL) return 0;
sl@0
   527
	if (!bn_wexpand(s, 2 * a->top)) goto err;
sl@0
   528
sl@0
   529
	for (i = a->top - 1; i >= 0; i--)
sl@0
   530
		{
sl@0
   531
		s->d[2*i+1] = SQR1(a->d[i]);
sl@0
   532
		s->d[2*i  ] = SQR0(a->d[i]);
sl@0
   533
		}
sl@0
   534
sl@0
   535
	s->top = 2 * a->top;
sl@0
   536
	bn_correct_top(s);
sl@0
   537
	if (!BN_GF2m_mod_arr(r, s, p)) goto err;
sl@0
   538
	bn_check_top(r);
sl@0
   539
	ret = 1;
sl@0
   540
err:
sl@0
   541
	BN_CTX_end(ctx);
sl@0
   542
	return ret;
sl@0
   543
	}
sl@0
   544
sl@0
   545
/* Square a, reduce the result mod p, and store it in a.  r could be a.
sl@0
   546
 *
sl@0
   547
 * This function calls down to the BN_GF2m_mod_sqr_arr implementation; this wrapper
sl@0
   548
 * function is only provided for convenience; for best performance, use the 
sl@0
   549
 * BN_GF2m_mod_sqr_arr function.
sl@0
   550
 */
sl@0
   551
EXPORT_C int	BN_GF2m_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
sl@0
   552
	{
sl@0
   553
	int ret = 0;
sl@0
   554
	const int max = BN_num_bits(p);
sl@0
   555
	unsigned int *arr=NULL;
sl@0
   556
sl@0
   557
	bn_check_top(a);
sl@0
   558
	bn_check_top(p);
sl@0
   559
	if ((arr = (unsigned int *)OPENSSL_malloc(sizeof(unsigned int) * max)) == NULL) goto err;
sl@0
   560
	ret = BN_GF2m_poly2arr(p, arr, max);
sl@0
   561
	if (!ret || ret > max)
sl@0
   562
		{
sl@0
   563
		BNerr(BN_F_BN_GF2M_MOD_SQR,BN_R_INVALID_LENGTH);
sl@0
   564
		goto err;
sl@0
   565
		}
sl@0
   566
	ret = BN_GF2m_mod_sqr_arr(r, a, arr, ctx);
sl@0
   567
	bn_check_top(r);
sl@0
   568
err:
sl@0
   569
	if (arr) OPENSSL_free(arr);
sl@0
   570
	return ret;
sl@0
   571
	}
sl@0
   572
sl@0
   573
sl@0
   574
/* Invert a, reduce modulo p, and store the result in r. r could be a. 
sl@0
   575
 * Uses Modified Almost Inverse Algorithm (Algorithm 10) from
sl@0
   576
 *     Hankerson, D., Hernandez, J.L., and Menezes, A.  "Software Implementation
sl@0
   577
 *     of Elliptic Curve Cryptography Over Binary Fields".
sl@0
   578
 */
sl@0
   579
EXPORT_C int BN_GF2m_mod_inv(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
sl@0
   580
	{
sl@0
   581
	BIGNUM *b, *c, *u, *v, *tmp;
sl@0
   582
	int ret = 0;
sl@0
   583
sl@0
   584
	bn_check_top(a);
sl@0
   585
	bn_check_top(p);
sl@0
   586
sl@0
   587
	BN_CTX_start(ctx);
sl@0
   588
	
sl@0
   589
	b = BN_CTX_get(ctx);
sl@0
   590
	c = BN_CTX_get(ctx);
sl@0
   591
	u = BN_CTX_get(ctx);
sl@0
   592
	v = BN_CTX_get(ctx);
sl@0
   593
	if (v == NULL) goto err;
sl@0
   594
sl@0
   595
	if (!BN_one(b)) goto err;
sl@0
   596
	if (!BN_GF2m_mod(u, a, p)) goto err;
sl@0
   597
	if (!BN_copy(v, p)) goto err;
sl@0
   598
sl@0
   599
	if (BN_is_zero(u)) goto err;
sl@0
   600
sl@0
   601
	while (1)
sl@0
   602
		{
sl@0
   603
		while (!BN_is_odd(u))
sl@0
   604
			{
sl@0
   605
			if (!BN_rshift1(u, u)) goto err;
sl@0
   606
			if (BN_is_odd(b))
sl@0
   607
				{
sl@0
   608
				if (!BN_GF2m_add(b, b, p)) goto err;
sl@0
   609
				}
sl@0
   610
			if (!BN_rshift1(b, b)) goto err;
sl@0
   611
			}
sl@0
   612
sl@0
   613
		if (BN_abs_is_word(u, 1)) break;
sl@0
   614
sl@0
   615
		if (BN_num_bits(u) < BN_num_bits(v))
sl@0
   616
			{
sl@0
   617
			tmp = u; u = v; v = tmp;
sl@0
   618
			tmp = b; b = c; c = tmp;
sl@0
   619
			}
sl@0
   620
		
sl@0
   621
		if (!BN_GF2m_add(u, u, v)) goto err;
sl@0
   622
		if (!BN_GF2m_add(b, b, c)) goto err;
sl@0
   623
		}
sl@0
   624
sl@0
   625
sl@0
   626
	if (!BN_copy(r, b)) goto err;
sl@0
   627
	bn_check_top(r);
sl@0
   628
	ret = 1;
sl@0
   629
sl@0
   630
err:
sl@0
   631
  	BN_CTX_end(ctx);
sl@0
   632
	return ret;
sl@0
   633
	}
sl@0
   634
sl@0
   635
/* Invert xx, reduce modulo p, and store the result in r. r could be xx. 
sl@0
   636
 *
sl@0
   637
 * This function calls down to the BN_GF2m_mod_inv implementation; this wrapper
sl@0
   638
 * function is only provided for convenience; for best performance, use the 
sl@0
   639
 * BN_GF2m_mod_inv function.
sl@0
   640
 */
sl@0
   641
EXPORT_C int BN_GF2m_mod_inv_arr(BIGNUM *r, const BIGNUM *xx, const unsigned int p[], BN_CTX *ctx)
sl@0
   642
	{
sl@0
   643
	BIGNUM *field;
sl@0
   644
	int ret = 0;
sl@0
   645
sl@0
   646
	bn_check_top(xx);
sl@0
   647
	BN_CTX_start(ctx);
sl@0
   648
	if ((field = BN_CTX_get(ctx)) == NULL) goto err;
sl@0
   649
	if (!BN_GF2m_arr2poly(p, field)) goto err;
sl@0
   650
	
sl@0
   651
	ret = BN_GF2m_mod_inv(r, xx, field, ctx);
sl@0
   652
	bn_check_top(r);
sl@0
   653
sl@0
   654
err:
sl@0
   655
	BN_CTX_end(ctx);
sl@0
   656
	return ret;
sl@0
   657
	}
sl@0
   658
sl@0
   659
sl@0
   660
#ifndef OPENSSL_SUN_GF2M_DIV
sl@0
   661
/* Divide y by x, reduce modulo p, and store the result in r. r could be x 
sl@0
   662
 * or y, x could equal y.
sl@0
   663
 */
sl@0
   664
EXPORT_C int BN_GF2m_mod_div(BIGNUM *r, const BIGNUM *y, const BIGNUM *x, const BIGNUM *p, BN_CTX *ctx)
sl@0
   665
	{
sl@0
   666
	BIGNUM *xinv = NULL;
sl@0
   667
	int ret = 0;
sl@0
   668
sl@0
   669
	bn_check_top(y);
sl@0
   670
	bn_check_top(x);
sl@0
   671
	bn_check_top(p);
sl@0
   672
sl@0
   673
	BN_CTX_start(ctx);
sl@0
   674
	xinv = BN_CTX_get(ctx);
sl@0
   675
	if (xinv == NULL) goto err;
sl@0
   676
	
sl@0
   677
	if (!BN_GF2m_mod_inv(xinv, x, p, ctx)) goto err;
sl@0
   678
	if (!BN_GF2m_mod_mul(r, y, xinv, p, ctx)) goto err;
sl@0
   679
	bn_check_top(r);
sl@0
   680
	ret = 1;
sl@0
   681
sl@0
   682
err:
sl@0
   683
	BN_CTX_end(ctx);
sl@0
   684
	return ret;
sl@0
   685
	}
sl@0
   686
#else
sl@0
   687
/* Divide y by x, reduce modulo p, and store the result in r. r could be x 
sl@0
   688
 * or y, x could equal y.
sl@0
   689
 * Uses algorithm Modular_Division_GF(2^m) from 
sl@0
   690
 *     Chang-Shantz, S.  "From Euclid's GCD to Montgomery Multiplication to 
sl@0
   691
 *     the Great Divide".
sl@0
   692
 */
sl@0
   693
EXPORT_C int BN_GF2m_mod_div(BIGNUM *r, const BIGNUM *y, const BIGNUM *x, const BIGNUM *p, BN_CTX *ctx)
sl@0
   694
	{
sl@0
   695
	BIGNUM *a, *b, *u, *v;
sl@0
   696
	int ret = 0;
sl@0
   697
sl@0
   698
	bn_check_top(y);
sl@0
   699
	bn_check_top(x);
sl@0
   700
	bn_check_top(p);
sl@0
   701
sl@0
   702
	BN_CTX_start(ctx);
sl@0
   703
	
sl@0
   704
	a = BN_CTX_get(ctx);
sl@0
   705
	b = BN_CTX_get(ctx);
sl@0
   706
	u = BN_CTX_get(ctx);
sl@0
   707
	v = BN_CTX_get(ctx);
sl@0
   708
	if (v == NULL) goto err;
sl@0
   709
sl@0
   710
	/* reduce x and y mod p */
sl@0
   711
	if (!BN_GF2m_mod(u, y, p)) goto err;
sl@0
   712
	if (!BN_GF2m_mod(a, x, p)) goto err;
sl@0
   713
	if (!BN_copy(b, p)) goto err;
sl@0
   714
	
sl@0
   715
	while (!BN_is_odd(a))
sl@0
   716
		{
sl@0
   717
		if (!BN_rshift1(a, a)) goto err;
sl@0
   718
		if (BN_is_odd(u)) if (!BN_GF2m_add(u, u, p)) goto err;
sl@0
   719
		if (!BN_rshift1(u, u)) goto err;
sl@0
   720
		}
sl@0
   721
sl@0
   722
	do
sl@0
   723
		{
sl@0
   724
		if (BN_GF2m_cmp(b, a) > 0)
sl@0
   725
			{
sl@0
   726
			if (!BN_GF2m_add(b, b, a)) goto err;
sl@0
   727
			if (!BN_GF2m_add(v, v, u)) goto err;
sl@0
   728
			do
sl@0
   729
				{
sl@0
   730
				if (!BN_rshift1(b, b)) goto err;
sl@0
   731
				if (BN_is_odd(v)) if (!BN_GF2m_add(v, v, p)) goto err;
sl@0
   732
				if (!BN_rshift1(v, v)) goto err;
sl@0
   733
				} while (!BN_is_odd(b));
sl@0
   734
			}
sl@0
   735
		else if (BN_abs_is_word(a, 1))
sl@0
   736
			break;
sl@0
   737
		else
sl@0
   738
			{
sl@0
   739
			if (!BN_GF2m_add(a, a, b)) goto err;
sl@0
   740
			if (!BN_GF2m_add(u, u, v)) goto err;
sl@0
   741
			do
sl@0
   742
				{
sl@0
   743
				if (!BN_rshift1(a, a)) goto err;
sl@0
   744
				if (BN_is_odd(u)) if (!BN_GF2m_add(u, u, p)) goto err;
sl@0
   745
				if (!BN_rshift1(u, u)) goto err;
sl@0
   746
				} while (!BN_is_odd(a));
sl@0
   747
			}
sl@0
   748
		} while (1);
sl@0
   749
sl@0
   750
	if (!BN_copy(r, u)) goto err;
sl@0
   751
	bn_check_top(r);
sl@0
   752
	ret = 1;
sl@0
   753
sl@0
   754
err:
sl@0
   755
  	BN_CTX_end(ctx);
sl@0
   756
	return ret;
sl@0
   757
	}
sl@0
   758
#endif
sl@0
   759
sl@0
   760
/* Divide yy by xx, reduce modulo p, and store the result in r. r could be xx 
sl@0
   761
 * or yy, xx could equal yy.
sl@0
   762
 *
sl@0
   763
 * This function calls down to the BN_GF2m_mod_div implementation; this wrapper
sl@0
   764
 * function is only provided for convenience; for best performance, use the 
sl@0
   765
 * BN_GF2m_mod_div function.
sl@0
   766
 */
sl@0
   767
EXPORT_C int BN_GF2m_mod_div_arr(BIGNUM *r, const BIGNUM *yy, const BIGNUM *xx, const unsigned int p[], BN_CTX *ctx)
sl@0
   768
	{
sl@0
   769
	BIGNUM *field;
sl@0
   770
	int ret = 0;
sl@0
   771
sl@0
   772
	bn_check_top(yy);
sl@0
   773
	bn_check_top(xx);
sl@0
   774
sl@0
   775
	BN_CTX_start(ctx);
sl@0
   776
	if ((field = BN_CTX_get(ctx)) == NULL) goto err;
sl@0
   777
	if (!BN_GF2m_arr2poly(p, field)) goto err;
sl@0
   778
	
sl@0
   779
	ret = BN_GF2m_mod_div(r, yy, xx, field, ctx);
sl@0
   780
	bn_check_top(r);
sl@0
   781
sl@0
   782
err:
sl@0
   783
	BN_CTX_end(ctx);
sl@0
   784
	return ret;
sl@0
   785
	}
sl@0
   786
sl@0
   787
sl@0
   788
/* Compute the bth power of a, reduce modulo p, and store
sl@0
   789
 * the result in r.  r could be a.
sl@0
   790
 * Uses simple square-and-multiply algorithm A.5.1 from IEEE P1363.
sl@0
   791
 */
sl@0
   792
EXPORT_C int	BN_GF2m_mod_exp_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const unsigned int p[], BN_CTX *ctx)
sl@0
   793
	{
sl@0
   794
	int ret = 0, i, n;
sl@0
   795
	BIGNUM *u;
sl@0
   796
sl@0
   797
	bn_check_top(a);
sl@0
   798
	bn_check_top(b);
sl@0
   799
sl@0
   800
	if (BN_is_zero(b))
sl@0
   801
		return(BN_one(r));
sl@0
   802
sl@0
   803
	if (BN_abs_is_word(b, 1))
sl@0
   804
		return (BN_copy(r, a) != NULL);
sl@0
   805
sl@0
   806
	BN_CTX_start(ctx);
sl@0
   807
	if ((u = BN_CTX_get(ctx)) == NULL) goto err;
sl@0
   808
	
sl@0
   809
	if (!BN_GF2m_mod_arr(u, a, p)) goto err;
sl@0
   810
	
sl@0
   811
	n = BN_num_bits(b) - 1;
sl@0
   812
	for (i = n - 1; i >= 0; i--)
sl@0
   813
		{
sl@0
   814
		if (!BN_GF2m_mod_sqr_arr(u, u, p, ctx)) goto err;
sl@0
   815
		if (BN_is_bit_set(b, i))
sl@0
   816
			{
sl@0
   817
			if (!BN_GF2m_mod_mul_arr(u, u, a, p, ctx)) goto err;
sl@0
   818
			}
sl@0
   819
		}
sl@0
   820
	if (!BN_copy(r, u)) goto err;
sl@0
   821
	bn_check_top(r);
sl@0
   822
	ret = 1;
sl@0
   823
err:
sl@0
   824
	BN_CTX_end(ctx);
sl@0
   825
	return ret;
sl@0
   826
	}
sl@0
   827
sl@0
   828
/* Compute the bth power of a, reduce modulo p, and store
sl@0
   829
 * the result in r.  r could be a.
sl@0
   830
 *
sl@0
   831
 * This function calls down to the BN_GF2m_mod_exp_arr implementation; this wrapper
sl@0
   832
 * function is only provided for convenience; for best performance, use the 
sl@0
   833
 * BN_GF2m_mod_exp_arr function.
sl@0
   834
 */
sl@0
   835
EXPORT_C int BN_GF2m_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *p, BN_CTX *ctx)
sl@0
   836
	{
sl@0
   837
	int ret = 0;
sl@0
   838
	const int max = BN_num_bits(p);
sl@0
   839
	unsigned int *arr=NULL;
sl@0
   840
	bn_check_top(a);
sl@0
   841
	bn_check_top(b);
sl@0
   842
	bn_check_top(p);
sl@0
   843
	if ((arr = (unsigned int *)OPENSSL_malloc(sizeof(unsigned int) * max)) == NULL) goto err;
sl@0
   844
	ret = BN_GF2m_poly2arr(p, arr, max);
sl@0
   845
	if (!ret || ret > max)
sl@0
   846
		{
sl@0
   847
		BNerr(BN_F_BN_GF2M_MOD_EXP,BN_R_INVALID_LENGTH);
sl@0
   848
		goto err;
sl@0
   849
		}
sl@0
   850
	ret = BN_GF2m_mod_exp_arr(r, a, b, arr, ctx);
sl@0
   851
	bn_check_top(r);
sl@0
   852
err:
sl@0
   853
	if (arr) OPENSSL_free(arr);
sl@0
   854
	return ret;
sl@0
   855
	}
sl@0
   856
sl@0
   857
/* Compute the square root of a, reduce modulo p, and store
sl@0
   858
 * the result in r.  r could be a.
sl@0
   859
 * Uses exponentiation as in algorithm A.4.1 from IEEE P1363.
sl@0
   860
 */
sl@0
   861
EXPORT_C int	BN_GF2m_mod_sqrt_arr(BIGNUM *r, const BIGNUM *a, const unsigned int p[], BN_CTX *ctx)
sl@0
   862
	{
sl@0
   863
	int ret = 0;
sl@0
   864
	BIGNUM *u;
sl@0
   865
sl@0
   866
	bn_check_top(a);
sl@0
   867
sl@0
   868
	if (!p[0])
sl@0
   869
		{
sl@0
   870
		/* reduction mod 1 => return 0 */
sl@0
   871
		BN_zero(r);
sl@0
   872
		return 1;
sl@0
   873
		}
sl@0
   874
sl@0
   875
	BN_CTX_start(ctx);
sl@0
   876
	if ((u = BN_CTX_get(ctx)) == NULL) goto err;
sl@0
   877
	
sl@0
   878
	if (!BN_set_bit(u, p[0] - 1)) goto err;
sl@0
   879
	ret = BN_GF2m_mod_exp_arr(r, a, u, p, ctx);
sl@0
   880
	bn_check_top(r);
sl@0
   881
sl@0
   882
err:
sl@0
   883
	BN_CTX_end(ctx);
sl@0
   884
	return ret;
sl@0
   885
	}
sl@0
   886
sl@0
   887
/* Compute the square root of a, reduce modulo p, and store
sl@0
   888
 * the result in r.  r could be a.
sl@0
   889
 *
sl@0
   890
 * This function calls down to the BN_GF2m_mod_sqrt_arr implementation; this wrapper
sl@0
   891
 * function is only provided for convenience; for best performance, use the 
sl@0
   892
 * BN_GF2m_mod_sqrt_arr function.
sl@0
   893
 */
sl@0
   894
EXPORT_C int BN_GF2m_mod_sqrt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
sl@0
   895
	{
sl@0
   896
	int ret = 0;
sl@0
   897
	const int max = BN_num_bits(p);
sl@0
   898
	unsigned int *arr=NULL;
sl@0
   899
	bn_check_top(a);
sl@0
   900
	bn_check_top(p);
sl@0
   901
	if ((arr = (unsigned int *)OPENSSL_malloc(sizeof(unsigned int) * max)) == NULL) goto err;
sl@0
   902
	ret = BN_GF2m_poly2arr(p, arr, max);
sl@0
   903
	if (!ret || ret > max)
sl@0
   904
		{
sl@0
   905
		BNerr(BN_F_BN_GF2M_MOD_SQRT,BN_R_INVALID_LENGTH);
sl@0
   906
		goto err;
sl@0
   907
		}
sl@0
   908
	ret = BN_GF2m_mod_sqrt_arr(r, a, arr, ctx);
sl@0
   909
	bn_check_top(r);
sl@0
   910
err:
sl@0
   911
	if (arr) OPENSSL_free(arr);
sl@0
   912
	return ret;
sl@0
   913
	}
sl@0
   914
sl@0
   915
/* Find r such that r^2 + r = a mod p.  r could be a. If no r exists returns 0.
sl@0
   916
 * Uses algorithms A.4.7 and A.4.6 from IEEE P1363.
sl@0
   917
 */
sl@0
   918
EXPORT_C int BN_GF2m_mod_solve_quad_arr(BIGNUM *r, const BIGNUM *a_, const unsigned int p[], BN_CTX *ctx)
sl@0
   919
	{
sl@0
   920
	int ret = 0, count = 0;
sl@0
   921
	unsigned int j;
sl@0
   922
	BIGNUM *a, *z, *rho, *w, *w2, *tmp;
sl@0
   923
sl@0
   924
	bn_check_top(a_);
sl@0
   925
sl@0
   926
	if (!p[0])
sl@0
   927
		{
sl@0
   928
		/* reduction mod 1 => return 0 */
sl@0
   929
		BN_zero(r);
sl@0
   930
		return 1;
sl@0
   931
		}
sl@0
   932
sl@0
   933
	BN_CTX_start(ctx);
sl@0
   934
	a = BN_CTX_get(ctx);
sl@0
   935
	z = BN_CTX_get(ctx);
sl@0
   936
	w = BN_CTX_get(ctx);
sl@0
   937
	if (w == NULL) goto err;
sl@0
   938
sl@0
   939
	if (!BN_GF2m_mod_arr(a, a_, p)) goto err;
sl@0
   940
	
sl@0
   941
	if (BN_is_zero(a))
sl@0
   942
		{
sl@0
   943
		BN_zero(r);
sl@0
   944
		ret = 1;
sl@0
   945
		goto err;
sl@0
   946
		}
sl@0
   947
sl@0
   948
	if (p[0] & 0x1) /* m is odd */
sl@0
   949
		{
sl@0
   950
		/* compute half-trace of a */
sl@0
   951
		if (!BN_copy(z, a)) goto err;
sl@0
   952
		for (j = 1; j <= (p[0] - 1) / 2; j++)
sl@0
   953
			{
sl@0
   954
			if (!BN_GF2m_mod_sqr_arr(z, z, p, ctx)) goto err;
sl@0
   955
			if (!BN_GF2m_mod_sqr_arr(z, z, p, ctx)) goto err;
sl@0
   956
			if (!BN_GF2m_add(z, z, a)) goto err;
sl@0
   957
			}
sl@0
   958
		
sl@0
   959
		}
sl@0
   960
	else /* m is even */
sl@0
   961
		{
sl@0
   962
		rho = BN_CTX_get(ctx);
sl@0
   963
		w2 = BN_CTX_get(ctx);
sl@0
   964
		tmp = BN_CTX_get(ctx);
sl@0
   965
		if (tmp == NULL) goto err;
sl@0
   966
		do
sl@0
   967
			{
sl@0
   968
			if (!BN_rand(rho, p[0], 0, 0)) goto err;
sl@0
   969
			if (!BN_GF2m_mod_arr(rho, rho, p)) goto err;
sl@0
   970
			BN_zero(z);
sl@0
   971
			if (!BN_copy(w, rho)) goto err;
sl@0
   972
			for (j = 1; j <= p[0] - 1; j++)
sl@0
   973
				{
sl@0
   974
				if (!BN_GF2m_mod_sqr_arr(z, z, p, ctx)) goto err;
sl@0
   975
				if (!BN_GF2m_mod_sqr_arr(w2, w, p, ctx)) goto err;
sl@0
   976
				if (!BN_GF2m_mod_mul_arr(tmp, w2, a, p, ctx)) goto err;
sl@0
   977
				if (!BN_GF2m_add(z, z, tmp)) goto err;
sl@0
   978
				if (!BN_GF2m_add(w, w2, rho)) goto err;
sl@0
   979
				}
sl@0
   980
			count++;
sl@0
   981
			} while (BN_is_zero(w) && (count < MAX_ITERATIONS));
sl@0
   982
		if (BN_is_zero(w))
sl@0
   983
			{
sl@0
   984
			BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR,BN_R_TOO_MANY_ITERATIONS);
sl@0
   985
			goto err;
sl@0
   986
			}
sl@0
   987
		}
sl@0
   988
	
sl@0
   989
	if (!BN_GF2m_mod_sqr_arr(w, z, p, ctx)) goto err;
sl@0
   990
	if (!BN_GF2m_add(w, z, w)) goto err;
sl@0
   991
	if (BN_GF2m_cmp(w, a))
sl@0
   992
		{
sl@0
   993
		BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR, BN_R_NO_SOLUTION);
sl@0
   994
		goto err;
sl@0
   995
		}
sl@0
   996
sl@0
   997
	if (!BN_copy(r, z)) goto err;
sl@0
   998
	bn_check_top(r);
sl@0
   999
sl@0
  1000
	ret = 1;
sl@0
  1001
sl@0
  1002
err:
sl@0
  1003
	BN_CTX_end(ctx);
sl@0
  1004
	return ret;
sl@0
  1005
	}
sl@0
  1006
sl@0
  1007
/* Find r such that r^2 + r = a mod p.  r could be a. If no r exists returns 0.
sl@0
  1008
 *
sl@0
  1009
 * This function calls down to the BN_GF2m_mod_solve_quad_arr implementation; this wrapper
sl@0
  1010
 * function is only provided for convenience; for best performance, use the 
sl@0
  1011
 * BN_GF2m_mod_solve_quad_arr function.
sl@0
  1012
 */
sl@0
  1013
EXPORT_C int BN_GF2m_mod_solve_quad(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
sl@0
  1014
	{
sl@0
  1015
	int ret = 0;
sl@0
  1016
	const int max = BN_num_bits(p);
sl@0
  1017
	unsigned int *arr=NULL;
sl@0
  1018
	bn_check_top(a);
sl@0
  1019
	bn_check_top(p);
sl@0
  1020
	if ((arr = (unsigned int *)OPENSSL_malloc(sizeof(unsigned int) *
sl@0
  1021
						max)) == NULL) goto err;
sl@0
  1022
	ret = BN_GF2m_poly2arr(p, arr, max);
sl@0
  1023
	if (!ret || ret > max)
sl@0
  1024
		{
sl@0
  1025
		BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD,BN_R_INVALID_LENGTH);
sl@0
  1026
		goto err;
sl@0
  1027
		}
sl@0
  1028
	ret = BN_GF2m_mod_solve_quad_arr(r, a, arr, ctx);
sl@0
  1029
	bn_check_top(r);
sl@0
  1030
err:
sl@0
  1031
	if (arr) OPENSSL_free(arr);
sl@0
  1032
	return ret;
sl@0
  1033
	}
sl@0
  1034
sl@0
  1035
/* Convert the bit-string representation of a polynomial
sl@0
  1036
 * ( \sum_{i=0}^n a_i * x^i , where a_0 is *not* zero) into an array
sl@0
  1037
 * of integers corresponding to the bits with non-zero coefficient.
sl@0
  1038
 * Up to max elements of the array will be filled.  Return value is total
sl@0
  1039
 * number of coefficients that would be extracted if array was large enough.
sl@0
  1040
 */
sl@0
  1041
EXPORT_C int BN_GF2m_poly2arr(const BIGNUM *a, unsigned int p[], int max)
sl@0
  1042
	{
sl@0
  1043
	int i, j, k = 0;
sl@0
  1044
	BN_ULONG mask;
sl@0
  1045
sl@0
  1046
	if (BN_is_zero(a) || !BN_is_bit_set(a, 0))
sl@0
  1047
		/* a_0 == 0 => return error (the unsigned int array
sl@0
  1048
		 * must be terminated by 0)
sl@0
  1049
		 */
sl@0
  1050
		return 0;
sl@0
  1051
sl@0
  1052
	for (i = a->top - 1; i >= 0; i--)
sl@0
  1053
		{
sl@0
  1054
		if (!a->d[i])
sl@0
  1055
			/* skip word if a->d[i] == 0 */
sl@0
  1056
			continue;
sl@0
  1057
		mask = BN_TBIT;
sl@0
  1058
		for (j = BN_BITS2 - 1; j >= 0; j--)
sl@0
  1059
			{
sl@0
  1060
			if (a->d[i] & mask) 
sl@0
  1061
				{
sl@0
  1062
				if (k < max) p[k] = BN_BITS2 * i + j;
sl@0
  1063
				k++;
sl@0
  1064
				}
sl@0
  1065
			mask >>= 1;
sl@0
  1066
			}
sl@0
  1067
		}
sl@0
  1068
sl@0
  1069
	return k;
sl@0
  1070
	}
sl@0
  1071
sl@0
  1072
/* Convert the coefficient array representation of a polynomial to a 
sl@0
  1073
 * bit-string.  The array must be terminated by 0.
sl@0
  1074
 */
sl@0
  1075
EXPORT_C int BN_GF2m_arr2poly(const unsigned int p[], BIGNUM *a)
sl@0
  1076
	{
sl@0
  1077
	int i;
sl@0
  1078
sl@0
  1079
	bn_check_top(a);
sl@0
  1080
	BN_zero(a);
sl@0
  1081
	for (i = 0; p[i] != 0; i++)
sl@0
  1082
		{
sl@0
  1083
  		if (BN_set_bit(a, p[i]) == 0)
sl@0
  1084
			return 0;
sl@0
  1085
sl@0
  1086
		}
sl@0
  1087
	BN_set_bit(a, 0);
sl@0
  1088
	bn_check_top(a);
sl@0
  1089
sl@0
  1090
	return 1;
sl@0
  1091
	}
sl@0
  1092