os/ossrv/ssl/libcrypto/src/crypto/bn/bn_mul.c
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200 (2012-06-15)
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
/* crypto/bn/bn_mul.c */
sl@0
     2
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
sl@0
     3
 * All rights reserved.
sl@0
     4
 *
sl@0
     5
 * This package is an SSL implementation written
sl@0
     6
 * by Eric Young (eay@cryptsoft.com).
sl@0
     7
 * The implementation was written so as to conform with Netscapes SSL.
sl@0
     8
 * 
sl@0
     9
 * This library is free for commercial and non-commercial use as long as
sl@0
    10
 * the following conditions are aheared to.  The following conditions
sl@0
    11
 * apply to all code found in this distribution, be it the RC4, RSA,
sl@0
    12
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
sl@0
    13
 * included with this distribution is covered by the same copyright terms
sl@0
    14
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
sl@0
    15
 * 
sl@0
    16
 * Copyright remains Eric Young's, and as such any Copyright notices in
sl@0
    17
 * the code are not to be removed.
sl@0
    18
 * If this package is used in a product, Eric Young should be given attribution
sl@0
    19
 * as the author of the parts of the library used.
sl@0
    20
 * This can be in the form of a textual message at program startup or
sl@0
    21
 * in documentation (online or textual) provided with the package.
sl@0
    22
 * 
sl@0
    23
 * Redistribution and use in source and binary forms, with or without
sl@0
    24
 * modification, are permitted provided that the following conditions
sl@0
    25
 * are met:
sl@0
    26
 * 1. Redistributions of source code must retain the copyright
sl@0
    27
 *    notice, this list of conditions and the following disclaimer.
sl@0
    28
 * 2. Redistributions in binary form must reproduce the above copyright
sl@0
    29
 *    notice, this list of conditions and the following disclaimer in the
sl@0
    30
 *    documentation and/or other materials provided with the distribution.
sl@0
    31
 * 3. All advertising materials mentioning features or use of this software
sl@0
    32
 *    must display the following acknowledgement:
sl@0
    33
 *    "This product includes cryptographic software written by
sl@0
    34
 *     Eric Young (eay@cryptsoft.com)"
sl@0
    35
 *    The word 'cryptographic' can be left out if the rouines from the library
sl@0
    36
 *    being used are not cryptographic related :-).
sl@0
    37
 * 4. If you include any Windows specific code (or a derivative thereof) from 
sl@0
    38
 *    the apps directory (application code) you must include an acknowledgement:
sl@0
    39
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
sl@0
    40
 * 
sl@0
    41
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
sl@0
    42
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
sl@0
    43
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
sl@0
    44
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
sl@0
    45
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
sl@0
    46
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
sl@0
    47
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
sl@0
    48
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
sl@0
    49
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
sl@0
    50
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
sl@0
    51
 * SUCH DAMAGE.
sl@0
    52
 * 
sl@0
    53
 * The licence and distribution terms for any publically available version or
sl@0
    54
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
sl@0
    55
 * copied and put under another distribution licence
sl@0
    56
 * [including the GNU Public Licence.]
sl@0
    57
 */
sl@0
    58
sl@0
    59
#ifndef BN_DEBUG
sl@0
    60
# undef NDEBUG /* avoid conflicting definitions */
sl@0
    61
# define NDEBUG
sl@0
    62
#endif
sl@0
    63
sl@0
    64
#include <stdio.h>
sl@0
    65
#include <assert.h>
sl@0
    66
#include "cryptlib.h"
sl@0
    67
#include "bn_lcl.h"
sl@0
    68
sl@0
    69
#if defined(OPENSSL_NO_ASM) || !defined(OPENSSL_BN_ASM_PART_WORDS)
sl@0
    70
/* Here follows specialised variants of bn_add_words() and
sl@0
    71
   bn_sub_words().  They have the property performing operations on
sl@0
    72
   arrays of different sizes.  The sizes of those arrays is expressed through
sl@0
    73
   cl, which is the common length ( basicall, min(len(a),len(b)) ), and dl,
sl@0
    74
   which is the delta between the two lengths, calculated as len(a)-len(b).
sl@0
    75
   All lengths are the number of BN_ULONGs...  For the operations that require
sl@0
    76
   a result array as parameter, it must have the length cl+abs(dl).
sl@0
    77
   These functions should probably end up in bn_asm.c as soon as there are
sl@0
    78
   assembler counterparts for the systems that use assembler files.  */
sl@0
    79
sl@0
    80
EXPORT_C BN_ULONG bn_sub_part_words(BN_ULONG *r,
sl@0
    81
	const BN_ULONG *a, const BN_ULONG *b,
sl@0
    82
	int cl, int dl)
sl@0
    83
	{
sl@0
    84
	BN_ULONG c, t;
sl@0
    85
sl@0
    86
	assert(cl >= 0);
sl@0
    87
	c = bn_sub_words(r, a, b, cl);
sl@0
    88
sl@0
    89
	if (dl == 0)
sl@0
    90
		return c;
sl@0
    91
sl@0
    92
	r += cl;
sl@0
    93
	a += cl;
sl@0
    94
	b += cl;
sl@0
    95
sl@0
    96
	if (dl < 0)
sl@0
    97
		{
sl@0
    98
#ifdef BN_COUNT
sl@0
    99
		fprintf(stderr, "  bn_sub_part_words %d + %d (dl < 0, c = %d)\n", cl, dl, c);
sl@0
   100
#endif
sl@0
   101
		for (;;)
sl@0
   102
			{
sl@0
   103
			t = b[0];
sl@0
   104
			r[0] = (0-t-c)&BN_MASK2;
sl@0
   105
			if (t != 0) c=1;
sl@0
   106
			if (++dl >= 0) break;
sl@0
   107
sl@0
   108
			t = b[1];
sl@0
   109
			r[1] = (0-t-c)&BN_MASK2;
sl@0
   110
			if (t != 0) c=1;
sl@0
   111
			if (++dl >= 0) break;
sl@0
   112
sl@0
   113
			t = b[2];
sl@0
   114
			r[2] = (0-t-c)&BN_MASK2;
sl@0
   115
			if (t != 0) c=1;
sl@0
   116
			if (++dl >= 0) break;
sl@0
   117
sl@0
   118
			t = b[3];
sl@0
   119
			r[3] = (0-t-c)&BN_MASK2;
sl@0
   120
			if (t != 0) c=1;
sl@0
   121
			if (++dl >= 0) break;
sl@0
   122
sl@0
   123
			b += 4;
sl@0
   124
			r += 4;
sl@0
   125
			}
sl@0
   126
		}
sl@0
   127
	else
sl@0
   128
		{
sl@0
   129
		int save_dl = dl;
sl@0
   130
#ifdef BN_COUNT
sl@0
   131
		fprintf(stderr, "  bn_sub_part_words %d + %d (dl > 0, c = %d)\n", cl, dl, c);
sl@0
   132
#endif
sl@0
   133
		while(c)
sl@0
   134
			{
sl@0
   135
			t = a[0];
sl@0
   136
			r[0] = (t-c)&BN_MASK2;
sl@0
   137
			if (t != 0) c=0;
sl@0
   138
			if (--dl <= 0) break;
sl@0
   139
sl@0
   140
			t = a[1];
sl@0
   141
			r[1] = (t-c)&BN_MASK2;
sl@0
   142
			if (t != 0) c=0;
sl@0
   143
			if (--dl <= 0) break;
sl@0
   144
sl@0
   145
			t = a[2];
sl@0
   146
			r[2] = (t-c)&BN_MASK2;
sl@0
   147
			if (t != 0) c=0;
sl@0
   148
			if (--dl <= 0) break;
sl@0
   149
sl@0
   150
			t = a[3];
sl@0
   151
			r[3] = (t-c)&BN_MASK2;
sl@0
   152
			if (t != 0) c=0;
sl@0
   153
			if (--dl <= 0) break;
sl@0
   154
sl@0
   155
			save_dl = dl;
sl@0
   156
			a += 4;
sl@0
   157
			r += 4;
sl@0
   158
			}
sl@0
   159
		if (dl > 0)
sl@0
   160
			{
sl@0
   161
#ifdef BN_COUNT
sl@0
   162
			fprintf(stderr, "  bn_sub_part_words %d + %d (dl > 0, c == 0)\n", cl, dl);
sl@0
   163
#endif
sl@0
   164
			if (save_dl > dl)
sl@0
   165
				{
sl@0
   166
				switch (save_dl - dl)
sl@0
   167
					{
sl@0
   168
				case 1:
sl@0
   169
					r[1] = a[1];
sl@0
   170
					if (--dl <= 0) break;
sl@0
   171
				case 2:
sl@0
   172
					r[2] = a[2];
sl@0
   173
					if (--dl <= 0) break;
sl@0
   174
				case 3:
sl@0
   175
					r[3] = a[3];
sl@0
   176
					if (--dl <= 0) break;
sl@0
   177
					}
sl@0
   178
				a += 4;
sl@0
   179
				r += 4;
sl@0
   180
				}
sl@0
   181
			}
sl@0
   182
		if (dl > 0)
sl@0
   183
			{
sl@0
   184
#ifdef BN_COUNT
sl@0
   185
			fprintf(stderr, "  bn_sub_part_words %d + %d (dl > 0, copy)\n", cl, dl);
sl@0
   186
#endif
sl@0
   187
			for(;;)
sl@0
   188
				{
sl@0
   189
				r[0] = a[0];
sl@0
   190
				if (--dl <= 0) break;
sl@0
   191
				r[1] = a[1];
sl@0
   192
				if (--dl <= 0) break;
sl@0
   193
				r[2] = a[2];
sl@0
   194
				if (--dl <= 0) break;
sl@0
   195
				r[3] = a[3];
sl@0
   196
				if (--dl <= 0) break;
sl@0
   197
sl@0
   198
				a += 4;
sl@0
   199
				r += 4;
sl@0
   200
				}
sl@0
   201
			}
sl@0
   202
		}
sl@0
   203
	return c;
sl@0
   204
	}
sl@0
   205
#endif
sl@0
   206
sl@0
   207
EXPORT_C BN_ULONG bn_add_part_words(BN_ULONG *r,
sl@0
   208
	const BN_ULONG *a, const BN_ULONG *b,
sl@0
   209
	int cl, int dl)
sl@0
   210
	{
sl@0
   211
	BN_ULONG c, l, t;
sl@0
   212
sl@0
   213
	assert(cl >= 0);
sl@0
   214
	c = bn_add_words(r, a, b, cl);
sl@0
   215
sl@0
   216
	if (dl == 0)
sl@0
   217
		return c;
sl@0
   218
sl@0
   219
	r += cl;
sl@0
   220
	a += cl;
sl@0
   221
	b += cl;
sl@0
   222
sl@0
   223
	if (dl < 0)
sl@0
   224
		{
sl@0
   225
		int save_dl = dl;
sl@0
   226
#ifdef BN_COUNT
sl@0
   227
		fprintf(stderr, "  bn_add_part_words %d + %d (dl < 0, c = %d)\n", cl, dl, c);
sl@0
   228
#endif
sl@0
   229
		while (c)
sl@0
   230
			{
sl@0
   231
			l=(c+b[0])&BN_MASK2;
sl@0
   232
			c=(l < c);
sl@0
   233
			r[0]=l;
sl@0
   234
			if (++dl >= 0) break;
sl@0
   235
sl@0
   236
			l=(c+b[1])&BN_MASK2;
sl@0
   237
			c=(l < c);
sl@0
   238
			r[1]=l;
sl@0
   239
			if (++dl >= 0) break;
sl@0
   240
sl@0
   241
			l=(c+b[2])&BN_MASK2;
sl@0
   242
			c=(l < c);
sl@0
   243
			r[2]=l;
sl@0
   244
			if (++dl >= 0) break;
sl@0
   245
sl@0
   246
			l=(c+b[3])&BN_MASK2;
sl@0
   247
			c=(l < c);
sl@0
   248
			r[3]=l;
sl@0
   249
			if (++dl >= 0) break;
sl@0
   250
sl@0
   251
			save_dl = dl;
sl@0
   252
			b+=4;
sl@0
   253
			r+=4;
sl@0
   254
			}
sl@0
   255
		if (dl < 0)
sl@0
   256
			{
sl@0
   257
#ifdef BN_COUNT
sl@0
   258
			fprintf(stderr, "  bn_add_part_words %d + %d (dl < 0, c == 0)\n", cl, dl);
sl@0
   259
#endif
sl@0
   260
			if (save_dl < dl)
sl@0
   261
				{
sl@0
   262
				switch (dl - save_dl)
sl@0
   263
					{
sl@0
   264
				case 1:
sl@0
   265
					r[1] = b[1];
sl@0
   266
					if (++dl >= 0) break;
sl@0
   267
				case 2:
sl@0
   268
					r[2] = b[2];
sl@0
   269
					if (++dl >= 0) break;
sl@0
   270
				case 3:
sl@0
   271
					r[3] = b[3];
sl@0
   272
					if (++dl >= 0) break;
sl@0
   273
					}
sl@0
   274
				b += 4;
sl@0
   275
				r += 4;
sl@0
   276
				}
sl@0
   277
			}
sl@0
   278
		if (dl < 0)
sl@0
   279
			{
sl@0
   280
#ifdef BN_COUNT
sl@0
   281
			fprintf(stderr, "  bn_add_part_words %d + %d (dl < 0, copy)\n", cl, dl);
sl@0
   282
#endif
sl@0
   283
			for(;;)
sl@0
   284
				{
sl@0
   285
				r[0] = b[0];
sl@0
   286
				if (++dl >= 0) break;
sl@0
   287
				r[1] = b[1];
sl@0
   288
				if (++dl >= 0) break;
sl@0
   289
				r[2] = b[2];
sl@0
   290
				if (++dl >= 0) break;
sl@0
   291
				r[3] = b[3];
sl@0
   292
				if (++dl >= 0) break;
sl@0
   293
sl@0
   294
				b += 4;
sl@0
   295
				r += 4;
sl@0
   296
				}
sl@0
   297
			}
sl@0
   298
		}
sl@0
   299
	else
sl@0
   300
		{
sl@0
   301
		int save_dl = dl;
sl@0
   302
#ifdef BN_COUNT
sl@0
   303
		fprintf(stderr, "  bn_add_part_words %d + %d (dl > 0)\n", cl, dl);
sl@0
   304
#endif
sl@0
   305
		while (c)
sl@0
   306
			{
sl@0
   307
			t=(a[0]+c)&BN_MASK2;
sl@0
   308
			c=(t < c);
sl@0
   309
			r[0]=t;
sl@0
   310
			if (--dl <= 0) break;
sl@0
   311
sl@0
   312
			t=(a[1]+c)&BN_MASK2;
sl@0
   313
			c=(t < c);
sl@0
   314
			r[1]=t;
sl@0
   315
			if (--dl <= 0) break;
sl@0
   316
sl@0
   317
			t=(a[2]+c)&BN_MASK2;
sl@0
   318
			c=(t < c);
sl@0
   319
			r[2]=t;
sl@0
   320
			if (--dl <= 0) break;
sl@0
   321
sl@0
   322
			t=(a[3]+c)&BN_MASK2;
sl@0
   323
			c=(t < c);
sl@0
   324
			r[3]=t;
sl@0
   325
			if (--dl <= 0) break;
sl@0
   326
sl@0
   327
			save_dl = dl;
sl@0
   328
			a+=4;
sl@0
   329
			r+=4;
sl@0
   330
			}
sl@0
   331
#ifdef BN_COUNT
sl@0
   332
		fprintf(stderr, "  bn_add_part_words %d + %d (dl > 0, c == 0)\n", cl, dl);
sl@0
   333
#endif
sl@0
   334
		if (dl > 0)
sl@0
   335
			{
sl@0
   336
			if (save_dl > dl)
sl@0
   337
				{
sl@0
   338
				switch (save_dl - dl)
sl@0
   339
					{
sl@0
   340
				case 1:
sl@0
   341
					r[1] = a[1];
sl@0
   342
					if (--dl <= 0) break;
sl@0
   343
				case 2:
sl@0
   344
					r[2] = a[2];
sl@0
   345
					if (--dl <= 0) break;
sl@0
   346
				case 3:
sl@0
   347
					r[3] = a[3];
sl@0
   348
					if (--dl <= 0) break;
sl@0
   349
					}
sl@0
   350
				a += 4;
sl@0
   351
				r += 4;
sl@0
   352
				}
sl@0
   353
			}
sl@0
   354
		if (dl > 0)
sl@0
   355
			{
sl@0
   356
#ifdef BN_COUNT
sl@0
   357
			fprintf(stderr, "  bn_add_part_words %d + %d (dl > 0, copy)\n", cl, dl);
sl@0
   358
#endif
sl@0
   359
			for(;;)
sl@0
   360
				{
sl@0
   361
				r[0] = a[0];
sl@0
   362
				if (--dl <= 0) break;
sl@0
   363
				r[1] = a[1];
sl@0
   364
				if (--dl <= 0) break;
sl@0
   365
				r[2] = a[2];
sl@0
   366
				if (--dl <= 0) break;
sl@0
   367
				r[3] = a[3];
sl@0
   368
				if (--dl <= 0) break;
sl@0
   369
sl@0
   370
				a += 4;
sl@0
   371
				r += 4;
sl@0
   372
				}
sl@0
   373
			}
sl@0
   374
		}
sl@0
   375
	return c;
sl@0
   376
	}
sl@0
   377
sl@0
   378
#ifdef BN_RECURSION
sl@0
   379
/* Karatsuba recursive multiplication algorithm
sl@0
   380
 * (cf. Knuth, The Art of Computer Programming, Vol. 2) */
sl@0
   381
sl@0
   382
/* r is 2*n2 words in size,
sl@0
   383
 * a and b are both n2 words in size.
sl@0
   384
 * n2 must be a power of 2.
sl@0
   385
 * We multiply and return the result.
sl@0
   386
 * t must be 2*n2 words in size
sl@0
   387
 * We calculate
sl@0
   388
 * a[0]*b[0]
sl@0
   389
 * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0])
sl@0
   390
 * a[1]*b[1]
sl@0
   391
 */
sl@0
   392
EXPORT_C void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,
sl@0
   393
	int dna, int dnb, BN_ULONG *t)
sl@0
   394
	{
sl@0
   395
	int n=n2/2,c1,c2;
sl@0
   396
	int tna=n+dna, tnb=n+dnb;
sl@0
   397
	unsigned int neg,zero;
sl@0
   398
	BN_ULONG ln,lo,*p;
sl@0
   399
sl@0
   400
# ifdef BN_COUNT
sl@0
   401
	fprintf(stderr," bn_mul_recursive %d * %d\n",n2,n2);
sl@0
   402
# endif
sl@0
   403
# ifdef BN_MUL_COMBA
sl@0
   404
#  if 0
sl@0
   405
	if (n2 == 4)
sl@0
   406
		{
sl@0
   407
		bn_mul_comba4(r,a,b);
sl@0
   408
		return;
sl@0
   409
		}
sl@0
   410
#  endif
sl@0
   411
	/* Only call bn_mul_comba 8 if n2 == 8 and the
sl@0
   412
	 * two arrays are complete [steve]
sl@0
   413
	 */
sl@0
   414
	if (n2 == 8 && dna == 0 && dnb == 0)
sl@0
   415
		{
sl@0
   416
		bn_mul_comba8(r,a,b);
sl@0
   417
		return; 
sl@0
   418
		}
sl@0
   419
# endif /* BN_MUL_COMBA */
sl@0
   420
	/* Else do normal multiply */
sl@0
   421
	if (n2 < BN_MUL_RECURSIVE_SIZE_NORMAL)
sl@0
   422
		{
sl@0
   423
		bn_mul_normal(r,a,n2+dna,b,n2+dnb);
sl@0
   424
		if ((dna + dnb) < 0)
sl@0
   425
			memset(&r[2*n2 + dna + dnb], 0,
sl@0
   426
				sizeof(BN_ULONG) * -(dna + dnb));
sl@0
   427
		return;
sl@0
   428
		}
sl@0
   429
	/* r=(a[0]-a[1])*(b[1]-b[0]) */
sl@0
   430
	c1=bn_cmp_part_words(a,&(a[n]),tna,n-tna);
sl@0
   431
	c2=bn_cmp_part_words(&(b[n]),b,tnb,tnb-n);
sl@0
   432
	zero=neg=0;
sl@0
   433
	switch (c1*3+c2)
sl@0
   434
		{
sl@0
   435
	case -4:
sl@0
   436
		bn_sub_part_words(t,      &(a[n]),a,      tna,tna-n); /* - */
sl@0
   437
		bn_sub_part_words(&(t[n]),b,      &(b[n]),tnb,n-tnb); /* - */
sl@0
   438
		break;
sl@0
   439
	case -3:
sl@0
   440
		zero=1;
sl@0
   441
		break;
sl@0
   442
	case -2:
sl@0
   443
		bn_sub_part_words(t,      &(a[n]),a,      tna,tna-n); /* - */
sl@0
   444
		bn_sub_part_words(&(t[n]),&(b[n]),b,      tnb,tnb-n); /* + */
sl@0
   445
		neg=1;
sl@0
   446
		break;
sl@0
   447
	case -1:
sl@0
   448
	case 0:
sl@0
   449
	case 1:
sl@0
   450
		zero=1;
sl@0
   451
		break;
sl@0
   452
	case 2:
sl@0
   453
		bn_sub_part_words(t,      a,      &(a[n]),tna,n-tna); /* + */
sl@0
   454
		bn_sub_part_words(&(t[n]),b,      &(b[n]),tnb,n-tnb); /* - */
sl@0
   455
		neg=1;
sl@0
   456
		break;
sl@0
   457
	case 3:
sl@0
   458
		zero=1;
sl@0
   459
		break;
sl@0
   460
	case 4:
sl@0
   461
		bn_sub_part_words(t,      a,      &(a[n]),tna,n-tna);
sl@0
   462
		bn_sub_part_words(&(t[n]),&(b[n]),b,      tnb,tnb-n);
sl@0
   463
		break;
sl@0
   464
		}
sl@0
   465
sl@0
   466
# ifdef BN_MUL_COMBA
sl@0
   467
	if (n == 4 && dna == 0 && dnb == 0) /* XXX: bn_mul_comba4 could take
sl@0
   468
					       extra args to do this well */
sl@0
   469
		{
sl@0
   470
		if (!zero)
sl@0
   471
			bn_mul_comba4(&(t[n2]),t,&(t[n]));
sl@0
   472
		else
sl@0
   473
			memset(&(t[n2]),0,8*sizeof(BN_ULONG));
sl@0
   474
		
sl@0
   475
		bn_mul_comba4(r,a,b);
sl@0
   476
		bn_mul_comba4(&(r[n2]),&(a[n]),&(b[n]));
sl@0
   477
		}
sl@0
   478
	else if (n == 8 && dna == 0 && dnb == 0) /* XXX: bn_mul_comba8 could
sl@0
   479
						    take extra args to do this
sl@0
   480
						    well */
sl@0
   481
		{
sl@0
   482
		if (!zero)
sl@0
   483
			bn_mul_comba8(&(t[n2]),t,&(t[n]));
sl@0
   484
		else
sl@0
   485
			memset(&(t[n2]),0,16*sizeof(BN_ULONG));
sl@0
   486
		
sl@0
   487
		bn_mul_comba8(r,a,b);
sl@0
   488
		bn_mul_comba8(&(r[n2]),&(a[n]),&(b[n]));
sl@0
   489
		}
sl@0
   490
	else
sl@0
   491
# endif /* BN_MUL_COMBA */
sl@0
   492
		{
sl@0
   493
		p= &(t[n2*2]);
sl@0
   494
		if (!zero)
sl@0
   495
			bn_mul_recursive(&(t[n2]),t,&(t[n]),n,0,0,p);
sl@0
   496
		else
sl@0
   497
			memset(&(t[n2]),0,n2*sizeof(BN_ULONG));
sl@0
   498
		bn_mul_recursive(r,a,b,n,0,0,p);
sl@0
   499
		bn_mul_recursive(&(r[n2]),&(a[n]),&(b[n]),n,dna,dnb,p);
sl@0
   500
		}
sl@0
   501
sl@0
   502
	/* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign
sl@0
   503
	 * r[10] holds (a[0]*b[0])
sl@0
   504
	 * r[32] holds (b[1]*b[1])
sl@0
   505
	 */
sl@0
   506
sl@0
   507
	c1=(int)(bn_add_words(t,r,&(r[n2]),n2));
sl@0
   508
sl@0
   509
	if (neg) /* if t[32] is negative */
sl@0
   510
		{
sl@0
   511
		c1-=(int)(bn_sub_words(&(t[n2]),t,&(t[n2]),n2));
sl@0
   512
		}
sl@0
   513
	else
sl@0
   514
		{
sl@0
   515
		/* Might have a carry */
sl@0
   516
		c1+=(int)(bn_add_words(&(t[n2]),&(t[n2]),t,n2));
sl@0
   517
		}
sl@0
   518
sl@0
   519
	/* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1])
sl@0
   520
	 * r[10] holds (a[0]*b[0])
sl@0
   521
	 * r[32] holds (b[1]*b[1])
sl@0
   522
	 * c1 holds the carry bits
sl@0
   523
	 */
sl@0
   524
	c1+=(int)(bn_add_words(&(r[n]),&(r[n]),&(t[n2]),n2));
sl@0
   525
	if (c1)
sl@0
   526
		{
sl@0
   527
		p= &(r[n+n2]);
sl@0
   528
		lo= *p;
sl@0
   529
		ln=(lo+c1)&BN_MASK2;
sl@0
   530
		*p=ln;
sl@0
   531
sl@0
   532
		/* The overflow will stop before we over write
sl@0
   533
		 * words we should not overwrite */
sl@0
   534
		if (ln < (BN_ULONG)c1)
sl@0
   535
			{
sl@0
   536
			do	{
sl@0
   537
				p++;
sl@0
   538
				lo= *p;
sl@0
   539
				ln=(lo+1)&BN_MASK2;
sl@0
   540
				*p=ln;
sl@0
   541
				} while (ln == 0);
sl@0
   542
			}
sl@0
   543
		}
sl@0
   544
	}
sl@0
   545
sl@0
   546
/* n+tn is the word length
sl@0
   547
 * t needs to be n*4 is size, as does r */
sl@0
   548
EXPORT_C void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n,
sl@0
   549
	     int tna, int tnb, BN_ULONG *t)
sl@0
   550
	{
sl@0
   551
	int i,j,n2=n*2;
sl@0
   552
	int c1,c2,neg,zero;
sl@0
   553
	BN_ULONG ln,lo,*p;
sl@0
   554
sl@0
   555
# ifdef BN_COUNT
sl@0
   556
	fprintf(stderr," bn_mul_part_recursive (%d+%d) * (%d+%d)\n",
sl@0
   557
		tna, n, tnb, n);
sl@0
   558
# endif
sl@0
   559
	if (n < 8)
sl@0
   560
		{
sl@0
   561
		bn_mul_normal(r,a,n+tna,b,n+tnb);
sl@0
   562
		return;
sl@0
   563
		}
sl@0
   564
sl@0
   565
	/* r=(a[0]-a[1])*(b[1]-b[0]) */
sl@0
   566
	c1=bn_cmp_part_words(a,&(a[n]),tna,n-tna);
sl@0
   567
	c2=bn_cmp_part_words(&(b[n]),b,tnb,tnb-n);
sl@0
   568
	zero=neg=0;
sl@0
   569
	switch (c1*3+c2)
sl@0
   570
		{
sl@0
   571
	case -4:
sl@0
   572
		bn_sub_part_words(t,      &(a[n]),a,      tna,tna-n); /* - */
sl@0
   573
		bn_sub_part_words(&(t[n]),b,      &(b[n]),tnb,n-tnb); /* - */
sl@0
   574
		break;
sl@0
   575
	case -3:
sl@0
   576
		zero=1;
sl@0
   577
		/* break; */
sl@0
   578
	case -2:
sl@0
   579
		bn_sub_part_words(t,      &(a[n]),a,      tna,tna-n); /* - */
sl@0
   580
		bn_sub_part_words(&(t[n]),&(b[n]),b,      tnb,tnb-n); /* + */
sl@0
   581
		neg=1;
sl@0
   582
		break;
sl@0
   583
	case -1:
sl@0
   584
	case 0:
sl@0
   585
	case 1:
sl@0
   586
		zero=1;
sl@0
   587
		/* break; */
sl@0
   588
	case 2:
sl@0
   589
		bn_sub_part_words(t,      a,      &(a[n]),tna,n-tna); /* + */
sl@0
   590
		bn_sub_part_words(&(t[n]),b,      &(b[n]),tnb,n-tnb); /* - */
sl@0
   591
		neg=1;
sl@0
   592
		break;
sl@0
   593
	case 3:
sl@0
   594
		zero=1;
sl@0
   595
		/* break; */
sl@0
   596
	case 4:
sl@0
   597
		bn_sub_part_words(t,      a,      &(a[n]),tna,n-tna);
sl@0
   598
		bn_sub_part_words(&(t[n]),&(b[n]),b,      tnb,tnb-n);
sl@0
   599
		break;
sl@0
   600
		}
sl@0
   601
		/* The zero case isn't yet implemented here. The speedup
sl@0
   602
		   would probably be negligible. */
sl@0
   603
# if 0
sl@0
   604
	if (n == 4)
sl@0
   605
		{
sl@0
   606
		bn_mul_comba4(&(t[n2]),t,&(t[n]));
sl@0
   607
		bn_mul_comba4(r,a,b);
sl@0
   608
		bn_mul_normal(&(r[n2]),&(a[n]),tn,&(b[n]),tn);
sl@0
   609
		memset(&(r[n2+tn*2]),0,sizeof(BN_ULONG)*(n2-tn*2));
sl@0
   610
		}
sl@0
   611
	else
sl@0
   612
# endif
sl@0
   613
	if (n == 8)
sl@0
   614
		{
sl@0
   615
		bn_mul_comba8(&(t[n2]),t,&(t[n]));
sl@0
   616
		bn_mul_comba8(r,a,b);
sl@0
   617
		bn_mul_normal(&(r[n2]),&(a[n]),tna,&(b[n]),tnb);
sl@0
   618
		memset(&(r[n2+tna+tnb]),0,sizeof(BN_ULONG)*(n2-tna-tnb));
sl@0
   619
		}
sl@0
   620
	else
sl@0
   621
		{
sl@0
   622
		p= &(t[n2*2]);
sl@0
   623
		bn_mul_recursive(&(t[n2]),t,&(t[n]),n,0,0,p);
sl@0
   624
		bn_mul_recursive(r,a,b,n,0,0,p);
sl@0
   625
		i=n/2;
sl@0
   626
		/* If there is only a bottom half to the number,
sl@0
   627
		 * just do it */
sl@0
   628
		if (tna > tnb)
sl@0
   629
			j = tna - i;
sl@0
   630
		else
sl@0
   631
			j = tnb - i;
sl@0
   632
		if (j == 0)
sl@0
   633
			{
sl@0
   634
			bn_mul_recursive(&(r[n2]),&(a[n]),&(b[n]),
sl@0
   635
				i,tna-i,tnb-i,p);
sl@0
   636
			memset(&(r[n2+i*2]),0,sizeof(BN_ULONG)*(n2-i*2));
sl@0
   637
			}
sl@0
   638
		else if (j > 0) /* eg, n == 16, i == 8 and tn == 11 */
sl@0
   639
				{
sl@0
   640
				bn_mul_part_recursive(&(r[n2]),&(a[n]),&(b[n]),
sl@0
   641
					i,tna-i,tnb-i,p);
sl@0
   642
				memset(&(r[n2+tna+tnb]),0,
sl@0
   643
					sizeof(BN_ULONG)*(n2-tna-tnb));
sl@0
   644
				}
sl@0
   645
		else /* (j < 0) eg, n == 16, i == 8 and tn == 5 */
sl@0
   646
			{
sl@0
   647
			memset(&(r[n2]),0,sizeof(BN_ULONG)*n2);
sl@0
   648
			if (tna < BN_MUL_RECURSIVE_SIZE_NORMAL
sl@0
   649
				&& tnb < BN_MUL_RECURSIVE_SIZE_NORMAL)
sl@0
   650
				{
sl@0
   651
				bn_mul_normal(&(r[n2]),&(a[n]),tna,&(b[n]),tnb);
sl@0
   652
				}
sl@0
   653
			else
sl@0
   654
				{
sl@0
   655
				for (;;)
sl@0
   656
					{
sl@0
   657
					i/=2;
sl@0
   658
					if (i <= tna && tna == tnb)
sl@0
   659
						{
sl@0
   660
						bn_mul_recursive(&(r[n2]),
sl@0
   661
							&(a[n]),&(b[n]),
sl@0
   662
							i,tna-i,tnb-i,p);
sl@0
   663
						break;
sl@0
   664
						}
sl@0
   665
					else if (i < tna || i < tnb)
sl@0
   666
						{
sl@0
   667
						bn_mul_part_recursive(&(r[n2]),
sl@0
   668
							&(a[n]),&(b[n]),
sl@0
   669
							i,tna-i,tnb-i,p);
sl@0
   670
						break;
sl@0
   671
						}
sl@0
   672
					}
sl@0
   673
				}
sl@0
   674
			}
sl@0
   675
		}
sl@0
   676
sl@0
   677
	/* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign
sl@0
   678
	 * r[10] holds (a[0]*b[0])
sl@0
   679
	 * r[32] holds (b[1]*b[1])
sl@0
   680
	 */
sl@0
   681
sl@0
   682
	c1=(int)(bn_add_words(t,r,&(r[n2]),n2));
sl@0
   683
sl@0
   684
	if (neg) /* if t[32] is negative */
sl@0
   685
		{
sl@0
   686
		c1-=(int)(bn_sub_words(&(t[n2]),t,&(t[n2]),n2));
sl@0
   687
		}
sl@0
   688
	else
sl@0
   689
		{
sl@0
   690
		/* Might have a carry */
sl@0
   691
		c1+=(int)(bn_add_words(&(t[n2]),&(t[n2]),t,n2));
sl@0
   692
		}
sl@0
   693
sl@0
   694
	/* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1])
sl@0
   695
	 * r[10] holds (a[0]*b[0])
sl@0
   696
	 * r[32] holds (b[1]*b[1])
sl@0
   697
	 * c1 holds the carry bits
sl@0
   698
	 */
sl@0
   699
	c1+=(int)(bn_add_words(&(r[n]),&(r[n]),&(t[n2]),n2));
sl@0
   700
	if (c1)
sl@0
   701
		{
sl@0
   702
		p= &(r[n+n2]);
sl@0
   703
		lo= *p;
sl@0
   704
		ln=(lo+c1)&BN_MASK2;
sl@0
   705
		*p=ln;
sl@0
   706
sl@0
   707
		/* The overflow will stop before we over write
sl@0
   708
		 * words we should not overwrite */
sl@0
   709
		if (ln < (BN_ULONG)c1)
sl@0
   710
			{
sl@0
   711
			do	{
sl@0
   712
				p++;
sl@0
   713
				lo= *p;
sl@0
   714
				ln=(lo+1)&BN_MASK2;
sl@0
   715
				*p=ln;
sl@0
   716
				} while (ln == 0);
sl@0
   717
			}
sl@0
   718
		}
sl@0
   719
	}
sl@0
   720
sl@0
   721
/* a and b must be the same size, which is n2.
sl@0
   722
 * r needs to be n2 words and t needs to be n2*2
sl@0
   723
 */
sl@0
   724
EXPORT_C void bn_mul_low_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,
sl@0
   725
	     BN_ULONG *t)
sl@0
   726
	{
sl@0
   727
	int n=n2/2;
sl@0
   728
sl@0
   729
# ifdef BN_COUNT
sl@0
   730
	fprintf(stderr," bn_mul_low_recursive %d * %d\n",n2,n2);
sl@0
   731
# endif
sl@0
   732
sl@0
   733
	bn_mul_recursive(r,a,b,n,0,0,&(t[0]));
sl@0
   734
	if (n >= BN_MUL_LOW_RECURSIVE_SIZE_NORMAL)
sl@0
   735
		{
sl@0
   736
		bn_mul_low_recursive(&(t[0]),&(a[0]),&(b[n]),n,&(t[n2]));
sl@0
   737
		bn_add_words(&(r[n]),&(r[n]),&(t[0]),n);
sl@0
   738
		bn_mul_low_recursive(&(t[0]),&(a[n]),&(b[0]),n,&(t[n2]));
sl@0
   739
		bn_add_words(&(r[n]),&(r[n]),&(t[0]),n);
sl@0
   740
		}
sl@0
   741
	else
sl@0
   742
		{
sl@0
   743
		bn_mul_low_normal(&(t[0]),&(a[0]),&(b[n]),n);
sl@0
   744
		bn_mul_low_normal(&(t[n]),&(a[n]),&(b[0]),n);
sl@0
   745
		bn_add_words(&(r[n]),&(r[n]),&(t[0]),n);
sl@0
   746
		bn_add_words(&(r[n]),&(r[n]),&(t[n]),n);
sl@0
   747
		}
sl@0
   748
	}
sl@0
   749
sl@0
   750
/* a and b must be the same size, which is n2.
sl@0
   751
 * r needs to be n2 words and t needs to be n2*2
sl@0
   752
 * l is the low words of the output.
sl@0
   753
 * t needs to be n2*3
sl@0
   754
 */
sl@0
   755
EXPORT_C void bn_mul_high(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, BN_ULONG *l, int n2,
sl@0
   756
	     BN_ULONG *t)
sl@0
   757
	{
sl@0
   758
	int i,n;
sl@0
   759
	int c1,c2;
sl@0
   760
	int neg,oneg,zero;
sl@0
   761
	BN_ULONG ll,lc,*lp,*mp;
sl@0
   762
sl@0
   763
# ifdef BN_COUNT
sl@0
   764
	fprintf(stderr," bn_mul_high %d * %d\n",n2,n2);
sl@0
   765
# endif
sl@0
   766
	n=n2/2;
sl@0
   767
sl@0
   768
	/* Calculate (al-ah)*(bh-bl) */
sl@0
   769
	neg=zero=0;
sl@0
   770
	c1=bn_cmp_words(&(a[0]),&(a[n]),n);
sl@0
   771
	c2=bn_cmp_words(&(b[n]),&(b[0]),n);
sl@0
   772
	switch (c1*3+c2)
sl@0
   773
		{
sl@0
   774
	case -4:
sl@0
   775
		bn_sub_words(&(r[0]),&(a[n]),&(a[0]),n);
sl@0
   776
		bn_sub_words(&(r[n]),&(b[0]),&(b[n]),n);
sl@0
   777
		break;
sl@0
   778
	case -3:
sl@0
   779
		zero=1;
sl@0
   780
		break;
sl@0
   781
	case -2:
sl@0
   782
		bn_sub_words(&(r[0]),&(a[n]),&(a[0]),n);
sl@0
   783
		bn_sub_words(&(r[n]),&(b[n]),&(b[0]),n);
sl@0
   784
		neg=1;
sl@0
   785
		break;
sl@0
   786
	case -1:
sl@0
   787
	case 0:
sl@0
   788
	case 1:
sl@0
   789
		zero=1;
sl@0
   790
		break;
sl@0
   791
	case 2:
sl@0
   792
		bn_sub_words(&(r[0]),&(a[0]),&(a[n]),n);
sl@0
   793
		bn_sub_words(&(r[n]),&(b[0]),&(b[n]),n);
sl@0
   794
		neg=1;
sl@0
   795
		break;
sl@0
   796
	case 3:
sl@0
   797
		zero=1;
sl@0
   798
		break;
sl@0
   799
	case 4:
sl@0
   800
		bn_sub_words(&(r[0]),&(a[0]),&(a[n]),n);
sl@0
   801
		bn_sub_words(&(r[n]),&(b[n]),&(b[0]),n);
sl@0
   802
		break;
sl@0
   803
		}
sl@0
   804
		
sl@0
   805
	oneg=neg;
sl@0
   806
	/* t[10] = (a[0]-a[1])*(b[1]-b[0]) */
sl@0
   807
	/* r[10] = (a[1]*b[1]) */
sl@0
   808
# ifdef BN_MUL_COMBA
sl@0
   809
	if (n == 8)
sl@0
   810
		{
sl@0
   811
		bn_mul_comba8(&(t[0]),&(r[0]),&(r[n]));
sl@0
   812
		bn_mul_comba8(r,&(a[n]),&(b[n]));
sl@0
   813
		}
sl@0
   814
	else
sl@0
   815
# endif
sl@0
   816
		{
sl@0
   817
		bn_mul_recursive(&(t[0]),&(r[0]),&(r[n]),n,0,0,&(t[n2]));
sl@0
   818
		bn_mul_recursive(r,&(a[n]),&(b[n]),n,0,0,&(t[n2]));
sl@0
   819
		}
sl@0
   820
sl@0
   821
	/* s0 == low(al*bl)
sl@0
   822
	 * s1 == low(ah*bh)+low((al-ah)*(bh-bl))+low(al*bl)+high(al*bl)
sl@0
   823
	 * We know s0 and s1 so the only unknown is high(al*bl)
sl@0
   824
	 * high(al*bl) == s1 - low(ah*bh+s0+(al-ah)*(bh-bl))
sl@0
   825
	 * high(al*bl) == s1 - (r[0]+l[0]+t[0])
sl@0
   826
	 */
sl@0
   827
	if (l != NULL)
sl@0
   828
		{
sl@0
   829
		lp= &(t[n2+n]);
sl@0
   830
		c1=(int)(bn_add_words(lp,&(r[0]),&(l[0]),n));
sl@0
   831
		}
sl@0
   832
	else
sl@0
   833
		{
sl@0
   834
		c1=0;
sl@0
   835
		lp= &(r[0]);
sl@0
   836
		}
sl@0
   837
sl@0
   838
	if (neg)
sl@0
   839
		neg=(int)(bn_sub_words(&(t[n2]),lp,&(t[0]),n));
sl@0
   840
	else
sl@0
   841
		{
sl@0
   842
		bn_add_words(&(t[n2]),lp,&(t[0]),n);
sl@0
   843
		neg=0;
sl@0
   844
		}
sl@0
   845
sl@0
   846
	if (l != NULL)
sl@0
   847
		{
sl@0
   848
		bn_sub_words(&(t[n2+n]),&(l[n]),&(t[n2]),n);
sl@0
   849
		}
sl@0
   850
	else
sl@0
   851
		{
sl@0
   852
		lp= &(t[n2+n]);
sl@0
   853
		mp= &(t[n2]);
sl@0
   854
		for (i=0; i<n; i++)
sl@0
   855
			lp[i]=((~mp[i])+1)&BN_MASK2;
sl@0
   856
		}
sl@0
   857
sl@0
   858
	/* s[0] = low(al*bl)
sl@0
   859
	 * t[3] = high(al*bl)
sl@0
   860
	 * t[10] = (a[0]-a[1])*(b[1]-b[0]) neg is the sign
sl@0
   861
	 * r[10] = (a[1]*b[1])
sl@0
   862
	 */
sl@0
   863
	/* R[10] = al*bl
sl@0
   864
	 * R[21] = al*bl + ah*bh + (a[0]-a[1])*(b[1]-b[0])
sl@0
   865
	 * R[32] = ah*bh
sl@0
   866
	 */
sl@0
   867
	/* R[1]=t[3]+l[0]+r[0](+-)t[0] (have carry/borrow)
sl@0
   868
	 * R[2]=r[0]+t[3]+r[1](+-)t[1] (have carry/borrow)
sl@0
   869
	 * R[3]=r[1]+(carry/borrow)
sl@0
   870
	 */
sl@0
   871
	if (l != NULL)
sl@0
   872
		{
sl@0
   873
		lp= &(t[n2]);
sl@0
   874
		c1= (int)(bn_add_words(lp,&(t[n2+n]),&(l[0]),n));
sl@0
   875
		}
sl@0
   876
	else
sl@0
   877
		{
sl@0
   878
		lp= &(t[n2+n]);
sl@0
   879
		c1=0;
sl@0
   880
		}
sl@0
   881
	c1+=(int)(bn_add_words(&(t[n2]),lp,  &(r[0]),n));
sl@0
   882
	if (oneg)
sl@0
   883
		c1-=(int)(bn_sub_words(&(t[n2]),&(t[n2]),&(t[0]),n));
sl@0
   884
	else
sl@0
   885
		c1+=(int)(bn_add_words(&(t[n2]),&(t[n2]),&(t[0]),n));
sl@0
   886
sl@0
   887
	c2 =(int)(bn_add_words(&(r[0]),&(r[0]),&(t[n2+n]),n));
sl@0
   888
	c2+=(int)(bn_add_words(&(r[0]),&(r[0]),&(r[n]),n));
sl@0
   889
	if (oneg)
sl@0
   890
		c2-=(int)(bn_sub_words(&(r[0]),&(r[0]),&(t[n]),n));
sl@0
   891
	else
sl@0
   892
		c2+=(int)(bn_add_words(&(r[0]),&(r[0]),&(t[n]),n));
sl@0
   893
	
sl@0
   894
	if (c1 != 0) /* Add starting at r[0], could be +ve or -ve */
sl@0
   895
		{
sl@0
   896
		i=0;
sl@0
   897
		if (c1 > 0)
sl@0
   898
			{
sl@0
   899
			lc=c1;
sl@0
   900
			do	{
sl@0
   901
				ll=(r[i]+lc)&BN_MASK2;
sl@0
   902
				r[i++]=ll;
sl@0
   903
				lc=(lc > ll);
sl@0
   904
				} while (lc);
sl@0
   905
			}
sl@0
   906
		else
sl@0
   907
			{
sl@0
   908
			lc= -c1;
sl@0
   909
			do	{
sl@0
   910
				ll=r[i];
sl@0
   911
				r[i++]=(ll-lc)&BN_MASK2;
sl@0
   912
				lc=(lc > ll);
sl@0
   913
				} while (lc);
sl@0
   914
			}
sl@0
   915
		}
sl@0
   916
	if (c2 != 0) /* Add starting at r[1] */
sl@0
   917
		{
sl@0
   918
		i=n;
sl@0
   919
		if (c2 > 0)
sl@0
   920
			{
sl@0
   921
			lc=c2;
sl@0
   922
			do	{
sl@0
   923
				ll=(r[i]+lc)&BN_MASK2;
sl@0
   924
				r[i++]=ll;
sl@0
   925
				lc=(lc > ll);
sl@0
   926
				} while (lc);
sl@0
   927
			}
sl@0
   928
		else
sl@0
   929
			{
sl@0
   930
			lc= -c2;
sl@0
   931
			do	{
sl@0
   932
				ll=r[i];
sl@0
   933
				r[i++]=(ll-lc)&BN_MASK2;
sl@0
   934
				lc=(lc > ll);
sl@0
   935
				} while (lc);
sl@0
   936
			}
sl@0
   937
		}
sl@0
   938
	}
sl@0
   939
#endif /* BN_RECURSION */
sl@0
   940
sl@0
   941
EXPORT_C int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
sl@0
   942
	{
sl@0
   943
	int ret=0;
sl@0
   944
	int top,al,bl;
sl@0
   945
	BIGNUM *rr;
sl@0
   946
#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
sl@0
   947
	int i;
sl@0
   948
#endif
sl@0
   949
#ifdef BN_RECURSION
sl@0
   950
	BIGNUM *t=NULL;
sl@0
   951
	int j=0,k;
sl@0
   952
#endif
sl@0
   953
sl@0
   954
#ifdef BN_COUNT
sl@0
   955
	fprintf(stderr,"BN_mul %d * %d\n",a->top,b->top);
sl@0
   956
#endif
sl@0
   957
sl@0
   958
	bn_check_top(a);
sl@0
   959
	bn_check_top(b);
sl@0
   960
	bn_check_top(r);
sl@0
   961
sl@0
   962
	al=a->top;
sl@0
   963
	bl=b->top;
sl@0
   964
sl@0
   965
	if ((al == 0) || (bl == 0))
sl@0
   966
		{
sl@0
   967
		BN_zero(r);
sl@0
   968
		return(1);
sl@0
   969
		}
sl@0
   970
	top=al+bl;
sl@0
   971
sl@0
   972
	BN_CTX_start(ctx);
sl@0
   973
	if ((r == a) || (r == b))
sl@0
   974
		{
sl@0
   975
		if ((rr = BN_CTX_get(ctx)) == NULL) goto err;
sl@0
   976
		}
sl@0
   977
	else
sl@0
   978
		rr = r;
sl@0
   979
	rr->neg=a->neg^b->neg;
sl@0
   980
sl@0
   981
#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
sl@0
   982
	i = al-bl;
sl@0
   983
#endif
sl@0
   984
#ifdef BN_MUL_COMBA
sl@0
   985
	if (i == 0)
sl@0
   986
		{
sl@0
   987
# if 0
sl@0
   988
		if (al == 4)
sl@0
   989
			{
sl@0
   990
			if (bn_wexpand(rr,8) == NULL) goto err;
sl@0
   991
			rr->top=8;
sl@0
   992
			bn_mul_comba4(rr->d,a->d,b->d);
sl@0
   993
			goto end;
sl@0
   994
			}
sl@0
   995
# endif
sl@0
   996
		if (al == 8)
sl@0
   997
			{
sl@0
   998
			if (bn_wexpand(rr,16) == NULL) goto err;
sl@0
   999
			rr->top=16;
sl@0
  1000
			bn_mul_comba8(rr->d,a->d,b->d);
sl@0
  1001
			goto end;
sl@0
  1002
			}
sl@0
  1003
		}
sl@0
  1004
#endif /* BN_MUL_COMBA */
sl@0
  1005
#ifdef BN_RECURSION
sl@0
  1006
	if ((al >= BN_MULL_SIZE_NORMAL) && (bl >= BN_MULL_SIZE_NORMAL))
sl@0
  1007
		{
sl@0
  1008
		if (i >= -1 && i <= 1)
sl@0
  1009
			{
sl@0
  1010
			int sav_j =0;
sl@0
  1011
			/* Find out the power of two lower or equal
sl@0
  1012
			   to the longest of the two numbers */
sl@0
  1013
			if (i >= 0)
sl@0
  1014
				{
sl@0
  1015
				j = BN_num_bits_word((BN_ULONG)al);
sl@0
  1016
				}
sl@0
  1017
			if (i == -1)
sl@0
  1018
				{
sl@0
  1019
				j = BN_num_bits_word((BN_ULONG)bl);
sl@0
  1020
				}
sl@0
  1021
			sav_j = j;
sl@0
  1022
			j = 1<<(j-1);
sl@0
  1023
			assert(j <= al || j <= bl);
sl@0
  1024
			k = j+j;
sl@0
  1025
			t = BN_CTX_get(ctx);
sl@0
  1026
			if (al > j || bl > j)
sl@0
  1027
				{
sl@0
  1028
				bn_wexpand(t,k*4);
sl@0
  1029
				bn_wexpand(rr,k*4);
sl@0
  1030
				bn_mul_part_recursive(rr->d,a->d,b->d,
sl@0
  1031
					j,al-j,bl-j,t->d);
sl@0
  1032
				}
sl@0
  1033
			else	/* al <= j || bl <= j */
sl@0
  1034
				{
sl@0
  1035
				bn_wexpand(t,k*2);
sl@0
  1036
				bn_wexpand(rr,k*2);
sl@0
  1037
				bn_mul_recursive(rr->d,a->d,b->d,
sl@0
  1038
					j,al-j,bl-j,t->d);
sl@0
  1039
				}
sl@0
  1040
			rr->top=top;
sl@0
  1041
			goto end;
sl@0
  1042
			}
sl@0
  1043
#if 0
sl@0
  1044
		if (i == 1 && !BN_get_flags(b,BN_FLG_STATIC_DATA))
sl@0
  1045
			{
sl@0
  1046
			BIGNUM *tmp_bn = (BIGNUM *)b;
sl@0
  1047
			if (bn_wexpand(tmp_bn,al) == NULL) goto err;
sl@0
  1048
			tmp_bn->d[bl]=0;
sl@0
  1049
			bl++;
sl@0
  1050
			i--;
sl@0
  1051
			}
sl@0
  1052
		else if (i == -1 && !BN_get_flags(a,BN_FLG_STATIC_DATA))
sl@0
  1053
			{
sl@0
  1054
			BIGNUM *tmp_bn = (BIGNUM *)a;
sl@0
  1055
			if (bn_wexpand(tmp_bn,bl) == NULL) goto err;
sl@0
  1056
			tmp_bn->d[al]=0;
sl@0
  1057
			al++;
sl@0
  1058
			i++;
sl@0
  1059
			}
sl@0
  1060
		if (i == 0)
sl@0
  1061
			{
sl@0
  1062
			/* symmetric and > 4 */
sl@0
  1063
			/* 16 or larger */
sl@0
  1064
			j=BN_num_bits_word((BN_ULONG)al);
sl@0
  1065
			j=1<<(j-1);
sl@0
  1066
			k=j+j;
sl@0
  1067
			t = BN_CTX_get(ctx);
sl@0
  1068
			if (al == j) /* exact multiple */
sl@0
  1069
				{
sl@0
  1070
				if (bn_wexpand(t,k*2) == NULL) goto err;
sl@0
  1071
				if (bn_wexpand(rr,k*2) == NULL) goto err;
sl@0
  1072
				bn_mul_recursive(rr->d,a->d,b->d,al,t->d);
sl@0
  1073
				}
sl@0
  1074
			else
sl@0
  1075
				{
sl@0
  1076
				if (bn_wexpand(t,k*4) == NULL) goto err;
sl@0
  1077
				if (bn_wexpand(rr,k*4) == NULL) goto err;
sl@0
  1078
				bn_mul_part_recursive(rr->d,a->d,b->d,al-j,j,t->d);
sl@0
  1079
				}
sl@0
  1080
			rr->top=top;
sl@0
  1081
			goto end;
sl@0
  1082
			}
sl@0
  1083
#endif
sl@0
  1084
		}
sl@0
  1085
#endif /* BN_RECURSION */
sl@0
  1086
	if (bn_wexpand(rr,top) == NULL) goto err;
sl@0
  1087
	rr->top=top;
sl@0
  1088
	bn_mul_normal(rr->d,a->d,al,b->d,bl);
sl@0
  1089
sl@0
  1090
#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
sl@0
  1091
end:
sl@0
  1092
#endif
sl@0
  1093
	bn_correct_top(rr);
sl@0
  1094
	if (r != rr) BN_copy(r,rr);
sl@0
  1095
	ret=1;
sl@0
  1096
err:
sl@0
  1097
	bn_check_top(r);
sl@0
  1098
	BN_CTX_end(ctx);
sl@0
  1099
	return(ret);
sl@0
  1100
	}
sl@0
  1101
sl@0
  1102
EXPORT_C void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb)
sl@0
  1103
	{
sl@0
  1104
	BN_ULONG *rr;
sl@0
  1105
sl@0
  1106
#ifdef BN_COUNT
sl@0
  1107
	fprintf(stderr," bn_mul_normal %d * %d\n",na,nb);
sl@0
  1108
#endif
sl@0
  1109
sl@0
  1110
	if (na < nb)
sl@0
  1111
		{
sl@0
  1112
		int itmp;
sl@0
  1113
		BN_ULONG *ltmp;
sl@0
  1114
sl@0
  1115
		itmp=na; na=nb; nb=itmp;
sl@0
  1116
		ltmp=a;   a=b;   b=ltmp;
sl@0
  1117
sl@0
  1118
		}
sl@0
  1119
	rr= &(r[na]);
sl@0
  1120
	if (nb <= 0)
sl@0
  1121
		{
sl@0
  1122
		(void)bn_mul_words(r,a,na,0);
sl@0
  1123
		return;
sl@0
  1124
		}
sl@0
  1125
	else
sl@0
  1126
		rr[0]=bn_mul_words(r,a,na,b[0]);
sl@0
  1127
sl@0
  1128
	for (;;)
sl@0
  1129
		{
sl@0
  1130
		if (--nb <= 0) return;
sl@0
  1131
		rr[1]=bn_mul_add_words(&(r[1]),a,na,b[1]);
sl@0
  1132
		if (--nb <= 0) return;
sl@0
  1133
		rr[2]=bn_mul_add_words(&(r[2]),a,na,b[2]);
sl@0
  1134
		if (--nb <= 0) return;
sl@0
  1135
		rr[3]=bn_mul_add_words(&(r[3]),a,na,b[3]);
sl@0
  1136
		if (--nb <= 0) return;
sl@0
  1137
		rr[4]=bn_mul_add_words(&(r[4]),a,na,b[4]);
sl@0
  1138
		rr+=4;
sl@0
  1139
		r+=4;
sl@0
  1140
		b+=4;
sl@0
  1141
		}
sl@0
  1142
	}
sl@0
  1143
sl@0
  1144
EXPORT_C void bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n)
sl@0
  1145
	{
sl@0
  1146
#ifdef BN_COUNT
sl@0
  1147
	fprintf(stderr," bn_mul_low_normal %d * %d\n",n,n);
sl@0
  1148
#endif
sl@0
  1149
	bn_mul_words(r,a,n,b[0]);
sl@0
  1150
sl@0
  1151
	for (;;)
sl@0
  1152
		{
sl@0
  1153
		if (--n <= 0) return;
sl@0
  1154
		bn_mul_add_words(&(r[1]),a,n,b[1]);
sl@0
  1155
		if (--n <= 0) return;
sl@0
  1156
		bn_mul_add_words(&(r[2]),a,n,b[2]);
sl@0
  1157
		if (--n <= 0) return;
sl@0
  1158
		bn_mul_add_words(&(r[3]),a,n,b[3]);
sl@0
  1159
		if (--n <= 0) return;
sl@0
  1160
		bn_mul_add_words(&(r[4]),a,n,b[4]);
sl@0
  1161
		r+=4;
sl@0
  1162
		b+=4;
sl@0
  1163
		}
sl@0
  1164
	}