summaryrefslogtreecommitdiff
path: root/usr/src/lib/libresolv2/common/cylink
diff options
context:
space:
mode:
authorstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
committerstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
commit7c478bd95313f5f23a4c958a745db2134aa03244 (patch)
treec871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/libresolv2/common/cylink
downloadillumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/libresolv2/common/cylink')
-rw-r--r--usr/src/lib/libresolv2/common/cylink/bits.c366
-rw-r--r--usr/src/lib/libresolv2/common/cylink/bn.c138
-rw-r--r--usr/src/lib/libresolv2/common/cylink/bn.h228
-rw-r--r--usr/src/lib/libresolv2/common/cylink/bn00.c76
-rw-r--r--usr/src/lib/libresolv2/common/cylink/bn16.c956
-rw-r--r--usr/src/lib/libresolv2/common/cylink/bn16.h100
-rw-r--r--usr/src/lib/libresolv2/common/cylink/bn32.c956
-rw-r--r--usr/src/lib/libresolv2/common/cylink/bn32.h100
-rw-r--r--usr/src/lib/libresolv2/common/cylink/bn68000.c69
-rw-r--r--usr/src/lib/libresolv2/common/cylink/bn8086.c69
-rw-r--r--usr/src/lib/libresolv2/common/cylink/bninit16.c63
-rw-r--r--usr/src/lib/libresolv2/common/cylink/bninit32.c63
-rw-r--r--usr/src/lib/libresolv2/common/cylink/bnsize00.h83
-rw-r--r--usr/src/lib/libresolv2/common/cylink/c_asm.h140
-rw-r--r--usr/src/lib/libresolv2/common/cylink/cencrint.h262
-rw-r--r--usr/src/lib/libresolv2/common/cylink/ctk_endian.h219
-rw-r--r--usr/src/lib/libresolv2/common/cylink/ctk_prime.c442
-rw-r--r--usr/src/lib/libresolv2/common/cylink/cylink.h89
-rw-r--r--usr/src/lib/libresolv2/common/cylink/dss.c1209
-rw-r--r--usr/src/lib/libresolv2/common/cylink/dssnum.h731
-rw-r--r--usr/src/lib/libresolv2/common/cylink/kludge.h165
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbn.h193
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbn00.c73
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbn16.c3651
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbn16.h188
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbn32.c3650
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbn32.h188
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbn68000.c507
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbn68000.h82
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbn68020.c356
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbn68020.h77
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbn80386.h176
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbn8086.h120
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbnmem.c202
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbnmem.h109
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbnppc.c365
-rw-r--r--usr/src/lib/libresolv2/common/cylink/lbnppc.h105
-rw-r--r--usr/src/lib/libresolv2/common/cylink/legal.c52
-rw-r--r--usr/src/lib/libresolv2/common/cylink/legal.h54
-rw-r--r--usr/src/lib/libresolv2/common/cylink/math.c1158
-rw-r--r--usr/src/lib/libresolv2/common/cylink/ppcasm.h582
-rw-r--r--usr/src/lib/libresolv2/common/cylink/rand.c340
-rw-r--r--usr/src/lib/libresolv2/common/cylink/sha.c706
-rw-r--r--usr/src/lib/libresolv2/common/cylink/sha.h162
-rw-r--r--usr/src/lib/libresolv2/common/cylink/sizetest.c58
-rw-r--r--usr/src/lib/libresolv2/common/cylink/swap.c218
-rw-r--r--usr/src/lib/libresolv2/common/cylink/toolkit.h399
47 files changed, 20295 insertions, 0 deletions
diff --git a/usr/src/lib/libresolv2/common/cylink/bits.c b/usr/src/lib/libresolv2/common/cylink/bits.c
new file mode 100644
index 0000000000..21cadf7a50
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/bits.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/****************************************************************************
+* FILENAME: bit.c PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT
+*
+* FILE STATUS:
+*
+* DESCRIPTION: Bit Utility Functions
+*
+* PUBLIC FUNCTIONS:
+*
+*
+* PRIVATE FUNCTIONS:
+*
+* REVISION HISTORY:
+*
+*
+****************************************************************************/
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/****************************************************************************
+* INCLUDE FILES
+****************************************************************************/
+/* bn files */
+#include "port_before.h"
+#include <sys/types.h>
+#include "bn.h"
+/* system files */
+#ifdef VXD
+#include <vtoolsc.h>
+#else
+#include <stdlib.h>
+#include <string.h>
+#endif
+/* program files */
+#include "cylink.h"
+#include "ctk_endian.h"
+#include "c_asm.h"
+#include "port_after.h"
+
+
+/****************************************************************************
+* NAME: void RShiftL( ord *X,
+* u_int32_t len_X,
+* u_int32_t n_bit )
+*
+* DESCRIPTION: Shift array to the right by n_bit.
+*
+* INPUTS:
+* PARAMETERS:
+* ord *X Pointer to array
+* u_int32_t len_X Length of array
+* u_int32_t n_bit Number of bits
+* OUTPUT:
+* PARAMETERS:
+* ord *X Pointer to array
+*
+* RETURN:
+*
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 14 Oct 94 GKL Second version (big endian support)
+*
+****************************************************************************/
+
+void RShiftL_big( ord *X,
+ u_int32_t len_X,
+ u_int32_t n_bit )
+{
+
+struct BigNum dest;
+bnInit();
+bnBegin(&dest);
+
+dest.ptr = X;
+dest.size = len_X;
+dest.allocated = len_X;
+
+bnRShift(&dest,n_bit);
+
+}
+
+/****************************************************************************
+* NAME: void LShiftL( ord *X,
+* u_int32_t len_X,
+* u_int32_t n_bit )
+*
+* DESCRIPTION: Shifts array to the left by n_bit.
+*
+* INPUTS:
+* PARAMETERS:
+* ord *X Pointer to array
+* u_int32_t len_X Length of array
+* u_int32_t n_bit Number of bits
+* OUTPUT:
+* PARAMETERS:
+* ord *X Pointer to array
+*
+* RETURN:
+*
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 14 Oct 94 GKL Second version (big endian support)
+*
+****************************************************************************/
+
+void LShiftL_big( ord *X,
+ u_int32_t len_X,
+ u_int32_t n_bit )
+{
+struct BigNum dest;
+bnInit();
+bnBegin(&dest);
+
+dest.ptr = X;
+dest.size = len_X;
+dest.allocated = len_X;
+
+bnLShift(&dest,n_bit);
+}
+
+/************9****************************************************************
+* NAME: int RShiftMostBit( ord *a,
+* u_int32_t len )
+*
+* DESCRIPTION: Find a least significant non zero bit
+* and sfift array to the right
+*
+* INPUTS:
+* PARAMETERS:
+* ord *a Pointer to array
+* u_int32_t len Number of elements in number
+* OUTPUT:
+*
+* RETURN:
+* Number of shifted bits
+*
+* REVISION HISTORY:
+*
+*
+* 24 Sep 94 KPZ Initial release
+* 14 Oct 94 GKL Second version (big endian support)
+*
+****************************************************************************/
+
+int RShiftMostBit( ord *a,
+ u_int32_t len )
+{
+
+struct BigNum n;
+bnInit();
+bnBegin(&n);
+
+n.size = len;
+n.ptr = a;
+n.allocated = len;
+
+return (bnMakeOdd(&n));
+
+}
+
+
+/****************************************************************************
+* NAME: void ByteLong (uchar *X, u_int32_t X_bytes,
+* u_int32_t *Y )
+*
+*
+* DESCRIPTION: Transfer bytes to u_int32_t.
+*
+* INPUTS:
+* PARAMETERS:
+* uchar *X Pointer to byte array
+* u_int32_t X_bytes Number of bytes in array
+* OUTPUT:
+* PARAMETERS:
+* u_int32_t *Y Pointer to long arrray
+*
+* RETURN:
+*
+*
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 14 Oct 94 GKL Second version (big endian support)
+*
+****************************************************************************/
+
+void ByteLong( uchar *X,
+ u_int32_t X_bytes,
+ u_int32_t *Y )
+{
+ u_int32_t i, j; /* counters */
+ for ( i = 0, j = 0; j < X_bytes; i++, j += 4)
+ {
+ Y[i] = ( (u_int32_t)X[j] ) | ( ((u_int32_t)X[j+1]) << 8 ) |
+ ( ((u_int32_t)X[j+2]) << 16 ) | ( ((u_int32_t)X[j+3]) << 24 );
+ }
+}
+
+/****************************************************************************
+* NAME: void ByteOrd (uchar *X, u_int32_t X_bytes,
+* ord *Y )
+*
+*
+* DESCRIPTION: Transfer bytes to ord.
+*
+* INPUTS:
+* PARAMETERS:
+* uchar *X Pointer to byte array
+* u_int32_t X_bytes Number of bytes in array
+* OUTPUT:
+* PARAMETERS:
+* ord *Y Pointer to long array
+*
+* RETURN:
+*
+*
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 14 Oct 94 GKL Second version (big endian support)
+*
+****************************************************************************/
+
+void ByteOrd( uchar *X,
+ u_int32_t X_bytes,
+ ord *Y )
+{
+ u_int32_t i, j; /* counters */
+ for ( i = 0, j = 0; j < X_bytes; i++, j += sizeof(ord))
+ {
+ Y[i] = ( (ord)X[j] ) | ( ((ord)X[j+1]) << 8 )
+#ifdef ORD_32
+ | ( ((ord)X[j+2]) << 16 ) | ( ((ord)X[j+3]) << 24 )
+#endif
+ ;
+ }
+}
+
+/****************************************************************************
+* NAME: void OrdByte (ord *X, u_int32_t X_bytes,
+* uchar *Y )
+*
+*
+* DESCRIPTION: Transfer ord to bytes.
+*
+* INPUTS:
+* PARAMETERS:
+* ord *X Pointer to ord array
+* u_int32_t X_bytes Number of bytes in array
+* OUTPUT:
+* PARAMETERS:
+* uchar *Y Pointer to byte array
+*
+* RETURN:
+*
+*
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 14 Oct 94 GKL Second version (big endian support)
+*
+****************************************************************************/
+
+void OrdByte( ord *X,
+ u_int32_t X_bytes,
+ uchar *Y )
+{
+ u_int32_t i, j; /* counters */
+ for ( i=0, j=0; j < X_bytes; i++, j += sizeof(ord))
+ {
+ Y[j] = (uchar ) ( X[i] & 0xff );
+ Y[j+1] = (uchar)( (X[i] >> 8) & 0xff );
+#ifdef ORD_32
+ Y[j+2] = (uchar)( (X[i] >> 16) & 0xff );
+ Y[j+3] = (uchar)( (X[i] >> 24) & 0xff );
+#endif
+ }
+}
+
+/****************************************************************************
+* NAME: void LongByte( u_int32_t *X,
+* u_int32_t X_bytes,
+* uchar *Y )
+*
+* DESCRIPTION: Transfer u_int32_t to bytes.
+*
+* INPUTS:
+* PARAMETERS:
+* u_int32_t *X Pointer to long array
+* u_int32_t X_bytes Number of longs in array
+* OUTPUT:
+* PARAMETERS:
+* uchar *Y Pointer to bytes array
+*
+* RETURN:
+*
+*
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 14 Oct 94 GKL Second version (big endian support)
+*
+****************************************************************************/
+
+void LongByte( u_int32_t *X,
+ u_int32_t X_bytes,
+ uchar *Y )
+{
+ u_int32_t i, j; /* counters */
+ for ( i=0, j=0; j < X_bytes; i++, j += 4)
+ {
+ Y[j] = (uchar ) ( X[i] & 0xff );
+ Y[j+1] = (uchar)( (X[i] >> 8) & 0xff );
+ Y[j+2] = (uchar)( (X[i] >> 16) & 0xff );
+ Y[j+3] = (uchar)( (X[i] >> 24) & 0xff );
+ }
+}
+
+
diff --git a/usr/src/lib/libresolv2/common/cylink/bn.c b/usr/src/lib/libresolv2/common/cylink/bn.c
new file mode 100644
index 0000000000..8825e1dba6
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/bn.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/*
+ * bn.c - the high-level bignum interface
+ *
+ * Copyright (c) 1995 Colin Plumb. All rights reserved.
+ * For licensing and other legal details, see the file legal.c.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "port_before.h"
+#include "bn.h"
+#include "port_after.h"
+
+/* Functions */
+void
+bnBegin(struct BigNum *bn)
+{
+ static int bninit = 0;
+
+ if (!bninit) {
+ bnInit();
+ bninit = 1;
+ }
+
+ bn->ptr = 0;
+ bn->size = 0;
+ bn->allocated = 0;
+}
+
+void
+bnSwap(struct BigNum *a, struct BigNum *b)
+{
+ void *p;
+ unsigned t;
+
+ p = a->ptr;
+ a->ptr = b->ptr;
+ b->ptr = p;
+
+ t = a->size;
+ a->size = b->size;
+ b->size = t;
+
+ t = a->allocated;
+ a->allocated = b->allocated;
+ b->allocated = t;
+}
+
+void (*bnEnd)(struct BigNum *bn);
+int (*bnPrealloc)(struct BigNum *bn, unsigned bits);
+int (*bnCopy)(struct BigNum *dest, struct BigNum const *src);
+void (*bnNorm)(struct BigNum *bn);
+void (*bnExtractBigBytes)(struct BigNum const *bn, unsigned char *dest,
+ unsigned lsbyte, unsigned len);
+int (*bnInsertBigBytes)(struct BigNum *bn, unsigned char const *src,
+ unsigned lsbyte, unsigned len);
+void (*bnExtractLittleBytes)(struct BigNum const *bn, unsigned char *dest,
+ unsigned lsbyte, unsigned len);
+int (*bnInsertLittleBytes)(struct BigNum *bn, unsigned char const *src,
+ unsigned lsbyte, unsigned len);
+unsigned (*bnLSWord)(struct BigNum const *src);
+unsigned (*bnBits)(struct BigNum const *src);
+int (*bnAdd)(struct BigNum *dest, struct BigNum const *src);
+int (*bnSub)(struct BigNum *dest, struct BigNum const *src);
+int (*bnCmpQ)(struct BigNum const *a, unsigned b);
+int (*bnSetQ)(struct BigNum *dest, unsigned src);
+int (*bnAddQ)(struct BigNum *dest, unsigned src);
+int (*bnSubQ)(struct BigNum *dest, unsigned src);
+int (*bnCmp)(struct BigNum const *a, struct BigNum const *b);
+int (*bnSquare)(struct BigNum *dest, struct BigNum const *src);
+int (*bnMul)(struct BigNum *dest, struct BigNum const *a,
+ struct BigNum const *b);
+int (*bnMulQ)(struct BigNum *dest, struct BigNum const *a, unsigned b);
+int (*bnDivMod)(struct BigNum *q, struct BigNum *r, struct BigNum const *n,
+ struct BigNum const *d);
+int (*bnMod)(struct BigNum *dest, struct BigNum const *src,
+ struct BigNum const *d);
+unsigned (*bnModQ)(struct BigNum const *src, unsigned d);
+int (*bnExpMod)(struct BigNum *result, struct BigNum const *n,
+ struct BigNum const *exp, struct BigNum const *mod);
+int (*bnDoubleExpMod)(struct BigNum *dest,
+ struct BigNum const *n1, struct BigNum const *e1,
+ struct BigNum const *n2, struct BigNum const *e2,
+ struct BigNum const *mod);
+int (*bnTwoExpMod)(struct BigNum *n, struct BigNum const *exp,
+ struct BigNum const *mod);
+int (*bnGcd)(struct BigNum *dest, struct BigNum const *a,
+ struct BigNum const *b);
+int (*bnInv)(struct BigNum *dest, struct BigNum const *src,
+ struct BigNum const *mod);
+int (*bnLShift)(struct BigNum *dest, unsigned amt);
+void (*bnRShift)(struct BigNum *dest, unsigned amt);
+unsigned (*bnMakeOdd)(struct BigNum *n);
diff --git a/usr/src/lib/libresolv2/common/cylink/bn.h b/usr/src/lib/libresolv2/common/cylink/bn.h
new file mode 100644
index 0000000000..9246388117
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/bn.h
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/*
+ * bn.h - the interface to the bignum routines.
+ * All functions which return ints can potentially allocate memory
+ * and return -1 if they are unable to. All "const" arguments
+ * are unmodified.
+ *
+ * This is not particularly asymmetric, as some operations are of the
+ * form a = b @ c, while others do a @= b. In general, outputs may not
+ * point to the same struct BigNums as inputs, except as specified
+ * below. This relationship is referred to as "being the same as".
+ * This is not numerical equivalence.
+ *
+ * The "Q" operations take "unsigned" inputs. Higher values of the
+ * extra input may work on some implementations, but 65535 is the
+ * highest portable value. Just because UNSIGNED_MAX is larger than
+ * that, or you know that the word size of the library is larger than that,
+ * that, does *not* mean it's allowed.
+ */
+#ifndef BN_H
+#define BN_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+struct BigNum {
+ void *ptr;
+ unsigned size; /* Note: in (variable-sized) words */
+ unsigned allocated;
+};
+
+/* Functions */
+
+/*
+ * You usually never have to call this function explicitly, as
+ * bnBegin() takes care of it. If the program jumps to address 0,
+ * this function has bot been called.
+ */
+void bnInit(void);
+
+/*
+ * This initializes an empty struct BigNum to a zero value.
+ * Do not use this on a BigNum which has had a value stored in it!
+ */
+void bnBegin(struct BigNum *bn);
+
+/* Swap two BigNums. Cheap. */
+void bnSwap(struct BigNum *a, struct BigNum *b);
+
+/* Reset an initialized bigNum to empty, pending deallocation. */
+extern void (*bnEnd)(struct BigNum *bn);
+
+/*
+ * If you know you'll need space in the number soon, you can use this function
+ * to ensure that there is room for at least "bits" bits. Optional.
+ * Returns <0 on out of memory, but the value is unaffected.
+ */
+extern int (*bnPrealloc)(struct BigNum *bn, unsigned bits);
+
+/* Hopefully obvious. dest = src. dest may be the same as src. */
+extern int (*bnCopy)(struct BigNum *dest, struct BigNum const *src);
+
+/*
+ * Mostly done automatically, but this removes leading zero words from
+ * the internal representation of the BigNum. Use is unclear.
+ */
+extern void (*bnNorm)(struct BigNum *bn);
+
+/*
+ * Move bytes between the given buffer and the given BigNum encoded in
+ * base 256. I.e. after either of these, the buffer will be equal to
+ * (bn / 256^lsbyte) % 256^len. The difference is which is altered to
+ * match the other!
+ */
+extern void (*bnExtractBigBytes)(struct BigNum const *bn,
+ unsigned char *dest, unsigned lsbyte, unsigned len);
+extern int (*bnInsertBigBytes)(struct BigNum *bn, unsigned char const *src,
+ unsigned lsbyte, unsigned len);
+
+/* The same, but the buffer is little-endian. */
+extern void (*bnExtractLittleBytes)(struct BigNum const *bn,
+ unsigned char *dest, unsigned lsbyte, unsigned len);
+extern int (*bnInsertLittleBytes)(struct BigNum *bn, unsigned char const *src,
+ unsigned lsbyte, unsigned len);
+
+/* Return the least-significant bits (at least 16) of the BigNum */
+extern unsigned (*bnLSWord)(struct BigNum const *src);
+
+/*
+ * Return the number of significant bits in the BigNum.
+ * 0 or 1+floor(log2(src))
+ */
+extern unsigned (*bnBits)(struct BigNum const *src);
+
+/*
+ * dest += src. dest and src may be the same. Guaranteed not to
+ * allocate memory unnecessarily, so if you're sure bnBits(dest)
+ * won't change, you don't need to check the return value.
+ */
+extern int (*bnAdd)(struct BigNum *dest, struct BigNum const *src);
+
+/*
+ * dest -= src. dest and src may be the same, but bnSetQ(dest, 0) is faster.
+ * if dest < src, returns +1 and sets dest = src-dest.
+ */
+extern int (*bnSub)(struct BigNum *dest, struct BigNum const *src);
+
+/* Return sign (-1, 0, +1) of a-b. a <=> b --> bnCmpQ(a, b) <=> 0 */
+extern int (*bnCmpQ)(struct BigNum const *a, unsigned b);
+
+/* dest = src, where 0 <= src < 2^16. */
+extern int (*bnSetQ)(struct BigNum *dest, unsigned src);
+
+/* dest += src, where 0 <= src < 2^16 */
+extern int (*bnAddQ)(struct BigNum *dest, unsigned src);
+
+/* dest -= src, where 0 <= src < 2^16 */
+extern int (*bnSubQ)(struct BigNum *dest, unsigned src);
+
+/* Return sign (-1, 0, +1) of a-b. a <=> b --> bnCmp(a, b) <=> 0 */
+extern int (*bnCmp)(struct BigNum const *a, struct BigNum const *b);
+
+/* dest = src^2. dest may be the same as src, but it costs time. */
+extern int (*bnSquare)(struct BigNum *dest, struct BigNum const *src);
+
+/* dest = a * b. dest may be the same as a or b, but it costs time. */
+extern int (*bnMul)(struct BigNum *dest, struct BigNum const *a,
+ struct BigNum const *b);
+
+/* dest = a * b, where 0 <= b < 2^16. dest and a may be the same. */
+extern int (*bnMulQ)(struct BigNum *dest, struct BigNum const *a, unsigned b);
+
+/*
+ * q = n/d, r = n%d. r may be the same as n, but not d,
+ * and q may not be the same as n or d.
+ * re-entrancy issue: this temporarily modifies d, but restores
+ * it for return.
+ */
+extern int (*bnDivMod)(struct BigNum *q, struct BigNum *r,
+ struct BigNum const *n, struct BigNum const *d);
+/*
+ * dest = src % d. dest and src may be the same, but not dest and d.
+ * re-entrancy issue: this temporarily modifies d, but restores
+ * it for return.
+ */
+extern int (*bnMod)(struct BigNum *dest, struct BigNum const *src,
+ struct BigNum const *d);
+
+/* return src % d, where 0 <= d < 2^16. */
+extern unsigned int (*bnModQ)(struct BigNum const *src, unsigned d);
+
+/* n = n^exp, modulo "mod" "mod" *must* be odd */
+extern int (*bnExpMod)(struct BigNum *result, struct BigNum const *n,
+ struct BigNum const *exp, struct BigNum const *mod);
+
+/*
+ * dest = n1^e1 * n2^e2, modulo "mod". "mod" *must* be odd.
+ * dest may be the same as n1 or n2.
+ */
+extern int (*bnDoubleExpMod)(struct BigNum *dest,
+ struct BigNum const *n1, struct BigNum const *e1,
+ struct BigNum const *n2, struct BigNum const *e2,
+ struct BigNum const *mod);
+
+/* n = 2^exp, modulo "mod" "mod" *must* be odd */
+extern int (*bnTwoExpMod)(struct BigNum *n, struct BigNum const *exp,
+ struct BigNum const *mod);
+
+/* dest = gcd(a, b). The inputs may overlap arbitrarily. */
+extern int (*bnGcd)(struct BigNum *dest, struct BigNum const *a,
+ struct BigNum const *b);
+
+/* dest = src^-1, modulo "mod". dest may be the same as src. */
+extern int (*bnInv)(struct BigNum *dest, struct BigNum const *src,
+ struct BigNum const *mod);
+
+/* Shift dest left "amt" places */
+extern int (*bnLShift)(struct BigNum *dest, unsigned amt);
+/* Shift dest right "amt" places, discarding low-order bits */
+extern void (*bnRShift)(struct BigNum *dest, unsigned amt);
+
+/* For the largest 2^k that divides n, divide n by it and return k. */
+extern unsigned (*bnMakeOdd)(struct BigNum *n);
+
+#endif/* !BN_H */
diff --git a/usr/src/lib/libresolv2/common/cylink/bn00.c b/usr/src/lib/libresolv2/common/cylink/bn00.c
new file mode 100644
index 0000000000..affc76dc64
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/bn00.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/*
+ * bn00.c - auto-size-detecting bn??.c file.
+ *
+ * Written in 1995 by Colin Plumb.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "port_before.h"
+#include "bnsize00.h"
+
+
+#if BNSIZE64
+
+/* Include all of the C source file by reference */
+#include "bn64.c"
+#include "bninit64.c"
+
+#elif BNSIZE32
+
+/* Include all of the C source file by reference */
+#include "bn32.c"
+#include "bninit32.c"
+
+#else /* BNSIZE16 */
+
+/* Include all of the C source file by reference */
+#include "bn16.c"
+#include "bninit16.c"
+
+#endif
diff --git a/usr/src/lib/libresolv2/common/cylink/bn16.c b/usr/src/lib/libresolv2/common/cylink/bn16.c
new file mode 100644
index 0000000000..3afa8f4751
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/bn16.c
@@ -0,0 +1,956 @@
+/*
+ * Copyright (c) 2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/*
+ * bn16.c - the high-level bignum interface
+ *
+ * Like lbn16.c, this reserves the string "16" for textual replacement.
+ * The string must not appear anywhere unless it is intended to be replaced
+ * to generate other bignum interface functions.
+ *
+ * Copyright (c) 1995 Colin Plumb. All rights reserved.
+ * For licensing and other legal details, see the file legal.c.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef HAVE_CONFIG_H
+#define HAVE_CONFIG_H 0
+#endif
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * Some compilers complain about #if FOO if FOO isn't defined,
+ * so do the ANSI-mandated thing explicitly...
+ */
+#ifndef NO_ASSERT_H
+#define NO_ASSERT_H 0
+#endif
+#ifndef NO_STRING_H
+#define NO_STRING_H 0
+#endif
+#ifndef HAVE_STRINGS_H
+#define HAVE_STRINGS_H 0
+#endif
+#ifndef NEED_MEMORY_H
+#define NEED_MEMORY_H 0
+#endif
+
+#if !NO_ASSERT_H
+#include <assert.h>
+#else
+#define assert(x) (void)0
+#endif
+
+#if !NO_STRING_H
+#include <string.h> /* for memmove() in bnMakeOdd */
+#elif HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#if NEED_MEMORY_H
+#include <memory.h>
+#endif
+
+/*
+ * This was useful during debugging, so it's left in here.
+ * You can ignore it. DBMALLOC is generally undefined.
+ */
+#ifndef DBMALLOC
+#define DBAMLLOC 0
+#endif
+#if DBMALLOC
+#include "../dbmalloc/malloc.h"
+#define MALLOCDB malloc_chain_check(1)
+#else
+#define MALLOCDB (void)0
+#endif
+
+#include "lbn.h"
+#include "lbn16.h"
+#include "lbnmem.h"
+#include "bn16.h"
+#include "bn.h"
+
+/* Work-arounds for some particularly broken systems */
+#include "kludge.h" /* For memmove() */
+#include <port_after.h>
+
+/* Functions */
+void
+bnInit_16(void)
+{
+ bnEnd = bnEnd_16;
+ bnPrealloc = bnPrealloc_16;
+ bnCopy = bnCopy_16;
+ bnNorm = bnNorm_16;
+ bnExtractBigBytes = bnExtractBigBytes_16;
+ bnInsertBigBytes = bnInsertBigBytes_16;
+ bnExtractLittleBytes = bnExtractLittleBytes_16;
+ bnInsertLittleBytes = bnInsertLittleBytes_16;
+ bnLSWord = bnLSWord_16;
+ bnBits = bnBits_16;
+ bnAdd = bnAdd_16;
+ bnSub = bnSub_16;
+ bnCmpQ = bnCmpQ_16;
+ bnSetQ = bnSetQ_16;
+ bnAddQ = bnAddQ_16;
+ bnSubQ = bnSubQ_16;
+ bnCmp = bnCmp_16;
+ bnSquare = bnSquare_16;
+ bnMul = bnMul_16;
+ bnMulQ = bnMulQ_16;
+ bnDivMod = bnDivMod_16;
+ bnMod = bnMod_16;
+ bnModQ = bnModQ_16;
+ bnExpMod = bnExpMod_16;
+ bnDoubleExpMod = bnDoubleExpMod_16;
+ bnTwoExpMod = bnTwoExpMod_16;
+ bnGcd = bnGcd_16;
+ bnInv = bnInv_16;
+ bnLShift = bnLShift_16;
+ bnRShift = bnRShift_16;
+ bnMakeOdd = bnMakeOdd_16;
+}
+
+void
+bnEnd_16(struct BigNum *bn)
+{
+ if (bn->ptr) {
+ LBNFREE((BNWORD16 *)bn->ptr, bn->allocated);
+ bn->ptr = 0;
+ }
+ bn->size = 0;
+ bn->allocated = 0;
+
+ MALLOCDB;
+}
+
+/* Internal function. It operates in words. */
+static int
+bnResize_16(struct BigNum *bn, unsigned len)
+{
+ void *p;
+
+ /* Round size up: most mallocs impose 8-byte granularity anyway */
+ len = (len + (8/sizeof(BNWORD16) - 1)) & ~(8/sizeof(BNWORD16) - 1);
+ p = LBNREALLOC((BNWORD16 *)bn->ptr, bn->allocated, len);
+ if (!p)
+ return -1;
+ bn->ptr = p;
+ bn->allocated = len;
+
+ MALLOCDB;
+
+ return 0;
+}
+
+#define bnSizeCheck(bn, size) \
+ if (bn->allocated < size && bnResize_16(bn, size) < 0) \
+ return -1
+
+int
+bnPrealloc_16(struct BigNum *bn, unsigned bits)
+{
+ bits = (bits + 16-1)/16;
+ bnSizeCheck(bn, bits);
+ MALLOCDB;
+ return 0;
+}
+
+int
+bnCopy_16(struct BigNum *dest, struct BigNum const *src)
+{
+ bnSizeCheck(dest, src->size);
+ dest->size = src->size;
+ lbnCopy_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, src->size);
+ MALLOCDB;
+ return 0;
+}
+
+void
+bnNorm_16(struct BigNum *bn)
+{
+ bn->size = lbnNorm_16((BNWORD16 *)bn->ptr, bn->size);
+}
+
+/*
+ * Convert a bignum to big-endian bytes. Returns, in big-endian form, a
+ * substring of the bignum starting from lsbyte and "len" bytes long.
+ * Unused high-order (leading) bytes are filled with 0.
+ */
+void
+bnExtractBigBytes_16(struct BigNum const *bn, unsigned char *dest,
+ unsigned lsbyte, unsigned len)
+{
+ unsigned s = bn->size * (16 / 8);
+
+ /* Fill unused leading bytes with 0 */
+ while (s < lsbyte+len) {
+ *dest++ = 0;
+ len--;
+ }
+
+ if (len)
+ lbnExtractBigBytes_16((BNWORD16 *)bn->ptr, dest, lsbyte, len);
+ MALLOCDB;
+}
+
+int
+bnInsertBigBytes_16(struct BigNum *bn, unsigned char const *src,
+ unsigned lsbyte, unsigned len)
+{
+ unsigned s = bn->size;
+ unsigned words = (len+lsbyte+sizeof(BNWORD16)-1) / sizeof(BNWORD16);
+
+ /* Pad with zeros as required */
+ bnSizeCheck(bn, words);
+
+ if (s < words) {
+ lbnZero_16((BNWORD16 *)bn->ptr BIGLITTLE(-s,+s), words-s);
+ s = words;
+ }
+
+ lbnInsertBigBytes_16((BNWORD16 *)bn->ptr, src, lsbyte, len);
+
+ bn->size = lbnNorm_16((BNWORD16 *)bn->ptr, s);
+
+ MALLOCDB;
+ return 0;
+}
+
+
+/*
+ * Convert a bignum to little-endian bytes. Returns, in little-endian form, a
+ * substring of the bignum starting from lsbyte and "len" bytes long.
+ * Unused high-order (trailing) bytes are filled with 0.
+ */
+void
+bnExtractLittleBytes_16(struct BigNum const *bn, unsigned char *dest,
+ unsigned lsbyte, unsigned len)
+{
+ unsigned s = bn->size * (16 / 8);
+
+ /* Fill unused leading bytes with 0 */
+ while (s < lsbyte+len)
+ dest[--len] = 0;
+
+ if (len)
+ lbnExtractLittleBytes_16((BNWORD16 *)bn->ptr, dest,
+ lsbyte, len);
+ MALLOCDB;
+}
+
+int
+bnInsertLittleBytes_16(struct BigNum *bn, unsigned char const *src,
+ unsigned lsbyte, unsigned len)
+{
+ unsigned s = bn->size;
+ unsigned words = (len+lsbyte+sizeof(BNWORD16)-1) / sizeof(BNWORD16);
+
+ /* Pad with zeros as required */
+ bnSizeCheck(bn, words);
+
+ if (s < words) {
+ lbnZero_16((BNWORD16 *)bn->ptr BIGLITTLE(-s,+s), words-s);
+ s = words;
+ }
+
+ lbnInsertLittleBytes_16((BNWORD16 *)bn->ptr, src, lsbyte, len);
+
+ bn->size = lbnNorm_16((BNWORD16 *)bn->ptr, s);
+
+ MALLOCDB;
+ return 0;
+}
+
+/* Return the least-significant word of the input. */
+unsigned
+bnLSWord_16(struct BigNum const *src)
+{
+ return src->size ? (unsigned)((BNWORD16 *)src->ptr)[BIGLITTLE(-1,0)]: 0;
+}
+
+unsigned
+bnBits_16(struct BigNum const *src)
+{
+ return lbnBits_16((BNWORD16 *)src->ptr, src->size);
+}
+
+int
+bnAdd_16(struct BigNum *dest, struct BigNum const *src)
+{
+ unsigned s = src->size, d = dest->size;
+ BNWORD16 t;
+
+ if (!s)
+ return 0;
+
+ bnSizeCheck(dest, s);
+
+ if (d < s) {
+ lbnZero_16((BNWORD16 *)dest->ptr BIGLITTLE(-d,+d), s-d);
+ dest->size = d = s;
+ MALLOCDB;
+ }
+ t = lbnAddN_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, s);
+ MALLOCDB;
+ if (t) {
+ if (d > s) {
+ t = lbnAdd1_16((BNWORD16 *)dest->ptr BIGLITTLE(-s,+s),
+ d-s, t);
+ MALLOCDB;
+ }
+ if (t) {
+ bnSizeCheck(dest, d+1);
+ ((BNWORD16 *)dest->ptr)[BIGLITTLE(-1-d,d)] = t;
+ dest->size = d+1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * dest -= src.
+ * If dest goes negative, this produces the absolute value of
+ * the difference (the negative of the true value) and returns 1.
+ * Otherwise, it returls 0.
+ */
+int
+bnSub_16(struct BigNum *dest, struct BigNum const *src)
+{
+ unsigned s = src->size, d = dest->size;
+ BNWORD16 t;
+
+ if (d < s && d < (s = lbnNorm_16((BNWORD16 *)src->ptr, s))) {
+ bnSizeCheck(dest, s);
+ lbnZero_16((BNWORD16 *)dest->ptr BIGLITTLE(-d,+d), s-d);
+ dest->size = d = s;
+ MALLOCDB;
+ }
+ if (!s)
+ return 0;
+ t = lbnSubN_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, s);
+ MALLOCDB;
+ if (t) {
+ if (d > s) {
+ t = lbnSub1_16((BNWORD16 *)dest->ptr BIGLITTLE(-s,+s),
+ d-s, t);
+ MALLOCDB;
+ }
+ if (t) {
+ lbnNeg_16((BNWORD16 *)dest->ptr, d);
+ dest->size = lbnNorm_16((BNWORD16 *)dest->ptr,
+ dest->size);
+ MALLOCDB;
+ return 1;
+ }
+ }
+ dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, dest->size);
+ return 0;
+}
+
+/*
+ * Compare the BigNum to the given value, which must be < 65536.
+ * Returns -1. 0 or 1 if a<b, a == b or a>b.
+ * a <=> b --> bnCmpQ(a,b) <=> 0
+ */
+int
+bnCmpQ_16(struct BigNum const *a, unsigned b)
+{
+ unsigned t;
+ BNWORD16 v;
+
+ t = lbnNorm_16((BNWORD16 *)a->ptr, a->size);
+ /* If a is more than one word long or zero, it's easy... */
+ if (t != 1)
+ return (t > 1) ? 1 : (b ? -1 : 0);
+ v = (unsigned)((BNWORD16 *)a->ptr)[BIGLITTLE(-1,0)];
+ return (v > b) ? 1 : ((v < b) ? -1 : 0);
+}
+
+int
+bnSetQ_16(struct BigNum *dest, unsigned src)
+{
+ if (src) {
+ bnSizeCheck(dest, 1);
+
+ ((BNWORD16 *)dest->ptr)[BIGLITTLE(-1,0)] = (BNWORD16)src;
+ dest->size = 1;
+ } else {
+ dest->size = 0;
+ }
+ return 0;
+}
+
+int
+bnAddQ_16(struct BigNum *dest, unsigned src)
+{
+ BNWORD16 t;
+
+ if (!dest->size)
+ return bnSetQ(dest, src);
+
+ t = lbnAdd1_16((BNWORD16 *)dest->ptr, dest->size, (BNWORD16)src);
+ MALLOCDB;
+ if (t) {
+ src = dest->size;
+ bnSizeCheck(dest, src+1);
+ ((BNWORD16 *)dest->ptr)[BIGLITTLE(-1-src,src)] = t;
+ dest->size = src+1;
+ }
+ return 0;
+}
+
+/*
+ * Return value as for bnSub: 1 if subtract underflowed, in which
+ * case the return is the negative of the computed value.
+ */
+int
+bnSubQ_16(struct BigNum *dest, unsigned src)
+{
+ BNWORD16 t;
+
+ if (!dest->size)
+ return bnSetQ(dest, src) < 0 ? -1 : (src != 0);
+
+ t = lbnSub1_16((BNWORD16 *)dest->ptr, dest->size, (BNWORD16)src);
+ MALLOCDB;
+ if (t) {
+ /* Underflow. <= 1 word, so do it simply. */
+ lbnNeg_16((BNWORD16 *)dest->ptr, 1);
+ dest->size = 1;
+ return 1;
+ }
+/* Try to normalize? Needing this is going to be very rare. */
+/* dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, dest->size); */
+ return 0;
+}
+
+/*
+ * Compare two BigNums. Returns -1. 0 or 1 if a<b, a == b or a>b.
+ * a <=> b --> bnCmp(a,b) <=> 0
+ */
+int
+bnCmp_16(struct BigNum const *a, struct BigNum const *b)
+{
+ unsigned s, t;
+
+ s = lbnNorm_16((BNWORD16 *)a->ptr, a->size);
+ t = lbnNorm_16((BNWORD16 *)b->ptr, b->size);
+
+ if (s != t)
+ return s > t ? 1 : -1;
+ return lbnCmp_16((BNWORD16 *)a->ptr, (BNWORD16 *)b->ptr, s);
+}
+
+int
+bnSquare_16(struct BigNum *dest, struct BigNum const *src)
+{
+ unsigned s;
+ BNWORD16 *srcbuf;
+
+ s = lbnNorm_16((BNWORD16 *)src->ptr, src->size);
+ if (!s) {
+ dest->size = 0;
+ return 0;
+ }
+ bnSizeCheck(dest, 2*s);
+
+ if (src == dest) {
+ LBNALLOC(srcbuf, s);
+ if (!srcbuf)
+ return -1;
+ lbnCopy_16(srcbuf, (BNWORD16 *)src->ptr, s);
+ lbnSquare_16((BNWORD16 *)dest->ptr, (BNWORD16 *)srcbuf, s);
+ LBNFREE(srcbuf, s);
+ } else {
+ lbnSquare_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, s);
+ }
+
+ dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, 2*s);
+ MALLOCDB;
+ return 0;
+}
+
+int
+bnMul_16(struct BigNum *dest, struct BigNum const *a, struct BigNum const *b)
+{
+ unsigned s, t;
+ BNWORD16 *srcbuf;
+
+ s = lbnNorm_16((BNWORD16 *)a->ptr, a->size);
+ t = lbnNorm_16((BNWORD16 *)b->ptr, b->size);
+
+ if (!s || !t) {
+ dest->size = 0;
+ return 0;
+ }
+
+ if (a == b)
+ return bnSquare_16(dest, a);
+
+ bnSizeCheck(dest, s+t);
+
+ if (dest == a) {
+ LBNALLOC(srcbuf, s);
+ if (!srcbuf)
+ return -1;
+ lbnCopy_16(srcbuf, (BNWORD16 *)a->ptr, s);
+ lbnMul_16((BNWORD16 *)dest->ptr, srcbuf, s,
+ (BNWORD16 *)b->ptr, t);
+ LBNFREE(srcbuf, s);
+ } else if (dest == b) {
+ LBNALLOC(srcbuf, t);
+ if (!srcbuf)
+ return -1;
+ lbnCopy_16(srcbuf, (BNWORD16 *)b->ptr, t);
+ lbnMul_16((BNWORD16 *)dest->ptr, (BNWORD16 *)a->ptr, s,
+ srcbuf, t);
+ LBNFREE(srcbuf, t);
+ } else {
+ lbnMul_16((BNWORD16 *)dest->ptr, (BNWORD16 *)a->ptr, s,
+ (BNWORD16 *)b->ptr, t);
+ }
+ dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, s+t);
+ MALLOCDB;
+ return 0;
+}
+
+int
+bnMulQ_16(struct BigNum *dest, struct BigNum const *a, unsigned b)
+{
+ unsigned s;
+
+ s = lbnNorm_16((BNWORD16 *)a->ptr, a->size);
+ if (!s || !b) {
+ dest->size = 0;
+ return 0;
+ }
+ if (b == 1)
+ return bnCopy_16(dest, a);
+ bnSizeCheck(dest, s+1);
+ lbnMulN1_16((BNWORD16 *)dest->ptr, (BNWORD16 *)a->ptr, s, (BNWORD16)b);
+ dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, s+1);
+ MALLOCDB;
+ return 0;
+}
+
+int
+bnDivMod_16(struct BigNum *q, struct BigNum *r, struct BigNum const *n,
+ struct BigNum const *d)
+{
+ unsigned dsize, nsize;
+ BNWORD16 qhigh;
+
+ dsize = lbnNorm_16((BNWORD16 *)d->ptr, d->size);
+ nsize = lbnNorm_16((BNWORD16 *)n->ptr, n->size);
+
+ if (nsize < dsize) {
+ q->size = 0; /* No quotient */
+ r->size = nsize;
+ return 0; /* Success */
+ }
+
+ bnSizeCheck(q, nsize-dsize);
+
+ if (r != n) { /* You are allowed to reduce in place */
+ bnSizeCheck(r, nsize);
+ lbnCopy_16((BNWORD16 *)r->ptr, (BNWORD16 *)n->ptr, nsize);
+ }
+
+ qhigh = lbnDiv_16((BNWORD16 *)q->ptr, (BNWORD16 *)r->ptr, nsize,
+ (BNWORD16 *)d->ptr, dsize);
+ nsize -= dsize;
+ if (qhigh) {
+ bnSizeCheck(q, nsize+1);
+ *((BNWORD16 *)q->ptr BIGLITTLE(-nsize-1,+nsize)) = qhigh;
+ q->size = nsize+1;
+ } else {
+ q->size = lbnNorm_16((BNWORD16 *)q->ptr, nsize);
+ }
+ r->size = lbnNorm_16((BNWORD16 *)r->ptr, dsize);
+ MALLOCDB;
+ return 0;
+}
+
+int
+bnMod_16(struct BigNum *dest, struct BigNum const *src, struct BigNum const *d)
+{
+ unsigned dsize, nsize;
+
+ nsize = lbnNorm_16((BNWORD16 *)src->ptr, src->size);
+ dsize = lbnNorm_16((BNWORD16 *)d->ptr, d->size);
+
+
+ if (dest != src) {
+ bnSizeCheck(dest, nsize);
+ lbnCopy_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, nsize);
+ }
+
+ if (nsize < dsize) {
+ dest->size = nsize; /* No quotient */
+ return 0;
+ }
+
+ (void)lbnDiv_16((BNWORD16 *)dest->ptr BIGLITTLE(-dsize,+dsize),
+ (BNWORD16 *)dest->ptr, nsize,
+ (BNWORD16 *)d->ptr, dsize);
+ dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, dsize);
+ MALLOCDB;
+ return 0;
+}
+
+unsigned
+bnModQ_16(struct BigNum const *src, unsigned d)
+{
+ unsigned s;
+
+ s = lbnNorm_16((BNWORD16 *)src->ptr, src->size);
+ if (!s)
+ return 0;
+
+ return lbnModQ_16((BNWORD16 *)src->ptr, s, d);
+}
+
+int
+bnExpMod_16(struct BigNum *dest, struct BigNum const *n,
+ struct BigNum const *exp, struct BigNum const *mod)
+{
+ unsigned nsize, esize, msize;
+
+ nsize = lbnNorm_16((BNWORD16 *)n->ptr, n->size);
+ esize = lbnNorm_16((BNWORD16 *)exp->ptr, exp->size);
+ msize = lbnNorm_16((BNWORD16 *)mod->ptr, mod->size);
+
+ if (!msize || (((BNWORD16 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0)
+ return -1; /* Illegal modulus! */
+
+ bnSizeCheck(dest, msize);
+
+ /* Special-case base of 2 */
+ if (nsize == 1 && ((BNWORD16 *)n->ptr)[BIGLITTLE(-1,0)] == 2) {
+ if (lbnTwoExpMod_16((BNWORD16 *)dest->ptr,
+ (BNWORD16 *)exp->ptr, esize,
+ (BNWORD16 *)mod->ptr, msize) < 0)
+ return -1;
+ } else {
+ if (lbnExpMod_16((BNWORD16 *)dest->ptr,
+ (BNWORD16 *)n->ptr, nsize,
+ (BNWORD16 *)exp->ptr, esize,
+ (BNWORD16 *)mod->ptr, msize) < 0)
+ return -1;
+ }
+
+ dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, msize);
+ MALLOCDB;
+ return 0;
+}
+
+int
+bnDoubleExpMod_16(struct BigNum *dest,
+ struct BigNum const *n1, struct BigNum const *e1,
+ struct BigNum const *n2, struct BigNum const *e2,
+ struct BigNum const *mod)
+{
+ unsigned n1size, e1size, n2size, e2size, msize;
+
+ n1size = lbnNorm_16((BNWORD16 *)n1->ptr, n1->size);
+ e1size = lbnNorm_16((BNWORD16 *)e1->ptr, e1->size);
+ n2size = lbnNorm_16((BNWORD16 *)n2->ptr, n2->size);
+ e2size = lbnNorm_16((BNWORD16 *)e2->ptr, e2->size);
+ msize = lbnNorm_16((BNWORD16 *)mod->ptr, mod->size);
+
+ if (!msize || (((BNWORD16 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0)
+ return -1; /* Illegal modulus! */
+
+ bnSizeCheck(dest, msize);
+
+ if (lbnDoubleExpMod_16((BNWORD16 *)dest->ptr,
+ (BNWORD16 *)n1->ptr, n1size, (BNWORD16 *)e1->ptr, e1size,
+ (BNWORD16 *)n2->ptr, n2size, (BNWORD16 *)e2->ptr, e2size,
+ (BNWORD16 *)mod->ptr, msize) < 0)
+ return -1;
+
+ dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, msize);
+ MALLOCDB;
+ return 0;
+}
+
+int
+bnTwoExpMod_16(struct BigNum *n, struct BigNum const *exp,
+ struct BigNum const *mod)
+{
+ unsigned esize, msize;
+
+ esize = lbnNorm_16((BNWORD16 *)exp->ptr, exp->size);
+ msize = lbnNorm_16((BNWORD16 *)mod->ptr, mod->size);
+
+ if (!msize || (((BNWORD16 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0)
+ return -1; /* Illegal modulus! */
+
+ bnSizeCheck(n, msize);
+
+ if (lbnTwoExpMod_16((BNWORD16 *)n->ptr, (BNWORD16 *)exp->ptr, esize,
+ (BNWORD16 *)mod->ptr, msize) < 0)
+ return -1;
+
+ n->size = lbnNorm_16((BNWORD16 *)n->ptr, msize);
+ MALLOCDB;
+ return 0;
+}
+
+int
+bnGcd_16(struct BigNum *dest, struct BigNum const *a, struct BigNum const *b)
+{
+ BNWORD16 *tmp;
+ unsigned asize, bsize;
+ int i;
+
+ /* Kind of silly, but we might as well permit it... */
+ if (a == b)
+ return dest == a ? 0 : bnCopy(dest, a);
+
+ /* Ensure a is not the same as "dest" */
+ if (a == dest) {
+ a = b;
+ b = dest;
+ }
+
+ asize = lbnNorm_16((BNWORD16 *)a->ptr, a->size);
+ bsize = lbnNorm_16((BNWORD16 *)b->ptr, b->size);
+
+ bnSizeCheck(dest, bsize+1);
+
+ /* Copy a to tmp */
+ LBNALLOC(tmp, asize+1);
+ if (!tmp)
+ return -1;
+ lbnCopy_16(tmp, (BNWORD16 *)a->ptr, asize);
+
+ /* Copy b to dest,if necessary */
+ if (dest != b)
+ lbnCopy_16((BNWORD16 *)dest->ptr,
+ (BNWORD16 *)b->ptr, bsize);
+ if (bsize > asize || (bsize == asize &&
+ lbnCmp_16((BNWORD16 *)b->ptr, (BNWORD16 *)a->ptr, asize) > 0))
+ {
+ i = lbnGcd_16((BNWORD16 *)dest->ptr, bsize, tmp, asize);
+ if (i >= 0) {
+ dest->size = (unsigned)i;
+ } else {
+ lbnCopy_16((BNWORD16 *)dest->ptr, tmp,
+ (unsigned)-i);
+ dest->size = (unsigned)-i;
+ }
+ } else {
+ i = lbnGcd_16(tmp, asize, (BNWORD16 *)dest->ptr, bsize);
+ if (i <= 0) {
+ dest->size = (unsigned)-i;
+ } else {
+ lbnCopy_16((BNWORD16 *)dest->ptr, tmp,
+ (unsigned)i);
+ dest->size = (unsigned)i;
+ }
+ }
+ LBNFREE(tmp, asize+1);
+ MALLOCDB;
+ return 0;
+}
+
+int
+bnInv_16(struct BigNum *dest, struct BigNum const *src,
+ struct BigNum const *mod)
+{
+ unsigned s, m;
+ int i;
+
+ s = lbnNorm_16((BNWORD16 *)src->ptr, src->size);
+ m = lbnNorm_16((BNWORD16 *)mod->ptr, mod->size);
+
+ /* lbnInv_16 requires that the input be less than the modulus */
+ if (m < s ||
+ (m==s && lbnCmp_16((BNWORD16 *)src->ptr, (BNWORD16 *)mod->ptr, s)))
+ {
+ bnSizeCheck(dest, s + (m==s));
+ if (dest != src)
+ lbnCopy_16((BNWORD16 *)dest->ptr,
+ (BNWORD16 *)src->ptr, s);
+ /* Pre-reduce modulo the modulus */
+ (void)lbnDiv_16((BNWORD16 *)dest->ptr BIGLITTLE(-m,+m),
+ (BNWORD16 *)dest->ptr, s,
+ (BNWORD16 *)mod->ptr, m);
+ s = lbnNorm_16((BNWORD16 *)dest->ptr, m);
+ MALLOCDB;
+ } else {
+ bnSizeCheck(dest, m+1);
+ if (dest != src)
+ lbnCopy_16((BNWORD16 *)dest->ptr,
+ (BNWORD16 *)src->ptr, s);
+ }
+
+ i = lbnInv_16((BNWORD16 *)dest->ptr, s, (BNWORD16 *)mod->ptr, m);
+ if (i == 0)
+ dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, m);
+
+ MALLOCDB;
+ return i;
+}
+
+/*
+ * Shift a bignum left the appropriate number of bits,
+ * multiplying by 2^amt.
+ */
+int
+bnLShift_16(struct BigNum *dest, unsigned amt)
+{
+ unsigned s = dest->size;
+ BNWORD16 carry;
+
+ if (amt % 16) {
+ carry = lbnLshift_16(dest->ptr, s, amt % 16);
+ if (carry) {
+ s++;
+ bnSizeCheck(dest, s);
+ ((BNWORD16 *)dest->ptr)[BIGLITTLE(-s,s-1)] = carry;
+ }
+ }
+
+ amt /= 16;
+ if (amt) {
+ bnSizeCheck(dest, s+amt);
+ memmove((BNWORD16 *)dest->ptr BIGLITTLE(-s-amt, +amt),
+ (BNWORD16 *)dest->ptr BIG(-s),
+ s * sizeof(BNWORD16));
+ lbnZero_16((BNWORD16 *)dest->ptr, amt);
+ s += amt;
+ }
+ dest->size = s;
+ MALLOCDB;
+ return 0;
+}
+
+/*
+ * Shift a bignum right the appropriate number of bits,
+ * dividing by 2^amt.
+ */
+void bnRShift_16(struct BigNum *dest, unsigned amt)
+{
+ unsigned s = dest->size;
+
+ if (amt >= 16) {
+ memmove(
+ (BNWORD16 *)dest->ptr BIG(-s+amt/16),
+ (BNWORD16 *)dest->ptr BIGLITTLE(-s, +amt/16),
+ s-amt/16 * sizeof(BNWORD16));
+ s -= amt/16;
+ amt %= 16;
+ }
+
+ if (amt)
+ (void)lbnRshift_16(dest->ptr, s, amt);
+
+ dest->size = lbnNorm_16(dest->ptr, s);
+ MALLOCDB;
+}
+
+/*
+ * Shift a bignum right until it is odd, and return the number of
+ * bits shifted. n = d * 2^s. Replaces n with d and returns s.
+ * Returns 0 when given 0. (Another valid answer is infinity.)
+ */
+unsigned
+bnMakeOdd_16(struct BigNum *n)
+{
+ unsigned size;
+ unsigned s; /* shift amount */
+ BNWORD16 *p;
+ BNWORD16 t;
+
+ p = (BNWORD16 *)n->ptr;
+ size = lbnNorm_16(p, n->size);
+ if (!size)
+ return 0;
+
+ t = BIGLITTLE(p[-1],p[0]);
+ s = 0;
+
+ /* See how many words we have to shift */
+ if (!t) {
+ /* Shift by words */
+ do {
+
+ s++;
+ BIGLITTLE(--p,p++);
+ } while ((t = BIGLITTLE(p[-1],p[0])) == 0);
+ size -= s;
+ s *= 16;
+ memmove((BNWORD16 *)n->ptr BIG(-size), p BIG(-size),
+ size * sizeof(BNWORD16));
+ p = (BNWORD16 *)n->ptr;
+ MALLOCDB;
+ }
+
+ assert(t);
+
+ /* Now count the bits */
+ while ((t & 1) == 0) {
+ t >>= 1;
+ s++;
+ }
+
+ /* Shift the bits */
+ if (s & (16-1)) {
+ lbnRshift_16(p, size, s & (16-1));
+ /* Renormalize */
+ if (BIGLITTLE(*(p-size),*(p+(size-1))) == 0)
+ --size;
+ }
+ n->size = size;
+
+ MALLOCDB;
+ return s;
+}
diff --git a/usr/src/lib/libresolv2/common/cylink/bn16.h b/usr/src/lib/libresolv2/common/cylink/bn16.h
new file mode 100644
index 0000000000..8f8402534e
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/bn16.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/*
+ * bn16.h - interface to 16-bit bignum routines.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+struct BigNum;
+
+void bnInit_16(void);
+void bnEnd_16(struct BigNum *bn);
+int bnPrealloc_16(struct BigNum *bn, unsigned bits);
+int bnCopy_16(struct BigNum *dest, struct BigNum const *src);
+int bnSwap_16(struct BigNum *a, struct BigNum *b);
+void bnNorm_16(struct BigNum *bn);
+void bnExtractBigBytes_16(struct BigNum const *bn, unsigned char *dest,
+ unsigned lsbyte, unsigned dlen);
+int bnInsertBigBytes_16(struct BigNum *bn, unsigned char const *src,
+ unsigned lsbyte, unsigned len);
+void bnExtractLittleBytes_16(struct BigNum const *bn, unsigned char *dest,
+ unsigned lsbyte, unsigned dlen);
+int bnInsertLittleBytes_16(struct BigNum *bn, unsigned char const *src,
+ unsigned lsbyte, unsigned len);
+unsigned bnLSWord_16(struct BigNum const *src);
+unsigned bnBits_16(struct BigNum const *src);
+int bnAdd_16(struct BigNum *dest, struct BigNum const *src);
+int bnSub_16(struct BigNum *dest, struct BigNum const *src);
+int bnCmpQ_16(struct BigNum const *a, unsigned b);
+int bnSetQ_16(struct BigNum *dest, unsigned src);
+int bnAddQ_16(struct BigNum *dest, unsigned src);
+int bnSubQ_16(struct BigNum *dest, unsigned src);
+int bnCmp_16(struct BigNum const *a, struct BigNum const *b);
+int bnSquare_16(struct BigNum *dest, struct BigNum const *src);
+int bnMul_16(struct BigNum *dest, struct BigNum const *a,
+ struct BigNum const *b);
+int bnMulQ_16(struct BigNum *dest, struct BigNum const *a, unsigned b);
+int bnDivMod_16(struct BigNum *q, struct BigNum *r, struct BigNum const *n,
+ struct BigNum const *d);
+int bnMod_16(struct BigNum *dest, struct BigNum const *src,
+ struct BigNum const *d);
+unsigned bnModQ_16(struct BigNum const *src, unsigned d);
+int bnExpMod_16(struct BigNum *dest, struct BigNum const *n,
+ struct BigNum const *exp, struct BigNum const *mod);
+int bnDoubleExpMod_16(struct BigNum *dest,
+ struct BigNum const *n1, struct BigNum const *e1,
+ struct BigNum const *n2, struct BigNum const *e2,
+ struct BigNum const *mod);
+int bnTwoExpMod_16(struct BigNum *n, struct BigNum const *exp,
+ struct BigNum const *mod);
+int bnGcd_16(struct BigNum *dest, struct BigNum const *a,
+ struct BigNum const *b);
+int bnInv_16(struct BigNum *dest, struct BigNum const *src,
+ struct BigNum const *mod);
+int bnLShift_16(struct BigNum *dest, unsigned amt);
+void bnRShift_16(struct BigNum *dest, unsigned amt);
+unsigned bnMakeOdd_16(struct BigNum *n);
diff --git a/usr/src/lib/libresolv2/common/cylink/bn32.c b/usr/src/lib/libresolv2/common/cylink/bn32.c
new file mode 100644
index 0000000000..449cb90567
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/bn32.c
@@ -0,0 +1,956 @@
+/*
+ * Copyright (c) 2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/*
+ * bn32.c - the high-level bignum interface
+ *
+ * Like lbn32.c, this reserves the string "32" for textual replacement.
+ * The string must not appear anywhere unless it is intended to be replaced
+ * to generate other bignum interface functions.
+ *
+ * Copyright (c) 1995 Colin Plumb. All rights reserved.
+ * For licensing and other legal details, see the file legal.c.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef HAVE_CONFIG_H
+#define HAVE_CONFIG_H 0
+#endif
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * Some compilers complain about #if FOO if FOO isn't defined,
+ * so do the ANSI-mandated thing explicitly...
+ */
+#ifndef NO_ASSERT_H
+#define NO_ASSERT_H 0
+#endif
+#ifndef NO_STRING_H
+#define NO_STRING_H 0
+#endif
+#ifndef HAVE_STRINGS_H
+#define HAVE_STRINGS_H 0
+#endif
+#ifndef NEED_MEMORY_H
+#define NEED_MEMORY_H 0
+#endif
+
+#if !NO_ASSERT_H
+#include <assert.h>
+#else
+#define assert(x) (void)0
+#endif
+
+#if !NO_STRING_H
+#include <string.h> /* for memmove() in bnMakeOdd */
+#elif HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#if NEED_MEMORY_H
+#include <memory.h>
+#endif
+
+/*
+ * This was useful during debugging, so it's left in here.
+ * You can ignore it. DBMALLOC is generally undefined.
+ */
+#ifndef DBMALLOC
+#define DBAMLLOC 0
+#endif
+#if DBMALLOC
+#include "../dbmalloc/malloc.h"
+#define MALLOCDB malloc_chain_check(1)
+#else
+#define MALLOCDB (void)0
+#endif
+
+#include "lbn.h"
+#include "lbn32.h"
+#include "lbnmem.h"
+#include "bn32.h"
+#include "bn.h"
+
+/* Work-arounds for some particularly broken systems */
+#include "kludge.h" /* For memmove() */
+#include <port_after.h>
+
+/* Functions */
+void
+bnInit_32(void)
+{
+ bnEnd = bnEnd_32;
+ bnPrealloc = bnPrealloc_32;
+ bnCopy = bnCopy_32;
+ bnNorm = bnNorm_32;
+ bnExtractBigBytes = bnExtractBigBytes_32;
+ bnInsertBigBytes = bnInsertBigBytes_32;
+ bnExtractLittleBytes = bnExtractLittleBytes_32;
+ bnInsertLittleBytes = bnInsertLittleBytes_32;
+ bnLSWord = bnLSWord_32;
+ bnBits = bnBits_32;
+ bnAdd = bnAdd_32;
+ bnSub = bnSub_32;
+ bnCmpQ = bnCmpQ_32;
+ bnSetQ = bnSetQ_32;
+ bnAddQ = bnAddQ_32;
+ bnSubQ = bnSubQ_32;
+ bnCmp = bnCmp_32;
+ bnSquare = bnSquare_32;
+ bnMul = bnMul_32;
+ bnMulQ = bnMulQ_32;
+ bnDivMod = bnDivMod_32;
+ bnMod = bnMod_32;
+ bnModQ = bnModQ_32;
+ bnExpMod = bnExpMod_32;
+ bnDoubleExpMod = bnDoubleExpMod_32;
+ bnTwoExpMod = bnTwoExpMod_32;
+ bnGcd = bnGcd_32;
+ bnInv = bnInv_32;
+ bnLShift = bnLShift_32;
+ bnRShift = bnRShift_32;
+ bnMakeOdd = bnMakeOdd_32;
+}
+
+void
+bnEnd_32(struct BigNum *bn)
+{
+ if (bn->ptr) {
+ LBNFREE((BNWORD32 *)bn->ptr, bn->allocated);
+ bn->ptr = 0;
+ }
+ bn->size = 0;
+ bn->allocated = 0;
+
+ MALLOCDB;
+}
+
+/* Internal function. It operates in words. */
+static int
+bnResize_32(struct BigNum *bn, unsigned len)
+{
+ void *p;
+
+ /* Round size up: most mallocs impose 8-byte granularity anyway */
+ len = (len + (8/sizeof(BNWORD32) - 1)) & ~(8/sizeof(BNWORD32) - 1);
+ p = LBNREALLOC((BNWORD32 *)bn->ptr, bn->allocated, len);
+ if (!p)
+ return -1;
+ bn->ptr = p;
+ bn->allocated = len;
+
+ MALLOCDB;
+
+ return 0;
+}
+
+#define bnSizeCheck(bn, size) \
+ if (bn->allocated < size && bnResize_32(bn, size) < 0) \
+ return -1
+
+int
+bnPrealloc_32(struct BigNum *bn, unsigned bits)
+{
+ bits = (bits + 32-1)/32;
+ bnSizeCheck(bn, bits);
+ MALLOCDB;
+ return 0;
+}
+
+int
+bnCopy_32(struct BigNum *dest, struct BigNum const *src)
+{
+ bnSizeCheck(dest, src->size);
+ dest->size = src->size;
+ lbnCopy_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, src->size);
+ MALLOCDB;
+ return 0;
+}
+
+void
+bnNorm_32(struct BigNum *bn)
+{
+ bn->size = lbnNorm_32((BNWORD32 *)bn->ptr, bn->size);
+}
+
+/*
+ * Convert a bignum to big-endian bytes. Returns, in big-endian form, a
+ * substring of the bignum starting from lsbyte and "len" bytes long.
+ * Unused high-order (leading) bytes are filled with 0.
+ */
+void
+bnExtractBigBytes_32(struct BigNum const *bn, unsigned char *dest,
+ unsigned lsbyte, unsigned len)
+{
+ unsigned s = bn->size * (32 / 8);
+
+ /* Fill unused leading bytes with 0 */
+ while (s < lsbyte+len) {
+ *dest++ = 0;
+ len--;
+ }
+
+ if (len)
+ lbnExtractBigBytes_32((BNWORD32 *)bn->ptr, dest, lsbyte, len);
+ MALLOCDB;
+}
+
+int
+bnInsertBigBytes_32(struct BigNum *bn, unsigned char const *src,
+ unsigned lsbyte, unsigned len)
+{
+ unsigned s = bn->size;
+ unsigned words = (len+lsbyte+sizeof(BNWORD32)-1) / sizeof(BNWORD32);
+
+ /* Pad with zeros as required */
+ bnSizeCheck(bn, words);
+
+ if (s < words) {
+ lbnZero_32((BNWORD32 *)bn->ptr BIGLITTLE(-s,+s), words-s);
+ s = words;
+ }
+
+ lbnInsertBigBytes_32((BNWORD32 *)bn->ptr, src, lsbyte, len);
+
+ bn->size = lbnNorm_32((BNWORD32 *)bn->ptr, s);
+
+ MALLOCDB;
+ return 0;
+}
+
+
+/*
+ * Convert a bignum to little-endian bytes. Returns, in little-endian form, a
+ * substring of the bignum starting from lsbyte and "len" bytes long.
+ * Unused high-order (trailing) bytes are filled with 0.
+ */
+void
+bnExtractLittleBytes_32(struct BigNum const *bn, unsigned char *dest,
+ unsigned lsbyte, unsigned len)
+{
+ unsigned s = bn->size * (32 / 8);
+
+ /* Fill unused leading bytes with 0 */
+ while (s < lsbyte+len)
+ dest[--len] = 0;
+
+ if (len)
+ lbnExtractLittleBytes_32((BNWORD32 *)bn->ptr, dest,
+ lsbyte, len);
+ MALLOCDB;
+}
+
+int
+bnInsertLittleBytes_32(struct BigNum *bn, unsigned char const *src,
+ unsigned lsbyte, unsigned len)
+{
+ unsigned s = bn->size;
+ unsigned words = (len+lsbyte+sizeof(BNWORD32)-1) / sizeof(BNWORD32);
+
+ /* Pad with zeros as required */
+ bnSizeCheck(bn, words);
+
+ if (s < words) {
+ lbnZero_32((BNWORD32 *)bn->ptr BIGLITTLE(-s,+s), words-s);
+ s = words;
+ }
+
+ lbnInsertLittleBytes_32((BNWORD32 *)bn->ptr, src, lsbyte, len);
+
+ bn->size = lbnNorm_32((BNWORD32 *)bn->ptr, s);
+
+ MALLOCDB;
+ return 0;
+}
+
+/* Return the least-significant word of the input. */
+unsigned
+bnLSWord_32(struct BigNum const *src)
+{
+ return src->size ? (unsigned)((BNWORD32 *)src->ptr)[BIGLITTLE(-1,0)]: 0;
+}
+
+unsigned
+bnBits_32(struct BigNum const *src)
+{
+ return lbnBits_32((BNWORD32 *)src->ptr, src->size);
+}
+
+int
+bnAdd_32(struct BigNum *dest, struct BigNum const *src)
+{
+ unsigned s = src->size, d = dest->size;
+ BNWORD32 t;
+
+ if (!s)
+ return 0;
+
+ bnSizeCheck(dest, s);
+
+ if (d < s) {
+ lbnZero_32((BNWORD32 *)dest->ptr BIGLITTLE(-d,+d), s-d);
+ dest->size = d = s;
+ MALLOCDB;
+ }
+ t = lbnAddN_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, s);
+ MALLOCDB;
+ if (t) {
+ if (d > s) {
+ t = lbnAdd1_32((BNWORD32 *)dest->ptr BIGLITTLE(-s,+s),
+ d-s, t);
+ MALLOCDB;
+ }
+ if (t) {
+ bnSizeCheck(dest, d+1);
+ ((BNWORD32 *)dest->ptr)[BIGLITTLE(-1-d,d)] = t;
+ dest->size = d+1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * dest -= src.
+ * If dest goes negative, this produces the absolute value of
+ * the difference (the negative of the true value) and returns 1.
+ * Otherwise, it returls 0.
+ */
+int
+bnSub_32(struct BigNum *dest, struct BigNum const *src)
+{
+ unsigned s = src->size, d = dest->size;
+ BNWORD32 t;
+
+ if (d < s && d < (s = lbnNorm_32((BNWORD32 *)src->ptr, s))) {
+ bnSizeCheck(dest, s);
+ lbnZero_32((BNWORD32 *)dest->ptr BIGLITTLE(-d,+d), s-d);
+ dest->size = d = s;
+ MALLOCDB;
+ }
+ if (!s)
+ return 0;
+ t = lbnSubN_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, s);
+ MALLOCDB;
+ if (t) {
+ if (d > s) {
+ t = lbnSub1_32((BNWORD32 *)dest->ptr BIGLITTLE(-s,+s),
+ d-s, t);
+ MALLOCDB;
+ }
+ if (t) {
+ lbnNeg_32((BNWORD32 *)dest->ptr, d);
+ dest->size = lbnNorm_32((BNWORD32 *)dest->ptr,
+ dest->size);
+ MALLOCDB;
+ return 1;
+ }
+ }
+ dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, dest->size);
+ return 0;
+}
+
+/*
+ * Compare the BigNum to the given value, which must be < 65536.
+ * Returns -1. 0 or 1 if a<b, a == b or a>b.
+ * a <=> b --> bnCmpQ(a,b) <=> 0
+ */
+int
+bnCmpQ_32(struct BigNum const *a, unsigned b)
+{
+ unsigned t;
+ BNWORD32 v;
+
+ t = lbnNorm_32((BNWORD32 *)a->ptr, a->size);
+ /* If a is more than one word long or zero, it's easy... */
+ if (t != 1)
+ return (t > 1) ? 1 : (b ? -1 : 0);
+ v = (unsigned)((BNWORD32 *)a->ptr)[BIGLITTLE(-1,0)];
+ return (v > b) ? 1 : ((v < b) ? -1 : 0);
+}
+
+int
+bnSetQ_32(struct BigNum *dest, unsigned src)
+{
+ if (src) {
+ bnSizeCheck(dest, 1);
+
+ ((BNWORD32 *)dest->ptr)[BIGLITTLE(-1,0)] = (BNWORD32)src;
+ dest->size = 1;
+ } else {
+ dest->size = 0;
+ }
+ return 0;
+}
+
+int
+bnAddQ_32(struct BigNum *dest, unsigned src)
+{
+ BNWORD32 t;
+
+ if (!dest->size)
+ return bnSetQ(dest, src);
+
+ t = lbnAdd1_32((BNWORD32 *)dest->ptr, dest->size, (BNWORD32)src);
+ MALLOCDB;
+ if (t) {
+ src = dest->size;
+ bnSizeCheck(dest, src+1);
+ ((BNWORD32 *)dest->ptr)[BIGLITTLE(-1-src,src)] = t;
+ dest->size = src+1;
+ }
+ return 0;
+}
+
+/*
+ * Return value as for bnSub: 1 if subtract underflowed, in which
+ * case the return is the negative of the computed value.
+ */
+int
+bnSubQ_32(struct BigNum *dest, unsigned src)
+{
+ BNWORD32 t;
+
+ if (!dest->size)
+ return bnSetQ(dest, src) < 0 ? -1 : (src != 0);
+
+ t = lbnSub1_32((BNWORD32 *)dest->ptr, dest->size, src);
+ MALLOCDB;
+ if (t) {
+ /* Underflow. <= 1 word, so do it simply. */
+ lbnNeg_32((BNWORD32 *)dest->ptr, 1);
+ dest->size = 1;
+ return 1;
+ }
+/* Try to normalize? Needing this is going to be very rare. */
+/* dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, dest->size); */
+ return 0;
+}
+
+/*
+ * Compare two BigNums. Returns -1. 0 or 1 if a<b, a == b or a>b.
+ * a <=> b --> bnCmp(a,b) <=> 0
+ */
+int
+bnCmp_32(struct BigNum const *a, struct BigNum const *b)
+{
+ unsigned s, t;
+
+ s = lbnNorm_32((BNWORD32 *)a->ptr, a->size);
+ t = lbnNorm_32((BNWORD32 *)b->ptr, b->size);
+
+ if (s != t)
+ return s > t ? 1 : -1;
+ return lbnCmp_32((BNWORD32 *)a->ptr, (BNWORD32 *)b->ptr, s);
+}
+
+int
+bnSquare_32(struct BigNum *dest, struct BigNum const *src)
+{
+ unsigned s;
+ BNWORD32 *srcbuf;
+
+ s = lbnNorm_32((BNWORD32 *)src->ptr, src->size);
+ if (!s) {
+ dest->size = 0;
+ return 0;
+ }
+ bnSizeCheck(dest, 2*s);
+
+ if (src == dest) {
+ LBNALLOC(srcbuf, s);
+ if (!srcbuf)
+ return -1;
+ lbnCopy_32(srcbuf, (BNWORD32 *)src->ptr, s);
+ lbnSquare_32((BNWORD32 *)dest->ptr, (BNWORD32 *)srcbuf, s);
+ LBNFREE(srcbuf, s);
+ } else {
+ lbnSquare_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, s);
+ }
+
+ dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, 2*s);
+ MALLOCDB;
+ return 0;
+}
+
+int
+bnMul_32(struct BigNum *dest, struct BigNum const *a, struct BigNum const *b)
+{
+ unsigned s, t;
+ BNWORD32 *srcbuf;
+
+ s = lbnNorm_32((BNWORD32 *)a->ptr, a->size);
+ t = lbnNorm_32((BNWORD32 *)b->ptr, b->size);
+
+ if (!s || !t) {
+ dest->size = 0;
+ return 0;
+ }
+
+ if (a == b)
+ return bnSquare_32(dest, a);
+
+ bnSizeCheck(dest, s+t);
+
+ if (dest == a) {
+ LBNALLOC(srcbuf, s);
+ if (!srcbuf)
+ return -1;
+ lbnCopy_32(srcbuf, (BNWORD32 *)a->ptr, s);
+ lbnMul_32((BNWORD32 *)dest->ptr, srcbuf, s,
+ (BNWORD32 *)b->ptr, t);
+ LBNFREE(srcbuf, s);
+ } else if (dest == b) {
+ LBNALLOC(srcbuf, t);
+ if (!srcbuf)
+ return -1;
+ lbnCopy_32(srcbuf, (BNWORD32 *)b->ptr, t);
+ lbnMul_32((BNWORD32 *)dest->ptr, (BNWORD32 *)a->ptr, s,
+ srcbuf, t);
+ LBNFREE(srcbuf, t);
+ } else {
+ lbnMul_32((BNWORD32 *)dest->ptr, (BNWORD32 *)a->ptr, s,
+ (BNWORD32 *)b->ptr, t);
+ }
+ dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, s+t);
+ MALLOCDB;
+ return 0;
+}
+
+int
+bnMulQ_32(struct BigNum *dest, struct BigNum const *a, unsigned b)
+{
+ unsigned s;
+
+ s = lbnNorm_32((BNWORD32 *)a->ptr, a->size);
+ if (!s || !b) {
+ dest->size = 0;
+ return 0;
+ }
+ if (b == 1)
+ return bnCopy_32(dest, a);
+ bnSizeCheck(dest, s+1);
+ lbnMulN1_32((BNWORD32 *)dest->ptr, (BNWORD32 *)a->ptr, s, b);
+ dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, s+1);
+ MALLOCDB;
+ return 0;
+}
+
+int
+bnDivMod_32(struct BigNum *q, struct BigNum *r, struct BigNum const *n,
+ struct BigNum const *d)
+{
+ unsigned dsize, nsize;
+ BNWORD32 qhigh;
+
+ dsize = lbnNorm_32((BNWORD32 *)d->ptr, d->size);
+ nsize = lbnNorm_32((BNWORD32 *)n->ptr, n->size);
+
+ if (nsize < dsize) {
+ q->size = 0; /* No quotient */
+ r->size = nsize;
+ return 0; /* Success */
+ }
+
+ bnSizeCheck(q, nsize-dsize);
+
+ if (r != n) { /* You are allowed to reduce in place */
+ bnSizeCheck(r, nsize);
+ lbnCopy_32((BNWORD32 *)r->ptr, (BNWORD32 *)n->ptr, nsize);
+ }
+
+ qhigh = lbnDiv_32((BNWORD32 *)q->ptr, (BNWORD32 *)r->ptr, nsize,
+ (BNWORD32 *)d->ptr, dsize);
+ nsize -= dsize;
+ if (qhigh) {
+ bnSizeCheck(q, nsize+1);
+ *((BNWORD32 *)q->ptr BIGLITTLE(-nsize-1,+nsize)) = qhigh;
+ q->size = nsize+1;
+ } else {
+ q->size = lbnNorm_32((BNWORD32 *)q->ptr, nsize);
+ }
+ r->size = lbnNorm_32((BNWORD32 *)r->ptr, dsize);
+ MALLOCDB;
+ return 0;
+}
+
+int
+bnMod_32(struct BigNum *dest, struct BigNum const *src, struct BigNum const *d)
+{
+ unsigned dsize, nsize;
+
+ nsize = lbnNorm_32((BNWORD32 *)src->ptr, src->size);
+ dsize = lbnNorm_32((BNWORD32 *)d->ptr, d->size);
+
+
+ if (dest != src) {
+ bnSizeCheck(dest, nsize);
+ lbnCopy_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, nsize);
+ }
+
+ if (nsize < dsize) {
+ dest->size = nsize; /* No quotient */
+ return 0;
+ }
+
+ (void)lbnDiv_32((BNWORD32 *)dest->ptr BIGLITTLE(-dsize,+dsize),
+ (BNWORD32 *)dest->ptr, nsize,
+ (BNWORD32 *)d->ptr, dsize);
+ dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, dsize);
+ MALLOCDB;
+ return 0;
+}
+
+unsigned
+bnModQ_32(struct BigNum const *src, unsigned d)
+{
+ unsigned s;
+
+ s = lbnNorm_32((BNWORD32 *)src->ptr, src->size);
+ if (!s)
+ return 0;
+
+ return lbnModQ_32((BNWORD32 *)src->ptr, s, d);
+}
+
+int
+bnExpMod_32(struct BigNum *dest, struct BigNum const *n,
+ struct BigNum const *exp, struct BigNum const *mod)
+{
+ unsigned nsize, esize, msize;
+
+ nsize = lbnNorm_32((BNWORD32 *)n->ptr, n->size);
+ esize = lbnNorm_32((BNWORD32 *)exp->ptr, exp->size);
+ msize = lbnNorm_32((BNWORD32 *)mod->ptr, mod->size);
+
+ if (!msize || (((BNWORD32 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0)
+ return -1; /* Illegal modulus! */
+
+ bnSizeCheck(dest, msize);
+
+ /* Special-case base of 2 */
+ if (nsize == 1 && ((BNWORD32 *)n->ptr)[BIGLITTLE(-1,0)] == 2) {
+ if (lbnTwoExpMod_32((BNWORD32 *)dest->ptr,
+ (BNWORD32 *)exp->ptr, esize,
+ (BNWORD32 *)mod->ptr, msize) < 0)
+ return -1;
+ } else {
+ if (lbnExpMod_32((BNWORD32 *)dest->ptr,
+ (BNWORD32 *)n->ptr, nsize,
+ (BNWORD32 *)exp->ptr, esize,
+ (BNWORD32 *)mod->ptr, msize) < 0)
+ return -1;
+ }
+
+ dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, msize);
+ MALLOCDB;
+ return 0;
+}
+
+int
+bnDoubleExpMod_32(struct BigNum *dest,
+ struct BigNum const *n1, struct BigNum const *e1,
+ struct BigNum const *n2, struct BigNum const *e2,
+ struct BigNum const *mod)
+{
+ unsigned n1size, e1size, n2size, e2size, msize;
+
+ n1size = lbnNorm_32((BNWORD32 *)n1->ptr, n1->size);
+ e1size = lbnNorm_32((BNWORD32 *)e1->ptr, e1->size);
+ n2size = lbnNorm_32((BNWORD32 *)n2->ptr, n2->size);
+ e2size = lbnNorm_32((BNWORD32 *)e2->ptr, e2->size);
+ msize = lbnNorm_32((BNWORD32 *)mod->ptr, mod->size);
+
+ if (!msize || (((BNWORD32 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0)
+ return -1; /* Illegal modulus! */
+
+ bnSizeCheck(dest, msize);
+
+ if (lbnDoubleExpMod_32((BNWORD32 *)dest->ptr,
+ (BNWORD32 *)n1->ptr, n1size, (BNWORD32 *)e1->ptr, e1size,
+ (BNWORD32 *)n2->ptr, n2size, (BNWORD32 *)e2->ptr, e2size,
+ (BNWORD32 *)mod->ptr, msize) < 0)
+ return -1;
+
+ dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, msize);
+ MALLOCDB;
+ return 0;
+}
+
+int
+bnTwoExpMod_32(struct BigNum *n, struct BigNum const *exp,
+ struct BigNum const *mod)
+{
+ unsigned esize, msize;
+
+ esize = lbnNorm_32((BNWORD32 *)exp->ptr, exp->size);
+ msize = lbnNorm_32((BNWORD32 *)mod->ptr, mod->size);
+
+ if (!msize || (((BNWORD32 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0)
+ return -1; /* Illegal modulus! */
+
+ bnSizeCheck(n, msize);
+
+ if (lbnTwoExpMod_32((BNWORD32 *)n->ptr, (BNWORD32 *)exp->ptr, esize,
+ (BNWORD32 *)mod->ptr, msize) < 0)
+ return -1;
+
+ n->size = lbnNorm_32((BNWORD32 *)n->ptr, msize);
+ MALLOCDB;
+ return 0;
+}
+
+int
+bnGcd_32(struct BigNum *dest, struct BigNum const *a, struct BigNum const *b)
+{
+ BNWORD32 *tmp;
+ unsigned asize, bsize;
+ int i;
+
+ /* Kind of silly, but we might as well permit it... */
+ if (a == b)
+ return dest == a ? 0 : bnCopy(dest, a);
+
+ /* Ensure a is not the same as "dest" */
+ if (a == dest) {
+ a = b;
+ b = dest;
+ }
+
+ asize = lbnNorm_32((BNWORD32 *)a->ptr, a->size);
+ bsize = lbnNorm_32((BNWORD32 *)b->ptr, b->size);
+
+ bnSizeCheck(dest, bsize+1);
+
+ /* Copy a to tmp */
+ LBNALLOC(tmp, asize+1);
+ if (!tmp)
+ return -1;
+ lbnCopy_32(tmp, (BNWORD32 *)a->ptr, asize);
+
+ /* Copy b to dest,if necessary */
+ if (dest != b)
+ lbnCopy_32((BNWORD32 *)dest->ptr,
+ (BNWORD32 *)b->ptr, bsize);
+ if (bsize > asize || (bsize == asize &&
+ lbnCmp_32((BNWORD32 *)b->ptr, (BNWORD32 *)a->ptr, asize) > 0))
+ {
+ i = lbnGcd_32((BNWORD32 *)dest->ptr, bsize, tmp, asize);
+ if (i >= 0) {
+ dest->size = (unsigned)i;
+ } else {
+ lbnCopy_32((BNWORD32 *)dest->ptr, tmp,
+ (unsigned)-i);
+ dest->size = (unsigned)-i;
+ }
+ } else {
+ i = lbnGcd_32(tmp, asize, (BNWORD32 *)dest->ptr, bsize);
+ if (i <= 0) {
+ dest->size = (unsigned)-i;
+ } else {
+ lbnCopy_32((BNWORD32 *)dest->ptr, tmp,
+ (unsigned)i);
+ dest->size = (unsigned)i;
+ }
+ }
+ LBNFREE(tmp, asize+1);
+ MALLOCDB;
+ return 0;
+}
+
+int
+bnInv_32(struct BigNum *dest, struct BigNum const *src,
+ struct BigNum const *mod)
+{
+ unsigned s, m;
+ int i;
+
+ s = lbnNorm_32((BNWORD32 *)src->ptr, src->size);
+ m = lbnNorm_32((BNWORD32 *)mod->ptr, mod->size);
+
+ /* lbnInv_32 requires that the input be less than the modulus */
+ if (m < s ||
+ (m==s && lbnCmp_32((BNWORD32 *)src->ptr, (BNWORD32 *)mod->ptr, s)))
+ {
+ bnSizeCheck(dest, s + (m==s));
+ if (dest != src)
+ lbnCopy_32((BNWORD32 *)dest->ptr,
+ (BNWORD32 *)src->ptr, s);
+ /* Pre-reduce modulo the modulus */
+ (void)lbnDiv_32((BNWORD32 *)dest->ptr BIGLITTLE(-m,+m),
+ (BNWORD32 *)dest->ptr, s,
+ (BNWORD32 *)mod->ptr, m);
+ s = lbnNorm_32((BNWORD32 *)dest->ptr, m);
+ MALLOCDB;
+ } else {
+ bnSizeCheck(dest, m+1);
+ if (dest != src)
+ lbnCopy_32((BNWORD32 *)dest->ptr,
+ (BNWORD32 *)src->ptr, s);
+ }
+
+ i = lbnInv_32((BNWORD32 *)dest->ptr, s, (BNWORD32 *)mod->ptr, m);
+ if (i == 0)
+ dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, m);
+
+ MALLOCDB;
+ return i;
+}
+
+/*
+ * Shift a bignum left the appropriate number of bits,
+ * multiplying by 2^amt.
+ */
+int
+bnLShift_32(struct BigNum *dest, unsigned amt)
+{
+ unsigned s = dest->size;
+ BNWORD32 carry;
+
+ if (amt % 32) {
+ carry = lbnLshift_32(dest->ptr, s, amt % 32);
+ if (carry) {
+ s++;
+ bnSizeCheck(dest, s);
+ ((BNWORD32 *)dest->ptr)[BIGLITTLE(-s,s-1)] = carry;
+ }
+ }
+
+ amt /= 32;
+ if (amt) {
+ bnSizeCheck(dest, s+amt);
+ memmove((BNWORD32 *)dest->ptr BIGLITTLE(-s-amt, +amt),
+ (BNWORD32 *)dest->ptr BIG(-s),
+ s * sizeof(BNWORD32));
+ lbnZero_32((BNWORD32 *)dest->ptr, amt);
+ s += amt;
+ }
+ dest->size = s;
+ MALLOCDB;
+ return 0;
+}
+
+/*
+ * Shift a bignum right the appropriate number of bits,
+ * dividing by 2^amt.
+ */
+void bnRShift_32(struct BigNum *dest, unsigned amt)
+{
+ unsigned s = dest->size;
+
+ if (amt >= 32) {
+ memmove(
+ (BNWORD32 *)dest->ptr BIG(-s+amt/32),
+ (BNWORD32 *)dest->ptr BIGLITTLE(-s, +amt/32),
+ s-amt/32 * sizeof(BNWORD32));
+ s -= amt/32;
+ amt %= 32;
+ }
+
+ if (amt)
+ (void)lbnRshift_32(dest->ptr, s, amt);
+
+ dest->size = lbnNorm_32(dest->ptr, s);
+ MALLOCDB;
+}
+
+/*
+ * Shift a bignum right until it is odd, and return the number of
+ * bits shifted. n = d * 2^s. Replaces n with d and returns s.
+ * Returns 0 when given 0. (Another valid answer is infinity.)
+ */
+unsigned
+bnMakeOdd_32(struct BigNum *n)
+{
+ unsigned size;
+ unsigned s; /* shift amount */
+ BNWORD32 *p;
+ BNWORD32 t;
+
+ p = (BNWORD32 *)n->ptr;
+ size = lbnNorm_32(p, n->size);
+ if (!size)
+ return 0;
+
+ t = BIGLITTLE(p[-1],p[0]);
+ s = 0;
+
+ /* See how many words we have to shift */
+ if (!t) {
+ /* Shift by words */
+ do {
+
+ s++;
+ BIGLITTLE(--p,p++);
+ } while ((t = BIGLITTLE(p[-1],p[0])) == 0);
+ size -= s;
+ s *= 32;
+ memmove((BNWORD32 *)n->ptr BIG(-size), p BIG(-size),
+ size * sizeof(BNWORD32));
+ p = (BNWORD32 *)n->ptr;
+ MALLOCDB;
+ }
+
+ assert(t);
+
+ /* Now count the bits */
+ while ((t & 1) == 0) {
+ t >>= 1;
+ s++;
+ }
+
+ /* Shift the bits */
+ if (s & (32-1)) {
+ lbnRshift_32(p, size, s & (32-1));
+ /* Renormalize */
+ if (BIGLITTLE(*(p-size),*(p+(size-1))) == 0)
+ --size;
+ }
+ n->size = size;
+
+ MALLOCDB;
+ return s;
+}
diff --git a/usr/src/lib/libresolv2/common/cylink/bn32.h b/usr/src/lib/libresolv2/common/cylink/bn32.h
new file mode 100644
index 0000000000..d6bdc189f6
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/bn32.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/*
+ * bn32.h - interface to 32-bit bignum routines.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+struct BigNum;
+
+void bnInit_32(void);
+void bnEnd_32(struct BigNum *bn);
+int bnPrealloc_32(struct BigNum *bn, unsigned bits);
+int bnCopy_32(struct BigNum *dest, struct BigNum const *src);
+int bnSwap_32(struct BigNum *a, struct BigNum *b);
+void bnNorm_32(struct BigNum *bn);
+void bnExtractBigBytes_32(struct BigNum const *bn, unsigned char *dest,
+ unsigned lsbyte, unsigned dlen);
+int bnInsertBigBytes_32(struct BigNum *bn, unsigned char const *src,
+ unsigned lsbyte, unsigned len);
+void bnExtractLittleBytes_32(struct BigNum const *bn, unsigned char *dest,
+ unsigned lsbyte, unsigned dlen);
+int bnInsertLittleBytes_32(struct BigNum *bn, unsigned char const *src,
+ unsigned lsbyte, unsigned len);
+unsigned bnLSWord_32(struct BigNum const *src);
+unsigned bnBits_32(struct BigNum const *src);
+int bnAdd_32(struct BigNum *dest, struct BigNum const *src);
+int bnSub_32(struct BigNum *dest, struct BigNum const *src);
+int bnCmpQ_32(struct BigNum const *a, unsigned b);
+int bnSetQ_32(struct BigNum *dest, unsigned src);
+int bnAddQ_32(struct BigNum *dest, unsigned src);
+int bnSubQ_32(struct BigNum *dest, unsigned src);
+int bnCmp_32(struct BigNum const *a, struct BigNum const *b);
+int bnSquare_32(struct BigNum *dest, struct BigNum const *src);
+int bnMul_32(struct BigNum *dest, struct BigNum const *a,
+ struct BigNum const *b);
+int bnMulQ_32(struct BigNum *dest, struct BigNum const *a, unsigned b);
+int bnDivMod_32(struct BigNum *q, struct BigNum *r, struct BigNum const *n,
+ struct BigNum const *d);
+int bnMod_32(struct BigNum *dest, struct BigNum const *src,
+ struct BigNum const *d);
+unsigned bnModQ_32(struct BigNum const *src, unsigned d);
+int bnExpMod_32(struct BigNum *dest, struct BigNum const *n,
+ struct BigNum const *exp, struct BigNum const *mod);
+int bnDoubleExpMod_32(struct BigNum *dest,
+ struct BigNum const *n1, struct BigNum const *e1,
+ struct BigNum const *n2, struct BigNum const *e2,
+ struct BigNum const *mod);
+int bnTwoExpMod_32(struct BigNum *n, struct BigNum const *exp,
+ struct BigNum const *mod);
+int bnGcd_32(struct BigNum *dest, struct BigNum const *a,
+ struct BigNum const *b);
+int bnInv_32(struct BigNum *dest, struct BigNum const *src,
+ struct BigNum const *mod);
+int bnLShift_32(struct BigNum *dest, unsigned amt);
+void bnRShift_32(struct BigNum *dest, unsigned amt);
+unsigned bnMakeOdd_32(struct BigNum *n);
diff --git a/usr/src/lib/libresolv2/common/cylink/bn68000.c b/usr/src/lib/libresolv2/common/cylink/bn68000.c
new file mode 100644
index 0000000000..91bcd1d7af
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/bn68000.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/*
+ * bn68000.c - bnInit() for Motorola 680x0 family, 16 or 32-bit.
+ *
+ * Written in 1995 by Colin Plumb.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "lbn.h"
+#include "bn16.h"
+#include "bn32.h"
+
+#ifndef BNINCLUDE
+#error You must define BNINCLUDE to lbn68000.h to use assembly primitives.
+#endif
+
+void
+bnInit(void)
+{
+ if (is68020())
+ bnInit_32();
+ else
+ bnInit_16();
+}
diff --git a/usr/src/lib/libresolv2/common/cylink/bn8086.c b/usr/src/lib/libresolv2/common/cylink/bn8086.c
new file mode 100644
index 0000000000..b50aab6ad6
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/bn8086.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/*
+ * bn8086.c - bnInit() for Intel x86 family in 16-bit mode.
+ *
+ * Written in 1995 by Colin Plumb.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "lbn.h"
+#include "bn16.h"
+#include "bn32.h"
+
+#ifndef BNINCLUDE
+#error You must define BNINCLUDE to lbn8086.h to use assembly primitives.
+#endif
+
+void
+bnInit(void)
+{
+/* if (not386())
+ bnInit_16();
+ else */
+ bnInit_32();
+}
diff --git a/usr/src/lib/libresolv2/common/cylink/bninit16.c b/usr/src/lib/libresolv2/common/cylink/bninit16.c
new file mode 100644
index 0000000000..efe5bd3475
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/bninit16.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/*
+ * bninit16.c - Provide an init function that sets things up for 16-bit
+ * operation. This is a seaparate tiny file so you can compile two bn
+ * packages into the library and write a custom init routine.
+ *
+ * Written in 1995 by Colin Plumb.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "bn.h"
+#include "bn16.h"
+
+void
+bnInit(void)
+{
+ bnInit_16();
+}
diff --git a/usr/src/lib/libresolv2/common/cylink/bninit32.c b/usr/src/lib/libresolv2/common/cylink/bninit32.c
new file mode 100644
index 0000000000..1f90d66780
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/bninit32.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/*
+ * bninit32.c - Provide an init function that sets things up for 32-bit
+ * operation. This is a seaparate tiny file so you can compile two bn
+ * packages into the library and write a custom init routine.
+ *
+ * Written in 1995 by Colin Plumb.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "bn.h"
+#include "bn32.h"
+
+void
+bnInit(void)
+{
+ bnInit_32();
+}
diff --git a/usr/src/lib/libresolv2/common/cylink/bnsize00.h b/usr/src/lib/libresolv2/common/cylink/bnsize00.h
new file mode 100644
index 0000000000..d59f9f40ff
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/bnsize00.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/*
+ * bnsize00.h - pick the correct machine word size to use.
+ *
+ * Copyright (c) 1995 Colin Plumb. All rights reserved.
+ * For licensing and other legal details, see the file legal.c.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "lbn.h" /* Get basic information */
+
+#if !BNSIZE64 && !BNSIZE32 && !BNSIZE16 && defined(BNWORD64)
+# if defined(BNWORD128) || (defined(lbnMulAdd1_64) && defined(lbnMulSub1_64))
+# define BNSIZE64 1
+# elif defined(mul64_ppmm) || defined(mul64_ppmma) || defined(mul64_ppmmaa)
+# define BNSIZE64 1
+# endif
+#endif
+
+#if !BNSIZE64 && !BNSIZE32 && !BNSIZE16 && defined(BNWORD32)
+# if defined(BNWORD64) || (defined(lbnMulAdd1_32) && defined(lbnMulSub1_32))
+# define BNSIZE32 1
+# elif defined(mul32_ppmm) || defined(mul32_ppmma) || defined(mul32_ppmmaa)
+# define BNSIZE32 1
+# endif
+#endif
+
+#if !BNSIZE64 && !BNSIZE32 && !BNSIZE16 && defined(BNWORD16)
+# if defined(BNWORD32) || (defined(lbnMulAdd1_16) && defined(lbnMulSub1_16))
+# define BNSIZE16 1
+# elif defined(mul16_ppmm) || defined(mul16_ppmma) || defined(mul16_ppmmaa)
+# define BNSIZE16 1
+# endif
+#endif
+
+#if !BNSIZE64 && !BNSIZE32 && !BNSIZE16
+#error Unable to find a viable word size to compile bignum library.
+#endif
diff --git a/usr/src/lib/libresolv2/common/cylink/c_asm.h b/usr/src/lib/libresolv2/common/cylink/c_asm.h
new file mode 100644
index 0000000000..c22bc614fb
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/c_asm.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/****************************************************************************
+* FILENAME: c_asm.h PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT
+*
+* FILE STATUS:
+*
+* DESCRIPTION: C / ASM Header File
+*
+* USAGE: File should be included to use Toolkit Functions
+*
+*
+* Copyright (c) Cylink Corporation 1994. All rights reserved.
+*
+* REVISION HISTORY:
+*
+* 14 Oct 94 GKL For Second version (big endian support)
+* 26 Oct 94 GKL (alignment for big endian support )
+*
+****************************************************************************/
+#if !defined( C_ASM_H )
+#define C_ASM_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+#include "cylink.h"
+#include "ctk_endian.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+ int Sum_big (ord *X,
+ ord *Y,
+ ord *Z,
+ int len_X );
+ int Sum (ord *X, ord *Y, ushort len_X );
+ int Sub_big (ord *X,
+ ord *Y,
+ ord *Z,
+ int len_X );
+/*
+ void Mul_big( ord *X, ord *Y,ord *XY,
+ ushort lx, ushort ly,
+ ushort elements_in_X,
+ ushort elements_in_Y);*/
+ void Mul_big( ord *X, ord *Y,ord *XY,
+ ushort lx, ushort ly);
+
+ void PReLo_big( ord *X, ord *P,
+ ushort len_X, ushort el);
+
+ void Div_big( ord *X, ord *P,
+ ushort len_X, ushort el,
+ ord *div);
+
+int LeftMostBit_big ( ord X );
+int LeftMostEl_big( ord *X, ushort len_X );
+void RShiftL_big( ord *X, u_int32_t len_X, u_int32_t n_bit );
+void LShiftL_big( ord *X, u_int32_t len_X, u_int32_t n_bit );
+int RShiftMostBit(ord *a, u_int32_t len);
+void ByteLong(uchar *X, u_int32_t X_bytes, u_int32_t *Y);
+void ByteOrd(uchar *X, u_int32_t X_bytes, ord *Y);
+void OrdByte(ord *X, u_int32_t X_bytes, uchar *Y);
+void LongByte(u_int32_t *X, u_int32_t X_bytes, uchar *Y);
+int BitValue_big( ord *X, ushort n_bits );
+int BitsValue_big( ord *X, ushort n_bits, ushort bit_count );
+void ByteSwap32_big( uchar *X, ushort X_len );
+void Complement_big( ord *X, ushort X_longs);
+void Diagonal_big (ord *X, ushort X_len, ord *X2);
+void Square_big( ord *X, ushort X_len, ord *X2);
+void Mul_big_1( ord X, ord *Y, ord *XY, ushort ly );
+int Sum_Q(ord *X, ushort src, ushort len_X );
+
+
+
+/* In-place DES encryption */
+ void DES_encrypt(uchar *keybuf, uchar *block);
+
+/* In-place DES decryption */
+ void DES_decrypt(uchar *keybuf, uchar *block);
+
+/* In-place KAPPA encryption */
+ void KAPPA_encrypt(uchar *a, uchar *k, ushort r);
+
+/* In-place KAPPA decryption */
+ void KAPPA_decrypt(uchar *a, uchar *k, ushort r);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /*C_ASM_H*/
+
diff --git a/usr/src/lib/libresolv2/common/cylink/cencrint.h b/usr/src/lib/libresolv2/common/cylink/cencrint.h
new file mode 100644
index 0000000000..16adb10348
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/cencrint.h
@@ -0,0 +1,262 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/****************************************************************************
+* FILENAME: cencrint.h PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT
+*
+* FILE STATUS:
+*
+* DESCRIPTION: Cryptographic Toolkit Internal Functions Header File
+*
+* USAGE: File should be included to use Toolkit Functions
+*
+*
+* Copyright (c) Cylink Corporation 1994. All rights reserved.
+*
+* REVISION HISTORY:
+*
+* 23 Aug 94 KPZ Initial release
+* 24 Sep 94 KPZ Added prototypes of internal functions
+* 14 Oct 94 GKL Second version (big endian support)
+* 08 Dec 94 GKL Added YIELD_context to Expo, VerPrime and GenPrime
+*
+****************************************************************************/
+
+#ifndef CENCRINT_H /* Prevent multiple inclusions of same header file */
+#define CENCRINT_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/****************************************************************************
+* INCLUDE FILES
+****************************************************************************/
+
+/* system files */
+#include <sys/types.h>
+#include "cylink.h"
+#include "ctk_endian.h"
+#include "toolkit.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Compute a modulo */
+ int PartReduct( u_int16_t X_bytes, ord *X,
+ u_int16_t P_bytes, ord *P,
+ ord *Z );
+
+/* Compute a modulo product */
+ int Mul( u_int16_t X_bytes, ord *X,
+ u_int16_t Y_bytes, ord *Y,
+ u_int16_t P_bytes, ord *P,
+ ord *Z );
+/*Compute a modulo squaring*/
+int Mul_Squr( u_int16_t X_bytes, ord *X,
+ u_int16_t P_bytes, ord *P,
+ ord *Z );
+int Square( u_int16_t X_bytes,
+ ord *X,
+ u_int16_t P_bytes,
+ ord *P,
+ ord *Z );
+
+/*Compare two array*/
+int Comp_Mont ( ord *X, ord *P, u_int16_t P_longs );
+/*Compute invers element*/
+ord Inv_Mont ( ord x );
+/*Modulo by the Mongomery*/
+void PartReduct_Mont( ord *X, u_int16_t P_bytes, ord *P, ord inv );
+/*Computes squaring by the Mongomery modulo*/
+int Mul_Squr_Mont(ord *X, u_int16_t P_bytes,
+ ord *P, ord *Z,
+ ord inv );
+/*Computes multiply by the montgomery modulo*/
+int Mul_Mont( ord *X, ord *Y,
+ u_int16_t P_bytes, ord *P,
+ ord *Z, ord inv );
+
+/* Compute a modulo exponent */
+ int Expo( u_int16_t X_bytes, ord *X,
+ u_int16_t Y_bytes, ord *Y,
+ u_int16_t P_bytes, ord *P,
+ ord *Z );
+ /*Compute double exponent */
+ int DoubleExpo( u_int16_t X1_bytes,ord *X1,
+ u_int16_t Y1_bytes,ord *Y1,
+ u_int16_t X2_bytes,ord *X2,
+ u_int16_t Y2_bytes,ord *Y2,
+ u_int16_t P_bytes,ord *P,
+ ord *Z);
+/* Compute a modulo inverse element */
+ int Inverse( u_int16_t X_bytes, ord *X,
+ u_int16_t P_bytes, ord *P,
+ ord *Z );
+
+/* Verify Pseudo Prime number */
+ int VerPrime( u_int16_t P_bytes, ord *P,
+ u_int16_t k, ord *RVAL,
+ YIELD_context *yield_cont ); /*TKL00601*/
+
+/* Generate Random Pseudo Prime number */
+ int GenPrime( u_int16_t P_bytes, ord *P,
+ u_int16_t k, ord *RVAL,
+ YIELD_context *yield_cont ); /*TKL00601*/
+
+/* Transfer bytes to u_int32_t */
+ void ByteLong( uchar *X,
+ u_int16_t X_bytes,
+ u_int32_t *Y );
+
+/* Transfer u_int32_t to bytes */
+ void LongByte( u_int32_t *X,
+ u_int16_t X_bytes,
+ uchar *Y );
+
+/* Transfer bytes to ord */
+ void ByteOrd( uchar *X,
+ u_int16_t X_bytes,
+ ord *Y );
+
+/* Transfer ord to bytes */
+ void OrdByte( ord *X,
+ u_int16_t X_bytes,
+ uchar *Y );
+
+/* Find the left most non zero bit */
+ int LeftMostBit ( ord X );
+
+/* Find the left most element */
+ int LeftMostEl( ord *X,
+ u_int16_t len_X );
+
+/* Shift array to rigth by n_bit */
+ void RShiftL( ord *X,
+ u_int16_t len_X,
+ u_int16_t n_bit );
+
+/* Shifts array to left by n_bit */
+ void LShiftL( ord *X,
+ u_int16_t len_X,
+ u_int16_t n_bit );
+
+/* Find the value of bit */
+ int BitValue( ord *X,
+ u_int16_t n_bits );
+
+/* Perform byte reversal on an array of ordinar type (longword or shortword) */
+ void ByteSwap( uchar *X,
+ u_int16_t X_len );
+
+/* Perform byte reversal on an array from LSB to MSB */
+ void BigSwap( uchar *X,
+ u_int16_t X_len );
+
+/* Perform byte reversal on an array of longword */
+ void ByteSwap32( uchar *X,
+ u_int16_t X_len );
+
+/* Perform short reversal on an array of longword */
+ void WordSwap( uchar *X,
+ u_int16_t X_len );
+
+/* Perform SHS transformation */
+ void shaTransform( u_int32_t *state,
+ const uchar *block );
+
+/* Compute modulo addition
+ int Add( ord *X,
+ ord *Y,
+ u_int16_t P_len,
+ ord *P,
+ ord *Z );
+ */
+ int Add( ord *X,
+ ord *Y,
+ u_int16_t P_len,
+ ord *P );
+/* Initialize Secure Hash Function for generate
+ random number for DSS */
+ void SHAInitK( SHA_context *hash_context );
+
+/* Set parity bits */
+ void SetKeyParity( uchar *key );
+
+/* Find a least significant non zero bit
+ and sfift array to right */
+ int RShiftMostBit( ord *a, u_int16_t len );
+
+/*Compute great common divisor */
+ int SteinGCD( ord *m, ord *b, u_int16_t len );
+
+/* Compute a modulo and divisor */
+ int DivRem( u_int16_t X_bytes, ord *X,
+ u_int16_t P_bytes, ord *P,
+ ord *Z, ord *D );
+
+/* Generate random number */
+int MyGenRand( u_int16_t A_bytes, ord *A,
+ ord *RVAL);
+
+/* Compute a Secure Hash Function */
+int MySHA( uchar *message,
+ u_int16_t message_bytes,
+ uchar *hash_result );
+
+/* Finalize Secure Hash Function */
+ int MySHAFinal( SHA_context *hash_context,
+ uchar *hash_result );
+
+ void shaTransform_new( u_int32_t *state,
+ uchar *block );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* CENCRINT_H */
+
diff --git a/usr/src/lib/libresolv2/common/cylink/ctk_endian.h b/usr/src/lib/libresolv2/common/cylink/ctk_endian.h
new file mode 100644
index 0000000000..1e5a27682f
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/ctk_endian.h
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/**********************************************************************\
+* FILENAME: ctk_endian.h PRODUCT NAME:
+*
+* DESCRIPTION: header file of defines
+*
+* USAGE: Platform-dependend compilation modes header
+*
+*
+* Copyright (c) Cylink Corporation 1994. All rights reserved.
+*
+* REVISION HISTORY:
+*
+\**********************************************************************/
+
+#ifndef CTK_ENDIAN_H /* Prevent multiple inclusions of same header file */
+#define CTK_ENDIAN_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <arpa/nameser_compat.h>
+#include "lbn.h"
+
+#if (defined(BIG_ENDIAN) || defined(_BIG_ENDIAN)) && !(defined(LITTLE_ENDIAN) || defined(_LITTLE_ENDIAN))
+# undef BIG_ENDIAN
+# undef _BIG_ENDIAN
+# define BIG_ENDIAN 4321
+# define LITTLE_ENDIAN 1234
+# define BYTE_ORDER BIG_ENDIAN
+
+#elif !(defined(BIG_ENDIAN) || defined(_BIG_ENDIAN)) && (defined(LITTLE_ENDIAN) || defined(_LITTLE_ENDIAN))
+# undef LITTLE_ENDIAN
+# undef _LITTLE_ENDIAN
+# define BIG_ENDIAN 4321
+# define LITTLE_ENDIAN 1234
+# define BYTE_ORDER LITTLE_ENDIAN
+#endif
+
+#if !defined(BYTE_ORDER) || \
+ (BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN)
+ /* you must determine what the correct bit order is for
+ * your compiler - the next line is an intentional error
+ * which will force your compiles to bomb until you fix
+ * the above macros.
+ */
+# if !defined(CTK_LITTLE_ENDIAN) && !defined(CTK_BIG_ENDIAN)
+# error "Undefined or invalid BYTE_ORDER";
+# endif
+#endif
+
+#if !defined(CTK_BIG_ENDIAN) && !defined(CTK_LITTLE_ENDIAN)
+# ifdef BYTE_ORDER
+# if (BYTE_ORDER == LITTLE_ENDIAN)
+# define CTK_LITTLE_ENDIAN
+# elif (BYTE_ORDER == BIG_ENDIAN)
+# define CTK_BIG_ENDIAN
+# else
+# error CAN NOT determine ENDIAN with BYTE_ORDER
+# endif
+# elif defined(_LITTLE_ENDIAN)
+# define CTK_LITTLE_ENDIAN
+# elif defined(_BIG_ENDIAN)
+# define CTK_BIG_ENDIAN
+# else
+# error CAN NOT determine ENDIAN
+# endif
+#endif
+
+#if !defined(CTK_BIG_ENDIAN) && !defined(CTK_LITTLE_ENDIAN)
+# error NO CTK_???_ENDIAN defined
+#endif
+
+#if defined( CTK_LITTLE_ENDIAN ) && defined( CTK_BIG_ENDIAN )
+# error Use only one define CPU type CTK_LITTLE or BIG ENDIAN.
+#endif
+
+#if !defined( ORD_32 ) && !defined( ORD_16 )
+# ifdef BNSIZE64
+# error BNSIZE64 do not know how to do this
+# elif defined(BNSIZE32)
+# define ORD_32
+# elif defined(BNSIZE16)
+# define ORD_16
+# elif !defined( UINT_MAX) /* No <limits.h> */
+# define ORD_16 /* default */
+# else
+# if ULONG_MAX == 0xffffffff
+# define ORD_16
+# else
+# define ORD_32
+# endif
+# endif
+#endif
+
+#if !defined( ORD_32 ) && !defined( ORD_16 )
+#error Not defined basic word type ORD_32 or ORD_16.
+#endif
+
+#if defined( ORD_32 ) && defined( ORD_16 )
+#error Use only one define basic word type ORD_32 or ORD_16.
+#endif
+
+
+#ifdef ORD_16
+/* typedef unsigned short ord; deleted by ogud@tis.com 1998/9/14 */
+typedef u_int16_t ord;
+#define BITS_COUNT 16
+#define MAXDIGIT (ord)(0xFFFF)
+#endif
+
+#ifdef ORD_32
+/* typedef unsigned long ord; deleted by ogud@tis.com 1998/9/14 */
+typedef u_int32_t ord;
+#define BITS_COUNT 32
+#define MAXDIGIT (ord)(0xFFFFFFFF)
+#endif /* ORD_32 */
+
+
+
+#define CALLOC(var,type,len) \
+ var=(type *)calloc(len,1); \
+ if (var==NULL) \
+ status=ERR_ALLOC
+#ifdef CTK_BIG_ENDIAN
+#define ALIGN_CALLOC(i,o,l) \
+ CALLOC(o,ord,l)
+#define ALIGN_CALLOC_COPY(i,o,l) \
+ CALLOC(o,ord,l); \
+ if (o) ByteOrd(i,l,o)
+#define ALIGN_CALLOC_MOVE(i,o,l) \
+ CALLOC(o,ord,l); \
+ if (o) memcpy(o,i,l)
+#define ALIGN_FREE(o) \
+ free ( o )
+#define ALIGN_COPY_FREE(o,i,l) \
+ if ((o) && (status==SUCCESS)) \
+ OrdByte(o,l,i); \
+ free (o)
+#define ALIGN_MOVE_FREE(o,i,l) \
+ if ((o) && (status==SUCCESS)) \
+ memcpy(i,o,l); \
+ memset(o,0,l); \
+ free (o)
+#else
+#define ALIGN_CALLOC(i,o,l) o=(ord *)i
+#define ALIGN_CALLOC_COPY(i,o,l) o=(ord *)i
+#define ALIGN_CALLOC_MOVE(i,o,l) o=(ord *)i
+#define ALIGN_FREE(o) ;
+#define ALIGN_COPY_FREE(o,i,l) ;
+#define ALIGN_MOVE_FREE(o,i,l) ;
+#endif
+#define DSS_P_ALIGN_CALLOC_COPY(i,o,l) \
+ if (i) \
+ { ALIGN_CALLOC_COPY(i,o,l);} \
+ else \
+ o = &DSS_P_NUMBERS[DSS_NUM_INDEX[(l-DSS_LENGTH_MIN)/LENGTH_STEP]]
+
+#define DSS_G_ALIGN_CALLOC_COPY(i,o,l) \
+ if (i) \
+ { ALIGN_CALLOC_COPY(i,o,l);} \
+ else \
+ o = &DSS_G_NUMBERS[DSS_NUM_INDEX[(l-DSS_LENGTH_MIN)/LENGTH_STEP]]
+
+#define DSS_Q_ALIGN_CALLOC_COPY(i,o,l) \
+ if (i) \
+ { ALIGN_CALLOC_COPY(i,o,l);} \
+ else \
+ o = DSS_Q_NUMBER
+
+#define DSS_ALIGN_FREE(o,i) \
+ if (i) \
+ { ALIGN_FREE(o);}
+#endif /* CTK_ENDIAN_H */
diff --git a/usr/src/lib/libresolv2/common/cylink/ctk_prime.c b/usr/src/lib/libresolv2/common/cylink/ctk_prime.c
new file mode 100644
index 0000000000..45b576eb3f
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/ctk_prime.c
@@ -0,0 +1,442 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/****************************************************************************
+* FILENAME: prime.c PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT
+*
+* FILE STATUS:
+*
+* DESCRIPTION: Cryptographic Toolkit Internal Functions File
+* Prime Number functions
+* PRIVATE FUNCTIONS:
+*
+* int VerPrime( u_int16_t P_bytes, ord *P,
+* u_int16_t k, ord *RVAL,
+* YIELD_context *yield_cont )
+* int GenPrime( u_int16_t P_bytes, ord *P,
+* u_int16_t k, ord *RVAL,
+* YIELD_context *yield_cont )
+* Copyright (c) Cylink Corporation 1996. All rights reserved.
+*
+* REVISION HISTORY:
+*
+*
+****************************************************************************/
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/****************************************************************************
+* INCLUDE FILES
+****************************************************************************/
+
+#include "port_before.h"
+#include <sys/types.h>
+#include "cylink.h"
+#include "ctk_endian.h"
+
+/* system files */
+#ifdef VXD
+#include <vtoolsc.h>
+#else
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#endif
+
+/* program files */
+#include "cylink.h"
+#include "ctk_endian.h"
+#include "toolkit.h"
+#include "cencrint.h"
+#include "port_after.h"
+
+/****************************************************************************
+* PRIVATE FUNCTIONS DEFINITIONS
+****************************************************************************/
+/****************************************************************************
+* NAME: int VerPrime( u_int16_t P_bytes,
+* ord *P,
+* u_int16_t k,
+* ord *RVAL,
+* YIELD_context *yield_cont )
+*
+* DESCRIPTION: Verify Pseudo Prime number
+*
+* INPUTS:
+* PARAMETERS:
+* u_int16_t P_bytes Number of bytes in array
+* u_int16_t k Number of testing
+* ord *RVAL Pointer to random number generator value
+* YIELD_context *yield_cont Pointer to yield_cont structure (NULL if not used)
+* OUTPUT:
+* PARAMETERS:
+* ord *P Pointer to prime number
+* ord *RVAL Pointer to updated value
+*
+* RETURN:
+* SUCCESS No errors
+* ERR_INPUT_LEN Invalid length for input data(zero bytes)
+* ERR_PRIME Number is not prime
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 14 Oct 94 GKL Second version (big endian support)
+* 08 Dec 94 GKL Added YIELD_context
+*
+****************************************************************************/
+
+ int VerPrime( u_int16_t P_bytes,
+ ord *P,
+ u_int16_t k,
+ ord *RVAL,
+ YIELD_context *yield_cont ) /*TKL00601*/
+
+{
+ int status = SUCCESS; /*function return status*/
+ ord *b, *n, *c, *pp; /*pointers to working buffers */
+ ord *m, *buf, *P_buf;
+ u_int16_t max_bytes; /*number of maximum bytes*/
+ u_int16_t P_longs; /*number of longs in Y*/
+ u_int16_t i, j, s, k_b; /*counters*/
+ u_int16_t exit ; /*flag for exit*/
+/* product of prime numbers from 3 to 379 (512-bit number) */
+#ifdef ORD_32
+ ord b1[DSS_LENGTH_MIN/sizeof(ord)]={
+ 0x2e30c48fL, 0x0decece9L, 0xbada8f98L, 0x9f7ecb29L,
+ 0xa4a11de4L, 0x6ef04659L, 0xcbc38405L, 0x233db117L,
+ 0x03e81187L, 0xc1b631a2L, 0x238bfb99L, 0x077ec3baL,
+ 0xc5d5f09fL, 0xb0813c28L, 0x7646fa6eL, 0x106aa9fbL };
+#else
+ ord b1[DSS_LENGTH_MIN/sizeof(ord)]={
+ 0xc48f, 0x2e30, 0xece9, 0x0dec, 0x8f98, 0xbada, 0xcb29, 0x9f7e,
+ 0x1de4, 0xa4a1, 0x4659, 0x6ef0, 0x8405, 0xcbc3, 0xb117, 0x233d,
+ 0x1187, 0x03e8, 0x31a2, 0xc1b6, 0xfb99, 0x238b, 0xc3ba, 0x077e,
+ 0xf09f, 0xc5d5, 0x3c28, 0xb081, 0xfa6e, 0x7646, 0xa9fb, 0x106a };
+#endif
+ if ( P_bytes % sizeof(ord) != 0 ) /* not multiple 4 (32 bit) */
+ {
+ status = ERR_INPUT_LEN; /* invalid length for input data */
+ return status;
+ }
+ if ( P_bytes <= DSS_LENGTH_MIN )
+ {
+ max_bytes = DSS_LENGTH_MIN;
+ }
+ else
+ {
+ max_bytes = P_bytes;
+ }
+ buf = (ord *)calloc( max_bytes / sizeof(ord), sizeof(ord) );
+ P_buf = (ord *)calloc( max_bytes / sizeof(ord), sizeof(ord));
+ if( !buf || !P_buf )
+ {
+ if ( buf )
+ free( buf );
+ if( P_buf )
+ free( P_buf );
+ return ERR_ALLOC;
+ }
+ memcpy( buf, b1, DSS_LENGTH_MIN );
+ memcpy( P_buf, P, P_bytes );
+
+ if ( (P_buf[0] & 0x1) == 0 )
+ {
+#ifdef DEBUG1
+ printf ("\n P is not pseudoprime");
+#endif
+ status = ERR_PRIME;
+ free ( buf );
+ free( P_buf );
+ return status;
+ }
+ P_longs = (u_int16_t) (P_bytes / sizeof(ord));
+ b = (ord *)calloc( P_longs, sizeof(ord) );
+ m = (ord *)malloc( P_longs * sizeof(ord) );
+ n = (ord *)calloc( P_longs, sizeof(ord) );
+ c = (ord *)calloc( P_longs, sizeof(ord) );
+ pp = (ord *)malloc( P_longs * sizeof(ord) );
+ if( !b || !m || !n || !c || !pp )
+ {
+ if( b )
+ free( b );
+ if( m )
+ free( m );
+ if( n )
+ free( n );
+ if( c )
+ free( c );
+ if( pp )
+ free ( pp );
+ }
+ memcpy( m, P, P_bytes );
+ memcpy( pp, P, P_bytes );
+ /* Compute great common divisor(gcd) */
+ if ( SteinGCD( P_buf, buf, (u_int16_t)(max_bytes / sizeof(ord)) ) == 0 )
+ {
+ pp[0] = pp[0] - 1; /* Initialized work buffer */
+ m[0] = m[0] - 1;
+ s = (u_int16_t) RShiftMostBit( m, (u_int16_t)(P_bytes / sizeof(ord)) ); /* Right shift by number of*/
+ exit = 0; /* zero bits at rigth */
+ k_b = 0;
+ while( k_b != k )
+ {
+ MyGenRand( 4, b, RVAL ); /* generate random number */
+ if ( SteinGCD( P_buf, b , (u_int16_t)(P_bytes / sizeof(ord)) ) ) /* check gcd */
+ {
+#ifdef DEBUG1
+ printf ("\n P is not pseudoprime");
+#endif
+ status = ERR_PRIME;
+ break;
+ }
+ k_b++; /* increment counter */
+ if ( ( status = Expo ( 4, b, P_bytes, m,
+ P_bytes, P, c ) ) != SUCCESS ) /* c=b^m mod(P) */ /*TKL00601*/
+ {
+ free( b );
+ free( m );
+ free( n );
+ free( c );
+ free( pp );
+ free (buf );
+ free( P_buf );
+ return status;
+ }
+ if ( c[0] == 1 ) /* if c==1 number is pseudo prime */
+ {
+ for ( i = 1; i < P_bytes / sizeof(ord); i++ )
+ {
+ if ( c[i] != 0 )
+ {
+ break;
+ }
+ }
+ if ( i == P_bytes / sizeof(ord) )
+ {
+ if (yield_cont) /*TKL00601*/
+#ifdef VXD
+ if ( VXD_Yield (yield_cont->yield_proc) )
+#else
+ if ( yield_cont->yield_proc(0xFFFF) )
+#endif
+
+ {
+ status = ERR_CANCEL;
+ free( b );
+ free( m );
+ free( n );
+ free( c );
+ free( pp );
+ free( P_buf );
+ free (buf );
+ return status;
+ }
+#ifdef DEBUG1
+ printf ("\n P is a pseudoprime %d",k_b);
+#endif
+ if ( k_b == k )
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ for ( j = 1; j <= s; j++ )
+ {
+ for ( i = 0; i < P_bytes / sizeof(ord); i++ ) /* if c==pp number is pseudo prime */
+ {
+ if ( c[i] != pp[i] )
+ {
+ break;
+ }
+ }
+ if ( i == P_bytes / sizeof(ord) )
+ {
+ if (yield_cont) /*TKL00601*/
+#ifdef VXD
+ if ( VXD_Yield (yield_cont->yield_proc) )
+#else
+ if ( yield_cont->yield_proc(0xFFFF) )
+#endif
+
+ {
+ status = ERR_CANCEL;
+ free( b );
+ free( m );
+ free( n );
+ free( c );
+ free( pp );
+ free( P_buf );
+ free (buf );
+ return status;
+ }
+#ifdef DEBUG1
+ printf ("\n P is a pseudoprime %d",k_b);
+#endif
+ break;
+ }
+ if ( j == s )
+ {
+#ifdef DEBUG1
+ printf ("\n P is not pseudoprime");
+#endif
+ status = ERR_PRIME;
+ exit = 1;
+ break;
+ }
+ else
+ {
+ if ( (status = Square(P_bytes, c, /*P_bytes,
+ c,*/ P_bytes, P, c) )
+ != SUCCESS ) /* c=c^2mod(p) */
+ {
+ free( b );
+ free( m );
+ free( n );
+ free( c );
+ free( pp );
+ free( P_buf );
+ free (buf );
+ return status;
+ }
+ }
+ }
+ }
+ if ( exit == 1 ) /* Exit */
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (yield_cont) /*TKL00601*/
+#ifdef VXD
+ if ( VXD_Yield (yield_cont->yield_proc) )
+#else
+ if ( yield_cont->yield_proc(0xFFFF) )
+#endif
+
+ {
+ status = ERR_CANCEL;
+ free( b );
+ free( m );
+ free( n );
+ free( c );
+ free( pp );
+ free( P_buf );
+ free (buf );
+ return status;
+ }
+#ifdef DEBUG1
+ printf ("\n P is not pseudoprime");
+#endif
+ status = ERR_PRIME;
+ }
+ free( b );
+ free( m );
+ free( n );
+ free( c );
+ free( pp );
+ free( P_buf );
+ free (buf );
+ return status;
+}
+
+/****************************************************************************
+* NAME: int GenPrime( u_int16_t P_bytes,
+* ord *P,
+* u_int16_t k,
+* ord *RVAL,
+* YIELD_context *yield_cont )
+*
+* DESCRIPTION: Generate Random Pseudo Prime number
+*
+* INPUTS:
+* PARAMETERS:
+* u_int16_t P_bytes Number of bytes in array
+* u_int16_t k Number of testing
+* ord *RVAL Pointer to random number generator value
+* YIELD_context *yield_cont Pointer to yield_cont structure (NULL if not used)
+* OUTPUT:
+* PARAMETERS:
+* ord *P Pointer to prime number
+* ord *RVAL Pointer to updated value
+*
+* RETURN:
+* SUCCESS No errors
+* ERR_INPUT_LEN Invalid length for input data(zero bytes)
+* ERR_PRIME Number is not prime
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 14 Oct 94 GKL Second version (big endian support)
+* 08 Dec 94 GKL Added YIELD_context
+*
+****************************************************************************/
+
+ int GenPrime( u_int16_t P_bytes,
+ ord *P,
+ u_int16_t k,
+ ord *RVAL,
+ YIELD_context *yield_cont ) /*TKL00601*/
+{
+ int status = SUCCESS; /* function return status */
+ if ( P_bytes % sizeof(ord) != 0 ) /* not multiple 4 (32 bit) */
+ {
+ status = ERR_INPUT_LEN; /* invalid length for input data */
+ return status;
+ }
+ do
+ {
+ MyGenRand( P_bytes, P, RVAL ); /* generate random number */
+ P[0] |= 1;
+ P[(P_bytes/sizeof(ord))-1] |= ((ord)1 << (BITS_COUNT-1));
+ status = VerPrime( P_bytes, P, k, RVAL, yield_cont); /*TKL00601*/
+ } while ((status != SUCCESS) && (status != ERR_CANCEL)); /*TKL00601*/
+ return status;
+}
+
diff --git a/usr/src/lib/libresolv2/common/cylink/cylink.h b/usr/src/lib/libresolv2/common/cylink/cylink.h
new file mode 100644
index 0000000000..1ebbfbbd92
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/cylink.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/**********************************************************************\
+* FILENAME: cylink.h PRODUCT NAME:
+*
+* DESCRIPTION: Company standard include file
+*
+* USAGE: File should be #included
+*
+*
+* Copyright (c) Cylink Corporation 1994. All rights reserved.
+*
+* REVISION HISTORY:
+*
+\**********************************************************************/
+
+#ifndef CYLINK_H /* Prevent multiple inclusions of same header file */
+#define CYLINK_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/param.h>
+#if (!defined(BSD)) || (BSD < 199306)
+# include <sys/bitypes.h>
+#else
+# include <sys/types.h>
+#endif
+
+#if ! ( defined(__alpha) && defined(__osf__) ) /* in sys/types.h */
+#if !defined(_H_INTTYPES) && !defined (_H_TYPES) /* AIX puts this in inttypes.h */
+typedef unsigned char uchar;
+#endif /* _H_INTTYPES */
+#endif
+
+typedef u_int16_t USHORT;
+typedef u_int32_t ULONG;
+
+#define FALSE 0
+#define TRUE 1
+
+/*-- ANSI-recommended NULL Pointer definition --*/
+#ifndef NULL
+#define NULL (void *) 0
+#endif
+
+#endif /* CYLINK_H */
diff --git a/usr/src/lib/libresolv2/common/cylink/dss.c b/usr/src/lib/libresolv2/common/cylink/dss.c
new file mode 100644
index 0000000000..fe907a6f21
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/dss.c
@@ -0,0 +1,1209 @@
+/*
+ * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/****************************************************************************
+* FILENAME: dss.c PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT
+*
+* FILE STATUS:
+*
+* DESCRIPTION: Cryptographic Toolkit Functions File
+* Digital Signature Algorithms
+* PUBLIC FUNCTIONS:
+* uchar *RVAL )
+* int GenDSSKey( u_int16_t dss_p_bytes, uchar *dss_p,
+* uchar *dss_q, uchar *dss_g,
+* uchar *dss_x, uchar *dss_y,
+* uchar *XKEY )
+*
+* int GenDSSNumber( uchar *dss_k, uchar dss_q,
+* uchar *KKEY )
+* int GenDSSParameters( u_int16_t dss_p_bytes, uchar *dss_p,
+* uchar *dss_q, uchar *dss_g,
+* uchar *RVAL );
+*
+* Copyright (c) Cylink Corporation 1996. All rights reserved.
+*
+* REVISION HISTORY:
+*
+*
+****************************************************************************/
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/****************************************************************************
+* INCLUDE FILES
+****************************************************************************/
+
+#include "port_before.h"
+#include <sys/types.h>
+#include "cylink.h"
+#include "ctk_endian.h"
+
+/* system files */
+#ifdef VXD
+#include <vtoolsc.h>
+#else
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+/* program files */
+#ifdef VXD
+#include "tkvxd.h"
+#endif
+#include "toolkit.h"
+#include "cencrint.h"
+#define INITIALIZ_PQG /*TKL01101*/
+#include "dssnum.h" /*TKL01101*/
+#include "sha.h"
+#include "port_after.h"
+
+#define BEGIN_PROCESSING do {
+#define END_PROCESSING } while (0);
+#define ERROR_BREAK break
+#define CONTINUE continue
+
+#define BEGIN_LOOP do {
+#define END_LOOP } while (1);
+#define BREAK break
+
+
+extern u_int16_t DataOrder;
+
+/****************************************************************************
+* NAME: int GenDSSSignature( u_int16_t dss_p_bytes,
+* uchar *dss_p,
+* uchar *dss_q,
+* uchar *dss_g,
+* uchar *dss_x,
+* uchar *dss_k,
+* uchar *r,
+* uchar *s,
+* uchar *hash_result)
+*
+* DESCRIPTION: Compute a DSS Signature
+*
+* INPUTS:
+* PARAMETERS:
+* u_int16_t dss_p_bytes Length of dss_p
+* uchar *dss_p Pointer to p prime
+* uchar *dss_q Pointer to q prime
+* uchar *dss_g Pointer to g
+* uchar *dss_x Pointer to secret number
+* uchar *dss_k Pointer to random secret number
+* uchar *hash_result Pointer to message hashing result
+*
+*
+* OUTPUT:
+* PARAMETERS:
+* uchar *r Pointer to r part of signature
+* uchar *s Pointer to s part of signature
+*
+* RETURN:
+* E_SUCCESS No errors
+* E_DSS_LEN Invalid length for dss_p
+* ERR_ALLOC Insufficient memory
+*
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 14 Oct 94 GKL Second version (big endian support)
+* 26 Oct 94 GKL (alignment for big endian support & ERR_ALLOC)
+* 08 Dec 94 GKL Changed Expo call
+*
+****************************************************************************/
+
+int GenDSSSignature( u_int16_t dss_p_bytes,
+ uchar *dss_p,
+ uchar *dss_q,
+ uchar *dss_g,
+ uchar *dss_x,
+ uchar *dss_k,
+ uchar *r,
+ uchar *s,
+ uchar *hash_result)
+
+{
+ int status = SUCCESS; /* function return status */
+ ord r_temp[DSS_LENGTH_MAX]; /* r intermidiate value */
+ ord k_inverse[SHA_LENGTH+1];
+ ord temp[SHA_LENGTH+1]; /* intermidiate values */
+ ord *dss_p_a;
+ ord *dss_g_a;
+ ord *dss_q_a;
+ ord *dss_x_a;
+ ord *dss_k_a;
+ ord *hash_result_a;
+ ord *r_a;
+ ord *s_a;
+
+ if ( (dss_p_bytes < DSS_LENGTH_MIN) || /* less than minimal */
+ (dss_p_bytes > DSS_LENGTH_MAX) ) /* more than maximal */
+ {
+ status = ERR_DSS_LEN; /* invalid length for dss_p */
+ return status;
+ }
+ if ( dss_p_bytes & 0x07 ) /* not multiple 8 (64 bit)*/
+ {
+ status = ERR_DSS_LEN; /* invalid length for dss_p */
+ return status;
+ }
+
+ if (DataOrder)
+ {
+ if (dss_p)
+ BigSwap(dss_p, dss_p_bytes);
+ if (dss_q)
+ BigSwap(dss_q, SHA_LENGTH);
+ if (dss_g)
+ BigSwap(dss_g, dss_p_bytes);
+ BigSwap(dss_x, SHA_LENGTH);
+ BigSwap(dss_k, SHA_LENGTH);
+ BigSwap(hash_result, SHA_LENGTH);
+ }
+
+ DSS_G_ALIGN_CALLOC_COPY(dss_g, dss_g_a, dss_p_bytes); /*TKL01101*/
+ DSS_P_ALIGN_CALLOC_COPY(dss_p, dss_p_a, dss_p_bytes); /*TKL01101*/
+ DSS_Q_ALIGN_CALLOC_COPY(dss_q, dss_q_a, SHA_LENGTH); /*TKL01101*/
+
+ ALIGN_CALLOC_COPY(dss_x, dss_x_a, SHA_LENGTH);
+ ALIGN_CALLOC_COPY(dss_k, dss_k_a, SHA_LENGTH);
+ ALIGN_CALLOC_COPY(hash_result, hash_result_a, SHA_LENGTH);
+ ALIGN_CALLOC(r, r_a, SHA_LENGTH);
+ ALIGN_CALLOC(s, s_a, SHA_LENGTH);
+ if ( status != SUCCESS )
+ {
+ if( dss_p_a )
+ DSS_ALIGN_FREE(dss_p_a,dss_p);
+ if( dss_g_a )
+ DSS_ALIGN_FREE(dss_g_a,dss_g);
+ if( dss_q_a )
+ DSS_ALIGN_FREE(dss_q_a,dss_q);
+ if( dss_x_a )
+ {
+ memset ( dss_x_a , 0 , SHA_LENGTH );
+ ALIGN_FREE(dss_x_a);
+ }
+ if( dss_k_a )
+ {
+ ALIGN_FREE(dss_k_a);
+ }
+ if( hash_result_a )
+ {
+ ALIGN_FREE(hash_result_a);
+ }
+ if( r_a )
+ {
+ ALIGN_COPY_FREE(r_a,r,SHA_LENGTH);
+ }
+ if( s_a )
+ {
+ ALIGN_COPY_FREE(s_a,s,SHA_LENGTH);
+ }
+ if (DataOrder)
+ {
+ if (dss_p)
+ BigSwap(dss_p, dss_p_bytes);
+ if (dss_q)
+ BigSwap(dss_q, SHA_LENGTH);
+ if (dss_g)
+ BigSwap(dss_g, dss_p_bytes);
+ BigSwap(dss_x, SHA_LENGTH);
+ BigSwap(dss_k, SHA_LENGTH);
+ BigSwap(hash_result, SHA_LENGTH);
+ }
+ return status; /* ERR_ALLOC insufficient memory */
+ }
+
+/* Compute DSS r value */
+ BEGIN_PROCESSING
+ if (( status = Expo ( dss_p_bytes,
+ dss_g_a,
+ SHA_LENGTH, /* r_temp=(dss_g^dss_k)mod(dss_p)*/
+ dss_k_a,
+ dss_p_bytes,
+ dss_p_a,
+ r_temp )) != SUCCESS )
+ {
+ ERROR_BREAK;
+ }
+ if (( status = PartReduct ( dss_p_bytes,
+ r_temp,
+ SHA_LENGTH, /* r=(r_temp)mod(dss_q) */
+ dss_q_a,
+ r_a )) != SUCCESS )
+ {
+ ERROR_BREAK;
+ }
+/* Compute k modulo inverse value */
+ if (( status = Inverse( SHA_LENGTH, /* k_inverse=dss_k^(-1)mod(dss_q)*/
+ dss_k_a,
+ SHA_LENGTH,
+ dss_q_a,
+ k_inverse )) != SUCCESS )
+ {
+ ERROR_BREAK;
+ }
+/* Compute DSS s value */
+ if (( status = Mul ( SHA_LENGTH, /* temp=(dss_x*r)mod(dss_q) */
+ dss_x_a,
+ SHA_LENGTH,
+ r_a,
+ SHA_LENGTH,
+ dss_q_a,
+ temp )) != SUCCESS )
+ {
+ ERROR_BREAK;
+ }
+
+ /* Add( temp, hash_result_a,
+ SHA_LENGTH, dss_q_a, temp ); temp=(temp+hash_result)mod(dss_q)*/
+
+ Add( temp, hash_result_a,
+ SHA_LENGTH, dss_q_a );
+ if (( status = Mul ( SHA_LENGTH, /* s=(temp*k_inverse)mod(dss_q) */
+ temp,
+ SHA_LENGTH,
+ k_inverse,
+ SHA_LENGTH,
+ dss_q_a,
+ s_a )) != SUCCESS )
+ {
+ ERROR_BREAK;
+ }
+ END_PROCESSING
+
+ DSS_ALIGN_FREE(dss_p_a,dss_p); /*TKL01101*/
+ DSS_ALIGN_FREE(dss_g_a,dss_g); /*TKL01101*/
+ DSS_ALIGN_FREE(dss_q_a,dss_q); /*TKL01101*/
+ ALIGN_FREE(dss_x_a);
+ ALIGN_FREE(dss_k_a);
+ ALIGN_FREE(hash_result_a);
+ ALIGN_COPY_FREE(r_a,r,SHA_LENGTH);
+ ALIGN_COPY_FREE(s_a,s,SHA_LENGTH);
+
+ if (DataOrder)
+ {
+ if (dss_p)
+ BigSwap(dss_p, dss_p_bytes);
+ if (dss_q)
+ BigSwap(dss_q, SHA_LENGTH);
+ if (dss_g)
+ BigSwap(dss_g, dss_p_bytes);
+ BigSwap(dss_x, SHA_LENGTH);
+ BigSwap(dss_k, SHA_LENGTH);
+ BigSwap(hash_result, SHA_LENGTH);
+ BigSwap(r, SHA_LENGTH);
+ BigSwap(s, SHA_LENGTH);
+ }
+
+ return status;
+}
+
+/****************************************************************************
+* NAME: int VerDSSSignature( u_int16_t dss_p_bytes,
+* uchar *dss_p,
+* uchar *dss_q,
+* uchar *dss_g,
+* uchar *dss_y,
+* uchar *r,
+* uchar *s,
+* uchar *hash_result)
+*
+* DESCRIPTION: Verify a DSS Signature
+*
+* INPUTS:
+* PARAMETERS:
+* u_int16_t dss_p_bytes Length of dss_p
+* uchar *dss_p Pointer to p prime
+* uchar *dss_q Pointer to q prime
+* uchar *dss_g Pointer to g
+* uchar *dss_y Pointer to public number
+* uchar *hash_result Pointer to message hashing result
+* OUTPUT:
+* PARAMETERS:
+*
+* RETURN:
+* SUCCESS No errors
+* ERR_SIGNATURE Signature is not valid
+* ERR_DSS_LEN Invalid length for dss_p
+* ERR_ALLOC Insufficient memory
+*
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 14 Oct 94 GKL Second version (big endian support)
+* 26 Oct 94 GKL (alignment for big endian support & ERR_ALLOC)
+* 08 Dec 94 GKL Changed Expo call
+* 21 Aug 96 AAB DoubleExpo call
+****************************************************************************/
+
+int VerDSSSignature( u_int16_t dss_p_bytes,
+ uchar *dss_p,
+ uchar *dss_q,
+ uchar *dss_g,
+ uchar *dss_y,
+ uchar *r,
+ uchar *s,
+ uchar *hash_result)
+{
+ int status = SUCCESS; /* function return status */
+ ord w[(SHA_LENGTH / sizeof(ord)) + 1];
+ ord u1[SHA_LENGTH / sizeof(ord)];
+ ord u2[SHA_LENGTH / sizeof(ord)];
+ ord *v;
+ ord *dss_p_a;
+ ord *dss_g_a;
+ ord *dss_q_a;
+ ord *dss_y_a;
+ ord *hash_result_a;
+ ord *r_a;
+ ord *s_a;
+ if ( (dss_p_bytes < DSS_LENGTH_MIN) || /* less than minimal */
+ (dss_p_bytes > DSS_LENGTH_MAX) ) /* more than maximal */
+ {
+ status = ERR_DSS_LEN; /* invalid length for dss_p */
+ return status;
+ }
+ if ( dss_p_bytes & 0x07 ) /* not multiple 8 (64 bit)*/
+ {
+ status = ERR_DSS_LEN; /* invalid length for dss_p */
+ return status;
+ }
+
+ if (DataOrder)
+ {
+ if (dss_p)
+ BigSwap(dss_p, dss_p_bytes);
+ if (dss_q)
+ BigSwap(dss_q, SHA_LENGTH);
+ if (dss_g)
+ BigSwap(dss_g, dss_p_bytes);
+ BigSwap(dss_y, dss_p_bytes);
+ BigSwap(hash_result, SHA_LENGTH);
+ BigSwap(r, SHA_LENGTH);
+ BigSwap(s, SHA_LENGTH);
+ }
+
+ DSS_P_ALIGN_CALLOC_COPY(dss_p, dss_p_a, dss_p_bytes); /*TKL01101*/
+ DSS_Q_ALIGN_CALLOC_COPY(dss_q, dss_q_a, SHA_LENGTH); /*TKL01101*/
+ DSS_G_ALIGN_CALLOC_COPY(dss_g, dss_g_a, dss_p_bytes); /*TKL01101*/
+
+ ALIGN_CALLOC_COPY(dss_y, dss_y_a, dss_p_bytes);
+ ALIGN_CALLOC_COPY(hash_result, hash_result_a, SHA_LENGTH);
+ ALIGN_CALLOC_COPY(r, r_a, SHA_LENGTH);
+ ALIGN_CALLOC_COPY(s, s_a, SHA_LENGTH);
+ CALLOC(v,ord,dss_p_bytes);
+
+ if ( status != SUCCESS )
+ {
+ if( dss_p_a )
+ {
+ DSS_ALIGN_FREE(dss_p_a,dss_p);
+ }
+ if( dss_g_a )
+ {
+ DSS_ALIGN_FREE(dss_g_a,dss_g);
+ }
+ if ( dss_q_a )
+ {
+ DSS_ALIGN_FREE(dss_q_a,dss_q);
+ }
+ if( dss_y_a )
+ {
+ ALIGN_FREE(dss_y_a);
+ }
+ if( hash_result_a )
+ {
+ ALIGN_FREE(hash_result_a);
+ }
+ if( r_a )
+ {
+ ALIGN_FREE(r_a);
+ }
+ if( s_a )
+ {
+ ALIGN_FREE(s_a);
+ }
+ if( v )
+ {
+ free ( v );
+ }
+ if (DataOrder)
+ {
+ if (dss_p)
+ BigSwap(dss_p, dss_p_bytes);
+ if (dss_q)
+ BigSwap(dss_q, SHA_LENGTH);
+ if (dss_g)
+ BigSwap(dss_g, dss_p_bytes);
+ BigSwap(dss_y, dss_p_bytes);
+ BigSwap(hash_result, SHA_LENGTH);
+ BigSwap(r, SHA_LENGTH);
+ BigSwap(s, SHA_LENGTH);
+ }
+
+ return status; /* ERR_ALLOC insufficient memory */
+ }
+
+ BEGIN_PROCESSING
+ if (( status = Inverse( SHA_LENGTH, /* w=dss_k^(-1)mod(dss_q)*/
+ s_a,
+ SHA_LENGTH,
+ dss_q_a,
+ w )) !=SUCCESS )
+ {
+ ERROR_BREAK;
+ }
+ if (( status = Mul ( SHA_LENGTH, /* u1=(hash_result_*w)mod(dss_q) */
+ hash_result_a,
+ SHA_LENGTH,
+ w,
+ SHA_LENGTH,
+ dss_q_a,
+ u1 )) != SUCCESS )
+ {
+ ERROR_BREAK;
+ }
+ if (( status = Mul ( SHA_LENGTH, /* u2=(r*w)mod(dss_q) */
+ r_a,
+ SHA_LENGTH,
+ w,
+ SHA_LENGTH,
+ dss_q_a,
+ u2 )) != SUCCESS )
+ {
+ ERROR_BREAK;
+ }
+ /* v = dss_g_a^u1*dss_y_a^u2 moddss_p_a */
+ if((status = DoubleExpo( dss_p_bytes, dss_g_a,
+ SHA_LENGTH, u1,
+ dss_p_bytes, dss_y_a,
+ SHA_LENGTH, u2,
+ dss_p_bytes, dss_p_a, v)) != SUCCESS )
+ {
+
+ ERROR_BREAK;
+ }
+ if (( status = PartReduct ( dss_p_bytes, /*v = v mod(dss_q)*/
+ v,
+ SHA_LENGTH,
+ dss_q_a,
+ v )) != SUCCESS )
+ {
+ ERROR_BREAK;
+ }
+
+ if (( status = memcmp( r_a, v, SHA_LENGTH)) != 0) /*if v=r sign valid */
+ {
+ status = ERR_SIGNATURE; /* signature is not valid */
+ ERROR_BREAK;
+ }
+ END_PROCESSING
+ free ( v );
+ DSS_ALIGN_FREE(dss_p_a,dss_p); /*TKL01101*/
+ DSS_ALIGN_FREE(dss_g_a,dss_g); /*TKL01101*/
+ DSS_ALIGN_FREE(dss_q_a,dss_q); /*TKL01101*/
+ ALIGN_FREE(dss_y_a);
+ ALIGN_FREE(hash_result_a);
+ ALIGN_FREE(r_a);
+ ALIGN_FREE(s_a);
+
+ if (DataOrder)
+ {
+ if (dss_p)
+ BigSwap(dss_p, dss_p_bytes);
+ if (dss_q)
+ BigSwap(dss_q, SHA_LENGTH);
+ if (dss_g)
+ BigSwap(dss_g, dss_p_bytes);
+ BigSwap(dss_y, dss_p_bytes);
+ BigSwap(hash_result, SHA_LENGTH);
+ BigSwap(r, SHA_LENGTH);
+ BigSwap(s, SHA_LENGTH);
+ }
+
+ return status;
+}
+
+
+/****************************************************************************
+* NAME: int GenDSSKey( u_int16_t dss_p_bytes,
+* uchar *dss_p,
+* uchar *dss_q,
+* uchar *dss_g,
+* uchar *dss_x,
+* uchar *dss_y,
+* uchar *XKEY )
+*
+*
+* DESCRIPTION: Compute DSS public/secret number pair.
+*
+* INPUTS:
+* PARAMETERS:
+* u_int16_t dss_p_bytes Length of modulo
+* uchar *dss_p Pointer to modulo
+* uchar *dss_q Pointer to modulo
+* uchar *dss_g Pointer to public key
+* uchar *XKEY Pointer to user supplied random number
+*
+*
+* OUTPUT:
+* PARAMETERS:
+* uchar *dss_x Pointer to secret key
+* uchar *dss_y Pointer to public key
+* uchar *XKEY Pointer to updated number
+*
+* RETURN:
+* SUCCESS No errors
+* ERR_INPUT_LEN Invalid length for input data
+* ERR_DATA Generic data error
+* ERR_ALLOC Insufficient memory
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 14 Oct 94 GKL Second version (big endian support)
+* 26 Oct 94 GKL (alignment for big endian support & ERR_ALLOC)
+* 08 Dec 94 GKL Changed Expo call
+*
+****************************************************************************/
+
+int GenDSSKey( u_int16_t dss_p_bytes,
+ uchar *dss_p,
+ uchar *dss_q,
+ uchar *dss_g,
+ uchar *dss_x,
+ uchar *dss_y,
+ uchar *XKEY )
+{
+
+ int status = SUCCESS; /* function return status */
+ SHA_context hash_context; /* SHA context structure */
+ uchar M[DSS_LENGTH_MIN]; /* message block */
+ ord *dss_p_a;
+ ord *dss_q_a;
+ ord *dss_g_a;
+ ord *dss_x_a;
+ ord *dss_y_a;
+ ord *XKEY_a;
+ if ( (dss_p_bytes < DSS_LENGTH_MIN) || /* less than minimal */
+ (dss_p_bytes > DSS_LENGTH_MAX) ) /* more than maximal */
+ {
+ status = ERR_DSS_LEN; /* invalid length for dss_p */
+ return status;
+ }
+ if ( dss_p_bytes & 0x07 ) /* not multiple 8 (64 bit)*/
+ {
+ status = ERR_DSS_LEN; /* invalid length for dss_p */
+ return status;
+ }
+ if (DataOrder)
+ {
+ if (dss_p)
+ BigSwap(dss_p, dss_p_bytes);
+ if (dss_q)
+ BigSwap(dss_q, SHA_LENGTH);
+ if (dss_g)
+ BigSwap(dss_g, dss_p_bytes);
+ }
+
+ DSS_P_ALIGN_CALLOC_COPY(dss_p, dss_p_a, dss_p_bytes); /*TKL01101*/
+ DSS_G_ALIGN_CALLOC_COPY(dss_g, dss_g_a, dss_p_bytes); /*TKL01101*/
+ DSS_Q_ALIGN_CALLOC_COPY(dss_q, dss_q_a, SHA_LENGTH); /*TKL01101*/
+ ALIGN_CALLOC(dss_x, dss_x_a, SHA_LENGTH);
+ ALIGN_CALLOC(dss_y, dss_y_a, dss_p_bytes);
+ if ( status != SUCCESS )
+ {
+ if( dss_p_a )
+ DSS_ALIGN_FREE(dss_p_a,dss_p);
+ if( dss_g_a )
+ DSS_ALIGN_FREE(dss_g_a,dss_g);
+ if( dss_q_a )
+ DSS_ALIGN_FREE(dss_q_a,dss_q);
+ if( dss_x_a )
+ {
+ memset(dss_x_a, 0, SHA_LENGTH );
+ ALIGN_COPY_FREE(dss_x_a,dss_x,SHA_LENGTH);
+ }
+ if( dss_y_a )
+ {
+ ALIGN_COPY_FREE(dss_y_a,dss_y,dss_p_bytes);
+ }
+
+ if (DataOrder)
+ {
+ if (dss_p)
+ BigSwap(dss_p, dss_p_bytes);
+ if (dss_q)
+ BigSwap(dss_q, SHA_LENGTH);
+ if (dss_g)
+ BigSwap(dss_g, dss_p_bytes);
+ }
+ return status; /* ERR_ALLOC insufficient memory */
+ }
+
+ BEGIN_PROCESSING
+ SHAInit ( &hash_context );
+ memcpy( M, XKEY, SHA_LENGTH);
+ memset( M + SHA_LENGTH, 0, DSS_LENGTH_MIN - SHA_LENGTH );
+ if ( (status = SHAUpdate( &hash_context, M, DSS_LENGTH_MIN ))
+ != SUCCESS )
+ {
+ ERROR_BREAK;
+ }
+ if ( (status = MySHAFinal (&hash_context, (uchar *)dss_x_a)) != SUCCESS )
+ {
+ ERROR_BREAK;
+ }
+ if (( status = PartReduct ( SHA_LENGTH, /* dss_x = dss_x mod(dss_q)*/
+ dss_x_a,
+ SHA_LENGTH,
+ dss_q_a,
+ dss_x_a )) != SUCCESS )
+ {
+ ERROR_BREAK;
+ }
+
+ BigSwap(XKEY, SHA_LENGTH);
+ ALIGN_CALLOC_COPY(XKEY, XKEY_a, SHA_LENGTH);
+ if ( status != SUCCESS )
+ {
+ if( XKEY_a )
+ {
+ ALIGN_COPY_FREE(XKEY_a,XKEY,SHA_LENGTH);
+ BigSwap(XKEY, SHA_LENGTH);
+ return status; /* ERR_ALLOC insufficient memory */
+ }
+ }
+
+ Sum_Q((ord*)XKEY_a, 1, SHA_LENGTH / sizeof (ord) );
+
+ Sum_big( XKEY_a, dss_x_a, /* XKEY=XKEY+dss_x */
+ XKEY_a, SHA_LENGTH / sizeof(ord) );
+
+ ALIGN_COPY_FREE(XKEY_a,XKEY,SHA_LENGTH);
+ BigSwap(XKEY, SHA_LENGTH);
+
+ if (( status = Expo ( dss_p_bytes, /*dss_y = g^dss_x mod(dss_p)*/
+ dss_g_a,
+ SHA_LENGTH,
+ dss_x_a,
+ dss_p_bytes,
+ dss_p_a,
+ dss_y_a)) != SUCCESS ) /*TKL00601*/
+ {
+ ERROR_BREAK;
+ }
+ END_PROCESSING
+
+ DSS_ALIGN_FREE(dss_p_a,dss_p); /*TKL01101*/
+ DSS_ALIGN_FREE(dss_g_a,dss_g); /*TKL01101*/
+ DSS_ALIGN_FREE(dss_q_a,dss_q); /*TKL01101*/
+ ALIGN_COPY_FREE(dss_x_a,dss_x,SHA_LENGTH);
+ ALIGN_COPY_FREE(dss_y_a,dss_y,dss_p_bytes);
+ if (DataOrder)
+ {
+ if (dss_p)
+ BigSwap(dss_p, dss_p_bytes);
+ if (dss_q)
+ BigSwap(dss_q, SHA_LENGTH);
+ if (dss_g)
+ BigSwap(dss_g, dss_p_bytes);
+ BigSwap(dss_x, SHA_LENGTH);
+ BigSwap(dss_y, dss_p_bytes);
+ }
+
+ return status;
+}
+
+
+
+/****************************************************************************
+* NAME: int GenDSSNumber( uchar *dss_k,
+* uchar *dss_q,
+* uchar *KKEY )
+*
+* DESCRIPTION: Generate secret number
+*
+* INPUTS:
+* PARAMETERS:
+* uchar *KKEY Pointer to input random number
+* uchar *dss_q Pointer to modulo
+*
+*
+* OUTPUT:
+* PARAMETERS:
+* uchar *dss_x Pointer to secret number
+* uchar *KKEY Pointer to updated KKEY
+*
+* RETURN:
+* SUCCESS No errors
+* ERR_DATA Generic data error
+* ERR_ALLOC Insufficient memory
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 14 Oct 94 GKL Second version (big endian support)
+* 26 Oct 94 GKL (alignment for big endian support & ERR_ALLOC)
+*
+****************************************************************************/
+
+int GenDSSNumber( uchar *dss_k,
+ uchar *dss_q,
+ uchar *KKEY )
+{
+
+ int status = SUCCESS; /* function return status */
+ ord *dss_k_a;
+ ord *dss_q_a;
+ ord *KKEY_a;
+ SHA_context hash_context; /* SHA context structure*/
+ uchar M[DSS_LENGTH_MIN]; /* message block */
+
+ if (DataOrder)
+ {
+ if (dss_q)
+ BigSwap(dss_q, SHA_LENGTH);
+ }
+
+ DSS_Q_ALIGN_CALLOC_COPY(dss_q, dss_q_a, SHA_LENGTH); /*TKL01101*/
+ ALIGN_CALLOC(dss_k, dss_k_a, SHA_LENGTH);
+ if ( status != SUCCESS )
+ {
+ if( dss_q_a )
+ DSS_ALIGN_FREE(dss_q_a,dss_q);
+ if( dss_k_a )
+ {
+ ALIGN_COPY_FREE(dss_k_a,dss_k,SHA_LENGTH);
+ }
+ if (DataOrder)
+ {
+ if (dss_q)
+ BigSwap(dss_q, SHA_LENGTH);
+ }
+ return status; /* ERR_ALLOC insufficient memory */
+ }
+
+ BEGIN_PROCESSING
+ SHAInitK ( &hash_context );
+ memcpy( M, KKEY, SHA_LENGTH);
+ memset( M + SHA_LENGTH, 0, DSS_LENGTH_MIN - SHA_LENGTH );
+ if ( (status = SHAUpdate( &hash_context, M, DSS_LENGTH_MIN ))
+ != SUCCESS )
+ {
+ ERROR_BREAK;
+ }
+ if ( (status = MySHAFinal (&hash_context, (uchar *)dss_k_a)) != SUCCESS )
+ {
+ ERROR_BREAK;
+ }
+ if (( status = PartReduct ( SHA_LENGTH, /* dss_k = dss_k mod(dss_q)*/
+ dss_k_a,
+ SHA_LENGTH,
+ dss_q_a,
+ dss_k_a )) != SUCCESS )
+ {
+ ERROR_BREAK;
+ }
+ BigSwap(KKEY, SHA_LENGTH);
+ ALIGN_CALLOC_COPY(KKEY, KKEY_a, SHA_LENGTH );
+ if ( status != SUCCESS )
+ {
+ if ( KKEY_a )
+ {
+ ALIGN_COPY_FREE(KKEY_a,KKEY,SHA_LENGTH);
+ BigSwap(KKEY, SHA_LENGTH);
+ }
+ return status; /* ERR_ALLOC insufficient memory */
+ }
+
+ Sum_Q( KKEY_a, 1, SHA_LENGTH / sizeof(ord));
+
+ Sum_big( KKEY_a, dss_k_a, /* KKEY=KKEY+dss_k*/
+ KKEY_a, SHA_LENGTH / sizeof(ord) );
+
+ ALIGN_COPY_FREE(KKEY_a,KKEY,SHA_LENGTH);
+ BigSwap(KKEY, SHA_LENGTH);
+
+ END_PROCESSING
+
+ DSS_ALIGN_FREE(dss_q_a,dss_q); /*TKL01101*/
+
+ ALIGN_COPY_FREE(dss_k_a,dss_k,SHA_LENGTH);
+ if (DataOrder)
+ {
+ if (dss_q)
+ BigSwap(dss_q, SHA_LENGTH);
+ BigSwap(dss_k, SHA_LENGTH);
+ }
+
+ return status;
+}
+
+
+/****************************************************************************
+* NAME: int GenDSSParameters( u_int16_t dss_p_bytes,
+* uchar *dss_p,
+* uchar *dss_q,
+* uchar *dss_g,
+* uchar *RVAL,
+* YIELD_context *yield_cont )
+*
+* DESCRIPTION: Generate DSS Common Parameters
+*
+* INPUTS:
+* PARAMETERS:
+* u_int16_t dss_p_bytes Number of bytes in dss_p
+* uchar *RVAL Pointer to user supplied random number
+* YIELD_context *yield_cont Pointer to yield_cont structure (NULL if not used)
+* OUTPUT:
+* PARAMETERS:
+* uchar *dss_p Pointer to N-byte prime number
+* uchar *dss_q Pointer to SHA_LENGTH prime number
+* uchar *dss_g Pointer to N-byte number
+* RETURN:
+* SUCCESS No errors
+* ERR_INPUT_LEN Invalid length for input data(zero bytes)
+* ERR_DSS_LEN; Invalid length for dss_p
+* ERR_ALLOC Insufficient memory
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 14 Oct 94 GKL Second version (big endian support)
+* 26 Oct 94 GKL (alignment for big endian support & ERR_ALLOC)
+* 08 Dec 94 GKL Added YIELD_context
+*
+****************************************************************************/
+
+ int GenDSSParameters( u_int16_t dss_p_bytes,
+ uchar *dss_p,
+ uchar *dss_q,
+ uchar *dss_g,
+ uchar *RVAL,
+ YIELD_context *yield_cont ) /*TKL00701*/
+{
+ int status = SUCCESS; /* function return status */
+ ord seed[SHA_LENGTH / sizeof (ord)];
+ ord u[SHA_LENGTH / sizeof (ord)]; /* work buffers */
+ ord u1[SHA_LENGTH / sizeof (ord)];
+ ord *dss_p_a;
+ ord *dss_q_a;
+ ord *dss_g_a;
+ ord *RVAL_a;
+ ord ofone[SHA_LENGTH / sizeof(ord)];
+ ord dss_q2[SHA_LENGTH / sizeof(ord) + 1]; /* dss_q2 = 2 * q */
+ ord v[SHA_LENGTH / sizeof(ord)];
+ ord *w, *c, *c1, *one, *e; /* Pointers to work buffers */
+ u_int16_t i, n, count, offset, k; /* counters */
+ u_int16_t dss_p_longs; /* number of longs */
+ if ( dss_p_bytes == 0 ) /* invalid length for input data (zero bytes) */
+ {
+ status = ERR_INPUT_LEN;
+ return status;
+ }
+ if ( (dss_p_bytes < DSS_LENGTH_MIN) || /* less than minimal */
+ (dss_p_bytes > DSS_LENGTH_MAX) ) /* more than maximal */
+ {
+ status = ERR_DSS_LEN; /* invalid length for dss_p */
+ return status;
+ }
+ if ( dss_p_bytes & 0x07 ) /* not multiple 4 (64 bit)*/
+ {
+ status = ERR_DSS_LEN; /* invalid length for dss_p */
+ return status;
+ }
+
+ n = (u_int16_t) (dss_p_bytes / SHA_LENGTH); /* SHA passes count */
+ dss_p_longs = (u_int16_t) (dss_p_bytes / sizeof(ord)); /* number of long in dss_p */
+ CALLOC(w, ord, (n + 1) * SHA_LENGTH);
+ CALLOC(c, ord, dss_p_bytes);
+ CALLOC(c1, ord, dss_p_bytes);
+ CALLOC(one, ord, dss_p_bytes);
+ CALLOC(e,ord, dss_p_bytes - SHA_LENGTH + sizeof(ord));
+ ALIGN_CALLOC_MOVE(RVAL, RVAL_a, SHA_LENGTH);
+ ALIGN_CALLOC(dss_p, dss_p_a, dss_p_bytes);
+ ALIGN_CALLOC(dss_q, dss_q_a, SHA_LENGTH);
+ ALIGN_CALLOC(dss_g, dss_g_a, dss_p_bytes);
+ if ( status != SUCCESS )
+ {
+ if( e )
+ free ( e );
+ if( one )
+ free ( one );
+ if( c )
+ free ( c );
+ if( w )
+ free ( w );
+ if( c1 )
+ free ( c1 );
+ if( dss_p_a )
+ {
+ ALIGN_COPY_FREE(dss_p_a, dss_p, dss_p_bytes);
+ }
+ if( dss_q_a )
+ {
+ ALIGN_COPY_FREE(dss_q_a, dss_q, SHA_LENGTH);
+ }
+ if( dss_g_a )
+ {
+ ALIGN_COPY_FREE(dss_g_a, dss_g, dss_p_bytes);
+ }
+ if( RVAL_a )
+ {
+ ALIGN_MOVE_FREE(RVAL_a, RVAL, SHA_LENGTH);
+ }
+ return status; /* ERR_ALLOC insufficient memory */
+ }
+ one[0] = 1;
+ BEGIN_PROCESSING /* Generate DSS Common Parameters */
+
+ BEGIN_LOOP /* Generate prime & dss_p */ /*TKL00501*/
+ /* generate prime number of length 160-bit */
+ do
+ {
+ MyGenRand( SHA_LENGTH, seed, RVAL_a); /* generate random number */
+ /* compute message digest from seed */
+ if ( (status = MySHA((uchar *)seed, SHA_LENGTH, (uchar *)u)) != SUCCESS )
+ {
+ break; /* error */
+ }
+ memcpy(ofone, seed,SHA_LENGTH);
+ Sum_Q( ofone, 1, SHA_LENGTH / sizeof(ord) );
+ /* compute message digest from seed */
+ if ( (status = MySHA( (uchar *)ofone, SHA_LENGTH,(uchar *)dss_q_a)) != SUCCESS )
+ {
+ break; /* error */
+ }
+
+ for ( i = 0; i < (SHA_LENGTH / sizeof(ord)); i++ ) /* dss_q = dss_q ^ u */
+ {
+ dss_q_a[i] = dss_q_a[i] ^ u[i];
+ }
+ /* set least and most significant bits */
+ dss_q_a[SHA_LENGTH / sizeof(ord) - 1] |= ((ord)1 << (BITS_COUNT-1));
+ dss_q_a[0] |= 0x01;
+ } while ( VerPrime( SHA_LENGTH, dss_q_a, TEST_COUNT, RVAL_a, yield_cont) /*TKL00701*/
+ != SUCCESS ); /* perform a robust primality test */
+ if (status != SUCCESS )
+ {
+ ERROR_BREAK;
+ }
+ /* dss_q2 = 2 * dss_q */
+ memcpy( dss_q2, dss_q_a, SHA_LENGTH );
+ dss_q2[SHA_LENGTH / sizeof(ord)] = 0;
+ LShiftL_big( dss_q2, SHA_LENGTH / sizeof(ord) +1, 1 );
+ count = 0;
+ offset = 2;
+ memset( ofone, 0, SHA_LENGTH );
+ do /* find dss_p */
+ {
+ /* generate random number by dss_p bytes */
+ for ( k = 0; k <= n; k++ )
+ {
+ ofone[0] = offset + k;
+ /* v = ofone + seed */
+ Sum_big( seed, ofone, v, SHA_LENGTH / sizeof(ord) );
+ if ( (status = MySHA ( (uchar *)v, SHA_LENGTH,
+ (uchar *)( w + (SHA_LENGTH / sizeof(ord)) * k )))
+ != SUCCESS ) /* compute message digest */
+ {
+ break; /* error */
+ }
+ }
+ if (status != SUCCESS )
+ {
+ break; /* error */
+ }
+ /* set most significant bit */
+ w[dss_p_longs - 1] |= ((ord)1 << (BITS_COUNT-1));
+ memcpy( c, w, dss_p_bytes);
+ /* c1 = c mod(dss_q2) */
+ if( (status = PartReduct( dss_p_bytes, c,
+ SHA_LENGTH + sizeof(ord),
+ dss_q2, c1)) != SUCCESS )
+ {
+ break; /* error */
+ }
+ /* c1 = c1 - 1*/
+ Sub_big( c1, one, c1, dss_p_longs );
+ /* dss_p = w - c1 */
+ Sub_big( w, c1, dss_p_a, dss_p_longs );
+ if ( dss_p_a[dss_p_bytes / sizeof(ord) - 1] >= (ord)((ord)1 << (BITS_COUNT-1)) )
+ {
+ if ( VerPrime ( dss_p_bytes, dss_p_a, TEST_COUNT, RVAL_a, yield_cont) /*TKL00701*/
+ == SUCCESS ) /* perform a robust primality test */
+ {
+ break;
+ }
+ }
+ count++;
+ offset = (u_int16_t) (offset + n + 1);
+ } while ( count < 4096);
+ if (status != SUCCESS )
+ {
+ ERROR_BREAK;
+ }
+ if (count != 4096) /*TKL00501*/
+ {
+ BREAK; /*TKL00501*/
+ }
+ END_LOOP /* Generate dss_p */ /*TKL00501*/
+
+ if (status != SUCCESS )
+ {
+ ERROR_BREAK;
+ }
+ dss_p_a[0] -= 1; /* dss_p = dss_p - 1 */
+ if ( (status= DivRem (dss_p_bytes, dss_p_a, SHA_LENGTH, dss_q_a, u1,
+ e )) != SUCCESS ) /* e = dss_p / dss_q */
+ {
+ ERROR_BREAK;
+ }
+ dss_p_a[0] += 1; /* dss_p = dss_p + 1 */
+
+ BEGIN_LOOP /* Generate dss_g */ /*TKL00501*/
+ MyGenRand( SHA_LENGTH, u, RVAL_a ); /*generate random number*/
+ u[SHA_LENGTH / sizeof(ord) - 1] &= ~((ord)1 << (BITS_COUNT-1)); /* u < dss_q */
+ if ( (status = Expo( SHA_LENGTH, u, (u_int16_t)(dss_p_bytes - SHA_LENGTH +
+ sizeof(ord)), e, dss_p_bytes, dss_p_a, dss_g_a ))
+ != SUCCESS ) /* dss_g = e ^ u mod(dss_p) */
+ {
+ ERROR_BREAK;
+ }
+ if ( dss_g_a[0] == 1 ) /* check dss_g == 1 */
+ {
+ for ( i = 1; i < (dss_p_bytes / sizeof(ord)); i++ )
+ {
+ if ( dss_g_a[i] != 0 )
+ {
+ break;
+ }
+ }
+ if ( i == (dss_p_bytes / sizeof(ord)) )
+ {
+ CONTINUE;
+ }
+ }
+ BREAK; /*TKL00501*/
+ END_LOOP /* Generate dss_g */ /*TKL00501*/
+ END_PROCESSING /* Generate DSS Common Parameters */
+ free ( e );
+ free ( one );
+ free ( c );
+ free ( w );
+ free ( c1 );
+ ALIGN_COPY_FREE(dss_p_a, dss_p, dss_p_bytes);
+ ALIGN_COPY_FREE(dss_q_a, dss_q, SHA_LENGTH);
+ ALIGN_COPY_FREE(dss_g_a, dss_g, dss_p_bytes);
+ ALIGN_MOVE_FREE(RVAL_a, RVAL, SHA_LENGTH);
+ if (DataOrder)
+ {
+ BigSwap(dss_p, dss_p_bytes);
+ BigSwap(dss_q, SHA_LENGTH);
+ BigSwap(dss_g, dss_p_bytes);
+ }
+ return status;
+}
+
+
+/****************************************************************************
+* NAME: int GetDSSPQG(u_int16_t dss_p_bytes,
+* uchar *dss_p,
+* uchar *dss_q,
+* uchar *dss_g)
+*
+* DESCRIPTION: Copy Cylink DSS P,Q,G numbers to *dss_p,*dss_q,*dss_g
+*
+* INPUTS:
+* PARAMETERS:
+* u_int16_t dss_p_bytes Number of bytes in dss_p
+* uchar *dss_p Pointer to N-byte buffer
+* uchar *dss_q Pointer to SHA_LENGTH-byte buffer
+* uchar *dss_g Pointer to N-byte buffer
+* OUTPUT:
+* RETURN:
+* SUCCESS No errors
+* ERR_DSS_LEN; Invalid length for dss_p
+* REVISION HISTORY:
+*
+* 22 Apr 95 GKL Initial release LOG TKL01201
+*
+****************************************************************************/
+int GetDSSPQG(u_int16_t dss_p_bytes,
+ uchar *dss_p,
+ uchar *dss_q,
+ uchar *dss_g)
+{
+ int status = SUCCESS; /* function return status */
+ ord *dss_p_a;
+ ord *dss_g_a;
+
+ if ( (dss_p_bytes < DSS_LENGTH_MIN) || /* less than minimal */
+ (dss_p_bytes > DSS_LENGTH_MAX) ) /* more than maximal */
+ {
+ status = ERR_DSS_LEN; /* invalid length for dss_p */
+ return status;
+ }
+ if ( dss_p_bytes & 0x07 ) /* not multiple 8 (64 bit)*/
+ {
+ status = ERR_DSS_LEN; /* invalid length for dss_p */
+ return status;
+ }
+ dss_p_a = &DSS_P_NUMBERS[DSS_NUM_INDEX[(dss_p_bytes-DSS_LENGTH_MIN)/LENGTH_STEP]];
+ dss_g_a = &DSS_G_NUMBERS[DSS_NUM_INDEX[(dss_p_bytes-DSS_LENGTH_MIN)/LENGTH_STEP]];
+ OrdByte(dss_p_a,dss_p_bytes,dss_p);
+ OrdByte(dss_g_a,dss_p_bytes,dss_g);
+ OrdByte(DSS_Q_NUMBER,SHA_LENGTH,dss_q);
+ if (DataOrder)
+ {
+ BigSwap(dss_p, dss_p_bytes);
+ BigSwap(dss_q, SHA_LENGTH);
+ BigSwap(dss_g, dss_p_bytes);
+ }
+
+ return status;
+}
+
+
diff --git a/usr/src/lib/libresolv2/common/cylink/dssnum.h b/usr/src/lib/libresolv2/common/cylink/dssnum.h
new file mode 100644
index 0000000000..f46f08fe61
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/dssnum.h
@@ -0,0 +1,731 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/**********************************************************************\
+* FILENAME: DSSNum.h PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT
+*
+* DESCRIPTION: Standard Cylink DSS numbers (P Q G) support.
+*
+* USAGE: File should be included to get access to
+* Cylink DSS numbers
+*
+*
+* Copyright (c) Cylink Corporation 1995. All rights reserved.
+*
+* REVISION HISTORY:
+* 10 APR 95 GKL Initial release
+*
+\**********************************************************************/
+#ifndef DSSNUMBER_H /* Prevent multiple inclusions */
+#define DSSNUMBER_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "ctk_endian.h"
+
+#define LENGTH_MULT_TO_64
+
+#define F0 0
+#define F1 (F0 + 1)
+#define F2 (F1 + 2)
+#define F3 (F2 + 3)
+#define F4 (F3 + 4)
+#define F5 (F4 + 5)
+#define F6 (F5 + 6)
+#define F7 (F6 + 7)
+#define F8 (F7 + 8)
+#define F9 (F8 + 9)
+#define F10 (F9 + 10)
+#define F11 (F10 + 11)
+#define F12 (F11 + 12)
+#define F13 (F12 + 13)
+#define F14 (F13 + 14)
+#define F15 (F14 + 15)
+
+
+#ifdef LENGTH_MULT_TO_64
+#define LENGTH_STEP 8U
+#define LAST_F F8
+#endif
+
+#ifdef LENGTH_MULT_TO_32
+#define LENGTH_STEP 4U
+#define LAST_F (F15 + 16)
+#endif
+
+
+#define DSS_LENS_NUMBER (int) (1 + ( DSS_LENGTH_MAX - DSS_LENGTH_MIN )/LENGTH_STEP)
+
+#define DSS_LAST_INDEX (DSS_LENGTH_MIN*DSS_LENS_NUMBER + LENGTH_STEP*LAST_F)/sizeof(ord)
+
+#ifndef INITIALIZ_PQG
+
+extern ushort DSS_NUM_INDEX[ DSS_LENS_NUMBER ];
+extern ord DSS_Q_NUMBER[SHA_LENGTH/sizeof(ord)];
+extern ord DSS_P_NUMBERS[DSS_LAST_INDEX];
+extern ord DSS_G_NUMBERS[DSS_LAST_INDEX];
+
+#else
+ushort DSS_NUM_INDEX[ DSS_LENS_NUMBER ] =
+{
+ (DSS_LENGTH_MIN*0 + LENGTH_STEP*0 )/sizeof(ord),
+ (DSS_LENGTH_MIN*1 + LENGTH_STEP*F0 )/sizeof(ord),
+ (DSS_LENGTH_MIN*2 + LENGTH_STEP*F1 )/sizeof(ord),
+ (DSS_LENGTH_MIN*3 + LENGTH_STEP*F2 )/sizeof(ord),
+ (DSS_LENGTH_MIN*4 + LENGTH_STEP*F3 )/sizeof(ord),
+ (DSS_LENGTH_MIN*5 + LENGTH_STEP*F4 )/sizeof(ord),
+ (DSS_LENGTH_MIN*6 + LENGTH_STEP*F5 )/sizeof(ord),
+ (DSS_LENGTH_MIN*7 + LENGTH_STEP*F6 )/sizeof(ord),
+ (DSS_LENGTH_MIN*8 + LENGTH_STEP*F7 )/sizeof(ord)
+#ifdef LENGTH_MULT_TO_32
+ ,
+ (DSS_LENGTH_MIN*9 + LENGTH_STEP*F8 )/sizeof(ord),
+ (DSS_LENGTH_MIN*10 + LENGTH_STEP*F9 )/sizeof(ord),
+ (DSS_LENGTH_MIN*11 + LENGTH_STEP*F10)/sizeof(ord),
+ (DSS_LENGTH_MIN*12 + LENGTH_STEP*F11)/sizeof(ord),
+ (DSS_LENGTH_MIN*13 + LENGTH_STEP*F12)/sizeof(ord),
+ (DSS_LENGTH_MIN*14 + LENGTH_STEP*F13)/sizeof(ord),
+ (DSS_LENGTH_MIN*15 + LENGTH_STEP*F14)/sizeof(ord),
+ (DSS_LENGTH_MIN*16 + LENGTH_STEP*F15)/sizeof(ord)
+#endif
+};
+
+ord DSS_Q_NUMBER[SHA_LENGTH/sizeof(ord)] =
+#ifdef ORD_16
+ {
+ 0x8fb7, 0x81f0, 0x6b9e, 0x122a, 0x4dc4, 0x03ca, 0xc896, 0x8d0e, 0xbe3b, 0xed4b
+ };
+#else
+ {
+ 0x81f08fb7L, 0x122a6b9eL, 0x03ca4dc4L, 0x8d0ec896L, 0xed4bbe3bL
+ };
+#endif
+
+
+ord DSS_P_NUMBERS[DSS_LAST_INDEX] =
+#ifdef ORD_16
+ {
+ /* dss_p length = 512*/
+ 0x92b7, 0xbd96, 0x9aab, 0x584c, 0xd617, 0xf2f0, 0xda85, 0xd370,
+ 0xcc82, 0x273e, 0x6b04, 0xc171, 0x5c32, 0xd3ff, 0x352e, 0xf2f8,
+ 0x4fc2, 0x20bc, 0xbdec, 0xe96e, 0x3503, 0x4d89, 0xe92d, 0xeb7d,
+ 0x9c1a, 0x7852, 0xfe2a, 0x0a25, 0x4446, 0xce18, 0x7829, 0x95d8,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_p length = 544*/
+ 0x12db, 0x0d31, 0x9950, 0x16c9, 0x3045, 0x0acb, 0x3c46, 0x3c5c,
+ 0x6c94, 0x2458, 0x0736, 0x13da, 0xa0af, 0x790f, 0xb177, 0xa6ae,
+ 0xd111, 0x2bda, 0x697c, 0x49a2, 0xe3e5, 0x6f27, 0x02f5, 0x9bc9,
+ 0xd4da, 0x7d9b, 0x89c6, 0x63bc, 0x0b6d, 0xfe2d, 0xc7a1, 0x435f,
+ 0x7fad, 0x9e40,
+#endif
+ /* dss_p length = 576*/
+ 0x626b, 0x41b5, 0xd218, 0x25bf, 0x1825, 0x42b3, 0x9eb0, 0xc244,
+ 0x96ce, 0x22ac, 0x3ac6, 0x713f, 0x321d, 0x398c, 0x3022, 0xbc49,
+ 0xdd03, 0x52d5, 0x29f8, 0x2a57, 0x8fa1, 0x2173, 0xee7d, 0xb90d,
+ 0xcc64, 0x5fae, 0xaa81, 0xe3d0, 0x648f, 0xfa6e, 0xdc6c, 0x039f,
+ 0x2cd6, 0xc552, 0xe2dc, 0xebec,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_p length = 608*/
+ 0x35f5, 0xb2af, 0x27d0, 0x398b, 0x493d, 0x6f2e, 0xbe27, 0xe5b5,
+ 0x972c, 0x3470, 0x9638, 0xe90e, 0xf7b7, 0x98ad, 0xd091, 0xb4ca,
+ 0x3f43, 0x5f58, 0xb6c5, 0xd014, 0x25ee, 0x414d, 0xe2c1, 0x6fd6,
+ 0xd737, 0x9be6, 0x66ca, 0xe241, 0x1897, 0xf740, 0xe5df, 0xceb0,
+ 0xdb38, 0xabc8, 0x8af8, 0xc58b, 0xc6a0, 0x9a04,
+#endif
+ /* dss_p length = 640*/
+ 0x4095, 0xf6bf, 0x7568, 0x4032, 0x5c0f, 0x64f2, 0x5aae, 0xb099,
+ 0x346f, 0x0e81, 0x357a, 0x7aeb, 0x0291, 0xfd0a, 0x8d54, 0xce80,
+ 0x0c05, 0xbea3, 0x889f, 0x8a1b, 0xf1c1, 0x6049, 0x214a, 0x8ec3,
+ 0xb926, 0xdde1, 0x61b4, 0x384e, 0x404b, 0xb6d7, 0x2e2d, 0x4584,
+ 0xae6a, 0xcc7a, 0x7bfa, 0x9eb0, 0x3a26, 0x3904, 0x8cac, 0xc036,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_p length = 672*/
+ 0x0abb, 0xaea3, 0xc749, 0x757c, 0x3035, 0x29d0, 0x46bd, 0xd56c,
+ 0xf49d, 0xa355, 0x1297, 0x8dcb, 0x9802, 0xc58c, 0xf1ec, 0x8aac,
+ 0x55dd, 0xb107, 0x0140, 0x26d1, 0x8a5d, 0x8a90, 0xf33e, 0xde0b,
+ 0xb844, 0xb429, 0x4db2, 0x9806, 0xf629, 0x4c3b, 0xcd76, 0x2f23,
+ 0x6c68, 0x7bf4, 0x2a7e, 0xd982, 0xc89f, 0x16a2, 0xfe84, 0x953c,
+ 0x3e4a, 0x8de8,
+#endif
+ /* dss_p length = 704*/
+ 0x0113, 0x1535, 0xca0b, 0x8faf, 0xa327, 0x989c, 0x12c8, 0xe512,
+ 0x796f, 0x1229, 0x12bf, 0x62c8, 0xa50a, 0x2b99, 0xc93b, 0x450c,
+ 0x71ad, 0x0826, 0xf4c6, 0x3913, 0x9b6e, 0x96da, 0xa08d, 0xbc5e,
+ 0xd4d3, 0x7b26, 0xf9fd, 0xdd76, 0x4e82, 0x2f06, 0x1f96, 0xbf47,
+ 0xcadf, 0x3610, 0x917b, 0x4e94, 0xe2e8, 0x0eaf, 0x1cb9, 0x6b90,
+ 0xb917, 0x6d6f, 0x92b9, 0xb329,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_p length = 736*/
+ 0x6dad, 0xd878, 0xc913, 0xe61e, 0x87d9, 0xe275, 0xad24, 0xf090,
+ 0xe12b, 0xfdfe, 0x39a3, 0xc9a1, 0x8330, 0x138a, 0x4bed, 0xc319,
+ 0x8094, 0x88ba, 0x4b80, 0x1325, 0x7852, 0x67e2, 0x715e, 0x7313,
+ 0x3b4e, 0x7727, 0x9870, 0x5c6e, 0xe0ce, 0xc67a, 0xd057, 0xf3c5,
+ 0x55ea, 0x98ba, 0x6ea0, 0xaee7, 0x31e8, 0x3cd6, 0x0e28, 0x42d1,
+ 0x8946, 0xc395, 0x34fc, 0x1b9d, 0x19d1, 0x86f9,
+#endif
+ /* dss_p length = 768*/
+ 0xe293, 0xea08, 0xcdd0, 0xf668, 0x8b2a, 0x06db, 0x7c71, 0xadb2,
+ 0x943d, 0x6721, 0x54f5, 0xbc44, 0xf7ca, 0x3345, 0x1bf6, 0x0b90,
+ 0xb475, 0xd3c4, 0xbdb6, 0x7caa, 0xa45f, 0xe9b4, 0x6e0e, 0x0c1a,
+ 0xb5c3, 0x9760, 0x851a, 0x53af, 0x96b7, 0x4979, 0xf162, 0xe951,
+ 0x6a54, 0xd020, 0x9ded, 0xdecb, 0xfc81, 0x7d74, 0x5e92, 0x2aee,
+ 0x0946, 0x0eb5, 0x3700, 0x9bce, 0x845a, 0xa7a3, 0x157a, 0x8618,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_p length = 800*/
+ 0xb0a1, 0xac27, 0xec4e, 0xf623, 0x55e2, 0x2cb6, 0x288b, 0x4b28,
+ 0xd74e, 0xbbe6, 0xfdf7, 0xaecd, 0x5758, 0xe251, 0x9074, 0x1aee,
+ 0xe6ed, 0x4d5e, 0x01d9, 0x529e, 0xf736, 0x0091, 0x0212, 0xc725,
+ 0x60ce, 0x966f, 0x851d, 0x5c4b, 0x80de, 0x34df, 0x1c88, 0x0636,
+ 0xbb71, 0x32ce, 0x45cb, 0x86da, 0x4d0e, 0x13e0, 0x7d7d, 0x544b,
+ 0x1272, 0x747f, 0xd6a7, 0xfa3b, 0xcb86, 0x6b43, 0x66f5, 0xd012,
+ 0xfe7a, 0xa0cb,
+#endif
+ /* dss_p length = 832*/
+ 0xed2d, 0x84dd, 0xf274, 0xdd8f, 0xcd5f, 0x7928, 0xbfc6, 0xa522,
+ 0xe4e4, 0x50f0, 0xcddf, 0x5842, 0xbb29, 0x7c4d, 0xeef4, 0x6946,
+ 0x87f6, 0xe486, 0x61b5, 0xc1b6, 0xadef, 0x575a, 0x360f, 0x724f,
+ 0xcb29, 0x591b, 0x9a4c, 0xf7bc, 0x309e, 0xa348, 0x0ff5, 0x94f3,
+ 0x932f, 0x9dc6, 0x992c, 0xc6d7, 0x12f6, 0xc2d7, 0x38aa, 0x8c01,
+ 0x5dca, 0x74f4, 0xfcfd, 0x4cf4, 0x588a, 0x7837, 0x097e, 0xd2e2,
+ 0x6eac, 0x8869, 0xe92f, 0xec62,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_p length = 864*/
+ 0x7c21, 0x931e, 0x553d, 0x00f2, 0xa860, 0x940f, 0x411e, 0x7d20,
+ 0xb168, 0x52a3, 0x69ee, 0x166e, 0xb9e6, 0x1b23, 0xd5e0, 0xef64,
+ 0x2850, 0x724c, 0xc1fe, 0xea73, 0xda8c, 0xe342, 0x1d7b, 0xd256,
+ 0x359b, 0x180f, 0xd7f5, 0xca77, 0x06ac, 0x2162, 0xa977, 0x78bb,
+ 0x5018, 0x5de2, 0x6061, 0xe217, 0x4d42, 0xfed1, 0x3929, 0xd50f,
+ 0xc946, 0x2433, 0x15f8, 0x361b, 0xbf51, 0x3ff0, 0x3efa, 0x3157,
+ 0x7350, 0x53a0, 0xd1a4, 0x261b, 0xde5b, 0x9236,
+#endif
+ /* dss_p length = 896*/
+ 0x8e21, 0x0364, 0x86d2, 0xe58c, 0x2274, 0x780a, 0x9ffc, 0x4951,
+ 0x3f99, 0xbc96, 0x9e60, 0x5a7e, 0x010a, 0x23d4, 0x54d1, 0x48e9,
+ 0xfd6b, 0x979c, 0x5202, 0x8af3, 0x5d87, 0xfe8f, 0x3e3c, 0x1e0c,
+ 0xe294, 0xcc52, 0xa8d6, 0x480e, 0xa898, 0xd4ce, 0x5949, 0xd341,
+ 0xe325, 0xf41b, 0x72d6, 0x6a90, 0x7a8b, 0x6f14, 0x3e2b, 0x6636,
+ 0x3748, 0x4eea, 0xa590, 0x03e4, 0x0524, 0x9c32, 0xeb53, 0x02af,
+ 0xca71, 0x6792, 0xd673, 0xedf8, 0x6448, 0x59c3, 0x7319, 0x883f,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_p length = 928*/
+ 0xc17d, 0xa4e8, 0xea08, 0x8ff8, 0x2cb0, 0x73f5, 0xd7ba, 0xc027,
+ 0xb9c8, 0x989d, 0xe5fe, 0xe3a1, 0xf324, 0x39d3, 0xf142, 0x5ba8,
+ 0xe6cb, 0x3708, 0xa0b7, 0xed9a, 0xb6b3, 0xe314, 0xf80a, 0x6778,
+ 0x4d27, 0x7107, 0x6ee8, 0xb9c2, 0xc6af, 0xab70, 0x53be, 0xc445,
+ 0x7926, 0x34bb, 0x5191, 0xe11d, 0x67f1, 0xcc3a, 0x5354, 0xd34d,
+ 0xa1ac, 0x08ba, 0x32d4, 0x068a, 0x7c3b, 0x415f, 0xbce0, 0xb549,
+ 0x0ecf, 0x538f, 0xb5d0, 0x22a3, 0x1d47, 0xe837, 0x14c0, 0x69dd,
+ 0xa02d, 0xce91,
+#endif
+ /* dss_p length = 960*/
+ 0x1ff3, 0xf77e, 0xae7a, 0x5a28, 0x43b1, 0xe187, 0x2e04, 0xb3ea,
+ 0x7394, 0xa3e8, 0x4985, 0xc9bc, 0x7b7d, 0x1e1c, 0xd99c, 0x55f8,
+ 0x447b, 0x5704, 0xd758, 0xbed1, 0xe698, 0x2a5e, 0x5c19, 0xc206,
+ 0x6d38, 0x1f88, 0x2ea4, 0x5f15, 0xebfd, 0xd716, 0x8a2a, 0xf960,
+ 0x83ac, 0xc493, 0xb966, 0x8f13, 0x4778, 0x9682, 0x4712, 0x84cd,
+ 0xbb4e, 0xe567, 0x644f, 0x0780, 0x133d, 0x0b0a, 0xe42e, 0x06e8,
+ 0xa4cc, 0x3131, 0x39d9, 0xfaf8, 0x12a3, 0x5550, 0x43b1, 0xb8a9,
+ 0xb0eb, 0x0fad, 0x986f, 0xd427,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_p length = 992*/
+ 0xbcfd, 0x363f, 0x050a, 0x18f0, 0x78d8, 0xcac9, 0x423a, 0xf31e,
+ 0x198f, 0xd0c3, 0xb319, 0x5d1b, 0x917a, 0xc0b0, 0x8d1b, 0x6b91,
+ 0xea69, 0xa9d1, 0x02ce, 0x5345, 0x2c80, 0x6992, 0x4dad, 0x7a28,
+ 0xbb75, 0xd46d, 0x0faa, 0x5612, 0x6878, 0x8a0e, 0x63b4, 0x46ab,
+ 0xaca0, 0x5381, 0xb90a, 0x3e70, 0x19c4, 0xb639, 0xf778, 0xe751,
+ 0x5974, 0xb726, 0x589f, 0x8679, 0xeb04, 0xc0b5, 0xdffd, 0x2b32,
+ 0x4b51, 0xc632, 0xd8c6, 0x9501, 0x4f94, 0x2026, 0x253a, 0x0d27,
+ 0x07bb, 0x0838, 0x2725, 0xa3eb, 0x3c4e, 0x89b6,
+#endif
+ /* dss_p length = 1024*/
+ 0xa141, 0xecf7, 0xc6d6, 0x867d, 0xefa3, 0x1cdd, 0x6c9d, 0x6ca5,
+ 0x2e2f, 0x68af, 0x90e1, 0x1d3e, 0xd75f, 0x0c2a, 0x844b, 0x36c7,
+ 0x3420, 0xfd1a, 0xb9ee, 0xf6e5, 0x5fde, 0xc8ed, 0x0c90, 0xd353,
+ 0x6faa, 0x80a4, 0x5bbd, 0xa59d, 0x9e72, 0x3223, 0x8f59, 0xf33d,
+ 0x10eb, 0xeccd, 0x184e, 0x3e2a, 0x4c07, 0x564b, 0x4c0a, 0x3263,
+ 0xc535, 0x8aeb, 0xf982, 0x2be2, 0xe475, 0x9b87, 0xcca0, 0x4d08,
+ 0x3adf, 0x0484, 0xd528, 0x7acd, 0x304d, 0x55a0, 0x70ae, 0x8298,
+ 0x6a7a, 0x2298, 0x15c0, 0x7a86, 0x7fc5, 0x654a, 0x14ad, 0xd0aa
+ };
+#else
+ {
+/* dss_p length = 512*/
+ 0xbd9692b7L, 0x584c9aabL, 0xf2f0d617L, 0xd370da85L,
+ 0x273ecc82L, 0xc1716b04L, 0xd3ff5c32L, 0xf2f8352eL,
+ 0x20bc4fc2L, 0xe96ebdecL, 0x4d893503L, 0xeb7de92dL,
+ 0x78529c1aL, 0x0a25fe2aL, 0xce184446L, 0x95d87829L,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_p length = 544*/
+ 0x0d3112dbL, 0x16c99950L, 0x0acb3045L, 0x3c5c3c46L,
+ 0x24586c94L, 0x13da0736L, 0x790fa0afL, 0xa6aeb177L,
+ 0x2bdad111L, 0x49a2697cL, 0x6f27e3e5L, 0x9bc902f5L,
+ 0x7d9bd4daL, 0x63bc89c6L, 0xfe2d0b6dL, 0x435fc7a1L,
+ 0x9e407fadL,
+#endif
+ /* dss_p length = 576*/
+ 0x41b5626bL, 0x25bfd218L, 0x42b31825L, 0xc2449eb0L,
+ 0x22ac96ceL, 0x713f3ac6L, 0x398c321dL, 0xbc493022L,
+ 0x52d5dd03L, 0x2a5729f8L, 0x21738fa1L, 0xb90dee7dL,
+ 0x5faecc64L, 0xe3d0aa81L, 0xfa6e648fL, 0x039fdc6cL,
+ 0xc5522cd6L, 0xebece2dcL,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_p length = 608*/
+ 0xb2af35f5L, 0x398b27d0L, 0x6f2e493dL, 0xe5b5be27L,
+ 0x3470972cL, 0xe90e9638L, 0x98adf7b7L, 0xb4cad091L,
+ 0x5f583f43L, 0xd014b6c5L, 0x414d25eeL, 0x6fd6e2c1L,
+ 0x9be6d737L, 0xe24166caL, 0xf7401897L, 0xceb0e5dfL,
+ 0xabc8db38L, 0xc58b8af8L, 0x9a04c6a0L,
+#endif
+ /* dss_p length = 640*/
+ 0xf6bf4095L, 0x40327568L, 0x64f25c0fL, 0xb0995aaeL,
+ 0x0e81346fL, 0x7aeb357aL, 0xfd0a0291L, 0xce808d54L,
+ 0xbea30c05L, 0x8a1b889fL, 0x6049f1c1L, 0x8ec3214aL,
+ 0xdde1b926L, 0x384e61b4L, 0xb6d7404bL, 0x45842e2dL,
+ 0xcc7aae6aL, 0x9eb07bfaL, 0x39043a26L, 0xc0368cacL,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_p length = 672*/
+ 0xaea30abbL, 0x757cc749L, 0x29d03035L, 0xd56c46bdL,
+ 0xa355f49dL, 0x8dcb1297L, 0xc58c9802L, 0x8aacf1ecL,
+ 0xb10755ddL, 0x26d10140L, 0x8a908a5dL, 0xde0bf33eL,
+ 0xb429b844L, 0x98064db2L, 0x4c3bf629L, 0x2f23cd76L,
+ 0x7bf46c68L, 0xd9822a7eL, 0x16a2c89fL, 0x953cfe84L,
+ 0x8de83e4aL,
+#endif
+ /* dss_p length = 704*/
+ 0x15350113L, 0x8fafca0bL, 0x989ca327L, 0xe51212c8L,
+ 0x1229796fL, 0x62c812bfL, 0x2b99a50aL, 0x450cc93bL,
+ 0x082671adL, 0x3913f4c6L, 0x96da9b6eL, 0xbc5ea08dL,
+ 0x7b26d4d3L, 0xdd76f9fdL, 0x2f064e82L, 0xbf471f96L,
+ 0x3610cadfL, 0x4e94917bL, 0x0eafe2e8L, 0x6b901cb9L,
+ 0x6d6fb917L, 0xb32992b9L,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_p length = 736*/
+ 0xd8786dadL, 0xe61ec913L, 0xe27587d9L, 0xf090ad24L,
+ 0xfdfee12bL, 0xc9a139a3L, 0x138a8330L, 0xc3194bedL,
+ 0x88ba8094L, 0x13254b80L, 0x67e27852L, 0x7313715eL,
+ 0x77273b4eL, 0x5c6e9870L, 0xc67ae0ceL, 0xf3c5d057L,
+ 0x98ba55eaL, 0xaee76ea0L, 0x3cd631e8L, 0x42d10e28L,
+ 0xc3958946L, 0x1b9d34fcL, 0x86f919d1L,
+#endif
+ /* dss_p length = 768*/
+ 0xea08e293L, 0xf668cdd0L, 0x06db8b2aL, 0xadb27c71L,
+ 0x6721943dL, 0xbc4454f5L, 0x3345f7caL, 0x0b901bf6L,
+ 0xd3c4b475L, 0x7caabdb6L, 0xe9b4a45fL, 0x0c1a6e0eL,
+ 0x9760b5c3L, 0x53af851aL, 0x497996b7L, 0xe951f162L,
+ 0xd0206a54L, 0xdecb9dedL, 0x7d74fc81L, 0x2aee5e92L,
+ 0x0eb50946L, 0x9bce3700L, 0xa7a3845aL, 0x8618157aL,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_p length = 800*/
+ 0xac27b0a1L, 0xf623ec4eL, 0x2cb655e2L, 0x4b28288bL,
+ 0xbbe6d74eL, 0xaecdfdf7L, 0xe2515758L, 0x1aee9074L,
+ 0x4d5ee6edL, 0x529e01d9L, 0x0091f736L, 0xc7250212L,
+ 0x966f60ceL, 0x5c4b851dL, 0x34df80deL, 0x06361c88L,
+ 0x32cebb71L, 0x86da45cbL, 0x13e04d0eL, 0x544b7d7dL,
+ 0x747f1272L, 0xfa3bd6a7L, 0x6b43cb86L, 0xd01266f5L,
+ 0xa0cbfe7aL,
+#endif
+ /* dss_p length = 832*/
+ 0x84dded2dL, 0xdd8ff274L, 0x7928cd5fL, 0xa522bfc6L,
+ 0x50f0e4e4L, 0x5842cddfL, 0x7c4dbb29L, 0x6946eef4L,
+ 0xe48687f6L, 0xc1b661b5L, 0x575aadefL, 0x724f360fL,
+ 0x591bcb29L, 0xf7bc9a4cL, 0xa348309eL, 0x94f30ff5L,
+ 0x9dc6932fL, 0xc6d7992cL, 0xc2d712f6L, 0x8c0138aaL,
+ 0x74f45dcaL, 0x4cf4fcfdL, 0x7837588aL, 0xd2e2097eL,
+ 0x88696eacL, 0xec62e92fL,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_p length = 864*/
+ 0x931e7c21L, 0x00f2553dL, 0x940fa860L, 0x7d20411eL,
+ 0x52a3b168L, 0x166e69eeL, 0x1b23b9e6L, 0xef64d5e0L,
+ 0x724c2850L, 0xea73c1feL, 0xe342da8cL, 0xd2561d7bL,
+ 0x180f359bL, 0xca77d7f5L, 0x216206acL, 0x78bba977L,
+ 0x5de25018L, 0xe2176061L, 0xfed14d42L, 0xd50f3929L,
+ 0x2433c946L, 0x361b15f8L, 0x3ff0bf51L, 0x31573efaL,
+ 0x53a07350L, 0x261bd1a4L, 0x9236de5bL,
+#endif
+ /* dss_p length = 896*/
+ 0x03648e21L, 0xe58c86d2L, 0x780a2274L, 0x49519ffcL,
+ 0xbc963f99L, 0x5a7e9e60L, 0x23d4010aL, 0x48e954d1L,
+ 0x979cfd6bL, 0x8af35202L, 0xfe8f5d87L, 0x1e0c3e3cL,
+ 0xcc52e294L, 0x480ea8d6L, 0xd4cea898L, 0xd3415949L,
+ 0xf41be325L, 0x6a9072d6L, 0x6f147a8bL, 0x66363e2bL,
+ 0x4eea3748L, 0x03e4a590L, 0x9c320524L, 0x02afeb53L,
+ 0x6792ca71L, 0xedf8d673L, 0x59c36448L, 0x883f7319L,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_p length = 928*/
+ 0xa4e8c17dL, 0x8ff8ea08L, 0x73f52cb0L, 0xc027d7baL,
+ 0x989db9c8L, 0xe3a1e5feL, 0x39d3f324L, 0x5ba8f142L,
+ 0x3708e6cbL, 0xed9aa0b7L, 0xe314b6b3L, 0x6778f80aL,
+ 0x71074d27L, 0xb9c26ee8L, 0xab70c6afL, 0xc44553beL,
+ 0x34bb7926L, 0xe11d5191L, 0xcc3a67f1L, 0xd34d5354L,
+ 0x08baa1acL, 0x068a32d4L, 0x415f7c3bL, 0xb549bce0L,
+ 0x538f0ecfL, 0x22a3b5d0L, 0xe8371d47L, 0x69dd14c0L,
+ 0xce91a02dL,
+#endif
+ /* dss_p length = 960*/
+ 0xf77e1ff3L, 0x5a28ae7aL, 0xe18743b1L, 0xb3ea2e04L,
+ 0xa3e87394L, 0xc9bc4985L, 0x1e1c7b7dL, 0x55f8d99cL,
+ 0x5704447bL, 0xbed1d758L, 0x2a5ee698L, 0xc2065c19L,
+ 0x1f886d38L, 0x5f152ea4L, 0xd716ebfdL, 0xf9608a2aL,
+ 0xc49383acL, 0x8f13b966L, 0x96824778L, 0x84cd4712L,
+ 0xe567bb4eL, 0x0780644fL, 0x0b0a133dL, 0x06e8e42eL,
+ 0x3131a4ccL, 0xfaf839d9L, 0x555012a3L, 0xb8a943b1L,
+ 0x0fadb0ebL, 0xd427986fL,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_p length = 992*/
+ 0x363fbcfdL, 0x18f0050aL, 0xcac978d8L, 0xf31e423aL,
+ 0xd0c3198fL, 0x5d1bb319L, 0xc0b0917aL, 0x6b918d1bL,
+ 0xa9d1ea69L, 0x534502ceL, 0x69922c80L, 0x7a284dadL,
+ 0xd46dbb75L, 0x56120faaL, 0x8a0e6878L, 0x46ab63b4L,
+ 0x5381aca0L, 0x3e70b90aL, 0xb63919c4L, 0xe751f778L,
+ 0xb7265974L, 0x8679589fL, 0xc0b5eb04L, 0x2b32dffdL,
+ 0xc6324b51L, 0x9501d8c6L, 0x20264f94L, 0x0d27253aL,
+ 0x083807bbL, 0xa3eb2725L, 0x89b63c4eL,
+#endif
+ /* dss_p length = 1024*/
+ 0xecf7a141L, 0x867dc6d6L, 0x1cddefa3L, 0x6ca56c9dL,
+ 0x68af2e2fL, 0x1d3e90e1L, 0x0c2ad75fL, 0x36c7844bL,
+ 0xfd1a3420L, 0xf6e5b9eeL, 0xc8ed5fdeL, 0xd3530c90L,
+ 0x80a46faaL, 0xa59d5bbdL, 0x32239e72L, 0xf33d8f59L,
+ 0xeccd10ebL, 0x3e2a184eL, 0x564b4c07L, 0x32634c0aL,
+ 0x8aebc535L, 0x2be2f982L, 0x9b87e475L, 0x4d08cca0L,
+ 0x04843adfL, 0x7acdd528L, 0x55a0304dL, 0x829870aeL,
+ 0x22986a7aL, 0x7a8615c0L, 0x654a7fc5L, 0xd0aa14adL
+ };
+#endif
+
+ord DSS_G_NUMBERS[DSS_LAST_INDEX] =
+#ifdef ORD_16
+ {
+ /* dss_g length = 512*/
+ 0x8b1a, 0xedfe, 0xef16, 0xdb26, 0xeae0, 0x1f1d, 0xaf3a, 0x3e30,
+ 0x2bd6, 0x25ec, 0xa451, 0x6255, 0xbc75, 0x499c, 0x4071, 0x5da2,
+ 0x1149, 0xc7fc, 0x1402, 0x9b69, 0xc168, 0xb0ea, 0xaf92, 0x6a33,
+ 0xf45f, 0xd93a, 0x75a6, 0x263c, 0xb820, 0x7eb1, 0x5f5b, 0x4bd7,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_g length = 544*/
+ 0x2772, 0xe0e6, 0xce97, 0x605b, 0x4aa8, 0x2586, 0x095a, 0xb83f,
+ 0x8b01, 0xfe53, 0x9250, 0x74ef, 0x74d4, 0xd9fa, 0xb78b, 0xa714,
+ 0x106f, 0x03a6, 0xb406, 0xc549, 0xc44d, 0xd559, 0x8100, 0xfef4,
+ 0x34a4, 0x1f4c, 0x3c6b, 0x4ae0, 0xe770, 0x158b, 0x3f8d, 0xf73d,
+ 0x0cc5, 0x61b7,
+#endif
+ /* dss_g length = 576*/
+ 0x3dde, 0x64fd, 0x2b69, 0x03c3, 0xad1d, 0x1751, 0x11dc, 0xfe67,
+ 0x6379, 0x76de, 0xe333, 0x3b8f, 0x242f, 0x27d8, 0x5f33, 0x3597,
+ 0xb98c, 0x11dc, 0x718c, 0xe3b5, 0xa3d4, 0x58f2, 0x71fa, 0x2675,
+ 0x49f9, 0xf2c7, 0x510e, 0xa4e1, 0xeca4, 0x7c64, 0x243b, 0x78fc,
+ 0x2ce2, 0x7017, 0x0095, 0x23b6,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_g length = 608*/
+ 0xdad8, 0x1e27, 0x41f5, 0xd536, 0x528f, 0x7047, 0x028a, 0x56f5,
+ 0xe55f, 0xe20d, 0x612c, 0x520f, 0xebfd, 0x8c86, 0x0924, 0x562a,
+ 0x2185, 0xe5ac, 0xa113, 0x4b8c, 0x87da, 0xfa4c, 0x8788, 0x9d8d,
+ 0x41c0, 0x9d25, 0x9c77, 0xff33, 0x6861, 0xd10a, 0xc734, 0x8454,
+ 0xf803, 0x55ce, 0xfeac, 0x6580, 0x6cd2, 0x482b,
+#endif
+ /* dss_g length = 640*/
+ 0x4ff7, 0x2829, 0x8ab0, 0xa0bd, 0x7b1c, 0xf544, 0xe633, 0x6e7b,
+ 0x9824, 0x494a, 0xfb7f, 0xc8ad, 0x45b6, 0x956e, 0x0574, 0x5b0d,
+ 0xd40c, 0xf807, 0x7372, 0x56fd, 0xdd12, 0x8960, 0x255c, 0x019e,
+ 0xfc39, 0x06b3, 0x9f8e, 0x4cd9, 0xe714, 0x77f6, 0x76f7, 0xb573,
+ 0x010e, 0x9b52, 0x04d2, 0xe269, 0xd4bb, 0xbdec, 0x089d, 0x7f88,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_g length = 672*/
+ 0x3d36, 0xb22d, 0x2144, 0xfda0, 0x1d4a, 0xc144, 0xef8f, 0x70e8,
+ 0xfd0f, 0xcbf9, 0x7433, 0xbf29, 0x1657, 0x757b, 0x011d, 0x5c7e,
+ 0xa0d3, 0xec5a, 0xd45d, 0xacd6, 0x136a, 0x9454, 0x61fd, 0xc3f6,
+ 0x3758, 0x5c89, 0xe4df, 0xd3c9, 0x6f99, 0xa113, 0x0992, 0x16b2,
+ 0xf92f, 0xfb67, 0x3f34, 0x57e6, 0xb224, 0xdfd1, 0x43c4, 0x639a,
+ 0xccf5, 0x86c4,
+#endif
+ /* dss_g length = 704*/
+ 0x1621, 0x8313, 0x216e, 0xcb3b, 0xde00, 0xa11b, 0xf27f, 0xd5d4,
+ 0x6d2e, 0xc870, 0x1c47, 0x2e21, 0x780b, 0x1db6, 0x8adf, 0xe5c6,
+ 0x837d, 0x7dba, 0x9c8c, 0x28b5, 0xd309, 0xf3fa, 0x6c65, 0xe37f,
+ 0x6a1e, 0x2601, 0xbb92, 0x56aa, 0x9c0e, 0x9db1, 0xb782, 0x642b,
+ 0x6cc9, 0xb9fb, 0x6a3c, 0x97b9, 0xf1a8, 0xd8a2, 0xfe6b, 0xcb93,
+ 0x59ee, 0x32a4, 0x0aa1, 0x58ad,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_g length = 736*/
+ 0x648c, 0xa15c, 0x27b2, 0x8137, 0xefb3, 0x0e81, 0x258e, 0xabe0,
+ 0x9f2f, 0x6c67, 0xbed6, 0xd201, 0x3647, 0xbe9a, 0x0091, 0xba9a,
+ 0x4df1, 0xdc8c, 0x5b15, 0x5a37, 0xb5b1, 0x50f8, 0xdfe6, 0x081b,
+ 0x48d7, 0xd40b, 0x7c51, 0x0417, 0x97c7, 0x2565, 0xf960, 0x89b2,
+ 0xa1f0, 0x7aac, 0xed6f, 0x20fe, 0x1d98, 0x0eee, 0x48b8, 0xb062,
+ 0x70e7, 0xa3f3, 0xbe3f, 0x9183, 0x76ae, 0x6cbc,
+#endif
+ /* dss_g length = 768*/
+ 0x6216, 0x4b90, 0xc254, 0x7ab6, 0x7a04, 0xf90f, 0x42dd, 0x58c7,
+ 0xd015, 0x904d, 0xfbf7, 0x624a, 0x5010, 0x627f, 0x696c, 0x1a32,
+ 0xe0bc, 0xcdfd, 0xe32f, 0xb081, 0x1377, 0x1913, 0x5f96, 0x86c6,
+ 0x864a, 0x8429, 0x4bb9, 0xd0c6, 0x3361, 0xbc7d, 0xbd8d, 0xa3b2,
+ 0x47d5, 0x5086, 0xed0b, 0x3bb6, 0xdba6, 0x6f2c, 0x707a, 0x434b,
+ 0xd4cc, 0x7b10, 0x8ef0, 0x3466, 0x4737, 0x8f27, 0x3399, 0x3716,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_g length = 800*/
+ 0x99a7, 0xa90c, 0xdf8e, 0xba50, 0x83b5, 0x7ea0, 0x1d8a, 0xe5bb,
+ 0x34c9, 0x8c4d, 0xb151, 0x3aba, 0xee2f, 0x76c8, 0xeebf, 0x3db9,
+ 0xc1e0, 0x2b9a, 0x774f, 0xb476, 0x9b93, 0x53b5, 0xc008, 0xed2c,
+ 0x0ad4, 0x8af4, 0xc0e6, 0x0e98, 0x2d7b, 0xdb37, 0x7b59, 0x8a31,
+ 0x0667, 0x1225, 0xb882, 0x0355, 0x58ba, 0xf079, 0x80d7, 0x8033,
+ 0x54bc, 0xf9cd, 0x461e, 0xc70a, 0x9170, 0x1dba, 0xc447, 0xd3e5,
+ 0xaf18, 0x04c4,
+#endif
+ /* dss_g length = 832*/
+ 0xd1b5, 0x3d20, 0xfbdb, 0xa0b6, 0x0505, 0x4e88, 0xa781, 0x7c65,
+ 0xd381, 0x5b6e, 0xfd1e, 0xbb71, 0xe085, 0x855d, 0x6d0b, 0x650a,
+ 0xa248, 0x82d0, 0xd4dd, 0x7ea0, 0x16d1, 0x6937, 0x2cc2, 0x2dec,
+ 0x5e07, 0x97b4, 0x0c5a, 0xcf21, 0x0299, 0x9b96, 0x4acf, 0xc732,
+ 0xfbcf, 0xeefb, 0x0032, 0x40bb, 0xc86e, 0xeacb, 0xae2b, 0x8adb,
+ 0x39aa, 0xbb47, 0xaf3a, 0xfd36, 0xf859, 0x97fc, 0x5535, 0x0d3d,
+ 0x627a, 0x3f62, 0x1f90, 0x5490,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_g length = 864*/
+ 0xbf83, 0x8b52, 0xc2b1, 0x0808, 0x4a3e, 0x6ccb, 0x8aa8, 0xcfdd,
+ 0xb046, 0x4948, 0xcdf4, 0x9881, 0x13d8, 0x85b0, 0xa22a, 0x3786,
+ 0xe9db, 0xcb8a, 0x89ad, 0x5e27, 0xd925, 0x1fcb, 0x3855, 0x4afd,
+ 0x7f67, 0x83be, 0xb092, 0xe061, 0x6703, 0xf21f, 0x403e, 0x4c6a,
+ 0xa8bd, 0x536a, 0x89b6, 0xb25e, 0xe165, 0xd259, 0xb765, 0xd7f3,
+ 0xc474, 0xd8bc, 0x617d, 0x1a0a, 0xa054, 0x8c28, 0x9fb0, 0x9595,
+ 0x6f2d, 0x6254, 0xe1c2, 0xb450, 0xef81, 0x277f,
+#endif
+ /* dss_g length = 896*/
+ 0x7490, 0x2aea, 0xd005, 0xa3cc, 0x9211, 0x235a, 0x7b6d, 0xacec,
+ 0xfca5, 0x5407, 0x8515, 0x5bc1, 0x8b2a, 0x9388, 0x8ff9, 0xed56,
+ 0xf4e9, 0xf31e, 0x7e05, 0x172a, 0x6e2a, 0x8165, 0x7a24, 0x975b,
+ 0x1f6e, 0xd4d1, 0x8232, 0xd6ff, 0x2363, 0x4072, 0xa1f1, 0xd18b,
+ 0xe574, 0xb032, 0xc330, 0x81b6, 0x6033, 0x07d5, 0x5107, 0xb7cc,
+ 0x2c10, 0xbd8e, 0xc6a3, 0xe731, 0xfcd6, 0xe567, 0x3440, 0xbcde,
+ 0x1976, 0xdbb3, 0xd15a, 0x4e39, 0xc282, 0x4b0b, 0x82b3, 0x286b,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_g length = 928*/
+ 0x9f66, 0xd0e5, 0xd7d2, 0xe875, 0x0707, 0x2dca, 0xa5a2, 0x266d,
+ 0x80c2, 0x6d20, 0x69b3, 0x759c, 0x497f, 0x74b4, 0x0f56, 0x4b63,
+ 0xa294, 0x4995, 0x3eda, 0xf5c4, 0x7951, 0x3a3d, 0x22e9, 0x617f,
+ 0x1906, 0xd45d, 0x047f, 0x2726, 0x27be, 0x660e, 0xc1d3, 0xa588,
+ 0xceb2, 0xe300, 0xca06, 0x8620, 0x1110, 0x76ae, 0xf7b8, 0xe368,
+ 0x89a7, 0x2ded, 0x2756, 0x3ed6, 0x5449, 0x4bd8, 0xb73d, 0xb406,
+ 0x25ec, 0x32f7, 0x989c, 0x6623, 0x6b1f, 0xf7f0, 0x4807, 0x0954,
+ 0x51e6, 0x97d0,
+#endif
+ /* dss_g length = 960*/
+ 0x4118, 0xe87c, 0x809a, 0x1287, 0x2a0f, 0x51d6, 0x7fc8, 0xdad8,
+ 0x8dc6, 0xddce, 0xd27c, 0x898a, 0x96a9, 0xaee1, 0xe44c, 0xd322,
+ 0x9d58, 0x3a34, 0xcebd, 0x322a, 0x5b48, 0x9c21, 0x6d04, 0x2d77,
+ 0x41f1, 0x5123, 0xaa5f, 0x2192, 0x8175, 0x5cac, 0xf547, 0xdc08,
+ 0xb0d9, 0x4f11, 0x85c9, 0xb5bf, 0x7147, 0x9fbf, 0x3c20, 0x7f7a,
+ 0xdd8a, 0xa163, 0x0ae4, 0xfcb2, 0x8251, 0x8162, 0xb96e, 0x84f9,
+ 0xd652, 0x94ba, 0xbb90, 0x9559, 0xac51, 0x6418, 0xdb54, 0x4739,
+ 0x3ec0, 0x9b7c, 0xae96, 0x3e14,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_g length = 992*/
+ 0x4eff, 0x399a, 0x5da9, 0x1e5a, 0x9040, 0x4bad, 0xc85d, 0x5b9a,
+ 0x825b, 0x5464, 0x7538, 0xe2ea, 0xb957, 0x5def, 0xbfa6, 0x4916,
+ 0x89be, 0x93fe, 0xe5da, 0x919f, 0x791c, 0xe7a8, 0xef86, 0xc186,
+ 0xbf63, 0xa881, 0x1e38, 0x9abe, 0x8b58, 0x70b4, 0x9dfd, 0x0719,
+ 0x85e5, 0xc60a, 0xab36, 0xe07d, 0x0c49, 0xd6fe, 0xfdb4, 0x6619,
+ 0xe55d, 0x997e, 0x5f38, 0x824f, 0x47ff, 0xf800, 0xb137, 0x839d,
+ 0x2dae, 0xe0db, 0x2a74, 0x2f58, 0x6fb3, 0x1bab, 0x62ed, 0x0e02,
+ 0xbef2, 0xd7f1, 0xe566, 0xa9ae, 0xbc35, 0x6357,
+#endif
+ /* dss_g length = 1024*/
+ 0x914d, 0x76b2, 0xfee4, 0x9cf7, 0xa136, 0x07a1, 0x3808, 0x1857,
+ 0x8f96, 0x870c, 0x1f3c, 0x59f2, 0x6f01, 0x4d4d, 0x580e, 0xafc6,
+ 0x99af, 0xff1b, 0xc019, 0x6c1f, 0xe449, 0x1698, 0x4787, 0x0aa2,
+ 0x6e68, 0x768d, 0x5ff0, 0x27dc, 0xca9e, 0x630f, 0x01ae, 0x9981,
+ 0x688d, 0xf278, 0x7f3d, 0x17ad, 0x48aa, 0x65d6, 0x181f, 0x1802,
+ 0x647c, 0x9ef5, 0x7081, 0x5843, 0x1f0d, 0x9364, 0xebe9, 0x6330,
+ 0x033a, 0x5d2a, 0xb68a, 0x5639, 0xfa7c, 0xd77e, 0x4bdc, 0x4a62,
+ 0x5c6d, 0xfed5, 0xa8aa, 0x5eff, 0x1138, 0xae4a, 0xe993, 0x3a73
+ };
+#else
+ {
+ /* dss_g length = 512*/
+ 0xedfe8b1aL, 0xdb26ef16L, 0x1f1deae0L, 0x3e30af3aL,
+ 0x25ec2bd6L, 0x6255a451L, 0x499cbc75L, 0x5da24071L,
+ 0xc7fc1149L, 0x9b691402L, 0xb0eac168L, 0x6a33af92L,
+ 0xd93af45fL, 0x263c75a6L, 0x7eb1b820L, 0x4bd75f5bL,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_g length = 544*/
+ 0xe0e62772L, 0x605bce97L, 0x25864aa8L, 0xb83f095aL,
+ 0xfe538b01L, 0x74ef9250L, 0xd9fa74d4L, 0xa714b78bL,
+ 0x03a6106fL, 0xc549b406L, 0xd559c44dL, 0xfef48100L,
+ 0x1f4c34a4L, 0x4ae03c6bL, 0x158be770L, 0xf73d3f8dL,
+ 0x61b70cc5L,
+#endif
+ /* dss_g length = 576*/
+ 0x64fd3ddeL, 0x03c32b69L, 0x1751ad1dL, 0xfe6711dcL,
+ 0x76de6379L, 0x3b8fe333L, 0x27d8242fL, 0x35975f33L,
+ 0x11dcb98cL, 0xe3b5718cL, 0x58f2a3d4L, 0x267571faL,
+ 0xf2c749f9L, 0xa4e1510eL, 0x7c64eca4L, 0x78fc243bL,
+ 0x70172ce2L, 0x23b60095L,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_g length = 608*/
+ 0x1e27dad8L, 0xd53641f5L, 0x7047528fL, 0x56f5028aL,
+ 0xe20de55fL, 0x520f612cL, 0x8c86ebfdL, 0x562a0924L,
+ 0xe5ac2185L, 0x4b8ca113L, 0xfa4c87daL, 0x9d8d8788L,
+ 0x9d2541c0L, 0xff339c77L, 0xd10a6861L, 0x8454c734L,
+ 0x55cef803L, 0x6580feacL, 0x482b6cd2L,
+#endif
+ /* dss_g length = 640*/
+ 0x28294ff7L, 0xa0bd8ab0L, 0xf5447b1cL, 0x6e7be633L,
+ 0x494a9824L, 0xc8adfb7fL, 0x956e45b6L, 0x5b0d0574L,
+ 0xf807d40cL, 0x56fd7372L, 0x8960dd12L, 0x019e255cL,
+ 0x06b3fc39L, 0x4cd99f8eL, 0x77f6e714L, 0xb57376f7L,
+ 0x9b52010eL, 0xe26904d2L, 0xbdecd4bbL, 0x7f88089dL,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_g length = 672*/
+ 0xb22d3d36L, 0xfda02144L, 0xc1441d4aL, 0x70e8ef8fL,
+ 0xcbf9fd0fL, 0xbf297433L, 0x757b1657L, 0x5c7e011dL,
+ 0xec5aa0d3L, 0xacd6d45dL, 0x9454136aL, 0xc3f661fdL,
+ 0x5c893758L, 0xd3c9e4dfL, 0xa1136f99L, 0x16b20992L,
+ 0xfb67f92fL, 0x57e63f34L, 0xdfd1b224L, 0x639a43c4L,
+ 0x86c4ccf5L,
+#endif
+ /* dss_g length = 704*/
+ 0x83131621L, 0xcb3b216eL, 0xa11bde00L, 0xd5d4f27fL,
+ 0xc8706d2eL, 0x2e211c47L, 0x1db6780bL, 0xe5c68adfL,
+ 0x7dba837dL, 0x28b59c8cL, 0xf3fad309L, 0xe37f6c65L,
+ 0x26016a1eL, 0x56aabb92L, 0x9db19c0eL, 0x642bb782L,
+ 0xb9fb6cc9L, 0x97b96a3cL, 0xd8a2f1a8L, 0xcb93fe6bL,
+ 0x32a459eeL, 0x58ad0aa1L,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_g length = 736*/
+ 0xa15c648cL, 0x813727b2L, 0x0e81efb3L, 0xabe0258eL,
+ 0x6c679f2fL, 0xd201bed6L, 0xbe9a3647L, 0xba9a0091L,
+ 0xdc8c4df1L, 0x5a375b15L, 0x50f8b5b1L, 0x081bdfe6L,
+ 0xd40b48d7L, 0x04177c51L, 0x256597c7L, 0x89b2f960L,
+ 0x7aaca1f0L, 0x20feed6fL, 0x0eee1d98L, 0xb06248b8L,
+ 0xa3f370e7L, 0x9183be3fL, 0x6cbc76aeL,
+#endif
+ /* dss_g length = 768*/
+ 0x4b906216L, 0x7ab6c254L, 0xf90f7a04L, 0x58c742ddL,
+ 0x904dd015L, 0x624afbf7L, 0x627f5010L, 0x1a32696cL,
+ 0xcdfde0bcL, 0xb081e32fL, 0x19131377L, 0x86c65f96L,
+ 0x8429864aL, 0xd0c64bb9L, 0xbc7d3361L, 0xa3b2bd8dL,
+ 0x508647d5L, 0x3bb6ed0bL, 0x6f2cdba6L, 0x434b707aL,
+ 0x7b10d4ccL, 0x34668ef0L, 0x8f274737L, 0x37163399L,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_g length = 800*/
+ 0xa90c99a7L, 0xba50df8eL, 0x7ea083b5L, 0xe5bb1d8aL,
+ 0x8c4d34c9L, 0x3abab151L, 0x76c8ee2fL, 0x3db9eebfL,
+ 0x2b9ac1e0L, 0xb476774fL, 0x53b59b93L, 0xed2cc008L,
+ 0x8af40ad4L, 0x0e98c0e6L, 0xdb372d7bL, 0x8a317b59L,
+ 0x12250667L, 0x0355b882L, 0xf07958baL, 0x803380d7L,
+ 0xf9cd54bcL, 0xc70a461eL, 0x1dba9170L, 0xd3e5c447L,
+ 0x04c4af18L,
+#endif
+ /* dss_g length = 832*/
+ 0x3d20d1b5L, 0xa0b6fbdbL, 0x4e880505L, 0x7c65a781L,
+ 0x5b6ed381L, 0xbb71fd1eL, 0x855de085L, 0x650a6d0bL,
+ 0x82d0a248L, 0x7ea0d4ddL, 0x693716d1L, 0x2dec2cc2L,
+ 0x97b45e07L, 0xcf210c5aL, 0x9b960299L, 0xc7324acfL,
+ 0xeefbfbcfL, 0x40bb0032L, 0xeacbc86eL, 0x8adbae2bL,
+ 0xbb4739aaL, 0xfd36af3aL, 0x97fcf859L, 0x0d3d5535L,
+ 0x3f62627aL, 0x54901f90L,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_g length = 864*/
+ 0x8b52bf83L, 0x0808c2b1L, 0x6ccb4a3eL, 0xcfdd8aa8L,
+ 0x4948b046L, 0x9881cdf4L, 0x85b013d8L, 0x3786a22aL,
+ 0xcb8ae9dbL, 0x5e2789adL, 0x1fcbd925L, 0x4afd3855L,
+ 0x83be7f67L, 0xe061b092L, 0xf21f6703L, 0x4c6a403eL,
+ 0x536aa8bdL, 0xb25e89b6L, 0xd259e165L, 0xd7f3b765L,
+ 0xd8bcc474L, 0x1a0a617dL, 0x8c28a054L, 0x95959fb0L,
+ 0x62546f2dL, 0xb450e1c2L, 0x277fef81L,
+#endif
+ /* dss_g length = 896*/
+ 0x2aea7490L, 0xa3ccd005L, 0x235a9211L, 0xacec7b6dL,
+ 0x5407fca5L, 0x5bc18515L, 0x93888b2aL, 0xed568ff9L,
+ 0xf31ef4e9L, 0x172a7e05L, 0x81656e2aL, 0x975b7a24L,
+ 0xd4d11f6eL, 0xd6ff8232L, 0x40722363L, 0xd18ba1f1L,
+ 0xb032e574L, 0x81b6c330L, 0x07d56033L, 0xb7cc5107L,
+ 0xbd8e2c10L, 0xe731c6a3L, 0xe567fcd6L, 0xbcde3440L,
+ 0xdbb31976L, 0x4e39d15aL, 0x4b0bc282L, 0x286b82b3L,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_g length = 928*/
+ 0xd0e59f66L, 0xe875d7d2L, 0x2dca0707L, 0x266da5a2L,
+ 0x6d2080c2L, 0x759c69b3L, 0x74b4497fL, 0x4b630f56L,
+ 0x4995a294L, 0xf5c43edaL, 0x3a3d7951L, 0x617f22e9L,
+ 0xd45d1906L, 0x2726047fL, 0x660e27beL, 0xa588c1d3L,
+ 0xe300ceb2L, 0x8620ca06L, 0x76ae1110L, 0xe368f7b8L,
+ 0x2ded89a7L, 0x3ed62756L, 0x4bd85449L, 0xb406b73dL,
+ 0x32f725ecL, 0x6623989cL, 0xf7f06b1fL, 0x09544807L,
+ 0x97d051e6L,
+#endif
+ /* dss_g length = 960*/
+ 0xe87c4118L, 0x1287809aL, 0x51d62a0fL, 0xdad87fc8L,
+ 0xddce8dc6L, 0x898ad27cL, 0xaee196a9L, 0xd322e44cL,
+ 0x3a349d58L, 0x322acebdL, 0x9c215b48L, 0x2d776d04L,
+ 0x512341f1L, 0x2192aa5fL, 0x5cac8175L, 0xdc08f547L,
+ 0x4f11b0d9L, 0xb5bf85c9L, 0x9fbf7147L, 0x7f7a3c20L,
+ 0xa163dd8aL, 0xfcb20ae4L, 0x81628251L, 0x84f9b96eL,
+ 0x94bad652L, 0x9559bb90L, 0x6418ac51L, 0x4739db54L,
+ 0x9b7c3ec0L, 0x3e14ae96L,
+#ifdef LENGTH_MULT_TO_32
+ /* dss_g length = 992*/
+ 0x399a4effL, 0x1e5a5da9L, 0x4bad9040L, 0x5b9ac85dL,
+ 0x5464825bL, 0xe2ea7538L, 0x5defb957L, 0x4916bfa6L,
+ 0x93fe89beL, 0x919fe5daL, 0xe7a8791cL, 0xc186ef86L,
+ 0xa881bf63L, 0x9abe1e38L, 0x70b48b58L, 0x07199dfdL,
+ 0xc60a85e5L, 0xe07dab36L, 0xd6fe0c49L, 0x6619fdb4L,
+ 0x997ee55dL, 0x824f5f38L, 0xf80047ffL, 0x839db137L,
+ 0xe0db2daeL, 0x2f582a74L, 0x1bab6fb3L, 0x0e0262edL,
+ 0xd7f1bef2L, 0xa9aee566L, 0x6357bc35L,
+#endif
+ /* dss_g length = 1024*/
+ 0x76b2914dL, 0x9cf7fee4L, 0x07a1a136L, 0x18573808L,
+ 0x870c8f96L, 0x59f21f3cL, 0x4d4d6f01L, 0xafc6580eL,
+ 0xff1b99afL, 0x6c1fc019L, 0x1698e449L, 0x0aa24787L,
+ 0x768d6e68L, 0x27dc5ff0L, 0x630fca9eL, 0x998101aeL,
+ 0xf278688dL, 0x17ad7f3dL, 0x65d648aaL, 0x1802181fL,
+ 0x9ef5647cL, 0x58437081L, 0x93641f0dL, 0x6330ebe9L,
+ 0x5d2a033aL, 0x5639b68aL, 0xd77efa7cL, 0x4a624bdcL,
+ 0xfed55c6dL, 0x5effa8aaL, 0xae4a1138L, 0x3a73e993L
+ };
+#endif
+
+#endif /*INITIALIZ_PQG*/
+
+#endif /*DSSNUMBER_H*/
diff --git a/usr/src/lib/libresolv2/common/cylink/kludge.h b/usr/src/lib/libresolv2/common/cylink/kludge.h
new file mode 100644
index 0000000000..7c85615e89
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/kludge.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef KLUDGE_H
+#define KLUDGE_H
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Kludges for not-quite-ANSI systems.
+ * This should always be the last file included, because it may
+ * mess up some system header files.
+ */
+
+/*
+ * Some compilers complain about #if FOO if FOO isn't defined,
+ * so do the ANSI-mandated thing explicitly...
+ */
+#ifndef ASSERT_NEEDS_STDIO
+#define ASSERT_NEEDS_STDIO 0
+#endif
+#ifndef ASSERT_NEEDS_STDLIB
+#define ASSERT_NEEDS_STDLIB 0
+#endif
+#ifndef NO_STDLIB_H
+#define NO_STDLIB_H 0
+#endif
+
+/* SunOS 4.1.x <assert.h> needs "stderr" defined, and "exit" declared... */
+#ifdef assert
+#if ASSERT_NEEDS_STDIO
+#include <stdio.h>
+#endif
+#if ASSERT_NEEDS_STDLIB
+#if !NO_STDLIB_H
+#include <stdlib.h>
+#endif
+#endif
+#endif
+
+#ifndef NO_MEMMOVE
+#define NO_MEMMOVE 0
+#endif
+#if NO_MEMMOVE /* memove() not in libraries */
+#define memmove(dest,src,len) bcopy(src,dest,len)
+#endif
+
+#ifndef NO_MEMCPY
+#define NO_MEMCPY 0
+#endif
+#if NO_MEMCPY /* memcpy() not in libraries */
+#define memcpy(dest,src,len) bcopy(src,dest,len)
+#endif
+
+#ifndef MEM_PROTOS_BROKEN
+#define MEM_PROTOS_BROKEN 0
+#endif
+#if MEM_PROTOS_BROKEN
+#define memcpy(d,s,l) memcpy((void *)(d), (void const *)(s), l)
+#define memmove(d,s,l) memmove((void *)(d), (void const *)(s), l)
+#define memcmp(d,s,l) memcmp((void const *)(d), (void const *)(s), l)
+#define memset(d,v,l) memset((void *)(d), v, l)
+#endif
+
+/*
+ * If there are no prototypes for the stdio functions, use these to
+ * reduce compiler warnings. Uses EOF as a giveaway to indicate
+ * that <stdio.h> was #included.
+ */
+#ifndef NO_STDIO_PROTOS
+#define NO_STDIO_PROTOS 0
+#endif
+#if NO_STDIO_PROTOS /* Missing prototypes for "simple" functions */
+#ifdef EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+int (puts)(char const *);
+int (fputs)(char const *, FILE *);
+int (fflush)(FILE *);
+int (printf)(char const *, ...);
+int (fprintf)(FILE *, char const *, ...);
+/* If we have a sufficiently old-fashioned stdio, it probably uses these... */
+int (_flsbuf)(int, FILE *);
+int (_filbuf)(FILE *);
+#ifdef __cplusplus
+}
+#endif
+#endif /* EOF */
+#endif /* NO_STDIO_PROTOS */
+
+/*
+ * Borland C seems to think that it's a bad idea to decleare a
+ * structure tag and not declare the contents. I happen to think
+ * it's a *good* idea to use such "opaque" structures wherever
+ * possible. So shut up.
+ */
+#ifdef __BORLANDC__
+#pragma warn -stu
+#ifndef MSDOS
+#define MSDOS 1
+#endif
+#endif
+
+/* Turn off warning about negation of unsigned values */
+#ifdef _MSC_VER
+#pragma warning(disable:4146)
+#endif
+
+/* Cope with people forgetting to define the OS, if possible... */
+
+#ifndef MSDOS
+#ifdef __MSDOS
+#define MSDOS 1
+#endif
+#endif
+#ifndef MSDOS
+#ifdef __MSDOS__
+#define MSDOS 1
+#endif
+#endif
+
+#endif /* KLUDGE_H */
diff --git a/usr/src/lib/libresolv2/common/cylink/lbn.h b/usr/src/lib/libresolv2/common/cylink/lbn.h
new file mode 100644
index 0000000000..c0385c60cc
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbn.h
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/*
+ * lbn.h - Low-level bignum header.
+ * Defines various word sizes and useful macros.
+ *
+ * Copyright (c) 1995 Colin Plumb. All rights reserved.
+ * For licensing and other legal details, see the file legal.c.
+ */
+#ifndef LBN_H
+#define LBN_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef HAVE_CONFIG_H
+#define HAVE_CONFIG_H 0
+#endif
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * Some compilers complain about #if FOO if FOO isn't defined,
+ * so do the ANSI-mandated thing explicitly...
+ */
+#ifndef NO_LIMITS_H
+#define NO_LIMITS_H 0
+#endif
+
+/* Make sure we have 8-bit bytes */
+#if !NO_LIMITS_H
+#include <limits.h>
+#if UCHAR_MAX != 0xff || CHAR_BIT != 8
+#error The bignum library requires 8-bit unsigned characters.
+#endif
+#endif /* !NO_LIMITS_H */
+
+#ifdef BNINCLUDE /* If this is defined as, say, foo.h */
+#define STR(x) #x /* STR(BNINCLUDE) -> "BNINCLUDE" */
+#define XSTR(x) STR(x) /* XSTR(BNINCLUDE) -> STR(foo.h) -> "foo.h" */
+#include XSTR(BNINCLUDE) /* #include "foo.h" */
+#undef XSTR
+#undef STR
+#endif
+
+/* Figure out the endianness */
+/* Error if more than one is defined */
+#if BN_BIG_ENDIAN && BN_LITTLE_ENDIAN
+#error Only one of BN_BIG_ENDIAN or BN_LITTLE_ENDIAN may be defined
+#endif
+
+/*
+ * If no preference is stated, little-endian C code is slightly more
+ * efficient, so prefer that. (The endianness here does NOT have to
+ * match the machine's native byte sex; the library's C code will work
+ * either way. The flexibility is allowed for assembly routines
+ * that do care.
+ */
+#if !defined(BN_BIG_ENDIAN) && !defined(BN_LITTLE_ENDIAN)
+#define BN_LITTLE_ENDIAN 1
+#endif /* !BN_BIG_ENDIAN && !BN_LITTLE_ENDIAN */
+
+/* Macros to choose between big and little endian */
+#if BN_BIG_ENDIAN
+#define BIG(b) b
+#define LITTLE(l) /*nothing*/
+#define BIGLITTLE(b,l) b
+#elif BN_LITTLE_ENDIAN
+#define BIG(b) /*nothing*/
+#define LITTLE(l) l
+#define BIGLITTLE(b,l) l
+#else
+#error One of BN_BIG_ENDIAN or BN_LITTLE_ENDIAN must be defined as 1
+#endif
+
+
+/*
+ * Find a 16-bit unsigned type.
+ * Unsigned short is preferred over unsigned int to make the type chosen
+ * by this file more stable on platforms (such as many 68000 compilers)
+ * which support both 16- and 32-bit ints.
+ */
+#ifndef BNWORD16
+#ifndef USHRT_MAX /* No <limits.h> available - guess */
+typedef unsigned short bnword16;
+#define BNWORD16 bnword16
+#elif USHRT_MAX == 0xffff
+typedef unsigned short bnword16;
+#define BNWORD16 bnword16
+#elif UINT_MAX == 0xffff
+typedef unsigned bnword16;
+#define BNWORD16 bnword16
+#endif
+#endif /* BNWORD16 */
+
+/*
+ * Find a 32-bit unsigned type.
+ * Unsigned long is preferred over unsigned int to make the type chosen
+ * by this file more stable on platforms (such as many 68000 compilers)
+ * which support both 16- and 32-bit ints.
+ */
+#ifndef BNWORD32
+#ifndef ULONG_MAX /* No <limits.h> available - guess */
+typedef unsigned long bnword32;
+#define BNWORD32 bnword32
+#elif ULONG_MAX == 0xfffffffful
+typedef unsigned long bnword32;
+#define BNWORD32 bnword32
+#elif UINT_MAX == 0xffffffff
+typedef unsigned bnword32;
+#define BNWORD32 bnword32
+#elif USHRT_MAX == 0xffffffff
+typedef unsigned short bnword32;
+#define BNWORD32 bnword32
+#endif
+#endif /* BNWORD16 */
+
+/*
+ * Find a 64-bit unsigned type.
+ * The conditions here are more complicated to avoid using numbers that
+ * will choke lesser preprocessors (like 0xffffffffffffffff) unless
+ * we're reasonably certain that they'll be acceptable.
+ */
+#if !defined(BNWORD64) && ULONG_MAX > 0xfffffffful
+#if ULONG_MAX == 0xffffffffffffffff
+typedef unsigned long bnword64;
+#define BNWORD64 bnword64
+#endif
+#endif
+
+#if 0
+/*
+ * I would test the value of unsigned long long, but some *preprocessors*
+ * don't constants that long even if the compiler can accept them, so it
+ * doesn't work reliably. So cross our fingers and hope that it's a 64-bit
+ * type.
+ *
+ * GCC uses ULONG_LONG_MAX. Solaris uses ULLONG_MAX. IRIX uses ULONGLONG_MAX.
+ * Are there any other names for this?
+ */
+#if !defined(BNWORD64) && \
+ (defined(ULONG_LONG_MAX) || defined (ULLONG_MAX) || defined(ULONGLONG_MAX))
+typedef unsigned long long bnword64;
+#define BNWORD64 bnword64
+#endif
+#endif
+
+/* We don't even try to find a 128-bit type at the moment */
+
+#endif /* !LBN_H */
diff --git a/usr/src/lib/libresolv2/common/cylink/lbn00.c b/usr/src/lib/libresolv2/common/cylink/lbn00.c
new file mode 100644
index 0000000000..f6686d7b00
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbn00.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/*
+ * lbn00.c - auto-size-detecting lbn??.c file.
+ *
+ * Written in 1995 by Colin Plumb.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "port_before.h"
+#include "bnsize00.h"
+
+
+#if BNSIZE64
+
+/* Include all of the C source file by reference */
+#include "lbn64.c"
+
+#elif BNSIZE32
+
+/* Include all of the C source file by reference */
+#include "lbn32.c"
+
+#else /* BNSIZE16 */
+
+/* Include all of the C source file by reference */
+#include "lbn16.c"
+
+#endif
diff --git a/usr/src/lib/libresolv2/common/cylink/lbn16.c b/usr/src/lib/libresolv2/common/cylink/lbn16.c
new file mode 100644
index 0000000000..938651d1d4
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbn16.c
@@ -0,0 +1,3651 @@
+/*
+ * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/*
+ * lbn16.c - Low-level bignum routines, 16-bit version.
+ *
+ * Copyright (c) 1995 Colin Plumb. All rights reserved.
+ * For licensing and other legal details, see the file legal.c.
+ *
+ * NOTE: the magic constants "16" and "32" appear in many places in this
+ * file, including inside identifiers. Because it is not possible to
+ * ask "#ifdef" of a macro expansion, it is not possible to use the
+ * preprocessor to conditionalize these properly. Thus, this file is
+ * intended to be edited with textual search and replace to produce
+ * alternate word size versions. Any reference to the number of bits
+ * in a word must be the string "16", and that string must not appear
+ * otherwise. Any reference to twice this number must appear as "32",
+ * which likewise must not appear otherwise. Is that clear?
+ *
+ * Remember, when doubling the bit size replace the larger number (32)
+ * first, then the smaller (16). When halving the bit size, do the
+ * opposite. Otherwise, things will get wierd. Also, be sure to replace
+ * every instance that appears. (:%s/foo/bar/g in vi)
+ *
+ * These routines work with a pointer to the least-significant end of
+ * an array of WORD16s. The BIG(x), LITTLE(y) and BIGLTTLE(x,y) macros
+ * defined in lbn.h (which expand to x on a big-edian machine and y on a
+ * little-endian machine) are used to conditionalize the code to work
+ * either way. If you have no assembly primitives, it doesn't matter.
+ * Note that on a big-endian machine, the least-significant-end pointer
+ * is ONE PAST THE END. The bytes are ptr[-1] through ptr[-len].
+ * On little-endian, they are ptr[0] through ptr[len-1]. This makes
+ * perfect sense if you consider pointers to point *between* bytes rather
+ * than at them.
+ *
+ * Because the array index values are unsigned integers, ptr[-i]
+ * may not work properly, since the index -i is evaluated as an unsigned,
+ * and if pointers are wider, zero-extension will produce a positive
+ * number rahter than the needed negative. The expression used in this
+ * code, *(ptr-i) will, however, work. (The array syntax is equivalent
+ * to *(ptr+-i), which is a pretty subtle difference.)
+ *
+ * Many of these routines will get very unhappy if fed zero-length inputs.
+ * They use assert() to enforce this. An higher layer of code must make
+ * sure that these aren't called with zero-length inputs.
+ *
+ * Any of these routines can be replaced with more efficient versions
+ * elsewhere, by just #defining their names. If one of the names
+ * is #defined, the C code is not compiled in and no declaration is
+ * made. Use the BNINCLUDE file to do that. Typically, you compile
+ * asm subroutines with the same name and just, e.g.
+ * #define lbnMulAdd1_16 lbnMulAdd1_16
+ *
+ * If you want to write asm routines, start with lbnMulAdd1_16().
+ * This is the workhorse of modular exponentiation. lbnMulN1_16() is
+ * also used a fair bit, although not as much and it's defined in terms
+ * of lbnMulAdd1_16 if that has a custom version. lbnMulSub1_16 and
+ * lbnDiv21_16 are used in the usual division and remainder finding.
+ * (Not the Montgomery reduction used in modular exponentiation, though.)
+ * Once you have lbnMulAdd1_16 defined, writing the other two should
+ * be pretty easy. (Just make sure you get the sign of the subtraction
+ * in lbnMulSub1_16 right - it's dest = dest - source * k.)
+ *
+ * The only definitions that absolutely need a double-word (BNWORD32)
+ * type are lbnMulAdd1_16 and lbnMulSub1_16; if those are provided,
+ * the rest follows. lbnDiv21_16, however, is a lot slower unless you
+ * have them, and lbnModQ_16 takes after it. That one is used quite a
+ * bit for prime sieving.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef HAVE_CONFIG_H
+#define HAVE_CONFIG_H 0
+#endif
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * Some compilers complain about #if FOO if FOO isn't defined,
+ * so do the ANSI-mandated thing explicitly...
+ */
+#ifndef NO_ASSERT_H
+#define NO_ASSERT_H 0
+#endif
+#ifndef NO_STRING_H
+#define NO_STRING_H 0
+#endif
+#ifndef HAVE_STRINGS_H
+#define HAVE_STRINGS_H 0
+#endif
+#ifndef NEED_MEMORY_H
+#define NEED_MEMORY_H 0
+#endif
+
+#if !NO_ASSERT_H
+#include <assert.h>
+#else
+#define assert(x) (void)0
+#endif
+
+#if !NO_STRING_H
+#include <string.h> /* For memcpy */
+#elif HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#if NEED_MEMORY_H
+#include <memory.h>
+#endif
+
+#include "lbn.h"
+#include "lbn16.h"
+#include "lbnmem.h"
+#include "legal.h"
+
+#include "kludge.h"
+#include <port_after.h>
+
+#ifndef BNWORD16
+#error 16-bit bignum library requires a 16-bit data type
+#endif
+
+/* Make sure the copyright notice gets included */
+volatile const char * volatile const lbnCopyright_16 = bnCopyright;
+
+/*
+ * Most of the multiply (and Montgomery reduce) routines use an outer
+ * loop that iterates over one of the operands - a so-called operand
+ * scanning approach. One big advantage of this is that the assembly
+ * support routines are simpler. The loops can be rearranged to have
+ * an outer loop that iterates over the product, a so-called product
+ * scanning approach. This has the advantage of writing less data
+ * and doing fewer adds to memory, so is supposedly faster. Some
+ * code has been written using a product-scanning approach, but
+ * it appears to be slower, so it is turned off by default. Some
+ * experimentation would be appreciated.
+ *
+ * (The code is also annoying to get right and not very well commented,
+ * one of my pet peeves about math libraries. I'm sorry.)
+ */
+#ifndef PRODUCT_SCAN
+#define PRODUCT_SCAN 0
+#endif
+
+/*
+ * Copy an array of words. <Marvin mode on> Thrilling, isn't it? </Marvin>
+ * This is a good example of how the byte offsets and BIGLITTLE() macros work.
+ * Another alternative would have been
+ * memcpy(dest BIG(-len), src BIG(-len), len*sizeof(BNWORD16)), but I find that
+ * putting operators into conditional macros is confusing.
+ */
+#ifndef lbnCopy_16
+void
+lbnCopy_16(BNWORD16 *dest, BNWORD16 const *src, unsigned len)
+{
+ memcpy(BIGLITTLE(dest-len,dest), BIGLITTLE(src-len,src),
+ len * sizeof(*src));
+}
+#endif /* !lbnCopy_16 */
+
+/*
+ * Fill n words with zero. This does it manually rather than calling
+ * memset because it can assume alignment to make things faster while
+ * memset can't. Note how big-endian numbers are naturally addressed
+ * using predecrement, while little-endian is postincrement.
+ */
+#ifndef lbnZero_16
+void
+lbnZero_16(BNWORD16 *num, unsigned len)
+{
+ while (len--)
+ BIGLITTLE(*--num,*num++) = 0;
+}
+#endif /* !lbnZero_16 */
+
+/*
+ * Negate an array of words.
+ * Negation is subtraction from zero. Negating low-order words
+ * entails doing nothing until a non-zero word is hit. Once that
+ * is negated, a borrow is generated and never dies until the end
+ * of the number is hit. Negation with borrow, -x-1, is the same as ~x.
+ * Repeat that until the end of the number.
+ *
+ * Doesn't return borrow out because that's pretty useless - it's
+ * always set unless the input is 0, which is easy to notice in
+ * normalized form.
+ */
+#ifndef lbnNeg_16
+void
+lbnNeg_16(BNWORD16 *num, unsigned len)
+{
+ assert(len);
+
+ /* Skip low-order zero words */
+ while (BIGLITTLE(*--num,*num) == 0) {
+ if (!--len)
+ return;
+ LITTLE(num++;)
+ }
+ /* Negate the lowest-order non-zero word */
+ *num = -*num;
+ /* Complement all the higher-order words */
+ while (--len) {
+ BIGLITTLE(--num,++num);
+ *num = ~*num;
+ }
+}
+#endif /* !lbnNeg_16 */
+
+
+/*
+ * lbnAdd1_16: add the single-word "carry" to the given number.
+ * Used for minor increments and propagating the carry after
+ * adding in a shorter bignum.
+ *
+ * Technique: If we have a double-width word, presumably the compiler
+ * can add using its carry in inline code, so we just use a larger
+ * accumulator to compute the carry from the first addition.
+ * If not, it's more complex. After adding the first carry, which may
+ * be > 1, compare the sum and the carry. If the sum wraps (causing a
+ * carry out from the addition), the result will be less than each of the
+ * inputs, since the wrap subtracts a number (2^16) which is larger than
+ * the other input can possibly be. If the sum is >= the carry input,
+ * return success immediately.
+ * In either case, if there is a carry, enter a loop incrementing words
+ * until one does not wrap. Since we are adding 1 each time, the wrap
+ * will be to 0 and we can test for equality.
+ */
+#ifndef lbnAdd1_16 /* If defined, it's provided as an asm subroutine */
+#ifdef BNWORD32
+BNWORD16
+lbnAdd1_16(BNWORD16 *num, unsigned len, BNWORD16 carry)
+{
+ BNWORD32 t;
+ assert(len > 0); /* Alternative: if (!len) return carry */
+
+ t = (BNWORD32)BIGLITTLE(*--num,*num) + carry;
+ BIGLITTLE(*num,*num++) = (BNWORD16)t;
+ if ((t >> 16) == 0)
+ return 0;
+ while (--len) {
+ if (++BIGLITTLE(*--num,*num++) != 0)
+ return 0;
+ }
+ return 1;
+}
+#else /* no BNWORD32 */
+BNWORD16
+lbnAdd1_16(BNWORD16 *num, unsigned len, BNWORD16 carry)
+{
+ assert(len > 0); /* Alternative: if (!len) return carry */
+
+ if ((BIGLITTLE(*--num,*num++) += carry) >= carry)
+ return 0;
+ while (--len) {
+ if (++BIGLITTLE(*--num,*num++) != 0)
+ return 0;
+ }
+ return 1;
+}
+#endif
+#endif/* !lbnAdd1_16 */
+
+/*
+ * lbnSub1_16: subtract the single-word "borrow" from the given number.
+ * Used for minor decrements and propagating the borrow after
+ * subtracting a shorter bignum.
+ *
+ * Technique: Similar to the add, above. If there is a double-length type,
+ * use that to generate the first borrow.
+ * If not, after subtracting the first borrow, which may be > 1, compare
+ * the difference and the *negative* of the carry. If the subtract wraps
+ * (causing a borrow out from the subtraction), the result will be at least
+ * as large as -borrow. If the result < -borrow, then no borrow out has
+ * appeared and we may return immediately, except when borrow == 0. To
+ * deal with that case, use the identity that -x = ~x+1, and instead of
+ * comparing < -borrow, compare for <= ~borrow.
+ * Either way, if there is a borrow out, enter a loop decrementing words
+ * until a non-zero word is reached.
+ *
+ * Note the cast of ~borrow to (BNWORD16). If the size of an int is larger
+ * than BNWORD16, C rules say the number is expanded for the arithmetic, so
+ * the inversion will be done on an int and the value won't be quite what
+ * is expected.
+ */
+#ifndef lbnSub1_16 /* If defined, it's provided as an asm subroutine */
+#ifdef BNWORD32
+BNWORD16
+lbnSub1_16(BNWORD16 *num, unsigned len, BNWORD16 borrow)
+{
+ BNWORD32 t;
+ assert(len > 0); /* Alternative: if (!len) return borrow */
+
+ t = (BNWORD32)BIGLITTLE(*--num,*num) - borrow;
+ BIGLITTLE(*num,*num++) = (BNWORD16)t;
+ if ((t >> 16) == 0)
+ return 0;
+ while (--len) {
+ if ((BIGLITTLE(*--num,*num++))-- != 0)
+ return 0;
+ }
+ return 1;
+}
+#else /* no BNWORD32 */
+BNWORD16
+lbnSub1_16(BNWORD16 *num, unsigned len, BNWORD16 borrow)
+{
+ assert(len > 0); /* Alternative: if (!len) return borrow */
+
+ if ((BIGLITTLE(*--num,*num++) -= borrow) <= (BNWORD16)~borrow)
+ return 0;
+ while (--len) {
+ if ((BIGLITTLE(*--num,*num++))-- != 0)
+ return 0;
+ }
+ return 1;
+}
+#endif
+#endif /* !lbnSub1_16 */
+
+/*
+ * lbnAddN_16: add two bignums of the same length, returning the carry (0 or 1).
+ * One of the building blocks, along with lbnAdd1, of adding two bignums of
+ * differing lengths.
+ *
+ * Technique: Maintain a word of carry. If there is no double-width type,
+ * use the same technique as in lbnAdd1, above, to maintain the carry by
+ * comparing the inputs. Adding the carry sources is used as an OR operator;
+ * at most one of the two comparisons can possibly be true. The first can
+ * only be true if carry == 1 and x, the result, is 0. In that case the
+ * second can't possibly be true.
+ */
+#ifndef lbnAddN_16
+#ifdef BNWORD32
+BNWORD16
+lbnAddN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len)
+{
+ BNWORD32 t;
+
+ assert(len > 0);
+
+ t = (BNWORD32)BIGLITTLE(*--num1,*num1) + BIGLITTLE(*--num2,*num2++);
+ BIGLITTLE(*num1,*num1++) = (BNWORD16)t;
+ while (--len) {
+ t = (BNWORD32)BIGLITTLE(*--num1,*num1) +
+ (BNWORD32)BIGLITTLE(*--num2,*num2++) + (t >> 16);
+ BIGLITTLE(*num1,*num1++) = (BNWORD16)t;
+ }
+
+ return (BNWORD16)(t>>16);
+}
+#else /* no BNWORD32 */
+BNWORD16
+lbnAddN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len)
+{
+ BNWORD16 x, carry = 0;
+
+ assert(len > 0); /* Alternative: change loop to test at start */
+
+ do {
+ x = BIGLITTLE(*--num2,*num2++);
+ carry = (x += carry) < carry;
+ carry += (BIGLITTLE(*--num1,*num1++) += x) < x;
+ } while (--len);
+
+ return carry;
+}
+#endif
+#endif /* !lbnAddN_16 */
+
+/*
+ * lbnSubN_16: add two bignums of the same length, returning the carry (0 or 1).
+ * One of the building blocks, along with subn1, of subtracting two bignums of
+ * differing lengths.
+ *
+ * Technique: If no double-width type is availble, maintain a word of borrow.
+ * First, add the borrow to the subtrahend (did you have to learn all those
+ * awful words in elementary school, too?), and if it overflows, set the
+ * borrow again. Then subtract the modified subtrahend from the next word
+ * of input, using the same technique as in subn1, above.
+ * Adding the borrows is used as an OR operator; at most one of the two
+ * comparisons can possibly be true. The first can only be true if
+ * borrow == 1 and x, the result, is 0. In that case the second can't
+ * possibly be true.
+ *
+ * In the double-word case, (BNWORD16)-(t>>16) is subtracted, rather than
+ * adding t>>16, because the shift would need to sign-extend and that's
+ * not guaranteed to happen in ANSI C, even with signed types.
+ */
+#ifndef lbnSubN_16
+#ifdef BNWORD32
+BNWORD16
+lbnSubN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len)
+{
+ BNWORD32 t;
+
+ assert(len > 0);
+
+ t = (BNWORD32)BIGLITTLE(*--num1,*num1) - BIGLITTLE(*--num2,*num2++);
+ BIGLITTLE(*num1,*num1++) = (BNWORD16)t;
+
+ while (--len) {
+ t = (BNWORD32)BIGLITTLE(*--num1,*num1) -
+ (BNWORD32)BIGLITTLE(*--num2,*num2++) - (BNWORD16)-(t >> 16);
+ BIGLITTLE(*num1,*num1++) = (BNWORD16)t;
+ }
+
+ return -(BNWORD16)(t>>16);
+}
+#else
+BNWORD16
+lbnSubN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len)
+{
+ BNWORD16 x, borrow = 0;
+
+ assert(len > 0); /* Alternative: change loop to test at start */
+
+ do {
+ x = BIGLITTLE(*--num2,*num2++);
+ borrow = (x += borrow) < borrow;
+ borrow += (BIGLITTLE(*--num1,*num1++) -= x) > (BNWORD16)~x;
+ } while (--len);
+
+ return borrow;
+}
+#endif
+#endif /* !lbnSubN_16 */
+
+#ifndef lbnCmp_16
+/*
+ * lbnCmp_16: compare two bignums of equal length, returning the sign of
+ * num1 - num2. (-1, 0 or +1).
+ *
+ * Technique: Change the little-endian pointers to big-endian pointers
+ * and compare from the most-significant end until a difference if found.
+ * When it is, figure out the sign of the difference and return it.
+ */
+int
+lbnCmp_16(BNWORD16 const *num1, BNWORD16 const *num2, unsigned len)
+{
+ BIGLITTLE(num1 -= len, num1 += len);
+ BIGLITTLE(num2 -= len, num2 += len);
+
+ while (len--) {
+ if (BIGLITTLE(*num1++ != *num2++, *--num1 != *--num2)) {
+ if (BIGLITTLE(num1[-1] < num2[-1], *num1 < *num2))
+ return -1;
+ else
+ return 1;
+ }
+ }
+ return 0;
+}
+#endif /* !lbnCmp_16 */
+
+/*
+ * mul16_ppmmaa(ph,pl,x,y,a,b) is an optional routine that
+ * computes (ph,pl) = x * y + a + b. mul16_ppmma and mul16_ppmm
+ * are simpler versions. If you want to be lazy, all of these
+ * can be defined in terms of the others, so here we create any
+ * that have not been defined in terms of the ones that have been.
+ */
+
+/* Define ones with fewer a's in terms of ones with more a's */
+#if !defined(mul16_ppmma) && defined(mul16_ppmmaa)
+#define mul16_ppmma(ph,pl,x,y,a) mul16_ppmmaa(ph,pl,x,y,a,0)
+#endif
+
+#if !defined(mul16_ppmm) && defined(mul16_ppmma)
+#define mul16_ppmm(ph,pl,x,y) mul16_ppmma(ph,pl,x,y,0)
+#endif
+
+/*
+ * Use this definition to test the mul16_ppmm-based operations on machines
+ * that do not provide mul16_ppmm. Change the final "0" to a "1" to
+ * enable it.
+ */
+#if !defined(mul16_ppmm) && defined(BNWORD32) && 0 /* Debugging */
+#define mul16_ppmm(ph,pl,x,y) \
+ ({BNWORD32 _ = (BNWORD32)(x)*(y); (pl) = _; (ph) = _>>16;})
+#endif
+
+#if defined(mul16_ppmm) && !defined(mul16_ppmma)
+#define mul16_ppmma(ph,pl,x,y,a) \
+ (mul16_ppmm(ph,pl,x,y), (ph) += ((pl) += (a)) < (a))
+#endif
+
+#if defined(mul16_ppmma) && !defined(mul16_ppmmaa)
+#define mul16_ppmmaa(ph,pl,x,y,a,b) \
+ (mul16_ppmma(ph,pl,x,y,a), (ph) += ((pl) += (b)) < (b))
+#endif
+
+/*
+ * lbnMulN1_16: Multiply an n-word input by a 1-word input and store the
+ * n+1-word product. This uses either the mul16_ppmm and mul16_ppmma
+ * macros, or C multiplication with the BNWORD32 type. This uses mul16_ppmma
+ * if available, assuming you won't bother defining it unless you can do
+ * better than the normal multiplication.
+ */
+#ifndef lbnMulN1_16
+#ifdef lbnMulAdd1_16 /* If we have this asm primitive, use it. */
+void
+lbnMulN1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k)
+{
+ lbnZero_16(out, len);
+ BIGLITTLE(*(out-len),*(out+len)) = lbnMulAdd1_16(out, in, len, k);
+}
+#elif defined(mul16_ppmm)
+void
+lbnMulN1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k)
+{
+ BNWORD16 prod, carry, carryin;
+
+ assert(len > 0);
+
+ BIG(--out;--in;);
+ mul16_ppmm(carry, *out, *in, k);
+ LITTLE(out++;in++;)
+
+ while (--len) {
+ BIG(--out;--in;)
+ carryin = carry;
+ mul16_ppmma(carry, *out, *in, k, carryin);
+ LITTLE(out++;in++;)
+ }
+ BIGLITTLE(*--out,*out) = carry;
+}
+#elif defined(BNWORD32)
+void
+lbnMulN1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k)
+{
+ BNWORD32 p;
+
+ assert(len > 0);
+
+ p = (BNWORD32)BIGLITTLE(*--in,*in++) * k;
+ BIGLITTLE(*--out,*out++) = (BNWORD16)p;
+
+ while (--len) {
+ p = (BNWORD32)BIGLITTLE(*--in,*in++) * k + (BNWORD16)(p >> 16);
+ BIGLITTLE(*--out,*out++) = (BNWORD16)p;
+ }
+ BIGLITTLE(*--out,*out) = (BNWORD16)(p >> 16);
+}
+#else
+#error No 16x16 -> 32 multiply available for 16-bit bignum package
+#endif
+#endif /* lbnMulN1_16 */
+
+/*
+ * lbnMulAdd1_16: Multiply an n-word input by a 1-word input and add the
+ * low n words of the product to the destination. *Returns the n+1st word
+ * of the product.* (That turns out to be more convenient than adding
+ * it into the destination and dealing with a possible unit carry out
+ * of *that*.) This uses either the mul16_ppmma and mul16_ppmmaa macros,
+ * or C multiplication with the BNWORD32 type.
+ *
+ * If you're going to write assembly primitives, this is the one to
+ * start with. It is by far the most commonly called function.
+ */
+#ifndef lbnMulAdd1_16
+#if defined(mul16_ppmm)
+BNWORD16
+lbnMulAdd1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k)
+{
+ BNWORD16 prod, carry, carryin;
+
+ assert(len > 0);
+
+ BIG(--out;--in;);
+ carryin = *out;
+ mul16_ppmma(carry, *out, *in, k, carryin);
+ LITTLE(out++;in++;)
+
+ while (--len) {
+ BIG(--out;--in;);
+ carryin = carry;
+ mul16_ppmmaa(carry, prod, *in, k, carryin, *out);
+ *out = prod;
+ LITTLE(out++;in++;)
+ }
+
+ return carry;
+}
+#elif defined(BNWORD32)
+BNWORD16
+lbnMulAdd1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k)
+{
+ BNWORD32 p;
+
+ assert(len > 0);
+
+ p = (BNWORD32)BIGLITTLE(*--in,*in++) * k + BIGLITTLE(*--out,*out);
+ BIGLITTLE(*out,*out++) = (BNWORD16)p;
+
+ while (--len) {
+ p = (BNWORD32)BIGLITTLE(*--in,*in++) * k +
+ (BNWORD16)(p >> 16) + BIGLITTLE(*--out,*out);
+ BIGLITTLE(*out,*out++) = (BNWORD16)p;
+ }
+
+ return (BNWORD16)(p >> 16);
+}
+#else
+#error No 16x16 -> 32 multiply available for 16-bit bignum package
+#endif
+#endif /* lbnMulAdd1_16 */
+
+/*
+ * lbnMulSub1_16: Multiply an n-word input by a 1-word input and subtract the
+ * n-word product from the destination. Returns the n+1st word of the product.
+ * This uses either the mul16_ppmm and mul16_ppmma macros, or
+ * C multiplication with the BNWORD32 type.
+ *
+ * This is rather uglier than adding, but fortunately it's only used in
+ * division which is not used too heavily.
+ */
+#ifndef lbnMulN1_16
+#if defined(mul16_ppmm)
+BNWORD16
+lbnMulSub1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k)
+{
+ BNWORD16 prod, carry, carryin;
+
+ assert(len > 0);
+
+ BIG(--in;)
+ mul16_ppmm(carry, prod, *in, k);
+ LITTLE(in++;)
+ carry += (BIGLITTLE(*--out,*out++) -= prod) > (BNWORD16)~prod;
+
+ while (--len) {
+ BIG(--in;);
+ carryin = carry;
+ mul16_ppmma(carry, prod, *in, k, carryin);
+ LITTLE(in++;)
+ carry += (BIGLITTLE(*--out,*out++) -= prod) > (BNWORD16)~prod;
+ }
+
+ return carry;
+}
+#elif defined(BNWORD32)
+BNWORD16
+lbnMulSub1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k)
+{
+ BNWORD32 p;
+ BNWORD16 carry, t;
+
+ assert(len > 0);
+
+ p = (BNWORD32)BIGLITTLE(*--in,*in++) * k;
+ t = BIGLITTLE(*--out,*out);
+ carry = (BNWORD16)(p>>16) + ((BIGLITTLE(*out,*out++)=t-(BNWORD16)p) > t);
+
+ while (--len) {
+ p = (BNWORD32)BIGLITTLE(*--in,*in++) * k + carry;
+ t = BIGLITTLE(*--out,*out);
+ carry = (BNWORD16)(p>>16) +
+ ( (BIGLITTLE(*out,*out++)=t-(BNWORD16)p) > t );
+ }
+
+ return carry;
+}
+#else
+#error No 16x16 -> 32 multiply available for 16-bit bignum package
+#endif
+#endif /* !lbnMulSub1_16 */
+
+/*
+ * Shift n words left "shift" bits. 0 < shift < 16. Returns the
+ * carry, any bits shifted off the left-hand side (0 <= carry < 2^shift).
+ */
+#ifndef lbnLshift_16
+BNWORD16
+lbnLshift_16(BNWORD16 *num, unsigned len, unsigned shift)
+{
+ BNWORD16 x, carry;
+
+ assert(shift > 0);
+ assert(shift < 16);
+
+ carry = 0;
+ while (len--) {
+ BIG(--num;)
+ x = *num;
+ *num = (x<<shift) | carry;
+ LITTLE(num++;)
+ carry = x >> (16-shift);
+ }
+ return carry;
+}
+#endif /* !lbnLshift_16 */
+
+/*
+ * An optimized version of the above, for shifts of 1.
+ * Some machines can use add-with-carry tricks for this.
+ */
+#ifndef lbnDouble_16
+BNWORD16
+lbnDouble_16(BNWORD16 *num, unsigned len)
+{
+ BNWORD16 x, carry;
+
+ carry = 0;
+ while (len--) {
+ BIG(--num;)
+ x = *num;
+ *num = (x<<1) | carry;
+ LITTLE(num++;)
+ carry = x >> (16-1);
+ }
+ return carry;
+}
+#endif /* !lbnDouble_16 */
+
+/*
+ * Shift n words right "shift" bits. 0 < shift < 16. Returns the
+ * carry, any bits shifted off the right-hand side (0 <= carry < 2^shift).
+ */
+#ifndef lbnRshift_16
+BNWORD16
+lbnRshift_16(BNWORD16 *num, unsigned len, unsigned shift)
+{
+ BNWORD16 x, carry = 0;
+
+ assert(shift > 0);
+ assert(shift < 16);
+
+ BIGLITTLE(num -= len, num += len);
+
+ while (len--) {
+ LITTLE(--num;)
+ x = *num;
+ *num = (x>>shift) | carry;
+ BIG(num++;)
+ carry = x << (16-shift);
+ }
+ return carry >> (16-shift);
+}
+#endif /* !lbnRshift_16 */
+
+/*
+ * Multiply two numbers of the given lengths. prod and num2 may overlap,
+ * provided that the low len1 bits of prod are free. (This corresponds
+ * nicely to the place the result is returned from lbnMontReduce_16.)
+ *
+ * TODO: Use Karatsuba multiply. The overlap constraints may have
+ * to get rewhacked.
+ */
+#ifndef lbnMul_16
+void
+lbnMul_16(BNWORD16 *prod, BNWORD16 const *num1, unsigned len1,
+ BNWORD16 const *num2, unsigned len2)
+{
+ /* Special case of zero */
+ if (!len1 || !len2) {
+ lbnZero_16(prod, len1+len2);
+ return;
+ }
+
+ /* Multiply first word */
+ lbnMulN1_16(prod, num1, len1, BIGLITTLE(*--num2,*num2++));
+
+ /*
+ * Add in subsequent words, storing the most significant word,
+ * which is new each time.
+ */
+ while (--len2) {
+ BIGLITTLE(--prod,prod++);
+ BIGLITTLE(*(prod-len1-1),*(prod+len1)) =
+ lbnMulAdd1_16(prod, num1, len1, BIGLITTLE(*--num2,*num2++));
+ }
+}
+#endif /* !lbnMul_16 */
+
+/*
+ * lbnMulX_16 is a square multiply - both inputs are the same length.
+ * It's normally just a macro wrapper around the general multiply,
+ * but might be implementable in assembly more efficiently (such as
+ * when product scanning).
+ */
+#ifndef lbnMulX_16
+#if defined(BNWORD32) && PRODUCT_SCAN
+/*
+ * Test code to see whether product scanning is any faster. It seems
+ * to make the C code slower, so PRODUCT_SCAN is not defined.
+ */
+static void
+lbnMulX_16(BNWORD16 *prod, BNWORD16 const *num1, BNWORD16 const *num2,
+ unsigned len)
+{
+ BNWORD32 x, y;
+ BNWORD16 const *p1, *p2;
+ unsigned carry;
+ unsigned i, j;
+
+ /* Special case of zero */
+ if (!len)
+ return;
+
+ x = (BNWORD32)BIGLITTLE(num1[-1] * num2[-1], num1[0] * num2[0]);
+ BIGLITTLE(*--prod, *prod++) = (BNWORD16)x;
+ x >>= 16;
+
+ for (i = 1; i < len; i++) {
+ carry = 0;
+ p1 = num1;
+ p2 = BIGLITTLE(num2-i-1,num2+i+1);
+ for (j = 0; j <= i; j++) {
+ BIG(y = (BNWORD32)*--p1 * *p2++;)
+ LITTLE(y = (BNWORD32)*p1++ * *--p2;)
+ x += y;
+ carry += (x < y);
+ }
+ BIGLITTLE(*--prod,*prod++) = (BNWORD16)x;
+ x = (x >> 16) | (BNWORD32)carry << 16;
+ }
+ for (i = 1; i < len; i++) {
+ carry = 0;
+ p1 = BIGLITTLE(num1-i,num1+i);
+ p2 = BIGLITTLE(num2-len,num2+len);
+ for (j = i; j < len; j++) {
+ BIG(y = (BNWORD32)*--p1 * *p2++;)
+ LITTLE(y = (BNWORD32)*p1++ * *--p2;)
+ x += y;
+ carry += (x < y);
+ }
+ BIGLITTLE(*--prod,*prod++) = (BNWORD16)x;
+ x = (x >> 16) | (BNWORD32)carry << 16;
+ }
+
+ BIGLITTLE(*--prod,*prod) = (BNWORD16)x;
+}
+#else /* !defined(BNWORD32) || !PRODUCT_SCAN */
+/* Default trivial macro definition */
+#define lbnMulX_16(prod, num1, num2, len) lbnMul_16(prod, num1, len, num2, len)
+#endif /* !defined(BNWORD32) || !PRODUCT_SCAN */
+#endif /* !lbmMulX_16 */
+
+#if !defined(lbnMontMul_16) && defined(BNWORD32) && PRODUCT_SCAN
+/*
+ * Test code for product-scanning multiply. This seems to slow the C
+ * code down rather than speed it up.
+ * This does a multiply and Montgomery reduction together, using the
+ * same loops. The outer loop scans across the product, twice.
+ * The first pass computes the low half of the product and the
+ * Montgomery multipliers. These are stored in the product array,
+ * which contains no data as of yet. x and carry add up the columns
+ * and propagate carries forward.
+ *
+ * The second half multiplies the upper half, adding in the modulus
+ * times the Montgomery multipliers. The results of this multiply
+ * are stored.
+ */
+static void
+lbnMontMul_16(BNWORD16 *prod, BNWORD16 const *num1, BNWORD16 const *num2,
+ BNWORD16 const *mod, unsigned len, BNWORD16 inv)
+{
+ BNWORD32 x, y;
+ BNWORD16 const *p1, *p2, *pm;
+ BNWORD16 *pp;
+ BNWORD16 t;
+ unsigned carry;
+ unsigned i, j;
+
+ /* Special case of zero */
+ if (!len)
+ return;
+
+ /*
+ * This computes directly into the high half of prod, so just
+ * shift the pointer and consider prod only "len" elements long
+ * for the rest of the code.
+ */
+ BIGLITTLE(prod -= len, prod += len);
+
+ /* Pass 1 - compute Montgomery multipliers */
+ /* First iteration can have certain simplifications. */
+ x = (BNWORD32)BIGLITTLE(num1[-1] * num2[-1], num1[0] * num2[0]);
+ BIGLITTLE(prod[-1], prod[0]) = t = inv * (BNWORD16)x;
+ y = (BNWORD32)t * BIGLITTLE(mod[-1],mod[0]);
+ x += y;
+ /* Note: GCC 2.6.3 has a bug if you try to eliminate "carry" */
+ carry = (x < y);
+ assert((BNWORD16)x == 0);
+ x = x >> 16 | (BNWORD32)carry << 16;
+
+ for (i = 1; i < len; i++) {
+ carry = 0;
+ p1 = num1;
+ p2 = BIGLITTLE(num2-i-1,num2+i+1);
+ pp = prod;
+ pm = BIGLITTLE(mod-i-1,mod+i+1);
+ for (j = 0; j < i; j++) {
+ y = (BNWORD32)BIGLITTLE(*--p1 * *p2++, *p1++ * *--p2);
+ x += y;
+ carry += (x < y);
+ y = (BNWORD32)BIGLITTLE(*--pp * *pm++, *pp++ * *--pm);
+ x += y;
+ carry += (x < y);
+ }
+ y = (BNWORD32)BIGLITTLE(p1[-1] * p2[0], p1[0] * p2[-1]);
+ x += y;
+ carry += (x < y);
+ assert(BIGLITTLE(pp == prod-i, pp == prod+i));
+ BIGLITTLE(pp[-1], pp[0]) = t = inv * (BNWORD16)x;
+ assert(BIGLITTLE(pm == mod-1, pm == mod+1));
+ y = (BNWORD32)t * BIGLITTLE(pm[0],pm[-1]);
+ x += y;
+ carry += (x < y);
+ assert((BNWORD16)x == 0);
+ x = x >> 16 | (BNWORD32)carry << 16;
+ }
+
+ /* Pass 2 - compute reduced product and store */
+ for (i = 1; i < len; i++) {
+ carry = 0;
+ p1 = BIGLITTLE(num1-i,num1+i);
+ p2 = BIGLITTLE(num2-len,num2+len);
+ pm = BIGLITTLE(mod-i,mod+i);
+ pp = BIGLITTLE(prod-len,prod+len);
+ for (j = i; j < len; j++) {
+ y = (BNWORD32)BIGLITTLE(*--p1 * *p2++, *p1++ * *--p2);
+ x += y;
+ carry += (x < y);
+ y = (BNWORD32)BIGLITTLE(*--pm * *pp++, *pm++ * *--pp);
+ x += y;
+ carry += (x < y);
+ }
+ assert(BIGLITTLE(pm == mod-len, pm == mod+len));
+ assert(BIGLITTLE(pp == prod-i, pp == prod+i));
+ BIGLITTLE(pp[0],pp[-1]) = (BNWORD16)x;
+ x = (x >> 16) | (BNWORD32)carry << 16;
+ }
+
+ /* Last round of second half, simplified. */
+ BIGLITTLE(*(prod-len),*(prod+len-1)) = (BNWORD16)x;
+ carry = (x >> 16);
+
+ while (carry)
+ carry -= lbnSubN_16(prod, mod, len);
+ while (lbnCmp_16(prod, mod, len) >= 0)
+ (void)lbnSubN_16(prod, mod, len);
+}
+/* Suppress later definition */
+#define lbnMontMul_16 lbnMontMul_16
+#endif
+
+#if !defined(lbnSquare_16) && defined(BNWORD32) && PRODUCT_SCAN
+/*
+ * Trial code for product-scanning squaring. This seems to slow the C
+ * code down rather than speed it up.
+ */
+void
+lbnSquare_16(BNWORD16 *prod, BNWORD16 const *num, unsigned len)
+{
+ BNWORD32 x, y, z;
+ BNWORD16 const *p1, *p2;
+ unsigned carry;
+ unsigned i, j;
+
+ /* Special case of zero */
+ if (!len)
+ return;
+
+ /* Word 0 of product */
+ x = (BNWORD32)BIGLITTLE(num[-1] * num[-1], num[0] * num[0]);
+ BIGLITTLE(*--prod, *prod++) = (BNWORD16)x;
+ x >>= 16;
+
+ /* Words 1 through len-1 */
+ for (i = 1; i < len; i++) {
+ carry = 0;
+ y = 0;
+ p1 = num;
+ p2 = BIGLITTLE(num-i-1,num+i+1);
+ for (j = 0; j < (i+1)/2; j++) {
+ BIG(z = (BNWORD32)*--p1 * *p2++;)
+ LITTLE(z = (BNWORD32)*p1++ * *--p2;)
+ y += z;
+ carry += (y < z);
+ }
+ y += z = y;
+ carry += carry + (y < z);
+ if ((i & 1) == 0) {
+ assert(BIGLITTLE(--p1 == p2, p1 == --p2));
+ BIG(z = (BNWORD32)*p2 * *p2;)
+ LITTLE(z = (BNWORD32)*p1 * *p1;)
+ y += z;
+ carry += (y < z);
+ }
+ x += y;
+ carry += (x < y);
+ BIGLITTLE(*--prod,*prod++) = (BNWORD16)x;
+ x = (x >> 16) | (BNWORD32)carry << 16;
+ }
+ /* Words len through 2*len-2 */
+ for (i = 1; i < len; i++) {
+ carry = 0;
+ y = 0;
+ p1 = BIGLITTLE(num-i,num+i);
+ p2 = BIGLITTLE(num-len,num+len);
+ for (j = 0; j < (len-i)/2; j++) {
+ BIG(z = (BNWORD32)*--p1 * *p2++;)
+ LITTLE(z = (BNWORD32)*p1++ * *--p2;)
+ y += z;
+ carry += (y < z);
+ }
+ y += z = y;
+ carry += carry + (y < z);
+ if ((len-i) & 1) {
+ assert(BIGLITTLE(--p1 == p2, p1 == --p2));
+ BIG(z = (BNWORD32)*p2 * *p2;)
+ LITTLE(z = (BNWORD32)*p1 * *p1;)
+ y += z;
+ carry += (y < z);
+ }
+ x += y;
+ carry += (x < y);
+ BIGLITTLE(*--prod,*prod++) = (BNWORD16)x;
+ x = (x >> 16) | (BNWORD32)carry << 16;
+ }
+
+ /* Word 2*len-1 */
+ BIGLITTLE(*--prod,*prod) = (BNWORD16)x;
+}
+/* Suppress later definition */
+#define lbnSquare_16 lbnSquare_16
+#endif
+
+/*
+ * Square a number, using optimized squaring to reduce the number of
+ * primitive multiples that are executed. There may not be any
+ * overlap of the input and output.
+ *
+ * Technique: Consider the partial products in the multiplication
+ * of "abcde" by itself:
+ *
+ * a b c d e
+ * * a b c d e
+ * ==================
+ * ae be ce de ee
+ * ad bd cd dd de
+ * ac bc cc cd ce
+ * ab bb bc bd be
+ * aa ab ac ad ae
+ *
+ * Note that everything above the main diagonal:
+ * ae be ce de = (abcd) * e
+ * ad bd cd = (abc) * d
+ * ac bc = (ab) * c
+ * ab = (a) * b
+ *
+ * is a copy of everything below the main diagonal:
+ * de
+ * cd ce
+ * bc bd be
+ * ab ac ad ae
+ *
+ * Thus, the sum is 2 * (off the diagonal) + diagonal.
+ *
+ * This is accumulated beginning with the diagonal (which
+ * consist of the squares of the digits of the input), which is then
+ * divided by two, the off-diagonal added, and multiplied by two
+ * again. The low bit is simply a copy of the low bit of the
+ * input, so it doesn't need special care.
+ *
+ * TODO: Merge the shift by 1 with the squaring loop.
+ * TODO: Use Karatsuba. (a*W+b)^2 = a^2 * (W^2+W) + b^2 * (W+1) - (a-b)^2 * W.
+ */
+#ifndef lbnSquare_16
+void
+lbnSquare_16(BNWORD16 *prod, BNWORD16 const *num, unsigned len)
+{
+ BNWORD16 t;
+ BNWORD16 *prodx = prod; /* Working copy of the argument */
+ BNWORD16 const *numx = num; /* Working copy of the argument */
+ unsigned lenx = len; /* Working copy of the argument */
+
+ if (!len)
+ return;
+
+ /* First, store all the squares */
+ while (lenx--) {
+#ifdef mul16_ppmm
+ BNWORD16 ph, pl;
+ t = BIGLITTLE(*--numx,*numx++);
+ mul16_ppmm(ph,pl,t,t);
+ BIGLITTLE(*--prodx,*prodx++) = pl;
+ BIGLITTLE(*--prodx,*prodx++) = ph;
+#elif defined(BNWORD32) /* use BNWORD32 */
+ BNWORD32 p;
+ t = BIGLITTLE(*--numx,*numx++);
+ p = (BNWORD32)t * t;
+ BIGLITTLE(*--prodx,*prodx++) = (BNWORD16)p;
+ BIGLITTLE(*--prodx,*prodx++) = (BNWORD16)(p>>16);
+#else /* Use lbnMulN1_16 */
+ t = BIGLITTLE(numx[-1],*numx);
+ lbnMulN1_16(prodx, numx, 1, t);
+ BIGLITTLE(--numx,numx++);
+ BIGLITTLE(prodx -= 2, prodx += 2);
+#endif
+ }
+ /* Then, shift right 1 bit */
+ (void)lbnRshift_16(prod, 2*len, 1);
+
+ /* Then, add in the off-diagonal sums */
+ lenx = len;
+ numx = num;
+ prodx = prod;
+ while (--lenx) {
+ t = BIGLITTLE(*--numx,*numx++);
+ BIGLITTLE(--prodx,prodx++);
+ t = lbnMulAdd1_16(prodx, numx, lenx, t);
+ lbnAdd1_16(BIGLITTLE(prodx-lenx,prodx+lenx), lenx+1, t);
+ BIGLITTLE(--prodx,prodx++);
+ }
+
+ /* Shift it back up */
+ lbnDouble_16(prod, 2*len);
+
+ /* And set the low bit appropriately */
+ BIGLITTLE(prod[-1],prod[0]) |= BIGLITTLE(num[-1],num[0]) & 1;
+}
+#endif /* !lbnSquare_16 */
+
+/*
+ * lbnNorm_16 - given a number, return a modified length such that the
+ * most significant digit is non-zero. Zero-length input is okay.
+ */
+#ifndef lbnNorm_16
+unsigned
+lbnNorm_16(BNWORD16 const *num, unsigned len)
+{
+ BIGLITTLE(num -= len,num += len);
+ while (len && BIGLITTLE(*num++,*--num) == 0)
+ --len;
+ return len;
+}
+#endif /* lbnNorm_16 */
+
+/*
+ * lbnBits_16 - return the number of significant bits in the array.
+ * It starts by normalizing the array. Zero-length input is okay.
+ * Then assuming there's anything to it, it fetches the high word,
+ * generates a bit length by multiplying the word length by 16, and
+ * subtracts off 16/2, 16/4, 16/8, ... bits if the high bits are clear.
+ */
+#ifndef lbnBits_16
+unsigned
+lbnBits_16(BNWORD16 const *num, unsigned len)
+{
+ BNWORD16 t;
+ unsigned i;
+
+ len = lbnNorm_16(num, len);
+ if (len) {
+ t = BIGLITTLE(*(num-len),*(num+(len-1)));
+ assert(t);
+ len *= 16;
+ i = 16/2;
+ do {
+ if (t >> i)
+ t >>= i;
+ else
+ len -= i;
+ } while ((i /= 2) != 0);
+ }
+ return len;
+}
+#endif /* lbnBits_16 */
+
+/*
+ * If defined, use hand-rolled divide rather than compiler's native.
+ * If the machine doesn't do it in line, the manual code is probably
+ * faster, since it can assume normalization and the fact that the
+ * quotient will fit into 16 bits, which a general 32-bit divide
+ * in a compiler's run-time library can't do.
+ */
+#ifndef BN_SLOW_DIVIDE_32
+/* Assume that divisors of more than thirty-two bits are slow */
+#define BN_SLOW_DIVIDE_32 (32 > 0x20)
+#endif
+
+/*
+ * Return (nh<<16|nl) % d, and place the quotient digit into *q.
+ * It is guaranteed that nh < d, and that d is normalized (with its high
+ * bit set). If we have a double-width type, it's easy. If not, ooh,
+ * yuk!
+ */
+#ifndef lbnDiv21_16
+#if defined(BNWORD32) && !BN_SLOW_DIVIDE_32
+BNWORD16
+lbnDiv21_16(BNWORD16 *q, BNWORD16 nh, BNWORD16 nl, BNWORD16 d)
+{
+ BNWORD32 n = (BNWORD32)nh << 16 | nl;
+
+ /* Divisor must be normalized */
+ assert(d >> (16-1) == 1);
+
+ *q = (BNWORD16)(n / d);
+ return (BNWORD16)(n % d);
+}
+#else
+/*
+ * This is where it gets ugly.
+ *
+ * Do the division in two halves, using Algorithm D from section 4.3.1
+ * of Knuth. Note Theorem B from that section, that the quotient estimate
+ * is never more than the true quotient, and is never more than two
+ * too low.
+ *
+ * The mapping onto conventional long division is (everything a half word):
+ * _____________qh___ql_
+ * dh dl ) nh.h nh.l nl.h nl.l
+ * - (qh * d)
+ * -----------
+ * rrrr rrrr nl.l
+ * - (ql * d)
+ * -----------
+ * rrrr rrrr
+ *
+ * The implicit 3/2-digit d*qh and d*ql subtractors are computed this way:
+ * First, estimate a q digit so that nh/dh works. Subtracting qh*dh from
+ * the (nh.h nh.l) list leaves a 1/2-word remainder r. Then compute the
+ * low part of the subtractor, qh * dl. This also needs to be subtracted
+ * from (nh.h nh.l nl.h) to get the final remainder. So we take the
+ * remainder, which is (nh.h nh.l) - qh*dl, shift it and add in nl.h, and
+ * try to subtract qh * dl from that. Since the remainder is 1/2-word
+ * long, shifting and adding nl.h results in a single word r.
+ * It is possible that the remainder we're working with, r, is less than
+ * the product qh * dl, if we estimated qh too high. The estimation
+ * technique can produce a qh that is too large (never too small), leading
+ * to r which is too small. In that case, decrement the digit qh, add
+ * shifted dh to r (to correct for that error), and subtract dl from the
+ * product we're comparing r with. That's the "correct" way to do it, but
+ * just adding dl to r instead of subtracting it from the product is
+ * equivalent and a lot simpler. You just have to watch out for overflow.
+ *
+ * The process is repeated with (rrrr rrrr nl.l) for the low digit of the
+ * quotient ql.
+ *
+ * The various uses of 16/2 for shifts are because of the note about
+ * automatic editing of this file at the very top of the file.
+ */
+#define highhalf(x) ( (x) >> 16/2 )
+#define lowhalf(x) ( (x) & (((BNWORD16)1 << 16/2)-1) )
+BNWORD16
+lbnDiv21_16(BNWORD16 *q, BNWORD16 nh, BNWORD16 nl, BNWORD16 d)
+{
+ BNWORD16 dh = highhalf(d), dl = lowhalf(d);
+ BNWORD16 qh, ql, prod, r;
+
+ /* Divisor must be normalized */
+ assert((d >> (16-1)) == 1);
+
+ /* Do first half-word of division */
+ qh = nh / dh;
+ r = nh % dh;
+ prod = qh * dl;
+
+ /*
+ * Add next half-word of numerator to remainder and correct.
+ * qh may be up to two too large.
+ */
+ r = (r << (16/2)) | highhalf(nl);
+ if (r < prod) {
+ --qh; r += d;
+ if (r >= d && r < prod) {
+ --qh; r += d;
+ }
+ }
+ r -= prod;
+
+ /* Do second half-word of division */
+ ql = r / dh;
+ r = r % dh;
+ prod = ql * dl;
+
+ r = (r << (16/2)) | lowhalf(nl);
+ if (r < prod) {
+ --ql; r += d;
+ if (r >= d && r < prod) {
+ --ql; r += d;
+ }
+ }
+ r -= prod;
+
+ *q = (qh << (16/2)) | ql;
+
+ return r;
+}
+#endif
+#endif /* lbnDiv21_16 */
+
+
+/*
+ * In the division functions, the dividend and divisor are referred to
+ * as "n" and "d", which stand for "numerator" and "denominator".
+ *
+ * The quotient is (nlen-dlen+1) digits long. It may be overlapped with
+ * the high (nlen-dlen) words of the dividend, but one extra word is needed
+ * on top to hold the top word.
+ */
+
+/*
+ * Divide an n-word number by a 1-word number, storing the remainder
+ * and n-1 words of the n-word quotient. The high word is returned.
+ * It IS legal for rem to point to the same address as n, and for
+ * q to point one word higher.
+ *
+ * TODO: If BN_SLOW_DIVIDE_32, add a divnhalf_16 which uses 16-bit
+ * dividends if the divisor is half that long.
+ * TODO: Shift the dividend on the fly to avoid the last division and
+ * instead have a remainder that needs shifting.
+ * TODO: Use reciprocals rather than dividing.
+ */
+#ifndef lbnDiv1_16
+BNWORD16
+lbnDiv1_16(BNWORD16 *q, BNWORD16 *rem, BNWORD16 const *n, unsigned len,
+ BNWORD16 d)
+{
+ unsigned shift;
+ unsigned xlen;
+ BNWORD16 r;
+ BNWORD16 qhigh;
+
+ assert(len > 0);
+ assert(d);
+
+ if (len == 1) {
+ r = *n;
+ *rem = r%d;
+ return r/d;
+ }
+
+ shift = 0;
+ r = d;
+ xlen = 16/2;
+ do {
+ if (r >> xlen)
+ r >>= xlen;
+ else
+ shift += xlen;
+ } while ((xlen /= 2) != 0);
+ assert((d >> (16-1-shift)) == 1);
+ d <<= shift;
+
+ BIGLITTLE(q -= len-1,q += len-1);
+ BIGLITTLE(n -= len,n += len);
+
+ r = BIGLITTLE(*n++,*--n);
+ if (r < d) {
+ qhigh = 0;
+ } else {
+ qhigh = r/d;
+ r %= d;
+ }
+
+ xlen = len;
+ while (--xlen)
+ r = lbnDiv21_16(BIGLITTLE(q++,--q), r, BIGLITTLE(*n++,*--n), d);
+
+ /*
+ * Final correction for shift - shift the quotient up "shift"
+ * bits, and merge in the extra bits of quotient. Then reduce
+ * the final remainder mod the real d.
+ */
+ if (shift) {
+ d >>= shift;
+ qhigh = (qhigh << shift) | lbnLshift_16(q, len-1, shift);
+ BIGLITTLE(q[-1],*q) |= r/d;
+ r %= d;
+ }
+ *rem = r;
+
+ return qhigh;
+}
+#endif
+
+/*
+ * This function performs a "quick" modulus of a number with a divisor
+ * d which is guaranteed to be at most sixteen bits, i.e. less than 65536.
+ * This applies regardless of the word size the library is compiled with.
+ *
+ * This function is important to prime generation, for sieving.
+ */
+#ifndef lbnModQ_16
+/* If there's a custom lbnMod21_16, no normalization needed */
+#ifdef lbnMod21_16
+unsigned
+lbnModQ_16(BNWORD16 const *n, unsigned len, unsigned d)
+{
+ unsigned i, shift;
+ BNWORD16 r;
+
+ assert(len > 0);
+
+ BIGLITTLE(n -= len,n += len);
+
+ /* Try using a compare to avoid the first divide */
+ r = BIGLITTLE(*n++,*--n);
+ if (r >= d)
+ r %= d;
+ while (--len)
+ r = lbnMod21_16(r, BIGLITTLE(*n++,*--n), d);
+
+ return r;
+}
+#elif defined(BNWORD32) && !BN_SLOW_DIVIDE_32
+unsigned
+lbnModQ_16(BNWORD16 const *n, unsigned len, unsigned d)
+{
+ BNWORD16 r;
+
+ if (!--len)
+ return BIGLITTLE(n[-1],n[0]) % d;
+
+ BIGLITTLE(n -= len,n += len);
+ r = BIGLITTLE(n[-1],n[0]);
+
+ do {
+ r = (BNWORD16)((((BNWORD32)r<<16) | BIGLITTLE(*n++,*--n)) % d);
+ } while (--len);
+
+ return r;
+}
+#elif 16 >= 0x20
+/*
+ * If the single word size can hold 65535*65536, then this function
+ * is avilable.
+ */
+#ifndef highhalf
+#define highhalf(x) ( (x) >> 16/2 )
+#define lowhalf(x) ( (x) & ((1 << 16/2)-1) )
+#endif
+unsigned
+lbnModQ_16(BNWORD16 const *n, unsigned len, unsigned d)
+{
+ BNWORD16 r, x;
+
+ BIGLITTLE(n -= len,n += len);
+
+ r = BIGLITTLE(*n++,*--n);
+ while (--len) {
+ x = BIGLITTLE(*n++,*--n);
+ r = (r%d << 16/2) | highhalf(x);
+ r = (r%d << 16/2) | lowhalf(x);
+ }
+
+ return r%d;
+}
+#else
+/* Default case - use lbnDiv21_16 */
+unsigned
+lbnModQ_16(BNWORD16 const *n, unsigned len, unsigned d)
+{
+ unsigned i, shift;
+ BNWORD16 r;
+ BNWORD16 q;
+
+ assert(len > 0);
+
+ shift = 0;
+ r = d;
+ i = 16;
+ while (i /= 2) {
+ if (r >> i)
+ r >>= i;
+ else
+ shift += i;
+ }
+ assert(d >> (16-1-shift) == 1);
+ d <<= shift;
+
+ BIGLITTLE(n -= len,n += len);
+
+ r = BIGLITTLE(*n++,*--n);
+ if (r >= d)
+ r %= d;
+
+ while (--len)
+ r = lbnDiv21_16(&q, r, BIGLITTLE(*n++,*--n), d);
+
+ /*
+ * Final correction for shift - shift the quotient up "shift"
+ * bits, and merge in the extra bits of quotient. Then reduce
+ * the final remainder mod the real d.
+ */
+ if (shift)
+ r %= d >> shift;
+
+ return r;
+}
+#endif
+#endif /* lbnModQ_16 */
+
+/*
+ * Reduce n mod d and return the quotient. That is, find:
+ * q = n / d;
+ * n = n % d;
+ * d is altered during the execution of this subroutine by normalizing it.
+ * It must already have its most significant word non-zero; it is shifted
+ * so its most significant bit is non-zero.
+ *
+ * The quotient q is nlen-dlen+1 words long. To make it possible to
+ * overlap the quptient with the input (you can store it in the high dlen
+ * words), the high word of the quotient is *not* stored, but is returned.
+ * (If all you want is the remainder, you don't care about it, anyway.)
+ *
+ * This uses algorithm D from Knuth (4.3.1), except that we do binary
+ * (shift) normalization of the divisor. WARNING: This is hairy!
+ *
+ * This function is used for some modular reduction, but it is not used in
+ * the modular exponentiation loops; they use Montgomery form and the
+ * corresponding, more efficient, Montgomery reduction. This code
+ * is needed for the conversion to Montgomery form, however, so it
+ * has to be here and it might as well be reasonably efficient.
+ *
+ * The overall operation is as follows ("top" and "up" refer to the
+ * most significant end of the number; "bottom" and "down", the least):
+ *
+ * - Shift the divisor up until the most significant bit is set.
+ * - Shift the dividend up the same amount. This will produce the
+ * correct quotient, and the remainder can be recovered by shifting
+ * it back down the same number of bits. This may produce an overflow
+ * word, but the word is always strictly less than the most significant
+ * divisor word.
+ * - Estimate the first quotient digit qhat:
+ * - First take the top two words (one of which is the overflow) of the
+ * dividend and divide by the top word of the divisor:
+ * qhat = (nh,nm)/dh. This qhat is >= the correct quotient digit
+ * and, since dh is normalized, it is at most two over.
+ * - Second, correct by comparing the top three words. If
+ * (dh,dl) * qhat > (nh,nm,ml), decrease qhat and try again.
+ * The second iteration can be simpler because there can't be a third.
+ * The computation can be simplified by subtracting dh*qhat from
+ * both sides, suitably shifted. This reduces the left side to
+ * dl*qhat. On the right, (nh,nm)-dh*qhat is simply the
+ * remainder r from (nh,nm)%dh, so the right is (r,nl).
+ * This produces qhat that is almost always correct and at
+ * most (prob ~ 2/2^16) one too high.
+ * - Subtract qhat times the divisor (suitably shifted) from the dividend.
+ * If there is a borrow, qhat was wrong, so decrement it
+ * and add the divisor back in (once).
+ * - Store the final quotient digit qhat in the quotient array q.
+ *
+ * Repeat the quotient digit computation for successive digits of the
+ * quotient until the whole quotient has been computed. Then shift the
+ * divisor and the remainder down to correct for the normalization.
+ *
+ * TODO: Special case 2-word divisors.
+ * TODO: Use reciprocals rather than dividing.
+ */
+#ifndef divn_16
+BNWORD16
+lbnDiv_16(BNWORD16 *q, BNWORD16 *n, unsigned nlen, BNWORD16 *d, unsigned dlen)
+{
+ BNWORD16 nh,nm,nl; /* Top three words of the dividend */
+ BNWORD16 dh,dl; /* Top two words of the divisor */
+ BNWORD16 qhat; /* Extimate of quotient word */
+ BNWORD16 r; /* Remainder from quotient estimate division */
+ BNWORD16 qhigh; /* High word of quotient */
+ unsigned i; /* Temp */
+ unsigned shift; /* Bits shifted by normalization */
+ unsigned qlen = nlen-dlen; /* Size of quotient (less 1) */
+#ifdef mul16_ppmm
+ BNWORD16 t16;
+#elif defined(BNWORD32)
+ BNWORD32 t32;
+#else /* use lbnMulN1_16 */
+ BNWORD16 t2[2];
+#define t2high BIGLITTLE(t2[0],t2[1])
+#define t2low BIGLITTLE(t2[1],t2[0])
+#endif
+
+ assert(dlen);
+ assert(nlen >= dlen);
+
+ /*
+ * Special cases for short divisors. The general case uses the
+ * top top 2 digits of the divisor (d) to estimate a quotient digit,
+ * so it breaks if there are fewer digits available. Thus, we need
+ * special cases for a divisor of length 1. A divisor of length
+ * 2 can have a *lot* of administrivia overhead removed removed,
+ * so it's probably worth special-casing that case, too.
+ */
+ if (dlen == 1)
+ return lbnDiv1_16(q, BIGLITTLE(n-1,n), n, nlen,
+ BIGLITTLE(d[-1],d[0]));
+
+#if 0
+ /*
+ * @@@ This is not yet written... The general loop will do,
+ * albeit less efficiently
+ */
+ if (dlen == 2) {
+ /*
+ * divisor two digits long:
+ * use the 3/2 technique from Knuth, but we know
+ * it's exact.
+ */
+ dh = BIGLITTLE(d[-1],d[0]);
+ dl = BIGLITTLE(d[-2],d[1]);
+ shift = 0;
+ if ((sh & ((BNWORD16)1 << 16-1-shift)) == 0) {
+ do {
+ shift++;
+ } while (dh & (BNWORD16)1<<16-1-shift) == 0);
+ dh = dh << shift | dl >> (16-shift);
+ dl <<= shift;
+
+
+ }
+
+
+ for (shift = 0; (dh & (BNWORD16)1 << 16-1-shift)) == 0; shift++)
+ ;
+ if (shift) {
+ }
+ dh = dh << shift | dl >> (16-shift);
+ shift = 0;
+ while (dh
+ }
+#endif
+
+ dh = BIGLITTLE(*(d-dlen),*(d+(dlen-1)));
+ assert(dh);
+
+ /* Normalize the divisor */
+ shift = 0;
+ r = dh;
+ i = 16/2;
+ do {
+ if (r >> i)
+ r >>= i;
+ else
+ shift += i;
+ } while ((i /= 2) != 0);
+
+ nh = 0;
+ if (shift) {
+ lbnLshift_16(d, dlen, shift);
+ dh = BIGLITTLE(*(d-dlen),*(d+(dlen-1)));
+ nh = lbnLshift_16(n, nlen, shift);
+ }
+
+ /* Assert that dh is now normalized */
+ assert(dh >> (16-1));
+
+ /* Also get the second-most significant word of the divisor */
+ dl = BIGLITTLE(*(d-(dlen-1)),*(d+(dlen-2)));
+
+ /*
+ * Adjust pointers: n to point to least significant end of first
+ * first subtract, and q to one the most-significant end of the
+ * quotient array.
+ */
+ BIGLITTLE(n -= qlen,n += qlen);
+ BIGLITTLE(q -= qlen,q += qlen);
+
+ /* Fetch the most significant stored word of the dividend */
+ nm = BIGLITTLE(*(n-dlen),*(n+(dlen-1)));
+
+ /*
+ * Compute the first digit of the quotient, based on the
+ * first two words of the dividend (the most significant of which
+ * is the overflow word h).
+ */
+ if (nh) {
+ assert(nh < dh);
+ r = lbnDiv21_16(&qhat, nh, nm, dh);
+ } else if (nm >= dh) {
+ qhat = nm/dh;
+ r = nm % dh;
+ } else { /* Quotient is zero */
+ qhigh = 0;
+ goto divloop;
+ }
+
+ /* Now get the third most significant word of the dividend */
+ nl = BIGLITTLE(*(n-(dlen-1)),*(n+(dlen-2)));
+
+ /*
+ * Correct qhat, the estimate of quotient digit.
+ * qhat can only be high, and at most two words high,
+ * so the loop can be unrolled and abbreviated.
+ */
+#ifdef mul16_ppmm
+ mul16_ppmm(nm, t16, qhat, dl);
+ if (nm > r || (nm == r && t16 > nl)) {
+ /* Decrement qhat and adjust comparison parameters */
+ qhat--;
+ if ((r += dh) >= dh) {
+ nm -= (t16 < dl);
+ t16 -= dl;
+ if (nm > r || (nm == r && t16 > nl))
+ qhat--;
+ }
+ }
+#elif defined(BNWORD32)
+ t32 = (BNWORD32)qhat * dl;
+ if (t32 > ((BNWORD32)r << 16) + nl) {
+ /* Decrement qhat and adjust comparison parameters */
+ qhat--;
+ if ((r += dh) > dh) {
+ t32 -= dl;
+ if (t32 > ((BNWORD32)r << 16) + nl)
+ qhat--;
+ }
+ }
+#else /* Use lbnMulN1_16 */
+ lbnMulN1_16(BIGLITTLE(t2+2,t2), &dl, 1, qhat);
+ if (t2high > r || (t2high == r && t2low > nl)) {
+ /* Decrement qhat and adjust comparison parameters */
+ qhat--;
+ if ((r += dh) >= dh) {
+ t2high -= (t2low < dl);
+ t2low -= dl;
+ if (t2high > r || (t2high == r && t2low > nl))
+ qhat--;
+ }
+ }
+#endif
+
+ /* Do the multiply and subtract */
+ r = lbnMulSub1_16(n, d, dlen, qhat);
+ /* If there was a borrow, add back once. */
+ if (r > nh) { /* Borrow? */
+ (void)lbnAddN_16(n, d, dlen);
+ qhat--;
+ }
+
+ /* Remember the first quotient digit. */
+ qhigh = qhat;
+
+ /* Now, the main division loop: */
+divloop:
+ while (qlen--) {
+
+ /* Advance n */
+ nh = BIGLITTLE(*(n-dlen),*(n+(dlen-1)));
+ BIGLITTLE(++n,--n);
+ nm = BIGLITTLE(*(n-dlen),*(n+(dlen-1)));
+
+ if (nh == dh) {
+ qhat = ~(BNWORD16)0;
+ /* Optimized computation of r = (nh,nm) - qhat * dh */
+ r = nh + nm;
+ if (r < nh)
+ goto subtract;
+ } else {
+ assert(nh < dh);
+ r = lbnDiv21_16(&qhat, nh, nm, dh);
+ }
+
+ nl = BIGLITTLE(*(n-(dlen-1)),*(n+(dlen-2)));
+#ifdef mul16_ppmm
+ mul16_ppmm(nm, t16, qhat, dl);
+ if (nm > r || (nm == r && t16 > nl)) {
+ /* Decrement qhat and adjust comparison parameters */
+ qhat--;
+ if ((r += dh) >= dh) {
+ nm -= (t16 < dl);
+ t16 -= dl;
+ if (nm > r || (nm == r && t16 > nl))
+ qhat--;
+ }
+ }
+#elif defined(BNWORD32)
+ t32 = (BNWORD32)qhat * dl;
+ if (t32 > ((BNWORD32)r<<16) + nl) {
+ /* Decrement qhat and adjust comparison parameters */
+ qhat--;
+ if ((r += dh) >= dh) {
+ t32 -= dl;
+ if (t32 > ((BNWORD32)r << 16) + nl)
+ qhat--;
+ }
+ }
+#else /* Use lbnMulN1_16 */
+ lbnMulN1_16(BIGLITTLE(t2+2,t2), &dl, 1, qhat);
+ if (t2high > r || (t2high == r && t2low > nl)) {
+ /* Decrement qhat and adjust comparison parameters */
+ qhat--;
+ if ((r += dh) >= dh) {
+ t2high -= (t2low < dl);
+ t2low -= dl;
+ if (t2high > r || (t2high == r && t2low > nl))
+ qhat--;
+ }
+ }
+#endif
+
+ /*
+ * As a point of interest, note that it is not worth checking
+ * for qhat of 0 or 1 and installing special-case code. These
+ * occur with probability 2^-16, so spending 1 cycle to check
+ * for them is only worth it if we save more than 2^15 cycles,
+ * and a multiply-and-subtract for numbers in the 1024-bit
+ * range just doesn't take that long.
+ */
+subtract:
+ /*
+ * n points to the least significant end of the substring
+ * of n to be subtracted from. qhat is either exact or
+ * one too large. If the subtract gets a borrow, it was
+ * one too large and the divisor is added back in. It's
+ * a dlen+1 word add which is guaranteed to produce a
+ * carry out, so it can be done very simply.
+ */
+ r = lbnMulSub1_16(n, d, dlen, qhat);
+ if (r > nh) { /* Borrow? */
+ (void)lbnAddN_16(n, d, dlen);
+ qhat--;
+ }
+ /* Store the quotient digit */
+ BIGLITTLE(*q++,*--q) = qhat;
+ }
+ /* Tah dah! */
+
+ if (shift) {
+ lbnRshift_16(d, dlen, shift);
+ lbnRshift_16(n, dlen, shift);
+ }
+
+ return qhigh;
+}
+#endif
+
+/*
+ * Find the negative multiplicative inverse of x (x must be odd!) modulo 2^16.
+ *
+ * This just performs Newton's iteration until it gets the
+ * inverse. The initial estimate is always correct to 3 bits, and
+ * sometimes 4. The number of valid bits doubles each iteration.
+ * (To prove it, assume x * y == 1 (mod 2^n), and introduce a variable
+ * for the error mod 2^2n. x * y == 1 + k*2^n (mod 2^2n) and follow
+ * the iteration through.)
+ */
+#ifndef lbnMontInv1_16
+BNWORD16
+lbnMontInv1_16(BNWORD16 const x)
+{
+ BNWORD16 y = x, z;
+
+ assert(x & 1);
+
+ while ((z = x*y) != 1)
+ y *= 2 - z;
+ return -y;
+}
+#endif /* !lbnMontInv1_16 */
+
+#if defined(BNWORD32) && PRODUCT_SCAN
+/*
+ * Test code for product-scanning Montgomery reduction.
+ * This seems to slow the C code down rather than speed it up.
+ *
+ * The first loop computes the Montgomery multipliers, storing them over
+ * the low half of the number n.
+ *
+ * The second half multiplies the upper half, adding in the modulus
+ * times the Montgomery multipliers. The results of this multiply
+ * are stored.
+ */
+void
+lbnMontReduce_16(BNWORD16 *n, BNWORD16 const *mod, unsigned mlen, BNWORD16 inv)
+{
+ BNWORD32 x, y;
+ BNWORD16 const *pm;
+ BNWORD16 *pn;
+ BNWORD16 t;
+ unsigned carry;
+ unsigned i, j;
+
+ /* Special case of zero */
+ if (!mlen)
+ return;
+
+ /* Pass 1 - compute Montgomery multipliers */
+ /* First iteration can have certain simplifications. */
+ t = BIGLITTLE(n[-1],n[0]);
+ x = t;
+ t *= inv;
+ BIGLITTLE(n[-1], n[0]) = t;
+ x += (BNWORD32)t * BIGLITTLE(mod[-1],mod[0]); /* Can't overflow */
+ assert((BNWORD16)x == 0);
+ x = x >> 16;
+
+ for (i = 1; i < mlen; i++) {
+ carry = 0;
+ pn = n;
+ pm = BIGLITTLE(mod-i-1,mod+i+1);
+ for (j = 0; j < i; j++) {
+ y = (BNWORD32)BIGLITTLE(*--pn * *pm++, *pn++ * *--pm);
+ x += y;
+ carry += (x < y);
+ }
+ assert(BIGLITTLE(pn == n-i, pn == n+i));
+ y = t = BIGLITTLE(pn[-1], pn[0]);
+ x += y;
+ carry += (x < y);
+ BIGLITTLE(pn[-1], pn[0]) = t = inv * (BNWORD16)x;
+ assert(BIGLITTLE(pm == mod-1, pm == mod+1));
+ y = (BNWORD32)t * BIGLITTLE(pm[0],pm[-1]);
+ x += y;
+ carry += (x < y);
+ assert((BNWORD16)x == 0);
+ x = x >> 16 | (BNWORD32)carry << 16;
+ }
+
+ BIGLITTLE(n -= mlen, n += mlen);
+
+ /* Pass 2 - compute upper words and add to n */
+ for (i = 1; i < mlen; i++) {
+ carry = 0;
+ pm = BIGLITTLE(mod-i,mod+i);
+ pn = n;
+ for (j = i; j < mlen; j++) {
+ y = (BNWORD32)BIGLITTLE(*--pm * *pn++, *pm++ * *--pn);
+ x += y;
+ carry += (x < y);
+ }
+ assert(BIGLITTLE(pm == mod-mlen, pm == mod+mlen));
+ assert(BIGLITTLE(pn == n+mlen-i, pn == n-mlen+i));
+ y = t = BIGLITTLE(*(n-i),*(n+i-1));
+ x += y;
+ carry += (x < y);
+ BIGLITTLE(*(n-i),*(n+i-1)) = (BNWORD16)x;
+ x = (x >> 16) | (BNWORD32)carry << 16;
+ }
+
+ /* Last round of second half, simplified. */
+ t = BIGLITTLE(*(n-mlen),*(n+mlen-1));
+ x += t;
+ BIGLITTLE(*(n-mlen),*(n+mlen-1)) = (BNWORD16)x;
+ carry = (unsigned)(x >> 16);
+
+ while (carry)
+ carry -= lbnSubN_16(n, mod, mlen);
+ while (lbnCmp_16(n, mod, mlen) >= 0)
+ (void)lbnSubN_16(n, mod, mlen);
+}
+#define lbnMontReduce_16 lbnMontReduce_16
+#endif
+
+/*
+ * Montgomery reduce n, modulo mod. This reduces modulo mod and divides by
+ * 2^(16*mlen). Returns the result in the *top* mlen words of the argument n.
+ * This is ready for another multiplication using lbnMul_16.
+ *
+ * Montgomery representation is a very useful way to encode numbers when
+ * you're doing lots of modular reduction. What you do is pick a multiplier
+ * R which is relatively prime to the modulus and very easy to divide by.
+ * Since the modulus is odd, R is closen as a power of 2, so the division
+ * is a shift. In fact, it's a shift of an integral number of words,
+ * so the shift can be implicit - just drop the low-order words.
+ *
+ * Now, choose R *larger* than the modulus m, 2^(16*mlen). Then convert
+ * all numbers a, b, etc. to Montgomery form M(a), M(b), etc using the
+ * relationship M(a) = a*R mod m, M(b) = b*R mod m, etc. Note that:
+ * - The Montgomery form of a number depends on the modulus m.
+ * A fixed modulus m is assumed throughout this discussion.
+ * - Since R is relaitvely prime to m, multiplication by R is invertible;
+ * no information about the numbers is lost, they're just scrambled.
+ * - Adding (and subtracting) numbers in this form works just as usual.
+ * M(a+b) = (a+b)*R mod m = (a*R + b*R) mod m = (M(a) + M(b)) mod m
+ * - Multiplying numbers in this form produces a*b*R*R. The problem
+ * is to divide out the excess factor of R, modulo m as well as to
+ * reduce to the given length mlen. It turns out that this can be
+ * done *faster* than a normal divide, which is where the speedup
+ * in Montgomery division comes from.
+ *
+ * Normal reduction chooses a most-significant quotient digit q and then
+ * subtracts q*m from the number to be reduced. Choosing q is tricky
+ * and involved (just look at lbnDiv_16 to see!) and is usually
+ * imperfect, requiring a check for correction after the subtraction.
+ *
+ * Montgomery reduction *adds* a multiple of m to the *low-order* part
+ * of the number to be reduced. This multiple is chosen to make the
+ * low-order part of the number come out to zero. This can be done
+ * with no trickery or error using a precomputed inverse of the modulus.
+ * In this code, the "part" is one word, but any width can be used.
+ *
+ * Repeating this step sufficiently often results in a value which
+ * is a multiple of R (a power of two, remember) but is still (since
+ * the additions were to the low-order part and thus did not increase
+ * the value of the number being reduced very much) still not much
+ * larger than m*R. Then implicitly divide by R and subtract off
+ * m until the result is in the correct range.
+ *
+ * Since the low-order part being cancelled is less than R, the
+ * multiple of m added must have a multiplier which is at most R-1.
+ * Assuming that the input is at most m*R-1, the final number is
+ * at most m*(2*R-1)-1 = 2*m*R - m - 1, so subtracting m once from
+ * the high-order part, equivalent to subtracting m*R from the
+ * while number, produces a result which is at most m*R - m - 1,
+ * which divided by R is at most m-1.
+ *
+ * To convert *to* Montgomery form, you need a regular remainder
+ * routine, although you can just compute R*R (mod m) and do the
+ * conversion using Montgomery multiplication. To convert *from*
+ * Montgomery form, just Montgomery reduce the number to
+ * remove the extra factor of R.
+ *
+ * TODO: Change to a full inverse and use Karatsuba's multiplication
+ * rather than this word-at-a-time.
+ */
+#ifndef lbnMontReduce_16
+void
+lbnMontReduce_16(BNWORD16 *n, BNWORD16 const *mod, unsigned const mlen,
+ BNWORD16 inv)
+{
+ BNWORD16 t;
+ BNWORD16 c = 0;
+ unsigned len = mlen;
+
+ /* inv must be the negative inverse of mod's least significant word */
+ assert((BNWORD16)(inv * BIGLITTLE(mod[-1],mod[0])) == (BNWORD16)-1);
+
+ assert(len);
+
+ do {
+ t = lbnMulAdd1_16(n, mod, mlen, (BNWORD16)(inv * BIGLITTLE(n[-1],n[0])));
+ c += lbnAdd1_16(BIGLITTLE(n-mlen,n+mlen), len, t);
+ BIGLITTLE(--n,++n);
+ } while (--len);
+
+ /*
+ * All that adding can cause an overflow past the modulus size,
+ * but it's unusual, and never by much, so a subtraction loop
+ * is the right way to deal with it.
+ * This subtraction happens infrequently - I've only ever seen it
+ * invoked once per reduction, and then just under 22.5% of the time.
+ */
+ while (c)
+ c -= lbnSubN_16(n, mod, mlen);
+ while (lbnCmp_16(n, mod, mlen) >= 0)
+ (void)lbnSubN_16(n, mod, mlen);
+}
+#endif /* !lbnMontReduce_16 */
+
+/*
+ * A couple of helpers that you might want to implement atomically
+ * in asm sometime.
+ */
+#ifndef lbnMontMul_16
+/*
+ * Multiply "num1" by "num2", modulo "mod", all of length "len", and
+ * place the result in the high half of "prod". "inv" is the inverse
+ * of the least-significant word of the modulus, modulo 2^16.
+ * This uses numbers in Montgomery form. Reduce using "len" and "inv".
+ *
+ * This is implemented as a macro to win on compilers that don't do
+ * inlining, since it's so trivial.
+ */
+#define lbnMontMul_16(prod, n1, n2, mod, len, inv) \
+ (lbnMulX_16(prod, n1, n2, len), lbnMontReduce_16(prod, mod, len, inv))
+#endif /* !lbnMontMul_16 */
+
+#ifndef lbnMontSquare_16
+/*
+ * Square "num", modulo "mod", both of length "len", and place the result
+ * in the high half of "prod". "inv" is the inverse of the least-significant
+ * word of the modulus, modulo 2^16.
+ * This uses numbers in Montgomery form. Reduce using "len" and "inv".
+ *
+ * This is implemented as a macro to win on compilers that don't do
+ * inlining, since it's so trivial.
+ */
+#define lbnMontSquare_16(prod, n, mod, len, inv) \
+ (lbnSquare_16(prod, n, len), lbnMontReduce_16(prod, mod, len, inv))
+
+#endif /* !lbnMontSquare_16 */
+
+/*
+ * Convert a number to Montgomery form - requires mlen + nlen words
+ * of memory in "n".
+ */
+void
+lbnToMont_16(BNWORD16 *n, unsigned nlen, BNWORD16 *mod, unsigned mlen)
+{
+ /* Move n up "mlen" words */
+ lbnCopy_16(BIGLITTLE(n-mlen,n+mlen), n, nlen);
+ lbnZero_16(n, mlen);
+ /* Do the division - dump the quotient in the high-order words */
+ (void)lbnDiv_16(BIGLITTLE(n-mlen,n+mlen), n, mlen+nlen, mod, mlen);
+}
+
+/*
+ * Convert from Montgomery form. Montgomery reduction is all that is
+ * needed.
+ */
+void
+lbnFromMont_16(BNWORD16 *n, BNWORD16 *mod, unsigned len)
+{
+ /* Zero the high words of n */
+ lbnZero_16(BIGLITTLE(n-len,n+len), len);
+ lbnMontReduce_16(n, mod, len, lbnMontInv1_16(BIGLITTLE(mod[-1],mod[0])));
+ /* Move n down len words */
+ lbnCopy_16(n, BIGLITTLE(n-len,n+len), len);
+}
+
+/*
+ * The windowed exponentiation algorithm, precomputes a table of odd
+ * powers of n up to 2^k. It takes 2^(k-1)-1 multiplies to compute
+ * the table, and (e-1)/(k+1) multiplies (on average) to perform the
+ * exponentiation. To minimize the sum, k must vary with e.
+ * The optimal window sizes vary with the exponent length. Here are
+ * some selected values and the boundary cases.
+ * (An underscore _ has been inserted into some of the numbers to ensure
+ * that magic strings like 16 do not appear in this table. It should be
+ * ignored.)
+ *
+ * At e = 1 bits, k=1 (0.000000) is best.
+ * At e = 2 bits, k=1 (0.500000) is best.
+ * At e = 4 bits, k=1 (1.500000) is best.
+ * At e = 8 bits, k=2 (3.333333) < k=1 (3.500000)
+ * At e = 1_6 bits, k=2 (6.000000) is best.
+ * At e = 26 bits, k=3 (9.250000) < k=2 (9.333333)
+ * At e = 3_2 bits, k=3 (10.750000) is best.
+ * At e = 6_4 bits, k=3 (18.750000) is best.
+ * At e = 82 bits, k=4 (23.200000) < k=3 (23.250000)
+ * At e = 128 bits, k=4 (3_2.400000) is best.
+ * At e = 242 bits, k=5 (55.1_66667) < k=4 (55.200000)
+ * At e = 256 bits, k=5 (57.500000) is best.
+ * At e = 512 bits, k=5 (100.1_66667) is best.
+ * At e = 674 bits, k=6 (127.142857) < k=5 (127.1_66667)
+ * At e = 1024 bits, k=6 (177.142857) is best.
+ * At e = 1794 bits, k=7 (287.125000) < k=6 (287.142857)
+ * At e = 2048 bits, k=7 (318.875000) is best.
+ * At e = 4096 bits, k=7 (574.875000) is best.
+ *
+ * The numbers in parentheses are the expected number of multiplications
+ * needed to do the computation. The normal russian-peasant modular
+ * exponentiation technique always uses (e-1)/2. For exponents as
+ * small as 192 bits (below the range of current factoring algorithms),
+ * half of the multiplies are eliminated, 45.2 as opposed to the naive
+ * 95.5. Counting the 191 squarings as 3/4 a multiply each (squaring
+ * proper is just over half of multiplying, but the Montgomery
+ * reduction in each case is also a multiply), that's 143.25
+ * multiplies, for totals of 188.45 vs. 238.75 - a 21% savings.
+ * For larger exponents (like 512 bits), it's 483.92 vs. 639.25, a
+ * 24.3% savings. It asymptotically approaches 25%.
+ *
+ * Given that exponents for which k>7 are useful are uncommon,
+ * a fixed size table for k <= 7 is used for simplicity.
+ * k = 8 is uzeful at 4610 bits, k = 9 at 11522 bits.
+ *
+ * The basic number of squarings needed is e-1, although a k-bit
+ * window (for k > 1) can save, on average, k-2 of those, too.
+ * That savings currently isn't counted here. It would drive the
+ * crossover points slightly lower.
+ * (Actually, this win is also reduced in the DoubleExpMod case,
+ * meaning we'd have to split the tables. Except for that, the
+ * multiplies by powers of the two bases are independent, so
+ * the same logic applies to each as the single case.)
+ *
+ * Table entry i is the largest number of bits in an exponent to
+ * process with a window size of i+1. So the window never goes above 7
+ * bits, requiring 2^(7-1) = 0x40 precomputed multiples.
+ */
+#define BNEXPMOD_MAX_WINDOW 7
+static unsigned const bnExpModThreshTable[BNEXPMOD_MAX_WINDOW] = {
+ 7, 25, 81, 241, 673, 1793, (unsigned)-1
+};
+
+/*
+ * Perform modular exponentiation, as fast as possible! This uses
+ * Montgomery reduction, optimized squaring, and windowed exponentiation.
+ * The modulus "mod" MUST be odd!
+ *
+ * This returns 0 on success, -1 on out of memory.
+ *
+ * The window algorithm:
+ * The idea is to keep a running product of b1 = n^(high-order bits of exp),
+ * and then keep appending exponent bits to it. The following patterns
+ * apply to a 3-bit window (k = 3):
+ * To append 0: square
+ * To append 1: square, multiply by n^1
+ * To append 10: square, multiply by n^1, square
+ * To append 11: square, square, multiply by n^3
+ * To append 100: square, multiply by n^1, square, square
+ * To append 101: square, square, square, multiply by n^5
+ * To append 110: square, square, multiply by n^3, square
+ * To append 111: square, square, square, multiply by n^7
+ *
+ * Since each pattern involves only one multiply, the longer the pattern
+ * the better, except that a 0 (no multiplies) can be appended directly.
+ * We precompute a table of odd powers of n, up to 2^k, and can then
+ * multiply k bits of exponent at a time. Actually, assuming random
+ * exponents, there is on average one zero bit between needs to
+ * multiply (1/2 of the time there's none, 1/4 of the time there's 1,
+ * 1/8 of the time, there's 2, 1/16 of the time, there's 3, etc.), so
+ * you have to do one multiply per k+1 bits of exponent.
+ *
+ * The loop walks down the exponent, squaring the result buffer as
+ * it goes. There is a wbits+1 bit lookahead buffer, buf, that is
+ * filled with the upcoming exponent bits. (What is read after the
+ * end of the exponent is unimportant, but it is filled with zero here.)
+ * When the most-significant bit of this buffer becomes set, i.e.
+ * (buf & tblmask) != 0, we have to decide what pattern to multiply
+ * by, and when to do it. We decide, remember to do it in future
+ * after a suitable number of squarings have passed (e.g. a pattern
+ * of "100" in the buffer requires that we multiply by n^1 immediately;
+ * a pattern of "110" calls for multiplying by n^3 after one more
+ * squaring), clear the buffer, and continue.
+ *
+ * When we start, there is one more optimization: the result buffer
+ * is implcitly one, so squaring it or multiplying by it can be
+ * optimized away. Further, if we start with a pattern like "100"
+ * in the lookahead window, rather than placing n into the buffer
+ * and then starting to square it, we have already computed n^2
+ * to compute the odd-powers table, so we can place that into
+ * the buffer and save a squaring.
+ *
+ * This means that if you have a k-bit window, to compute n^z,
+ * where z is the high k bits of the exponent, 1/2 of the time
+ * it requires no squarings. 1/4 of the time, it requires 1
+ * squaring, ... 1/2^(k-1) of the time, it reqires k-2 squarings.
+ * And the remaining 1/2^(k-1) of the time, the top k bits are a
+ * 1 followed by k-1 0 bits, so it again only requires k-2
+ * squarings, not k-1. The average of these is 1. Add that
+ * to the one squaring we have to do to compute the table,
+ * and you'll see that a k-bit window saves k-2 squarings
+ * as well as reducing the multiplies. (It actually doesn't
+ * hurt in the case k = 1, either.)
+ *
+ * n must have mlen words allocated. Although fewer may be in use
+ * when n is passed in, all are in use on exit.
+ */
+int
+lbnExpMod_16(BNWORD16 *result, BNWORD16 const *n, unsigned nlen,
+ BNWORD16 const *e, unsigned elen, BNWORD16 *mod, unsigned mlen)
+{
+ BNWORD16 *table[1 << (BNEXPMOD_MAX_WINDOW-1)];
+ /* Table of odd powers of n */
+ unsigned ebits; /* Exponent bits */
+ unsigned wbits; /* Window size */
+ unsigned tblmask; /* Mask of exponentiation window */
+ BNWORD16 bitpos; /* Mask of current look-ahead bit */
+ unsigned buf; /* Buffer of exponent bits */
+ unsigned multpos; /* Where to do pending multiply */
+ BNWORD16 const *mult; /* What to multiply by */
+ unsigned i; /* Loop counter */
+ int isone; /* Flag: accum. is implicitly one */
+ BNWORD16 *a, *b; /* Working buffers/accumulators */
+ BNWORD16 *t; /* Pointer into the working buffers */
+ BNWORD16 inv; /* mod^-1 modulo 2^16 */
+
+ assert(mlen);
+ assert(nlen <= mlen);
+
+ /* First, a couple of trivial cases. */
+ elen = lbnNorm_16(e, elen);
+ if (!elen) {
+ /* x ^ 0 == 1 */
+ lbnZero_16(result, mlen);
+ BIGLITTLE(result[-1],result[0]) = 1;
+ return 0;
+ }
+ ebits = lbnBits_16(e, elen);
+ if (ebits == 1) {
+ /* x ^ 1 == x */
+ if (n != result)
+ lbnCopy_16(result, n, nlen);
+ if (mlen > nlen)
+ lbnZero_16(BIGLITTLE(result-nlen,result+nlen),
+ mlen-nlen);
+ return 0;
+ }
+
+ /* Okay, now move the exponent pointer to the most-significant word */
+ e = BIGLITTLE(e-elen, e+elen-1);
+
+ /* Look up appropriate k-1 for the exponent - tblmask = 1<<(k-1) */
+ wbits = 0;
+ while (ebits > bnExpModThreshTable[wbits])
+ wbits++;
+
+ /* Allocate working storage: two product buffers and the tables. */
+ LBNALLOC(a, 2*mlen);
+ if (!a)
+ return -1;
+ LBNALLOC(b, 2*mlen);
+ if (!b) {
+ LBNFREE(a, 2*mlen);
+ return -1;
+ }
+
+ /* Convert to the appropriate table size: tblmask = 1<<(k-1) */
+ tblmask = 1u << wbits;
+
+ /* We have the result buffer available, so use it. */
+ table[0] = result;
+
+ /*
+ * Okay, we now have a minimal-sized table - expand it.
+ * This is allowed to fail! If so, scale back the table size
+ * and proceed.
+ */
+ for (i = 1; i < tblmask; i++) {
+ LBNALLOC(t, mlen);
+ if (!t) /* Out of memory! Quit the loop. */
+ break;
+ table[i] = t;
+ }
+
+ /* If we stopped, with i < tblmask, shrink the tables appropriately */
+ while (tblmask > i) {
+ wbits--;
+ tblmask >>= 1;
+ }
+ /* Free up our overallocations */
+ while (--i > tblmask)
+ LBNFREE(table[i], mlen);
+
+ /* Okay, fill in the table */
+
+ /* Compute the necessary modular inverse */
+ inv = lbnMontInv1_16(mod[BIGLITTLE(-1,0)]); /* LSW of modulus */
+
+ /* Convert n to Montgomery form */
+
+ /* Move n up "mlen" words into a */
+ t = BIGLITTLE(a-mlen, a+mlen);
+ lbnCopy_16(t, n, nlen);
+ lbnZero_16(a, mlen);
+ /* Do the division - lose the quotient into the high-order words */
+ (void)lbnDiv_16(t, a, mlen+nlen, mod, mlen);
+ /* Copy into first table entry */
+ lbnCopy_16(table[0], a, mlen);
+
+ /* Square a into b */
+ lbnMontSquare_16(b, a, mod, mlen, inv);
+
+ /* Use high half of b to initialize the table */
+ t = BIGLITTLE(b-mlen, b+mlen);
+ for (i = 1; i < tblmask; i++) {
+ lbnMontMul_16(a, t, table[i-1], mod, mlen, inv);
+ lbnCopy_16(table[i], BIGLITTLE(a-mlen, a+mlen), mlen);
+ }
+
+ /* We might use b = n^2 later... */
+
+ /* Initialze the fetch pointer */
+ bitpos = (BNWORD16)1 << ((ebits-1) & (16-1)); /* Initialize mask */
+
+ /* This should point to the msbit of e */
+ assert((*e & bitpos) != 0);
+
+ /*
+ * Pre-load the window. Becuase the window size is
+ * never larger than the exponent size, there is no need to
+ * detect running off the end of e in here.
+ *
+ * The read-ahead is controlled by elen and the bitpos mask.
+ * Note that this is *ahead* of ebits, which tracks the
+ * most significant end of the window. The purpose of this
+ * initialization is to get the two wbits+1 bits apart,
+ * like they should be.
+ *
+ * Note that bitpos and e1len together keep track of the
+ * lookahead read pointer in the exponent that is used here.
+ */
+ buf = 0;
+ for (i = 0; i <= wbits; i++) {
+ buf = (buf << 1) | ((*e & bitpos) != 0);
+ bitpos >>= 1;
+ if (!bitpos) {
+ BIGLITTLE(e++,e--);
+ bitpos = (BNWORD16)1 << (16-1);
+ elen--;
+ }
+ }
+ assert(buf & tblmask);
+
+ /*
+ * Set the pending multiply positions to a location that will
+ * never be encountered, thus ensuring that nothing will happen
+ * until the need for a multiply appears and one is scheduled.
+ */
+ multpos = ebits; /* A NULL value */
+ mult = 0; /* Force a crash if we use these */
+
+ /*
+ * Okay, now begins the real work. The first step is
+ * slightly magic, so it's done outside the main loop,
+ * but it's very similar to what's inside.
+ */
+ ebits--; /* Start processing the first bit... */
+ isone = 1;
+
+ /*
+ * This is just like the multiply in the loop, except that
+ * - We know the msbit of buf is set, and
+ * - We have the extra value n^2 floating around.
+ * So, do the usual computation, and if the result is that
+ * the buffer should be multiplied by n^1 immediately
+ * (which we'd normally then square), we multiply it
+ * (which reduces to a copy, which reduces to setting a flag)
+ * by n^2 and skip the squaring. Thus, we do the
+ * multiply and the squaring in one step.
+ */
+ assert(buf & tblmask);
+ multpos = ebits - wbits;
+ while ((buf & 1) == 0) {
+ buf >>= 1;
+ multpos++;
+ }
+ /* Intermediates can wrap, but final must NOT */
+ assert(multpos <= ebits);
+ mult = table[buf>>1];
+ buf = 0;
+
+ /* Special case: use already-computed value sitting in buffer */
+ if (multpos == ebits)
+ isone = 0;
+
+ /*
+ * At this point, the buffer (which is the high half of b) holds
+ * either 1 (implicitly, as the "isone" flag is set), or n^2.
+ */
+
+ /*
+ * The main loop. The procedure is:
+ * - Advance the window
+ * - If the most-significant bit of the window is set,
+ * schedule a multiply for the appropriate time in the
+ * future (may be immediately)
+ * - Perform any pending multiples
+ * - Check for termination
+ * - Square the buffer
+ *
+ * At any given time, the acumulated product is held in
+ * the high half of b.
+ */
+ for (;;) {
+ ebits--;
+
+ /* Advance the window */
+ assert(buf < tblmask);
+ buf <<= 1;
+ /*
+ * This reads ahead of the current exponent position
+ * (controlled by ebits), so we have to be able to read
+ * past the lsb of the exponents without error.
+ */
+ if (elen) {
+ buf |= ((*e & bitpos) != 0);
+ bitpos >>= 1;
+ if (!bitpos) {
+ BIGLITTLE(e++,e--);
+ bitpos = (BNWORD16)1 << (16-1);
+ elen--;
+ }
+ }
+
+ /* Examine the window for pending multiplies */
+ if (buf & tblmask) {
+ multpos = ebits - wbits;
+ while ((buf & 1) == 0) {
+ buf >>= 1;
+ multpos++;
+ }
+ /* Intermediates can wrap, but final must NOT */
+ assert(multpos <= ebits);
+ mult = table[buf>>1];
+ buf = 0;
+ }
+
+ /* If we have a pending multiply, do it */
+ if (ebits == multpos) {
+ /* Multiply by the table entry remembered previously */
+ t = BIGLITTLE(b-mlen, b+mlen);
+ if (isone) {
+ /* Multiply by 1 is a trivial case */
+ lbnCopy_16(t, mult, mlen);
+ isone = 0;
+ } else {
+ lbnMontMul_16(a, t, mult, mod, mlen, inv);
+ /* Swap a and b */
+ t = a; a = b; b = t;
+ }
+ }
+
+ /* Are we done? */
+ if (!ebits)
+ break;
+
+ /* Square the input */
+ if (!isone) {
+ t = BIGLITTLE(b-mlen, b+mlen);
+ lbnMontSquare_16(a, t, mod, mlen, inv);
+ /* Swap a and b */
+ t = a; a = b; b = t;
+ }
+ } /* for (;;) */
+
+ assert(!isone);
+ assert(!buf);
+
+ /* DONE! */
+
+ /* Convert result out of Montgomery form */
+ t = BIGLITTLE(b-mlen, b+mlen);
+ lbnCopy_16(b, t, mlen);
+ lbnZero_16(t, mlen);
+ lbnMontReduce_16(b, mod, mlen, inv);
+ lbnCopy_16(result, t, mlen);
+ /*
+ * Clean up - free intermediate storage.
+ * Do NOT free table[0], which is the result
+ * buffer.
+ */
+ while (--tblmask)
+ LBNFREE(table[tblmask], mlen);
+ LBNFREE(b, 2*mlen);
+ LBNFREE(a, 2*mlen);
+
+ return 0; /* Success */
+}
+
+/*
+ * Compute and return n1^e1 * n2^e2 mod "mod".
+ * result may be either input buffer, or something separate.
+ * It must be "mlen" words long.
+ *
+ * There is a current position in the exponents, which is kept in e1bits.
+ * (The exponents are swapped if necessary so e1 is the longer of the two.)
+ * At any given time, the value in the accumulator is
+ * n1^(e1>>e1bits) * n2^(e2>>e1bits) mod "mod".
+ * As e1bits is counted down, this is updated, by squaring it and doing
+ * any necessary multiplies.
+ * To decide on the necessary multiplies, two windows, each w1bits+1 bits
+ * wide, are maintained in buf1 and buf2, which read *ahead* of the
+ * e1bits position (with appropriate handling of the case when e1bits
+ * drops below w1bits+1). When the most-significant bit of either window
+ * becomes set, indicating that something needs to be multiplied by
+ * the accumulator or it will get out of sync, the window is examined
+ * to see which power of n1 or n2 to multiply by, and when (possibly
+ * later, if the power is greater than 1) the multiply should take
+ * place. Then the multiply and its location are remembered and the
+ * window is cleared.
+ *
+ * If we had every power of n1 in the table, the multiply would always
+ * be w1bits steps in the future. But we only keep the odd powers,
+ * so instead of waiting w1bits squarings and then multiplying
+ * by n1^k, we wait w1bits-k squarings and multiply by n1.
+ *
+ * Actually, w2bits can be less than w1bits, but the window is the same
+ * size, to make it easier to keep track of where we're reading. The
+ * appropriate number of low-order bits of the window are just ignored.
+ */
+int
+lbnDoubleExpMod_16(BNWORD16 *result,
+ BNWORD16 const *n1, unsigned n1len,
+ BNWORD16 const *e1, unsigned e1len,
+ BNWORD16 const *n2, unsigned n2len,
+ BNWORD16 const *e2, unsigned e2len,
+ BNWORD16 *mod, unsigned mlen)
+{
+ BNWORD16 *table1[1 << (BNEXPMOD_MAX_WINDOW-1)];
+ /* Table of odd powers of n1 */
+ BNWORD16 *table2[1 << (BNEXPMOD_MAX_WINDOW-1)];
+ /* Table of odd powers of n2 */
+ unsigned e1bits, e2bits; /* Exponent bits */
+ unsigned w1bits, w2bits; /* Window sizes */
+ unsigned tblmask; /* Mask of exponentiation window */
+ BNWORD16 bitpos; /* Mask of current look-ahead bit */
+ unsigned buf1, buf2; /* Buffer of exponent bits */
+ unsigned mult1pos, mult2pos; /* Where to do pending multiply */
+ BNWORD16 const *mult1, *mult2; /* What to multiply by */
+ unsigned i; /* Loop counter */
+ int isone; /* Flag: accum. is implicitly one */
+ BNWORD16 *a, *b; /* Working buffers/accumulators */
+ const BNWORD16 *ct; /* Temp pointer */
+ BNWORD16 *t; /* Pointer into the working buffers */
+ BNWORD16 inv; /* mod^-1 modulo 2^16 */
+
+ assert(mlen);
+ assert(n1len <= mlen);
+ assert(n2len <= mlen);
+
+ /* First, a couple of trivial cases. */
+ e1len = lbnNorm_16(e1, e1len);
+ e2len = lbnNorm_16(e2, e2len);
+
+ /* Ensure that the first exponent is the longer */
+ e1bits = lbnBits_16(e1, e1len);
+ e2bits = lbnBits_16(e2, e2len);
+ if (e1bits < e2bits) {
+ i = e1len; e1len = e2len; e2len = i;
+ i = e1bits; e1bits = e2bits; e2bits = i;
+ ct = (const BNWORD16 *)n1; n1 = n2; n2 = ct;
+ ct = (const BNWORD16 *)e1; e1 = e2; e2 = ct;
+ }
+ assert(e1bits >= e2bits);
+
+ /* Handle a trivial case */
+ if (!e2len)
+ return lbnExpMod_16(result, n1, n1len, e1, e1len, mod, mlen);
+ assert(e2bits);
+
+ /* The code below breaks if the exponents aren't at least 2 bits */
+ if (e1bits == 1) {
+ assert(e2bits == 1);
+
+ LBNALLOC(a, n1len+n2len);
+ if (!a)
+ return -1;
+
+ lbnMul_16(a, n1, n1len, n2, n2len);
+ /* Do a direct modular reduction */
+ if (n1len + n2len >= mlen)
+ (void)lbnDiv_16(a+mlen, a, n1len+n2len, mod, mlen);
+ lbnCopy_16(result, a, mlen);
+ LBNFREE(a, n1len+n2len);
+ return 0;
+ }
+
+ /* Okay, now move the exponent pointers to the most-significant word */
+ e1 = BIGLITTLE(e1-e1len, e1+e1len-1);
+ e2 = BIGLITTLE(e2-e2len, e2+e2len-1);
+
+ /* Look up appropriate k-1 for the exponent - tblmask = 1<<(k-1) */
+ w1bits = 0;
+ while (e1bits > bnExpModThreshTable[w1bits])
+ w1bits++;
+ w2bits = 0;
+ while (e2bits > bnExpModThreshTable[w2bits])
+ w2bits++;
+
+ assert(w1bits >= w2bits);
+
+ /* Allocate working storage: two product buffers and the tables. */
+ LBNALLOC(a, 2*mlen);
+ if (!a)
+ return -1;
+ LBNALLOC(b, 2*mlen);
+ if (!b) {
+ LBNFREE(a, 2*mlen);
+ return -1;
+ }
+
+ /* Convert to the appropriate table size: tblmask = 1<<(k-1) */
+ tblmask = 1u << w1bits;
+ /* Use buf2 for its size, temporarily */
+ buf2 = 1u << w2bits;
+
+ LBNALLOC(t, mlen);
+ if (!t) {
+ LBNFREE(b, 2*mlen);
+ LBNFREE(a, 2*mlen);
+ return -1;
+ }
+ table1[0] = t;
+ table2[0] = result;
+
+ /*
+ * Okay, we now have some minimal-sized tables - expand them.
+ * This is allowed to fail! If so, scale back the table sizes
+ * and proceed. We allocate both tables at the same time
+ * so if it fails partway through, they'll both be a reasonable
+ * size rather than one huge and one tiny.
+ * When i passes buf2 (the number of entries in the e2 window,
+ * which may be less than the number of entries in the e1 window),
+ * stop allocating e2 space.
+ */
+ for (i = 1; i < tblmask; i++) {
+ LBNALLOC(t, mlen);
+ if (!t) /* Out of memory! Quit the loop. */
+ break;
+ table1[i] = t;
+ if (i < buf2) {
+ LBNALLOC(t, mlen);
+ if (!t) {
+ LBNFREE(table1[i], mlen);
+ break;
+ }
+ table2[i] = t;
+ }
+ }
+
+ /* If we stopped, with i < tblmask, shrink the tables appropriately */
+ while (tblmask > i) {
+ w1bits--;
+ tblmask >>= 1;
+ }
+ /* Free up our overallocations */
+ while (--i > tblmask) {
+ if (i < buf2)
+ LBNFREE(table2[i], mlen);
+ LBNFREE(table1[i], mlen);
+ }
+ /* And shrink the second window too, if needed */
+ if (w2bits > w1bits) {
+ w2bits = w1bits;
+ buf2 = tblmask;
+ }
+
+ /*
+ * From now on, use the w2bits variable for the difference
+ * between w1bits and w2bits.
+ */
+ w2bits = w1bits-w2bits;
+
+ /* Okay, fill in the tables */
+
+ /* Compute the necessary modular inverse */
+ inv = lbnMontInv1_16(mod[BIGLITTLE(-1,0)]); /* LSW of modulus */
+
+ /* Convert n1 to Montgomery form */
+
+ /* Move n1 up "mlen" words into a */
+ t = BIGLITTLE(a-mlen, a+mlen);
+ lbnCopy_16(t, n1, n1len);
+ lbnZero_16(a, mlen);
+ /* Do the division - lose the quotient into the high-order words */
+ (void)lbnDiv_16(t, a, mlen+n1len, mod, mlen);
+ /* Copy into first table entry */
+ lbnCopy_16(table1[0], a, mlen);
+
+ /* Square a into b */
+ lbnMontSquare_16(b, a, mod, mlen, inv);
+
+ /* Use high half of b to initialize the first table */
+ t = BIGLITTLE(b-mlen, b+mlen);
+ for (i = 1; i < tblmask; i++) {
+ lbnMontMul_16(a, t, table1[i-1], mod, mlen, inv);
+ lbnCopy_16(table1[i], BIGLITTLE(a-mlen, a+mlen), mlen);
+ }
+
+ /* Convert n2 to Montgomery form */
+
+ t = BIGLITTLE(a-mlen, a+mlen);
+ /* Move n2 up "mlen" words into a */
+ lbnCopy_16(t, n2, n2len);
+ lbnZero_16(a, mlen);
+ /* Do the division - lose the quotient into the high-order words */
+ (void)lbnDiv_16(t, a, mlen+n2len, mod, mlen);
+ /* Copy into first table entry */
+ lbnCopy_16(table2[0], a, mlen);
+
+ /* Square it into a */
+ lbnMontSquare_16(a, table2[0], mod, mlen, inv);
+ /* Copy to b, low half */
+ lbnCopy_16(b, t, mlen);
+
+ /* Use b to initialize the second table */
+ for (i = 1; i < buf2; i++) {
+ lbnMontMul_16(a, b, table2[i-1], mod, mlen, inv);
+ lbnCopy_16(table2[i], t, mlen);
+ }
+
+ /*
+ * Okay, a recap: at this point, the low part of b holds
+ * n2^2, the high part holds n1^2, and the tables are
+ * initialized with the odd powers of n1 and n2 from 1
+ * through 2*tblmask-1 and 2*buf2-1.
+ *
+ * We might use those squares in b later, or we might not.
+ */
+
+ /* Initialze the fetch pointer */
+ bitpos = (BNWORD16)1 << ((e1bits-1) & (16-1)); /* Initialize mask */
+
+ /* This should point to the msbit of e1 */
+ assert((*e1 & bitpos) != 0);
+
+ /*
+ * Pre-load the windows. Becuase the window size is
+ * never larger than the exponent size, there is no need to
+ * detect running off the end of e1 in here.
+ *
+ * The read-ahead is controlled by e1len and the bitpos mask.
+ * Note that this is *ahead* of e1bits, which tracks the
+ * most significant end of the window. The purpose of this
+ * initialization is to get the two w1bits+1 bits apart,
+ * like they should be.
+ *
+ * Note that bitpos and e1len together keep track of the
+ * lookahead read pointer in the exponent that is used here.
+ * e2len is not decremented, it is only ever compared with
+ * e1len as *that* is decremented.
+ */
+ buf1 = buf2 = 0;
+ for (i = 0; i <= w1bits; i++) {
+ buf1 = (buf1 << 1) | ((*e1 & bitpos) != 0);
+ if (e1len <= e2len)
+ buf2 = (buf2 << 1) | ((*e2 & bitpos) != 0);
+ bitpos >>= 1;
+ if (!bitpos) {
+ BIGLITTLE(e1++,e1--);
+ if (e1len <= e2len)
+ BIGLITTLE(e2++,e2--);
+ bitpos = (BNWORD16)1 << (16-1);
+ e1len--;
+ }
+ }
+ assert(buf1 & tblmask);
+
+ /*
+ * Set the pending multiply positions to a location that will
+ * never be encountered, thus ensuring that nothing will happen
+ * until the need for a multiply appears and one is scheduled.
+ */
+ mult1pos = mult2pos = e1bits; /* A NULL value */
+ mult1 = mult2 = 0; /* Force a crash if we use these */
+
+ /*
+ * Okay, now begins the real work. The first step is
+ * slightly magic, so it's done outside the main loop,
+ * but it's very similar to what's inside.
+ */
+ isone = 1; /* Buffer is implicitly 1, so replace * by copy */
+ e1bits--; /* Start processing the first bit... */
+
+ /*
+ * This is just like the multiply in the loop, except that
+ * - We know the msbit of buf1 is set, and
+ * - We have the extra value n1^2 floating around.
+ * So, do the usual computation, and if the result is that
+ * the buffer should be multiplied by n1^1 immediately
+ * (which we'd normally then square), we multiply it
+ * (which reduces to a copy, which reduces to setting a flag)
+ * by n1^2 and skip the squaring. Thus, we do the
+ * multiply and the squaring in one step.
+ */
+ assert(buf1 & tblmask);
+ mult1pos = e1bits - w1bits;
+ while ((buf1 & 1) == 0) {
+ buf1 >>= 1;
+ mult1pos++;
+ }
+ /* Intermediates can wrap, but final must NOT */
+ assert(mult1pos <= e1bits);
+ mult1 = table1[buf1>>1];
+ buf1 = 0;
+
+ /* Special case: use already-computed value sitting in buffer */
+ if (mult1pos == e1bits)
+ isone = 0;
+
+ /*
+ * The first multiply by a power of n2. Similar, but
+ * we might not even want to schedule a multiply if e2 is
+ * shorter than e1, and the window might be shorter so
+ * we have to leave the low w2bits bits alone.
+ */
+ if (buf2 & tblmask) {
+ /* Remember low-order bits for later */
+ i = buf2 & ((1u << w2bits) - 1);
+ buf2 >>= w2bits;
+ mult2pos = e1bits - w1bits + w2bits;
+ while ((buf2 & 1) == 0) {
+ buf2 >>= 1;
+ mult2pos++;
+ }
+ assert(mult2pos <= e1bits);
+ mult2 = table2[buf2>>1];
+ buf2 = i;
+
+ if (mult2pos == e1bits) {
+ t = BIGLITTLE(b-mlen, b+mlen);
+ if (isone) {
+ lbnCopy_16(t, b, mlen); /* Copy low to high */
+ isone = 0;
+ } else {
+ lbnMontMul_16(a, t, b, mod, mlen, inv);
+ t = a; a = b; b = t;
+ }
+ }
+ }
+
+ /*
+ * At this point, the buffer (which is the high half of b)
+ * holds either 1 (implicitly, as the "isone" flag is set),
+ * n1^2, n2^2 or n1^2 * n2^2.
+ */
+
+ /*
+ * The main loop. The procedure is:
+ * - Advance the windows
+ * - If the most-significant bit of a window is set,
+ * schedule a multiply for the appropriate time in the
+ * future (may be immediately)
+ * - Perform any pending multiples
+ * - Check for termination
+ * - Square the buffers
+ *
+ * At any given time, the acumulated product is held in
+ * the high half of b.
+ */
+ for (;;) {
+ e1bits--;
+
+ /* Advance the windows */
+ assert(buf1 < tblmask);
+ buf1 <<= 1;
+ assert(buf2 < tblmask);
+ buf2 <<= 1;
+ /*
+ * This reads ahead of the current exponent position
+ * (controlled by e1bits), so we have to be able to read
+ * past the lsb of the exponents without error.
+ */
+ if (e1len) {
+ buf1 |= ((*e1 & bitpos) != 0);
+ if (e1len <= e2len)
+ buf2 |= ((*e2 & bitpos) != 0);
+ bitpos >>= 1;
+ if (!bitpos) {
+ BIGLITTLE(e1++,e1--);
+ if (e1len <= e2len)
+ BIGLITTLE(e2++,e2--);
+ bitpos = (BNWORD16)1 << (16-1);
+ e1len--;
+ }
+ }
+
+ /* Examine the first window for pending multiplies */
+ if (buf1 & tblmask) {
+ mult1pos = e1bits - w1bits;
+ while ((buf1 & 1) == 0) {
+ buf1 >>= 1;
+ mult1pos++;
+ }
+ /* Intermediates can wrap, but final must NOT */
+ assert(mult1pos <= e1bits);
+ mult1 = table1[buf1>>1];
+ buf1 = 0;
+ }
+
+ /*
+ * Examine the second window for pending multiplies.
+ * Window 2 can be smaller than window 1, but we
+ * keep the same number of bits in buf2, so we need
+ * to ignore any low-order bits in the buffer when
+ * computing what to multiply by, and recompute them
+ * later.
+ */
+ if (buf2 & tblmask) {
+ /* Remember low-order bits for later */
+ i = buf2 & ((1u << w2bits) - 1);
+ buf2 >>= w2bits;
+ mult2pos = e1bits - w1bits + w2bits;
+ while ((buf2 & 1) == 0) {
+ buf2 >>= 1;
+ mult2pos++;
+ }
+ assert(mult2pos <= e1bits);
+ mult2 = table2[buf2>>1];
+ buf2 = i;
+ }
+
+
+ /* If we have a pending multiply for e1, do it */
+ if (e1bits == mult1pos) {
+ /* Multiply by the table entry remembered previously */
+ t = BIGLITTLE(b-mlen, b+mlen);
+ if (isone) {
+ /* Multiply by 1 is a trivial case */
+ lbnCopy_16(t, mult1, mlen);
+ isone = 0;
+ } else {
+ lbnMontMul_16(a, t, mult1, mod, mlen, inv);
+ /* Swap a and b */
+ t = a; a = b; b = t;
+ }
+ }
+
+ /* If we have a pending multiply for e2, do it */
+ if (e1bits == mult2pos) {
+ /* Multiply by the table entry remembered previously */
+ t = BIGLITTLE(b-mlen, b+mlen);
+ if (isone) {
+ /* Multiply by 1 is a trivial case */
+ lbnCopy_16(t, mult2, mlen);
+ isone = 0;
+ } else {
+ lbnMontMul_16(a, t, mult2, mod, mlen, inv);
+ /* Swap a and b */
+ t = a; a = b; b = t;
+ }
+ }
+
+ /* Are we done? */
+ if (!e1bits)
+ break;
+
+ /* Square the buffer */
+ if (!isone) {
+ t = BIGLITTLE(b-mlen, b+mlen);
+ lbnMontSquare_16(a, t, mod, mlen, inv);
+ /* Swap a and b */
+ t = a; a = b; b = t;
+ }
+ } /* for (;;) */
+
+ assert(!isone);
+ assert(!buf1);
+ assert(!buf2);
+
+ /* DONE! */
+
+ /* Convert result out of Montgomery form */
+ t = BIGLITTLE(b-mlen, b+mlen);
+ lbnCopy_16(b, t, mlen);
+ lbnZero_16(t, mlen);
+ lbnMontReduce_16(b, mod, mlen, inv);
+ lbnCopy_16(result, t, mlen);
+
+ /* Clean up - free intermediate storage */
+ buf2 = tblmask >> w2bits;
+ while (--tblmask) {
+ if (tblmask < buf2)
+ LBNFREE(table2[tblmask], mlen);
+ LBNFREE(table1[tblmask], mlen);
+ }
+ t = table1[0];
+ LBNFREE(t, mlen);
+ LBNFREE(b, 2*mlen);
+ LBNFREE(a, 2*mlen);
+
+ return 0; /* Success */
+}
+
+/*
+ * 2^exp (mod mod). This is an optimized version for use in Fermat
+ * tests. The input value of n is ignored; it is returned with
+ * "mlen" words valid.
+ */
+int
+lbnTwoExpMod_16(BNWORD16 *n, BNWORD16 const *exp, unsigned elen,
+ BNWORD16 *mod, unsigned mlen)
+{
+ unsigned e; /* Copy of high words of the exponent */
+ unsigned bits; /* Assorted counter of bits */
+ BNWORD16 const *bitptr;
+ BNWORD16 bitword, bitpos;
+ BNWORD16 *a, *b, *a1;
+ BNWORD16 inv;
+
+ assert(mlen);
+
+ bitptr = BIGLITTLE(exp-elen, exp+elen-1);
+ bitword = *bitptr;
+ assert(bitword);
+
+ /* Clear n for future use. */
+ lbnZero_16(n, mlen);
+
+ bits = lbnBits_16(exp, elen);
+
+ /* First, a couple of trivial cases. */
+ if (bits <= 1) {
+ /* 2 ^ 0 == 1, 2 ^ 1 == 2 */
+ BIGLITTLE(n[-1],n[0]) = (BNWORD16)1<<elen;
+ return 0;
+ }
+
+ /* Set bitpos to the most significant bit */
+ bitpos = (BNWORD16)1 << ((bits-1) & (16-1));
+
+ /* Now, count the bits in the modulus. */
+ bits = lbnBits_16(mod, mlen);
+ assert(bits > 1); /* a 1-bit modulus is just stupid... */
+
+ /*
+ * We start with 1<<e, where "e" is as many high bits of the
+ * exponent as we can manage without going over the modulus.
+ * This first loop finds "e".
+ */
+ e = 1;
+ while (elen) {
+ /* Consume the first bit */
+ bitpos >>= 1;
+ if (!bitpos) {
+ if (!--elen)
+ break;
+ bitword = BIGLITTLE(*++bitptr,*--bitptr);
+ bitpos = (BNWORD16)1<<(16-1);
+ }
+ e = (e << 1) | ((bitpos & bitword) != 0);
+ if (e >= bits) { /* Overflow! Back out. */
+ e >>= 1;
+ break;
+ }
+ }
+ /*
+ * The bit in "bitpos" being examined by the bit buffer has NOT
+ * been consumed yet. This may be past the end of the exponent,
+ * in which case elen == 1.
+ */
+
+ /* Okay, now, set bit "e" in n. n is already zero. */
+ inv = (BNWORD16)1 << (e & (16-1));
+ e /= 16;
+ BIGLITTLE(n[-e-1],n[e]) = inv;
+ /*
+ * The effective length of n in words is now "e+1".
+ * This is used a little bit later.
+ */
+
+ if (!elen)
+ return 0; /* That was easy! */
+
+ /*
+ * We have now processed the first few bits. The next step
+ * is to convert this to Montgomery form for further squaring.
+ */
+
+ /* Allocate working storage: two product buffers */
+ LBNALLOC(a, 2*mlen);
+ if (!a)
+ return -1;
+ LBNALLOC(b, 2*mlen);
+ if (!b) {
+ LBNFREE(a, 2*mlen);
+ return -1;
+ }
+
+ /* Convert n to Montgomery form */
+ inv = BIGLITTLE(mod[-1],mod[0]); /* LSW of modulus */
+ assert(inv & 1); /* Modulus must be odd */
+ inv = lbnMontInv1_16(inv);
+ /* Move n (length e+1, remember?) up "mlen" words into b */
+ /* Note that we lie about a1 for a bit - it's pointing to b */
+ a1 = BIGLITTLE(b-mlen,b+mlen);
+ lbnCopy_16(a1, n, e+1);
+ lbnZero_16(b, mlen);
+ /* Do the division - dump the quotient into the high-order words */
+ (void)lbnDiv_16(a1, b, mlen+e+1, mod, mlen);
+ /*
+ * Now do the first squaring and modular reduction to put
+ * the number up in a1 where it belongs.
+ */
+ lbnMontSquare_16(a, b, mod, mlen, inv);
+ /* Fix up a1 to point to where it should go. */
+ a1 = BIGLITTLE(a-mlen,a+mlen);
+
+ /*
+ * Okay, now, a1 holds the number being accumulated, and
+ * b is a scratch register. Start working:
+ */
+ for (;;) {
+ /*
+ * Is the bit set? If so, double a1 as well.
+ * A modular doubling like this is very cheap.
+ */
+ if (bitpos & bitword) {
+ /*
+ * Double the number. If there was a carry out OR
+ * the result is greater than the modulus, subract
+ * the modulus.
+ */
+ if (lbnDouble_16(a1, mlen) ||
+ lbnCmp_16(a1, mod, mlen) > 0)
+ (void)lbnSubN_16(a1, mod, mlen);
+ }
+
+ /* Advance to the next exponent bit */
+ bitpos >>= 1;
+ if (!bitpos) {
+ if (!--elen)
+ break; /* Done! */
+ bitword = BIGLITTLE(*++bitptr,*--bitptr);
+ bitpos = (BNWORD16)1<<(16-1);
+ }
+
+ /*
+ * The elen/bitword/bitpos bit buffer is known to be
+ * non-empty, i.e. there is at least one more unconsumed bit.
+ * Thus, it's safe to square the number.
+ */
+ lbnMontSquare_16(b, a1, mod, mlen, inv);
+ /* Rename result (in b) back to a (a1, really). */
+ a1 = b; b = a; a = a1;
+ a1 = BIGLITTLE(a-mlen,a+mlen);
+ }
+
+ /* DONE! Just a little bit of cleanup... */
+
+ /*
+ * Convert result out of Montgomery form... this is
+ * just a Montgomery reduction.
+ */
+ lbnCopy_16(a, a1, mlen);
+ lbnZero_16(a1, mlen);
+ lbnMontReduce_16(a, mod, mlen, inv);
+ lbnCopy_16(n, a1, mlen);
+
+ /* Clean up - free intermediate storage */
+ LBNFREE(b, 2*mlen);
+ LBNFREE(a, 2*mlen);
+
+ return 0; /* Success */
+}
+
+
+/*
+ * Returns a substring of the big-endian array of bytes representation
+ * of the bignum array based on two parameters, the least significant
+ * byte number (0 to start with the least significant byte) and the
+ * length. I.e. the number returned is a representation of
+ * (bn / 2^(8*lsbyte)) % 2 ^ (8*buflen).
+ *
+ * It is an error if the bignum is not at least buflen + lsbyte bytes
+ * long.
+ *
+ * This code assumes that the compiler has the minimal intelligence
+ * neded to optimize divides and modulo operations on an unsigned data
+ * type with a power of two.
+ */
+void
+lbnExtractBigBytes_16(BNWORD16 const *n, unsigned char *buf,
+ unsigned lsbyte, unsigned buflen)
+{
+ BNWORD16 t = 0; /* Needed to shut up uninitialized var warnings */
+ unsigned shift;
+
+ lsbyte += buflen;
+
+ shift = (8 * lsbyte) % 16;
+ lsbyte /= (16/8); /* Convert to word offset */
+ BIGLITTLE(n -= lsbyte, n += lsbyte);
+
+ if (shift)
+ t = BIGLITTLE(n[-1],n[0]);
+
+ while (buflen--) {
+ if (!shift) {
+ t = BIGLITTLE(*n++,*--n);
+ shift = 16;
+ }
+ shift -= 8;
+ *buf++ = (unsigned char)(t>>shift);
+ }
+}
+
+/*
+ * Merge a big-endian array of bytes into a bignum array.
+ * The array had better be big enough. This is
+ * equivalent to extracting the entire bignum into a
+ * large byte array, copying the input buffer into the
+ * middle of it, and converting back to a bignum.
+ *
+ * The buf is "len" bytes long, and its *last* byte is at
+ * position "lsbyte" from the end of the bignum.
+ *
+ * Note that this is a pain to get right. Fortunately, it's hardly
+ * critical for efficiency.
+ */
+void
+lbnInsertBigBytes_16(BNWORD16 *n, unsigned char const *buf,
+ unsigned lsbyte, unsigned buflen)
+{
+ BNWORD16 t = 0; /* Shut up uninitialized varibale warnings */
+
+ lsbyte += buflen;
+
+ BIGLITTLE(n -= lsbyte/(16/8), n += lsbyte/(16/8));
+
+ /* Load up leading odd bytes */
+ if (lsbyte % (16/8)) {
+ t = BIGLITTLE(*--n,*n++);
+ t >>= (lsbyte * 8) % 16;
+ }
+
+ /* The main loop - merge into t, storing at each word boundary. */
+ while (buflen--) {
+ t = (t << 8) | *buf++;
+ if ((--lsbyte % (16/8)) == 0)
+ BIGLITTLE(*n++,*--n) = t;
+ }
+
+ /* Merge odd bytes in t into last word */
+ lsbyte = (lsbyte * 8) % 16;
+ if (lsbyte) {
+ t <<= lsbyte;
+ t |= (((BNWORD16)1 << lsbyte) - 1) & BIGLITTLE(n[0],n[-1]);
+ BIGLITTLE(n[0],n[-1]) = t;
+ }
+
+ return;
+}
+
+/*
+ * Returns a substring of the little-endian array of bytes representation
+ * of the bignum array based on two parameters, the least significant
+ * byte number (0 to start with the least significant byte) and the
+ * length. I.e. the number returned is a representation of
+ * (bn / 2^(8*lsbyte)) % 2 ^ (8*buflen).
+ *
+ * It is an error if the bignum is not at least buflen + lsbyte bytes
+ * long.
+ *
+ * This code assumes that the compiler has the minimal intelligence
+ * neded to optimize divides and modulo operations on an unsigned data
+ * type with a power of two.
+ */
+void
+lbnExtractLittleBytes_16(BNWORD16 const *n, unsigned char *buf,
+ unsigned lsbyte, unsigned buflen)
+{
+ BNWORD16 t = 0; /* Needed to shut up uninitialized var warnings */
+
+ BIGLITTLE(n -= lsbyte/(16/8), n += lsbyte/(16/8));
+
+ if (lsbyte % (16/8)) {
+ t = BIGLITTLE(*--n,*n++);
+ t >>= (lsbyte % (16/8)) * 8 ;
+ }
+
+ while (buflen--) {
+ if ((lsbyte++ % (16/8)) == 0)
+ t = BIGLITTLE(*--n,*n++);
+ *buf++ = (unsigned char)t;
+ t >>= 8;
+ }
+}
+
+/*
+ * Merge a little-endian array of bytes into a bignum array.
+ * The array had better be big enough. This is
+ * equivalent to extracting the entire bignum into a
+ * large byte array, copying the input buffer into the
+ * middle of it, and converting back to a bignum.
+ *
+ * The buf is "len" bytes long, and its first byte is at
+ * position "lsbyte" from the end of the bignum.
+ *
+ * Note that this is a pain to get right. Fortunately, it's hardly
+ * critical for efficiency.
+ */
+void
+lbnInsertLittleBytes_16(BNWORD16 *n, unsigned char const *buf,
+ unsigned lsbyte, unsigned buflen)
+{
+ BNWORD16 t = 0; /* Shut up uninitialized varibale warnings */
+
+ /* Move to most-significant end */
+ lsbyte += buflen;
+ buf += buflen;
+
+ BIGLITTLE(n -= lsbyte/(16/8), n += lsbyte/(16/8));
+
+ /* Load up leading odd bytes */
+ if (lsbyte % (16/8)) {
+ t = BIGLITTLE(*--n,*n++);
+ t >>= (lsbyte * 8) % 16;
+ }
+
+ /* The main loop - merge into t, storing at each word boundary. */
+ while (buflen--) {
+ t = (t << 8) | *--buf;
+ if ((--lsbyte % (16/8)) == 0)
+ BIGLITTLE(*n++,*--n) = t;
+ }
+
+ /* Merge odd bytes in t into last word */
+ lsbyte = (lsbyte * 8) % 16;
+ if (lsbyte) {
+ t <<= lsbyte;
+ t |= (((BNWORD16)1 << lsbyte) - 1) & BIGLITTLE(n[0],n[-1]);
+ BIGLITTLE(n[0],n[-1]) = t;
+ }
+
+ return;
+}
+
+#ifdef DEADCODE /* This was a precursor to the more flexible lbnExtractBytes */
+/*
+ * Convert a big-endian array of bytes to a bignum.
+ * Returns the number of words in the bignum.
+ * Note the expression "16/8" for the number of bytes per word.
+ * This is so the word-size adjustment will work.
+ */
+unsigned
+lbnFromBytes_16(BNWORD16 *a, unsigned char const *b, unsigned blen)
+{
+ BNWORD16 t;
+ unsigned alen = (blen + (16/8-1))/(16/8);
+ BIGLITTLE(a -= alen, a += alen);
+
+ while (blen) {
+ t = 0;
+ do {
+ t = t << 8 | *b++;
+ } while (--blen & (16/8-1));
+ BIGLITTLE(*a++,*--a) = t;
+ }
+ return alen;
+}
+#endif
+
+/*
+ * Computes the GCD of a and b. Modifies both arguments;
+ * when it returns, one of them is the GCD and the other is trash.
+ * The return value is the length of the GCD, with the sign telling
+ * whether it is in a (+ve) or b (-ve). Both inputs must have
+ * one extra word of precision. alen must be >= blen.
+ *
+ * TODO: use the binary algorithm (Knuth section 4.5.2, algorithm B).
+ * This is based on taking out common powers of 2, then repeatedly:
+ * gcd(2*u,v) = gcd(u,2*v) = gcd(u,v) - isolated powers of 2 can be deleted.
+ * gcd(u,v) = gcd(u-v,v) - the numbers can be easily reduced.
+ * It gets less reduction per step, but the steps are much faster than
+ * the division case.
+ */
+int
+lbnGcd_16(BNWORD16 *a, unsigned alen, BNWORD16 *b, unsigned blen)
+{
+ assert(alen >= blen);
+
+ while (blen != 0) {
+ (void)lbnDiv_16(BIGLITTLE(a-blen,a+blen), a, alen, b, blen);
+ alen = lbnNorm_16(a, blen);
+ if (alen == 0)
+ return -(int)blen;
+ (void)lbnDiv_16(BIGLITTLE(b-alen,b+alen), b, blen, a, alen);
+ blen = lbnNorm_16(b, alen);
+ }
+ return alen;
+}
+
+/*
+ * Invert "a" modulo "mod" using the extended Euclidean algorithm.
+ * Note that this only computes one of the cosequences, and uses the
+ * theorem that the signs flip every step and the absolute value of
+ * the cosequence values are always bounded by the modulus to avoid
+ * having to work with negative numbers.
+ * gcd(a,mod) had better equal 1. Returns 1 if the GCD is NOT 1.
+ * a must be one word longer than "mod". It is overwritten with the
+ * result.
+ * TODO: Use Richard Schroeppel's *much* faster algorithm.
+ */
+int
+lbnInv_16(BNWORD16 *a, unsigned alen, BNWORD16 const *mod, unsigned mlen)
+{
+ BNWORD16 *b; /* Hold a copy of mod during GCD reduction */
+ BNWORD16 *p; /* Temporary for products added to t0 and t1 */
+ BNWORD16 *t0, *t1; /* Inverse accumulators */
+ BNWORD16 cy;
+ unsigned blen, t0len, t1len, plen;
+
+ alen = lbnNorm_16(a, alen);
+ if (!alen)
+ return 1; /* No inverse */
+
+ mlen = lbnNorm_16(mod, mlen);
+
+ assert (alen <= mlen);
+
+ /* Inverse of 1 is 1 */
+ if (alen == 1 && BIGLITTLE(a[-1],a[0]) == 1) {
+ lbnZero_16(BIGLITTLE(a-alen,a+alen), mlen-alen);
+ return 0;
+ }
+
+ /* Allocate a pile of space */
+ LBNALLOC(b, mlen+1);
+ if (b) {
+ /*
+ * Although products are guaranteed to always be less than the
+ * modulus, it can involve multiplying two 3-word numbers to
+ * get a 5-word result, requiring a 6th word to store a 0
+ * temporarily. Thus, mlen + 1.
+ */
+ LBNALLOC(p, mlen+1);
+ if (p) {
+ LBNALLOC(t0, mlen);
+ if (t0) {
+ LBNALLOC(t1, mlen);
+ if (t1)
+ goto allocated;
+ LBNFREE(t0, mlen);
+ }
+ LBNFREE(p, mlen+1);
+ }
+ LBNFREE(b, mlen+1);
+ }
+ return -1;
+
+allocated:
+
+ /* Set t0 to 1 */
+ t0len = 1;
+ BIGLITTLE(t0[-1],t0[0]) = 1;
+
+ /* b = mod */
+ lbnCopy_16(b, mod, mlen);
+ /* blen = mlen (implicitly) */
+
+ /* t1 = b / a; b = b % a */
+ cy = lbnDiv_16(t1, b, mlen, a, alen);
+ *(BIGLITTLE(t1-(mlen-alen)-1,t1+(mlen-alen))) = cy;
+ t1len = lbnNorm_16(t1, mlen-alen+1);
+ blen = lbnNorm_16(b, alen);
+
+ /* while (b > 1) */
+ while (blen > 1 || BIGLITTLE(b[-1],b[0]) != (BNWORD16)1) {
+ /* q = a / b; a = a % b; */
+ if (alen < blen || (alen == blen && lbnCmp_16(a, a, alen) < 0))
+ assert(0);
+ cy = lbnDiv_16(BIGLITTLE(a-blen,a+blen), a, alen, b, blen);
+ *(BIGLITTLE(a-alen-1,a+alen)) = cy;
+ plen = lbnNorm_16(BIGLITTLE(a-blen,a+blen), alen-blen+1);
+ assert(plen);
+ alen = lbnNorm_16(a, blen);
+ if (!alen)
+ goto failure; /* GCD not 1 */
+
+ /* t0 += q * t1; */
+ assert(plen+t1len <= mlen+1);
+ lbnMul_16(p, BIGLITTLE(a-blen,a+blen), plen, t1, t1len);
+ plen = lbnNorm_16(p, plen + t1len);
+ assert(plen <= mlen);
+ if (plen > t0len) {
+ lbnZero_16(BIGLITTLE(t0-t0len,t0+t0len), plen-t0len);
+ t0len = plen;
+ }
+ cy = lbnAddN_16(t0, p, plen);
+ if (cy) {
+ if (t0len > plen) {
+ cy = lbnAdd1_16(BIGLITTLE(t0-plen,t0+plen),
+ t0len-plen, cy);
+ }
+ if (cy) {
+ BIGLITTLE(t0[-t0len-1],t0[t0len]) = cy;
+ t0len++;
+ }
+ }
+
+ /* if (a <= 1) return a ? t0 : FAIL; */
+ if (alen <= 1 && BIGLITTLE(a[-1],a[0]) == (BNWORD16)1) {
+ if (alen == 0)
+ goto failure; /* FAIL */
+ assert(t0len <= mlen);
+ lbnCopy_16(a, t0, t0len);
+ lbnZero_16(BIGLITTLE(a-t0len, a+t0len), mlen-t0len);
+ goto success;
+ }
+
+ /* q = b / a; b = b % a; */
+ if (blen < alen || (blen == alen && lbnCmp_16(b, a, alen) < 0))
+ assert(0);
+ cy = lbnDiv_16(BIGLITTLE(b-alen,b+alen), b, blen, a, alen);
+ *(BIGLITTLE(b-blen-1,b+blen)) = cy;
+ plen = lbnNorm_16(BIGLITTLE(b-alen,b+alen), blen-alen+1);
+ assert(plen);
+ blen = lbnNorm_16(b, alen);
+ if (!blen)
+ goto failure; /* GCD not 1 */
+
+ /* t1 += q * t0; */
+ assert(plen+t0len <= mlen+1);
+ lbnMul_16(p, BIGLITTLE(b-alen,b+alen), plen, t0, t0len);
+ plen = lbnNorm_16(p, plen + t0len);
+ assert(plen <= mlen);
+ if (plen > t1len) {
+ lbnZero_16(BIGLITTLE(t1-t1len,t1+t1len), plen-t1len);
+ t1len = plen;
+ }
+ cy = lbnAddN_16(t1, p, plen);
+ if (cy) {
+ if (t1len > plen) {
+ cy = lbnAdd1_16(BIGLITTLE(t1-plen,t0+plen),
+ t1len-plen, cy);
+ }
+ if (cy) {
+ BIGLITTLE(t1[-t1len-1],t1[t1len]) = cy;
+ t1len++;
+ }
+ }
+ }
+
+ if (!blen)
+ goto failure; /* gcd(a, mod) != 1 -- FAIL */
+
+ /* return mod-t1 */
+ lbnCopy_16(a, mod, mlen);
+ assert(t1len <= mlen);
+ cy = lbnSubN_16(a, t1, t1len);
+ if (cy) {
+ assert(mlen > t1len);
+ cy = lbnSub1_16(BIGLITTLE(a-t1len, a+t1len), mlen-t1len, cy);
+ assert(!cy);
+ }
+
+success:
+ LBNFREE(t1, mlen);
+ LBNFREE(t0, mlen);
+ LBNFREE(p, mlen+1);
+ LBNFREE(b, mlen+1);
+
+ return 0;
+
+failure:
+ LBNFREE(t1, mlen);
+ LBNFREE(t0, mlen);
+ LBNFREE(p, mlen+1);
+ LBNFREE(b, mlen+1);
+
+ return 1;
+}
diff --git a/usr/src/lib/libresolv2/common/cylink/lbn16.h b/usr/src/lib/libresolv2/common/cylink/lbn16.h
new file mode 100644
index 0000000000..52e156886e
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbn16.h
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef LBN16_H
+#define LBN16_H
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "lbn.h"
+
+#ifndef BNWORD16
+#error 16-bit bignum library requires a 16-bit data type
+#endif
+
+#ifndef lbnCopy_16
+void lbnCopy_16(BNWORD16 *dest, BNWORD16 const *src, unsigned len);
+#endif
+#ifndef lbnZero_16
+void lbnZero_16(BNWORD16 *num, unsigned len);
+#endif
+#ifndef lbnNeg_16
+void lbnNeg_16(BNWORD16 *num, unsigned len);
+#endif
+
+#ifndef lbnAdd1_16
+BNWORD16 lbnAdd1_16(BNWORD16 *num, unsigned len, BNWORD16 carry);
+#endif
+#ifndef lbnSub1_16
+BNWORD16 lbnSub1_16(BNWORD16 *num, unsigned len, BNWORD16 borrow);
+#endif
+
+#ifndef lbnAddN_16
+BNWORD16 lbnAddN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len);
+#endif
+#ifndef lbnSubN_16
+BNWORD16 lbnSubN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len);
+#endif
+
+#ifndef lbnCmp_16
+int lbnCmp_16(BNWORD16 const *num1, BNWORD16 const *num2, unsigned len);
+#endif
+
+#ifndef lbnMulN1_16
+void lbnMulN1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k);
+#endif
+#ifndef lbnMulAdd1_16
+BNWORD16
+lbnMulAdd1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k);
+#endif
+#ifndef lbnMulSub1_16
+BNWORD16 lbnMulSub1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k);
+#endif
+
+#ifndef lbnLshift_16
+BNWORD16 lbnLshift_16(BNWORD16 *num, unsigned len, unsigned shift);
+#endif
+#ifndef lbnDouble_16
+BNWORD16 lbnDouble_16(BNWORD16 *num, unsigned len);
+#endif
+#ifndef lbnRshift_16
+BNWORD16 lbnRshift_16(BNWORD16 *num, unsigned len, unsigned shift);
+#endif
+
+#ifndef lbnMul_16
+void lbnMul_16(BNWORD16 *prod, BNWORD16 const *num1, unsigned len1,
+ BNWORD16 const *num2, unsigned len2);
+#endif
+#ifndef lbnSquare_16
+void lbnSquare_16(BNWORD16 *prod, BNWORD16 const *num, unsigned len);
+#endif
+
+#ifndef lbnNorm_16
+unsigned lbnNorm_16(BNWORD16 const *num, unsigned len);
+#endif
+#ifndef lbnBits_16
+unsigned lbnBits_16(BNWORD16 const *num, unsigned len);
+#endif
+
+#ifndef lbnExtractBigBytes_16
+void lbnExtractBigBytes_16(BNWORD16 const *bn, unsigned char *buf,
+ unsigned lsbyte, unsigned buflen);
+#endif
+#ifndef lbnInsertBigytes_16
+void lbnInsertBigBytes_16(BNWORD16 *n, unsigned char const *buf,
+ unsigned lsbyte, unsigned buflen);
+#endif
+#ifndef lbnExtractLittleBytes_16
+void lbnExtractLittleBytes_16(BNWORD16 const *bn, unsigned char *buf,
+ unsigned lsbyte, unsigned buflen);
+#endif
+#ifndef lbnInsertLittleBytes_16
+void lbnInsertLittleBytes_16(BNWORD16 *n, unsigned char const *buf,
+ unsigned lsbyte, unsigned buflen);
+#endif
+
+#ifndef lbnDiv21_16
+BNWORD16 lbnDiv21_16(BNWORD16 *q, BNWORD16 nh, BNWORD16 nl, BNWORD16 d);
+#endif
+#ifndef lbnDiv1_16
+BNWORD16 lbnDiv1_16(BNWORD16 *q, BNWORD16 *rem,
+ BNWORD16 const *n, unsigned len, BNWORD16 d);
+#endif
+#ifndef lbnModQ_16
+unsigned lbnModQ_16(BNWORD16 const *n, unsigned len, unsigned d);
+#endif
+#ifndef lbnDiv_16
+BNWORD16
+lbnDiv_16(BNWORD16 *q, BNWORD16 *n, unsigned nlen, BNWORD16 *d, unsigned dlen);
+#endif
+
+#ifndef lbnMontInv1_16
+BNWORD16 lbnMontInv1_16(BNWORD16 const x);
+#endif
+#ifndef lbnMontReduce_16
+void lbnMontReduce_16(BNWORD16 *n, BNWORD16 const *mod, unsigned const mlen,
+ BNWORD16 inv);
+#endif
+#ifndef lbnToMont_16
+void lbnToMont_16(BNWORD16 *n, unsigned nlen, BNWORD16 *mod, unsigned mlen);
+#endif
+#ifndef lbnFromMont_16
+void lbnFromMont_16(BNWORD16 *n, BNWORD16 *mod, unsigned len);
+#endif
+
+#ifndef lbnExpMod_16
+int lbnExpMod_16(BNWORD16 *result, BNWORD16 const *n, unsigned nlen,
+ BNWORD16 const *exp, unsigned elen, BNWORD16 *mod, unsigned mlen);
+#endif
+#ifndef lbnDoubleExpMod_16
+int lbnDoubleExpMod_16(BNWORD16 *result,
+ BNWORD16 const *n1, unsigned n1len, BNWORD16 const *e1, unsigned e1len,
+ BNWORD16 const *n2, unsigned n2len, BNWORD16 const *e2, unsigned e2len,
+ BNWORD16 *mod, unsigned mlen);
+#endif
+#ifndef lbnTwoExpMod_16
+int lbnTwoExpMod_16(BNWORD16 *n, BNWORD16 const *exp, unsigned elen,
+ BNWORD16 *mod, unsigned mlen);
+#endif
+#ifndef lbnGcd_16
+int lbnGcd_16(BNWORD16 *a, unsigned alen, BNWORD16 *b, unsigned blen);
+#endif
+#ifndef lbnInv_16
+int lbnInv_16(BNWORD16 *a, unsigned alen, BNWORD16 const *mod, unsigned mlen);
+#endif
+
+#endif /* LBN16_H */
diff --git a/usr/src/lib/libresolv2/common/cylink/lbn32.c b/usr/src/lib/libresolv2/common/cylink/lbn32.c
new file mode 100644
index 0000000000..4cdfabf48e
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbn32.c
@@ -0,0 +1,3650 @@
+/*
+ * Copyright (c) 2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/*
+ * lbn32.c - Low-level bignum routines, 32-bit version.
+ *
+ * Copyright (c) 1995 Colin Plumb. All rights reserved.
+ * For licensing and other legal details, see the file legal.c.
+ *
+ * NOTE: the magic constants "32" and "64" appear in many places in this
+ * file, including inside identifiers. Because it is not possible to
+ * ask "#ifdef" of a macro expansion, it is not possible to use the
+ * preprocessor to conditionalize these properly. Thus, this file is
+ * intended to be edited with textual search and replace to produce
+ * alternate word size versions. Any reference to the number of bits
+ * in a word must be the string "32", and that string must not appear
+ * otherwise. Any reference to twice this number must appear as "64",
+ * which likewise must not appear otherwise. Is that clear?
+ *
+ * Remember, when doubling the bit size replace the larger number (64)
+ * first, then the smaller (32). When halving the bit size, do the
+ * opposite. Otherwise, things will get wierd. Also, be sure to replace
+ * every instance that appears. (:%s/foo/bar/g in vi)
+ *
+ * These routines work with a pointer to the least-significant end of
+ * an array of WORD32s. The BIG(x), LITTLE(y) and BIGLTTLE(x,y) macros
+ * defined in lbn.h (which expand to x on a big-edian machine and y on a
+ * little-endian machine) are used to conditionalize the code to work
+ * either way. If you have no assembly primitives, it doesn't matter.
+ * Note that on a big-endian machine, the least-significant-end pointer
+ * is ONE PAST THE END. The bytes are ptr[-1] through ptr[-len].
+ * On little-endian, they are ptr[0] through ptr[len-1]. This makes
+ * perfect sense if you consider pointers to point *between* bytes rather
+ * than at them.
+ *
+ * Because the array index values are unsigned integers, ptr[-i]
+ * may not work properly, since the index -i is evaluated as an unsigned,
+ * and if pointers are wider, zero-extension will produce a positive
+ * number rahter than the needed negative. The expression used in this
+ * code, *(ptr-i) will, however, work. (The array syntax is equivalent
+ * to *(ptr+-i), which is a pretty subtle difference.)
+ *
+ * Many of these routines will get very unhappy if fed zero-length inputs.
+ * They use assert() to enforce this. An higher layer of code must make
+ * sure that these aren't called with zero-length inputs.
+ *
+ * Any of these routines can be replaced with more efficient versions
+ * elsewhere, by just #defining their names. If one of the names
+ * is #defined, the C code is not compiled in and no declaration is
+ * made. Use the BNINCLUDE file to do that. Typically, you compile
+ * asm subroutines with the same name and just, e.g.
+ * #define lbnMulAdd1_32 lbnMulAdd1_32
+ *
+ * If you want to write asm routines, start with lbnMulAdd1_32().
+ * This is the workhorse of modular exponentiation. lbnMulN1_32() is
+ * also used a fair bit, although not as much and it's defined in terms
+ * of lbnMulAdd1_32 if that has a custom version. lbnMulSub1_32 and
+ * lbnDiv21_32 are used in the usual division and remainder finding.
+ * (Not the Montgomery reduction used in modular exponentiation, though.)
+ * Once you have lbnMulAdd1_32 defined, writing the other two should
+ * be pretty easy. (Just make sure you get the sign of the subtraction
+ * in lbnMulSub1_32 right - it's dest = dest - source * k.)
+ *
+ * The only definitions that absolutely need a double-word (BNWORD64)
+ * type are lbnMulAdd1_32 and lbnMulSub1_32; if those are provided,
+ * the rest follows. lbnDiv21_32, however, is a lot slower unless you
+ * have them, and lbnModQ_32 takes after it. That one is used quite a
+ * bit for prime sieving.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef HAVE_CONFIG_H
+#define HAVE_CONFIG_H 0
+#endif
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * Some compilers complain about #if FOO if FOO isn't defined,
+ * so do the ANSI-mandated thing explicitly...
+ */
+#ifndef NO_ASSERT_H
+#define NO_ASSERT_H 0
+#endif
+#ifndef NO_STRING_H
+#define NO_STRING_H 0
+#endif
+#ifndef HAVE_STRINGS_H
+#define HAVE_STRINGS_H 0
+#endif
+#ifndef NEED_MEMORY_H
+#define NEED_MEMORY_H 0
+#endif
+
+#if !NO_ASSERT_H
+#include <assert.h>
+#else
+#define assert(x) (void)0
+#endif
+
+#if !NO_STRING_H
+#include <string.h> /* For memcpy */
+#elif HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#if NEED_MEMORY_H
+#include <memory.h>
+#endif
+
+#include "lbn.h"
+#include "lbn32.h"
+#include "lbnmem.h"
+#include "legal.h"
+
+#include "kludge.h"
+#include <port_after.h>
+
+#ifndef BNWORD32
+#error 32-bit bignum library requires a 32-bit data type
+#endif
+
+/* Make sure the copyright notice gets included */
+volatile const char * volatile const lbnCopyright_32 = bnCopyright;
+
+/*
+ * Most of the multiply (and Montgomery reduce) routines use an outer
+ * loop that iterates over one of the operands - a so-called operand
+ * scanning approach. One big advantage of this is that the assembly
+ * support routines are simpler. The loops can be rearranged to have
+ * an outer loop that iterates over the product, a so-called product
+ * scanning approach. This has the advantage of writing less data
+ * and doing fewer adds to memory, so is supposedly faster. Some
+ * code has been written using a product-scanning approach, but
+ * it appears to be slower, so it is turned off by default. Some
+ * experimentation would be appreciated.
+ *
+ * (The code is also annoying to get right and not very well commented,
+ * one of my pet peeves about math libraries. I'm sorry.)
+ */
+#ifndef PRODUCT_SCAN
+#define PRODUCT_SCAN 0
+#endif
+
+/*
+ * Copy an array of words. <Marvin mode on> Thrilling, isn't it? </Marvin>
+ * This is a good example of how the byte offsets and BIGLITTLE() macros work.
+ * Another alternative would have been
+ * memcpy(dest BIG(-len), src BIG(-len), len*sizeof(BNWORD32)), but I find that
+ * putting operators into conditional macros is confusing.
+ */
+#ifndef lbnCopy_32
+void
+lbnCopy_32(BNWORD32 *dest, BNWORD32 const *src, unsigned len)
+{
+ memcpy(BIGLITTLE(dest-len,dest), BIGLITTLE(src-len,src),
+ len * sizeof(*src));
+}
+#endif /* !lbnCopy_32 */
+
+/*
+ * Fill n words with zero. This does it manually rather than calling
+ * memset because it can assume alignment to make things faster while
+ * memset can't. Note how big-endian numbers are naturally addressed
+ * using predecrement, while little-endian is postincrement.
+ */
+#ifndef lbnZero_32
+void
+lbnZero_32(BNWORD32 *num, unsigned len)
+{
+ while (len--)
+ BIGLITTLE(*--num,*num++) = 0;
+}
+#endif /* !lbnZero_32 */
+
+/*
+ * Negate an array of words.
+ * Negation is subtraction from zero. Negating low-order words
+ * entails doing nothing until a non-zero word is hit. Once that
+ * is negated, a borrow is generated and never dies until the end
+ * of the number is hit. Negation with borrow, -x-1, is the same as ~x.
+ * Repeat that until the end of the number.
+ *
+ * Doesn't return borrow out because that's pretty useless - it's
+ * always set unless the input is 0, which is easy to notice in
+ * normalized form.
+ */
+#ifndef lbnNeg_32
+void
+lbnNeg_32(BNWORD32 *num, unsigned len)
+{
+ assert(len);
+
+ /* Skip low-order zero words */
+ while (BIGLITTLE(*--num,*num) == 0) {
+ if (!--len)
+ return;
+ LITTLE(num++;)
+ }
+ /* Negate the lowest-order non-zero word */
+ *num = -*num;
+ /* Complement all the higher-order words */
+ while (--len) {
+ BIGLITTLE(--num,++num);
+ *num = ~*num;
+ }
+}
+#endif /* !lbnNeg_32 */
+
+
+/*
+ * lbnAdd1_32: add the single-word "carry" to the given number.
+ * Used for minor increments and propagating the carry after
+ * adding in a shorter bignum.
+ *
+ * Technique: If we have a double-width word, presumably the compiler
+ * can add using its carry in inline code, so we just use a larger
+ * accumulator to compute the carry from the first addition.
+ * If not, it's more complex. After adding the first carry, which may
+ * be > 1, compare the sum and the carry. If the sum wraps (causing a
+ * carry out from the addition), the result will be less than each of the
+ * inputs, since the wrap subtracts a number (2^32) which is larger than
+ * the other input can possibly be. If the sum is >= the carry input,
+ * return success immediately.
+ * In either case, if there is a carry, enter a loop incrementing words
+ * until one does not wrap. Since we are adding 1 each time, the wrap
+ * will be to 0 and we can test for equality.
+ */
+#ifndef lbnAdd1_32 /* If defined, it's provided as an asm subroutine */
+#ifdef BNWORD64
+BNWORD32
+lbnAdd1_32(BNWORD32 *num, unsigned len, BNWORD32 carry)
+{
+ BNWORD64 t;
+ assert(len > 0); /* Alternative: if (!len) return carry */
+
+ t = (BNWORD64)BIGLITTLE(*--num,*num) + carry;
+ BIGLITTLE(*num,*num++) = (BNWORD32)t;
+ if ((t >> 32) == 0)
+ return 0;
+ while (--len) {
+ if (++BIGLITTLE(*--num,*num++) != 0)
+ return 0;
+ }
+ return 1;
+}
+#else /* no BNWORD64 */
+BNWORD32
+lbnAdd1_32(BNWORD32 *num, unsigned len, BNWORD32 carry)
+{
+ assert(len > 0); /* Alternative: if (!len) return carry */
+
+ if ((BIGLITTLE(*--num,*num++) += carry) >= carry)
+ return 0;
+ while (--len) {
+ if (++BIGLITTLE(*--num,*num++) != 0)
+ return 0;
+ }
+ return 1;
+}
+#endif
+#endif/* !lbnAdd1_32 */
+
+/*
+ * lbnSub1_32: subtract the single-word "borrow" from the given number.
+ * Used for minor decrements and propagating the borrow after
+ * subtracting a shorter bignum.
+ *
+ * Technique: Similar to the add, above. If there is a double-length type,
+ * use that to generate the first borrow.
+ * If not, after subtracting the first borrow, which may be > 1, compare
+ * the difference and the *negative* of the carry. If the subtract wraps
+ * (causing a borrow out from the subtraction), the result will be at least
+ * as large as -borrow. If the result < -borrow, then no borrow out has
+ * appeared and we may return immediately, except when borrow == 0. To
+ * deal with that case, use the identity that -x = ~x+1, and instead of
+ * comparing < -borrow, compare for <= ~borrow.
+ * Either way, if there is a borrow out, enter a loop decrementing words
+ * until a non-zero word is reached.
+ *
+ * Note the cast of ~borrow to (BNWORD32). If the size of an int is larger
+ * than BNWORD32, C rules say the number is expanded for the arithmetic, so
+ * the inversion will be done on an int and the value won't be quite what
+ * is expected.
+ */
+#ifndef lbnSub1_32 /* If defined, it's provided as an asm subroutine */
+#ifdef BNWORD64
+BNWORD32
+lbnSub1_32(BNWORD32 *num, unsigned len, BNWORD32 borrow)
+{
+ BNWORD64 t;
+ assert(len > 0); /* Alternative: if (!len) return borrow */
+
+ t = (BNWORD64)BIGLITTLE(*--num,*num) - borrow;
+ BIGLITTLE(*num,*num++) = (BNWORD32)t;
+ if ((t >> 32) == 0)
+ return 0;
+ while (--len) {
+ if ((BIGLITTLE(*--num,*num++))-- != 0)
+ return 0;
+ }
+ return 1;
+}
+#else /* no BNWORD64 */
+BNWORD32
+lbnSub1_32(BNWORD32 *num, unsigned len, BNWORD32 borrow)
+{
+ assert(len > 0); /* Alternative: if (!len) return borrow */
+
+ if ((BIGLITTLE(*--num,*num++) -= borrow) <= (BNWORD32)~borrow)
+ return 0;
+ while (--len) {
+ if ((BIGLITTLE(*--num,*num++))-- != 0)
+ return 0;
+ }
+ return 1;
+}
+#endif
+#endif /* !lbnSub1_32 */
+
+/*
+ * lbnAddN_32: add two bignums of the same length, returning the carry (0 or 1).
+ * One of the building blocks, along with lbnAdd1, of adding two bignums of
+ * differing lengths.
+ *
+ * Technique: Maintain a word of carry. If there is no double-width type,
+ * use the same technique as in lbnAdd1, above, to maintain the carry by
+ * comparing the inputs. Adding the carry sources is used as an OR operator;
+ * at most one of the two comparisons can possibly be true. The first can
+ * only be true if carry == 1 and x, the result, is 0. In that case the
+ * second can't possibly be true.
+ */
+#ifndef lbnAddN_32
+#ifdef BNWORD64
+BNWORD32
+lbnAddN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len)
+{
+ BNWORD64 t;
+
+ assert(len > 0);
+
+ t = (BNWORD64)BIGLITTLE(*--num1,*num1) + BIGLITTLE(*--num2,*num2++);
+ BIGLITTLE(*num1,*num1++) = (BNWORD32)t;
+ while (--len) {
+ t = (BNWORD64)BIGLITTLE(*--num1,*num1) +
+ (BNWORD64)BIGLITTLE(*--num2,*num2++) + (t >> 32);
+ BIGLITTLE(*num1,*num1++) = (BNWORD32)t;
+ }
+
+ return (BNWORD32)(t>>32);
+}
+#else /* no BNWORD64 */
+BNWORD32
+lbnAddN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len)
+{
+ BNWORD32 x, carry = 0;
+
+ assert(len > 0); /* Alternative: change loop to test at start */
+
+ do {
+ x = BIGLITTLE(*--num2,*num2++);
+ carry = (x += carry) < carry;
+ carry += (BIGLITTLE(*--num1,*num1++) += x) < x;
+ } while (--len);
+
+ return carry;
+}
+#endif
+#endif /* !lbnAddN_32 */
+
+/*
+ * lbnSubN_32: add two bignums of the same length, returning the carry (0 or 1).
+ * One of the building blocks, along with subn1, of subtracting two bignums of
+ * differing lengths.
+ *
+ * Technique: If no double-width type is availble, maintain a word of borrow.
+ * First, add the borrow to the subtrahend (did you have to learn all those
+ * awful words in elementary school, too?), and if it overflows, set the
+ * borrow again. Then subtract the modified subtrahend from the next word
+ * of input, using the same technique as in subn1, above.
+ * Adding the borrows is used as an OR operator; at most one of the two
+ * comparisons can possibly be true. The first can only be true if
+ * borrow == 1 and x, the result, is 0. In that case the second can't
+ * possibly be true.
+ *
+ * In the double-word case, (BNWORD32)-(t>>32) is subtracted, rather than
+ * adding t>>32, because the shift would need to sign-extend and that's
+ * not guaranteed to happen in ANSI C, even with signed types.
+ */
+#ifndef lbnSubN_32
+#ifdef BNWORD64
+BNWORD32
+lbnSubN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len)
+{
+ BNWORD64 t;
+
+ assert(len > 0);
+
+ t = (BNWORD64)BIGLITTLE(*--num1,*num1) - BIGLITTLE(*--num2,*num2++);
+ BIGLITTLE(*num1,*num1++) = (BNWORD32)t;
+
+ while (--len) {
+ t = (BNWORD64)BIGLITTLE(*--num1,*num1) -
+ (BNWORD64)BIGLITTLE(*--num2,*num2++) - (BNWORD32)-(t >> 32);
+ BIGLITTLE(*num1,*num1++) = (BNWORD32)t;
+ }
+
+ return -(BNWORD32)(t>>32);
+}
+#else
+BNWORD32
+lbnSubN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len)
+{
+ BNWORD32 x, borrow = 0;
+
+ assert(len > 0); /* Alternative: change loop to test at start */
+
+ do {
+ x = BIGLITTLE(*--num2,*num2++);
+ borrow = (x += borrow) < borrow;
+ borrow += (BIGLITTLE(*--num1,*num1++) -= x) > (BNWORD32)~x;
+ } while (--len);
+
+ return borrow;
+}
+#endif
+#endif /* !lbnSubN_32 */
+
+#ifndef lbnCmp_32
+/*
+ * lbnCmp_32: compare two bignums of equal length, returning the sign of
+ * num1 - num2. (-1, 0 or +1).
+ *
+ * Technique: Change the little-endian pointers to big-endian pointers
+ * and compare from the most-significant end until a difference if found.
+ * When it is, figure out the sign of the difference and return it.
+ */
+int
+lbnCmp_32(BNWORD32 const *num1, BNWORD32 const *num2, unsigned len)
+{
+ BIGLITTLE(num1 -= len, num1 += len);
+ BIGLITTLE(num2 -= len, num2 += len);
+
+ while (len--) {
+ if (BIGLITTLE(*num1++ != *num2++, *--num1 != *--num2)) {
+ if (BIGLITTLE(num1[-1] < num2[-1], *num1 < *num2))
+ return -1;
+ else
+ return 1;
+ }
+ }
+ return 0;
+}
+#endif /* !lbnCmp_32 */
+
+/*
+ * mul32_ppmmaa(ph,pl,x,y,a,b) is an optional routine that
+ * computes (ph,pl) = x * y + a + b. mul32_ppmma and mul32_ppmm
+ * are simpler versions. If you want to be lazy, all of these
+ * can be defined in terms of the others, so here we create any
+ * that have not been defined in terms of the ones that have been.
+ */
+
+/* Define ones with fewer a's in terms of ones with more a's */
+#if !defined(mul32_ppmma) && defined(mul32_ppmmaa)
+#define mul32_ppmma(ph,pl,x,y,a) mul32_ppmmaa(ph,pl,x,y,a,0)
+#endif
+
+#if !defined(mul32_ppmm) && defined(mul32_ppmma)
+#define mul32_ppmm(ph,pl,x,y) mul32_ppmma(ph,pl,x,y,0)
+#endif
+
+/*
+ * Use this definition to test the mul32_ppmm-based operations on machines
+ * that do not provide mul32_ppmm. Change the final "0" to a "1" to
+ * enable it.
+ */
+#if !defined(mul32_ppmm) && defined(BNWORD64) && 0 /* Debugging */
+#define mul32_ppmm(ph,pl,x,y) \
+ ({BNWORD64 _ = (BNWORD64)(x)*(y); (pl) = _; (ph) = _>>32;})
+#endif
+
+#if defined(mul32_ppmm) && !defined(mul32_ppmma)
+#define mul32_ppmma(ph,pl,x,y,a) \
+ (mul32_ppmm(ph,pl,x,y), (ph) += ((pl) += (a)) < (a))
+#endif
+
+#if defined(mul32_ppmma) && !defined(mul32_ppmmaa)
+#define mul32_ppmmaa(ph,pl,x,y,a,b) \
+ (mul32_ppmma(ph,pl,x,y,a), (ph) += ((pl) += (b)) < (b))
+#endif
+
+/*
+ * lbnMulN1_32: Multiply an n-word input by a 1-word input and store the
+ * n+1-word product. This uses either the mul32_ppmm and mul32_ppmma
+ * macros, or C multiplication with the BNWORD64 type. This uses mul32_ppmma
+ * if available, assuming you won't bother defining it unless you can do
+ * better than the normal multiplication.
+ */
+#ifndef lbnMulN1_32
+#ifdef lbnMulAdd1_32 /* If we have this asm primitive, use it. */
+void
+lbnMulN1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
+{
+ lbnZero_32(out, len);
+ BIGLITTLE(*(out-len),*(out+len)) = lbnMulAdd1_32(out, in, len, k);
+}
+#elif defined(mul32_ppmm)
+void
+lbnMulN1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
+{
+ BNWORD32 prod, carry, carryin;
+
+ assert(len > 0);
+
+ BIG(--out;--in;);
+ mul32_ppmm(carry, *out, *in, k);
+ LITTLE(out++;in++;)
+
+ while (--len) {
+ BIG(--out;--in;)
+ carryin = carry;
+ mul32_ppmma(carry, *out, *in, k, carryin);
+ LITTLE(out++;in++;)
+ }
+ BIGLITTLE(*--out,*out) = carry;
+}
+#elif defined(BNWORD64)
+void
+lbnMulN1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
+{
+ BNWORD64 p;
+
+ assert(len > 0);
+
+ p = (BNWORD64)BIGLITTLE(*--in,*in++) * k;
+ BIGLITTLE(*--out,*out++) = (BNWORD32)p;
+
+ while (--len) {
+ p = (BNWORD64)BIGLITTLE(*--in,*in++) * k + (BNWORD32)(p >> 32);
+ BIGLITTLE(*--out,*out++) = (BNWORD32)p;
+ }
+ BIGLITTLE(*--out,*out) = (BNWORD32)(p >> 32);
+}
+#else
+#error No 32x32 -> 64 multiply available for 32-bit bignum package
+#endif
+#endif /* lbnMulN1_32 */
+
+/*
+ * lbnMulAdd1_32: Multiply an n-word input by a 1-word input and add the
+ * low n words of the product to the destination. *Returns the n+1st word
+ * of the product.* (That turns out to be more convenient than adding
+ * it into the destination and dealing with a possible unit carry out
+ * of *that*.) This uses either the mul32_ppmma and mul32_ppmmaa macros,
+ * or C multiplication with the BNWORD64 type.
+ *
+ * If you're going to write assembly primitives, this is the one to
+ * start with. It is by far the most commonly called function.
+ */
+#ifndef lbnMulAdd1_32
+#if defined(mul32_ppmm)
+BNWORD32
+lbnMulAdd1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
+{
+ BNWORD32 prod, carry, carryin;
+
+ assert(len > 0);
+
+ BIG(--out;--in;);
+ carryin = *out;
+ mul32_ppmma(carry, *out, *in, k, carryin);
+ LITTLE(out++;in++;)
+
+ while (--len) {
+ BIG(--out;--in;);
+ carryin = carry;
+ mul32_ppmmaa(carry, prod, *in, k, carryin, *out);
+ *out = prod;
+ LITTLE(out++;in++;)
+ }
+
+ return carry;
+}
+#elif defined(BNWORD64)
+BNWORD32
+lbnMulAdd1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
+{
+ BNWORD64 p;
+
+ assert(len > 0);
+
+ p = (BNWORD64)BIGLITTLE(*--in,*in++) * k + BIGLITTLE(*--out,*out);
+ BIGLITTLE(*out,*out++) = (BNWORD32)p;
+
+ while (--len) {
+ p = (BNWORD64)BIGLITTLE(*--in,*in++) * k +
+ (BNWORD32)(p >> 32) + BIGLITTLE(*--out,*out);
+ BIGLITTLE(*out,*out++) = (BNWORD32)p;
+ }
+
+ return (BNWORD32)(p >> 32);
+}
+#else
+#error No 32x32 -> 64 multiply available for 32-bit bignum package
+#endif
+#endif /* lbnMulAdd1_32 */
+
+/*
+ * lbnMulSub1_32: Multiply an n-word input by a 1-word input and subtract the
+ * n-word product from the destination. Returns the n+1st word of the product.
+ * This uses either the mul32_ppmm and mul32_ppmma macros, or
+ * C multiplication with the BNWORD64 type.
+ *
+ * This is rather uglier than adding, but fortunately it's only used in
+ * division which is not used too heavily.
+ */
+#ifndef lbnMulN1_32
+#if defined(mul32_ppmm)
+BNWORD32
+lbnMulSub1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
+{
+ BNWORD32 prod, carry, carryin;
+
+ assert(len > 0);
+
+ BIG(--in;)
+ mul32_ppmm(carry, prod, *in, k);
+ LITTLE(in++;)
+ carry += (BIGLITTLE(*--out,*out++) -= prod) > (BNWORD32)~prod;
+
+ while (--len) {
+ BIG(--in;);
+ carryin = carry;
+ mul32_ppmma(carry, prod, *in, k, carryin);
+ LITTLE(in++;)
+ carry += (BIGLITTLE(*--out,*out++) -= prod) > (BNWORD32)~prod;
+ }
+
+ return carry;
+}
+#elif defined(BNWORD64)
+BNWORD32
+lbnMulSub1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
+{
+ BNWORD64 p;
+ BNWORD32 carry, t;
+
+ assert(len > 0);
+
+ p = (BNWORD64)BIGLITTLE(*--in,*in++) * k;
+ t = BIGLITTLE(*--out,*out);
+ carry = (BNWORD32)(p>>32) + ((BIGLITTLE(*out,*out++)=t-(BNWORD32)p) > t);
+
+ while (--len) {
+ p = (BNWORD64)BIGLITTLE(*--in,*in++) * k + carry;
+ t = BIGLITTLE(*--out,*out);
+ carry = (BNWORD32)(p>>32) +
+ ( (BIGLITTLE(*out,*out++)=t-(BNWORD32)p) > t );
+ }
+
+ return carry;
+}
+#else
+#error No 32x32 -> 64 multiply available for 32-bit bignum package
+#endif
+#endif /* !lbnMulSub1_32 */
+
+/*
+ * Shift n words left "shift" bits. 0 < shift < 32. Returns the
+ * carry, any bits shifted off the left-hand side (0 <= carry < 2^shift).
+ */
+#ifndef lbnLshift_32
+BNWORD32
+lbnLshift_32(BNWORD32 *num, unsigned len, unsigned shift)
+{
+ BNWORD32 x, carry;
+
+ assert(shift > 0);
+ assert(shift < 32);
+
+ carry = 0;
+ while (len--) {
+ BIG(--num;)
+ x = *num;
+ *num = (x<<shift) | carry;
+ LITTLE(num++;)
+ carry = x >> (32-shift);
+ }
+ return carry;
+}
+#endif /* !lbnLshift_32 */
+
+/*
+ * An optimized version of the above, for shifts of 1.
+ * Some machines can use add-with-carry tricks for this.
+ */
+#ifndef lbnDouble_32
+BNWORD32
+lbnDouble_32(BNWORD32 *num, unsigned len)
+{
+ BNWORD32 x, carry;
+
+ carry = 0;
+ while (len--) {
+ BIG(--num;)
+ x = *num;
+ *num = (x<<1) | carry;
+ LITTLE(num++;)
+ carry = x >> (32-1);
+ }
+ return carry;
+}
+#endif /* !lbnDouble_32 */
+
+/*
+ * Shift n words right "shift" bits. 0 < shift < 32. Returns the
+ * carry, any bits shifted off the right-hand side (0 <= carry < 2^shift).
+ */
+#ifndef lbnRshift_32
+BNWORD32
+lbnRshift_32(BNWORD32 *num, unsigned len, unsigned shift)
+{
+ BNWORD32 x, carry = 0;
+
+ assert(shift > 0);
+ assert(shift < 32);
+
+ BIGLITTLE(num -= len, num += len);
+
+ while (len--) {
+ LITTLE(--num;)
+ x = *num;
+ *num = (x>>shift) | carry;
+ BIG(num++;)
+ carry = x << (32-shift);
+ }
+ return carry >> (32-shift);
+}
+#endif /* !lbnRshift_32 */
+
+/*
+ * Multiply two numbers of the given lengths. prod and num2 may overlap,
+ * provided that the low len1 bits of prod are free. (This corresponds
+ * nicely to the place the result is returned from lbnMontReduce_32.)
+ *
+ * TODO: Use Karatsuba multiply. The overlap constraints may have
+ * to get rewhacked.
+ */
+#ifndef lbnMul_32
+void
+lbnMul_32(BNWORD32 *prod, BNWORD32 const *num1, unsigned len1,
+ BNWORD32 const *num2, unsigned len2)
+{
+ /* Special case of zero */
+ if (!len1 || !len2) {
+ lbnZero_32(prod, len1+len2);
+ return;
+ }
+
+ /* Multiply first word */
+ lbnMulN1_32(prod, num1, len1, BIGLITTLE(*--num2,*num2++));
+
+ /*
+ * Add in subsequent words, storing the most significant word,
+ * which is new each time.
+ */
+ while (--len2) {
+ BIGLITTLE(--prod,prod++);
+ BIGLITTLE(*(prod-len1-1),*(prod+len1)) =
+ lbnMulAdd1_32(prod, num1, len1, BIGLITTLE(*--num2,*num2++));
+ }
+}
+#endif /* !lbnMul_32 */
+
+/*
+ * lbnMulX_32 is a square multiply - both inputs are the same length.
+ * It's normally just a macro wrapper around the general multiply,
+ * but might be implementable in assembly more efficiently (such as
+ * when product scanning).
+ */
+#ifndef lbnMulX_32
+#if defined(BNWORD64) && PRODUCT_SCAN
+/*
+ * Test code to see whether product scanning is any faster. It seems
+ * to make the C code slower, so PRODUCT_SCAN is not defined.
+ */
+static void
+lbnMulX_32(BNWORD32 *prod, BNWORD32 const *num1, BNWORD32 const *num2,
+ unsigned len)
+{
+ BNWORD64 x, y;
+ BNWORD32 const *p1, *p2;
+ unsigned carry;
+ unsigned i, j;
+
+ /* Special case of zero */
+ if (!len)
+ return;
+
+ x = (BNWORD64)BIGLITTLE(num1[-1] * num2[-1], num1[0] * num2[0]);
+ BIGLITTLE(*--prod, *prod++) = (BNWORD32)x;
+ x >>= 32;
+
+ for (i = 1; i < len; i++) {
+ carry = 0;
+ p1 = num1;
+ p2 = BIGLITTLE(num2-i-1,num2+i+1);
+ for (j = 0; j <= i; j++) {
+ BIG(y = (BNWORD64)*--p1 * *p2++;)
+ LITTLE(y = (BNWORD64)*p1++ * *--p2;)
+ x += y;
+ carry += (x < y);
+ }
+ BIGLITTLE(*--prod,*prod++) = (BNWORD32)x;
+ x = (x >> 32) | (BNWORD64)carry << 32;
+ }
+ for (i = 1; i < len; i++) {
+ carry = 0;
+ p1 = BIGLITTLE(num1-i,num1+i);
+ p2 = BIGLITTLE(num2-len,num2+len);
+ for (j = i; j < len; j++) {
+ BIG(y = (BNWORD64)*--p1 * *p2++;)
+ LITTLE(y = (BNWORD64)*p1++ * *--p2;)
+ x += y;
+ carry += (x < y);
+ }
+ BIGLITTLE(*--prod,*prod++) = (BNWORD32)x;
+ x = (x >> 32) | (BNWORD64)carry << 32;
+ }
+
+ BIGLITTLE(*--prod,*prod) = (BNWORD32)x;
+}
+#else /* !defined(BNWORD64) || !PRODUCT_SCAN */
+/* Default trivial macro definition */
+#define lbnMulX_32(prod, num1, num2, len) lbnMul_32(prod, num1, len, num2, len)
+#endif /* !defined(BNWORD64) || !PRODUCT_SCAN */
+#endif /* !lbmMulX_32 */
+
+#if !defined(lbnMontMul_32) && defined(BNWORD64) && PRODUCT_SCAN
+/*
+ * Test code for product-scanning multiply. This seems to slow the C
+ * code down rather than speed it up.
+ * This does a multiply and Montgomery reduction together, using the
+ * same loops. The outer loop scans across the product, twice.
+ * The first pass computes the low half of the product and the
+ * Montgomery multipliers. These are stored in the product array,
+ * which contains no data as of yet. x and carry add up the columns
+ * and propagate carries forward.
+ *
+ * The second half multiplies the upper half, adding in the modulus
+ * times the Montgomery multipliers. The results of this multiply
+ * are stored.
+ */
+static void
+lbnMontMul_32(BNWORD32 *prod, BNWORD32 const *num1, BNWORD32 const *num2,
+ BNWORD32 const *mod, unsigned len, BNWORD32 inv)
+{
+ BNWORD64 x, y;
+ BNWORD32 const *p1, *p2, *pm;
+ BNWORD32 *pp;
+ BNWORD32 t;
+ unsigned carry;
+ unsigned i, j;
+
+ /* Special case of zero */
+ if (!len)
+ return;
+
+ /*
+ * This computes directly into the high half of prod, so just
+ * shift the pointer and consider prod only "len" elements long
+ * for the rest of the code.
+ */
+ BIGLITTLE(prod -= len, prod += len);
+
+ /* Pass 1 - compute Montgomery multipliers */
+ /* First iteration can have certain simplifications. */
+ x = (BNWORD64)BIGLITTLE(num1[-1] * num2[-1], num1[0] * num2[0]);
+ BIGLITTLE(prod[-1], prod[0]) = t = inv * (BNWORD32)x;
+ y = (BNWORD64)t * BIGLITTLE(mod[-1],mod[0]);
+ x += y;
+ /* Note: GCC 2.6.3 has a bug if you try to eliminate "carry" */
+ carry = (x < y);
+ assert((BNWORD32)x == 0);
+ x = x >> 32 | (BNWORD64)carry << 32;
+
+ for (i = 1; i < len; i++) {
+ carry = 0;
+ p1 = num1;
+ p2 = BIGLITTLE(num2-i-1,num2+i+1);
+ pp = prod;
+ pm = BIGLITTLE(mod-i-1,mod+i+1);
+ for (j = 0; j < i; j++) {
+ y = (BNWORD64)BIGLITTLE(*--p1 * *p2++, *p1++ * *--p2);
+ x += y;
+ carry += (x < y);
+ y = (BNWORD64)BIGLITTLE(*--pp * *pm++, *pp++ * *--pm);
+ x += y;
+ carry += (x < y);
+ }
+ y = (BNWORD64)BIGLITTLE(p1[-1] * p2[0], p1[0] * p2[-1]);
+ x += y;
+ carry += (x < y);
+ assert(BIGLITTLE(pp == prod-i, pp == prod+i));
+ BIGLITTLE(pp[-1], pp[0]) = t = inv * (BNWORD32)x;
+ assert(BIGLITTLE(pm == mod-1, pm == mod+1));
+ y = (BNWORD64)t * BIGLITTLE(pm[0],pm[-1]);
+ x += y;
+ carry += (x < y);
+ assert((BNWORD32)x == 0);
+ x = x >> 32 | (BNWORD64)carry << 32;
+ }
+
+ /* Pass 2 - compute reduced product and store */
+ for (i = 1; i < len; i++) {
+ carry = 0;
+ p1 = BIGLITTLE(num1-i,num1+i);
+ p2 = BIGLITTLE(num2-len,num2+len);
+ pm = BIGLITTLE(mod-i,mod+i);
+ pp = BIGLITTLE(prod-len,prod+len);
+ for (j = i; j < len; j++) {
+ y = (BNWORD64)BIGLITTLE(*--p1 * *p2++, *p1++ * *--p2);
+ x += y;
+ carry += (x < y);
+ y = (BNWORD64)BIGLITTLE(*--pm * *pp++, *pm++ * *--pp);
+ x += y;
+ carry += (x < y);
+ }
+ assert(BIGLITTLE(pm == mod-len, pm == mod+len));
+ assert(BIGLITTLE(pp == prod-i, pp == prod+i));
+ BIGLITTLE(pp[0],pp[-1]) = (BNWORD32)x;
+ x = (x >> 32) | (BNWORD64)carry << 32;
+ }
+
+ /* Last round of second half, simplified. */
+ BIGLITTLE(*(prod-len),*(prod+len-1)) = (BNWORD32)x;
+ carry = (x >> 32);
+
+ while (carry)
+ carry -= lbnSubN_32(prod, mod, len);
+ while (lbnCmp_32(prod, mod, len) >= 0)
+ (void)lbnSubN_32(prod, mod, len);
+}
+/* Suppress later definition */
+#define lbnMontMul_32 lbnMontMul_32
+#endif
+
+#if !defined(lbnSquare_32) && defined(BNWORD64) && PRODUCT_SCAN
+/*
+ * Trial code for product-scanning squaring. This seems to slow the C
+ * code down rather than speed it up.
+ */
+void
+lbnSquare_32(BNWORD32 *prod, BNWORD32 const *num, unsigned len)
+{
+ BNWORD64 x, y, z;
+ BNWORD32 const *p1, *p2;
+ unsigned carry;
+ unsigned i, j;
+
+ /* Special case of zero */
+ if (!len)
+ return;
+
+ /* Word 0 of product */
+ x = (BNWORD64)BIGLITTLE(num[-1] * num[-1], num[0] * num[0]);
+ BIGLITTLE(*--prod, *prod++) = (BNWORD32)x;
+ x >>= 32;
+
+ /* Words 1 through len-1 */
+ for (i = 1; i < len; i++) {
+ carry = 0;
+ y = 0;
+ p1 = num;
+ p2 = BIGLITTLE(num-i-1,num+i+1);
+ for (j = 0; j < (i+1)/2; j++) {
+ BIG(z = (BNWORD64)*--p1 * *p2++;)
+ LITTLE(z = (BNWORD64)*p1++ * *--p2;)
+ y += z;
+ carry += (y < z);
+ }
+ y += z = y;
+ carry += carry + (y < z);
+ if ((i & 1) == 0) {
+ assert(BIGLITTLE(--p1 == p2, p1 == --p2));
+ BIG(z = (BNWORD64)*p2 * *p2;)
+ LITTLE(z = (BNWORD64)*p1 * *p1;)
+ y += z;
+ carry += (y < z);
+ }
+ x += y;
+ carry += (x < y);
+ BIGLITTLE(*--prod,*prod++) = (BNWORD32)x;
+ x = (x >> 32) | (BNWORD64)carry << 32;
+ }
+ /* Words len through 2*len-2 */
+ for (i = 1; i < len; i++) {
+ carry = 0;
+ y = 0;
+ p1 = BIGLITTLE(num-i,num+i);
+ p2 = BIGLITTLE(num-len,num+len);
+ for (j = 0; j < (len-i)/2; j++) {
+ BIG(z = (BNWORD64)*--p1 * *p2++;)
+ LITTLE(z = (BNWORD64)*p1++ * *--p2;)
+ y += z;
+ carry += (y < z);
+ }
+ y += z = y;
+ carry += carry + (y < z);
+ if ((len-i) & 1) {
+ assert(BIGLITTLE(--p1 == p2, p1 == --p2));
+ BIG(z = (BNWORD64)*p2 * *p2;)
+ LITTLE(z = (BNWORD64)*p1 * *p1;)
+ y += z;
+ carry += (y < z);
+ }
+ x += y;
+ carry += (x < y);
+ BIGLITTLE(*--prod,*prod++) = (BNWORD32)x;
+ x = (x >> 32) | (BNWORD64)carry << 32;
+ }
+
+ /* Word 2*len-1 */
+ BIGLITTLE(*--prod,*prod) = (BNWORD32)x;
+}
+/* Suppress later definition */
+#define lbnSquare_32 lbnSquare_32
+#endif
+
+/*
+ * Square a number, using optimized squaring to reduce the number of
+ * primitive multiples that are executed. There may not be any
+ * overlap of the input and output.
+ *
+ * Technique: Consider the partial products in the multiplication
+ * of "abcde" by itself:
+ *
+ * a b c d e
+ * * a b c d e
+ * ==================
+ * ae be ce de ee
+ * ad bd cd dd de
+ * ac bc cc cd ce
+ * ab bb bc bd be
+ * aa ab ac ad ae
+ *
+ * Note that everything above the main diagonal:
+ * ae be ce de = (abcd) * e
+ * ad bd cd = (abc) * d
+ * ac bc = (ab) * c
+ * ab = (a) * b
+ *
+ * is a copy of everything below the main diagonal:
+ * de
+ * cd ce
+ * bc bd be
+ * ab ac ad ae
+ *
+ * Thus, the sum is 2 * (off the diagonal) + diagonal.
+ *
+ * This is accumulated beginning with the diagonal (which
+ * consist of the squares of the digits of the input), which is then
+ * divided by two, the off-diagonal added, and multiplied by two
+ * again. The low bit is simply a copy of the low bit of the
+ * input, so it doesn't need special care.
+ *
+ * TODO: Merge the shift by 1 with the squaring loop.
+ * TODO: Use Karatsuba. (a*W+b)^2 = a^2 * (W^2+W) + b^2 * (W+1) - (a-b)^2 * W.
+ */
+#ifndef lbnSquare_32
+void
+lbnSquare_32(BNWORD32 *prod, BNWORD32 const *num, unsigned len)
+{
+ BNWORD32 t;
+ BNWORD32 *prodx = prod; /* Working copy of the argument */
+ BNWORD32 const *numx = num; /* Working copy of the argument */
+ unsigned lenx = len; /* Working copy of the argument */
+
+ if (!len)
+ return;
+
+ /* First, store all the squares */
+ while (lenx--) {
+#ifdef mul32_ppmm
+ BNWORD32 ph, pl;
+ t = BIGLITTLE(*--numx,*numx++);
+ mul32_ppmm(ph,pl,t,t);
+ BIGLITTLE(*--prodx,*prodx++) = pl;
+ BIGLITTLE(*--prodx,*prodx++) = ph;
+#elif defined(BNWORD64) /* use BNWORD64 */
+ BNWORD64 p;
+ t = BIGLITTLE(*--numx,*numx++);
+ p = (BNWORD64)t * t;
+ BIGLITTLE(*--prodx,*prodx++) = (BNWORD32)p;
+ BIGLITTLE(*--prodx,*prodx++) = (BNWORD32)(p>>32);
+#else /* Use lbnMulN1_32 */
+ t = BIGLITTLE(numx[-1],*numx);
+ lbnMulN1_32(prodx, numx, 1, t);
+ BIGLITTLE(--numx,numx++);
+ BIGLITTLE(prodx -= 2, prodx += 2);
+#endif
+ }
+ /* Then, shift right 1 bit */
+ (void)lbnRshift_32(prod, 2*len, 1);
+
+ /* Then, add in the off-diagonal sums */
+ lenx = len;
+ numx = num;
+ prodx = prod;
+ while (--lenx) {
+ t = BIGLITTLE(*--numx,*numx++);
+ BIGLITTLE(--prodx,prodx++);
+ t = lbnMulAdd1_32(prodx, numx, lenx, t);
+ lbnAdd1_32(BIGLITTLE(prodx-lenx,prodx+lenx), lenx+1, t);
+ BIGLITTLE(--prodx,prodx++);
+ }
+
+ /* Shift it back up */
+ lbnDouble_32(prod, 2*len);
+
+ /* And set the low bit appropriately */
+ BIGLITTLE(prod[-1],prod[0]) |= BIGLITTLE(num[-1],num[0]) & 1;
+}
+#endif /* !lbnSquare_32 */
+
+/*
+ * lbnNorm_32 - given a number, return a modified length such that the
+ * most significant digit is non-zero. Zero-length input is okay.
+ */
+#ifndef lbnNorm_32
+unsigned
+lbnNorm_32(BNWORD32 const *num, unsigned len)
+{
+ BIGLITTLE(num -= len,num += len);
+ while (len && BIGLITTLE(*num++,*--num) == 0)
+ --len;
+ return len;
+}
+#endif /* lbnNorm_32 */
+
+/*
+ * lbnBits_32 - return the number of significant bits in the array.
+ * It starts by normalizing the array. Zero-length input is okay.
+ * Then assuming there's anything to it, it fetches the high word,
+ * generates a bit length by multiplying the word length by 32, and
+ * subtracts off 32/2, 32/4, 32/8, ... bits if the high bits are clear.
+ */
+#ifndef lbnBits_32
+unsigned
+lbnBits_32(BNWORD32 const *num, unsigned len)
+{
+ BNWORD32 t;
+ unsigned i;
+
+ len = lbnNorm_32(num, len);
+ if (len) {
+ t = BIGLITTLE(*(num-len),*(num+(len-1)));
+ assert(t);
+ len *= 32;
+ i = 32/2;
+ do {
+ if (t >> i)
+ t >>= i;
+ else
+ len -= i;
+ } while ((i /= 2) != 0);
+ }
+ return len;
+}
+#endif /* lbnBits_32 */
+
+/*
+ * If defined, use hand-rolled divide rather than compiler's native.
+ * If the machine doesn't do it in line, the manual code is probably
+ * faster, since it can assume normalization and the fact that the
+ * quotient will fit into 32 bits, which a general 64-bit divide
+ * in a compiler's run-time library can't do.
+ */
+#ifndef BN_SLOW_DIVIDE_64
+/* Assume that divisors of more than thirty-two bits are slow */
+#define BN_SLOW_DIVIDE_64 (64 > 0x20)
+#endif
+
+/*
+ * Return (nh<<32|nl) % d, and place the quotient digit into *q.
+ * It is guaranteed that nh < d, and that d is normalized (with its high
+ * bit set). If we have a double-width type, it's easy. If not, ooh,
+ * yuk!
+ */
+#ifndef lbnDiv21_32
+#if defined(BNWORD64) && !BN_SLOW_DIVIDE_64
+BNWORD32
+lbnDiv21_32(BNWORD32 *q, BNWORD32 nh, BNWORD32 nl, BNWORD32 d)
+{
+ BNWORD64 n = (BNWORD64)nh << 32 | nl;
+
+ /* Divisor must be normalized */
+ assert(d >> (32-1) == 1);
+
+ *q = n / d;
+ return n % d;
+}
+#else
+/*
+ * This is where it gets ugly.
+ *
+ * Do the division in two halves, using Algorithm D from section 4.3.1
+ * of Knuth. Note Theorem B from that section, that the quotient estimate
+ * is never more than the true quotient, and is never more than two
+ * too low.
+ *
+ * The mapping onto conventional long division is (everything a half word):
+ * _____________qh___ql_
+ * dh dl ) nh.h nh.l nl.h nl.l
+ * - (qh * d)
+ * -----------
+ * rrrr rrrr nl.l
+ * - (ql * d)
+ * -----------
+ * rrrr rrrr
+ *
+ * The implicit 3/2-digit d*qh and d*ql subtractors are computed this way:
+ * First, estimate a q digit so that nh/dh works. Subtracting qh*dh from
+ * the (nh.h nh.l) list leaves a 1/2-word remainder r. Then compute the
+ * low part of the subtractor, qh * dl. This also needs to be subtracted
+ * from (nh.h nh.l nl.h) to get the final remainder. So we take the
+ * remainder, which is (nh.h nh.l) - qh*dl, shift it and add in nl.h, and
+ * try to subtract qh * dl from that. Since the remainder is 1/2-word
+ * long, shifting and adding nl.h results in a single word r.
+ * It is possible that the remainder we're working with, r, is less than
+ * the product qh * dl, if we estimated qh too high. The estimation
+ * technique can produce a qh that is too large (never too small), leading
+ * to r which is too small. In that case, decrement the digit qh, add
+ * shifted dh to r (to correct for that error), and subtract dl from the
+ * product we're comparing r with. That's the "correct" way to do it, but
+ * just adding dl to r instead of subtracting it from the product is
+ * equivalent and a lot simpler. You just have to watch out for overflow.
+ *
+ * The process is repeated with (rrrr rrrr nl.l) for the low digit of the
+ * quotient ql.
+ *
+ * The various uses of 32/2 for shifts are because of the note about
+ * automatic editing of this file at the very top of the file.
+ */
+#define highhalf(x) ( (x) >> 32/2 )
+#define lowhalf(x) ( (x) & (((BNWORD32)1 << 32/2)-1) )
+BNWORD32
+lbnDiv21_32(BNWORD32 *q, BNWORD32 nh, BNWORD32 nl, BNWORD32 d)
+{
+ BNWORD32 dh = highhalf(d), dl = lowhalf(d);
+ BNWORD32 qh, ql, prod, r;
+
+ /* Divisor must be normalized */
+ assert((d >> (32-1)) == 1);
+
+ /* Do first half-word of division */
+ qh = nh / dh;
+ r = nh % dh;
+ prod = qh * dl;
+
+ /*
+ * Add next half-word of numerator to remainder and correct.
+ * qh may be up to two too large.
+ */
+ r = (r << (32/2)) | highhalf(nl);
+ if (r < prod) {
+ --qh; r += d;
+ if (r >= d && r < prod) {
+ --qh; r += d;
+ }
+ }
+ r -= prod;
+
+ /* Do second half-word of division */
+ ql = r / dh;
+ r = r % dh;
+ prod = ql * dl;
+
+ r = (r << (32/2)) | lowhalf(nl);
+ if (r < prod) {
+ --ql; r += d;
+ if (r >= d && r < prod) {
+ --ql; r += d;
+ }
+ }
+ r -= prod;
+
+ *q = (qh << (32/2)) | ql;
+
+ return r;
+}
+#endif
+#endif /* lbnDiv21_32 */
+
+
+/*
+ * In the division functions, the dividend and divisor are referred to
+ * as "n" and "d", which stand for "numerator" and "denominator".
+ *
+ * The quotient is (nlen-dlen+1) digits long. It may be overlapped with
+ * the high (nlen-dlen) words of the dividend, but one extra word is needed
+ * on top to hold the top word.
+ */
+
+/*
+ * Divide an n-word number by a 1-word number, storing the remainder
+ * and n-1 words of the n-word quotient. The high word is returned.
+ * It IS legal for rem to point to the same address as n, and for
+ * q to point one word higher.
+ *
+ * TODO: If BN_SLOW_DIVIDE_64, add a divnhalf_32 which uses 32-bit
+ * dividends if the divisor is half that long.
+ * TODO: Shift the dividend on the fly to avoid the last division and
+ * instead have a remainder that needs shifting.
+ * TODO: Use reciprocals rather than dividing.
+ */
+#ifndef lbnDiv1_32
+BNWORD32
+lbnDiv1_32(BNWORD32 *q, BNWORD32 *rem, BNWORD32 const *n, unsigned len,
+ BNWORD32 d)
+{
+ unsigned shift;
+ unsigned xlen;
+ BNWORD32 r;
+ BNWORD32 qhigh;
+
+ assert(len > 0);
+ assert(d);
+
+ if (len == 1) {
+ r = *n;
+ *rem = r%d;
+ return r/d;
+ }
+
+ shift = 0;
+ r = d;
+ xlen = 32/2;
+ do {
+ if (r >> xlen)
+ r >>= xlen;
+ else
+ shift += xlen;
+ } while ((xlen /= 2) != 0);
+ assert((d >> (32-1-shift)) == 1);
+ d <<= shift;
+
+ BIGLITTLE(q -= len-1,q += len-1);
+ BIGLITTLE(n -= len,n += len);
+
+ r = BIGLITTLE(*n++,*--n);
+ if (r < d) {
+ qhigh = 0;
+ } else {
+ qhigh = r/d;
+ r %= d;
+ }
+
+ xlen = len;
+ while (--xlen)
+ r = lbnDiv21_32(BIGLITTLE(q++,--q), r, BIGLITTLE(*n++,*--n), d);
+
+ /*
+ * Final correction for shift - shift the quotient up "shift"
+ * bits, and merge in the extra bits of quotient. Then reduce
+ * the final remainder mod the real d.
+ */
+ if (shift) {
+ d >>= shift;
+ qhigh = (qhigh << shift) | lbnLshift_32(q, len-1, shift);
+ BIGLITTLE(q[-1],*q) |= r/d;
+ r %= d;
+ }
+ *rem = r;
+
+ return qhigh;
+}
+#endif
+
+/*
+ * This function performs a "quick" modulus of a number with a divisor
+ * d which is guaranteed to be at most sixteen bits, i.e. less than 65536.
+ * This applies regardless of the word size the library is compiled with.
+ *
+ * This function is important to prime generation, for sieving.
+ */
+#ifndef lbnModQ_32
+/* If there's a custom lbnMod21_32, no normalization needed */
+#ifdef lbnMod21_32
+unsigned
+lbnModQ_32(BNWORD32 const *n, unsigned len, unsigned d)
+{
+ unsigned i, shift;
+ BNWORD32 r;
+
+ assert(len > 0);
+
+ BIGLITTLE(n -= len,n += len);
+
+ /* Try using a compare to avoid the first divide */
+ r = BIGLITTLE(*n++,*--n);
+ if (r >= d)
+ r %= d;
+ while (--len)
+ r = lbnMod21_32(r, BIGLITTLE(*n++,*--n), d);
+
+ return r;
+}
+#elif defined(BNWORD64) && !BN_SLOW_DIVIDE_64
+unsigned
+lbnModQ_32(BNWORD32 const *n, unsigned len, unsigned d)
+{
+ BNWORD32 r;
+
+ if (!--len)
+ return BIGLITTLE(n[-1],n[0]) % d;
+
+ BIGLITTLE(n -= len,n += len);
+ r = BIGLITTLE(n[-1],n[0]);
+
+ do {
+ r = (BNWORD32)((((BNWORD64)r<<32) | BIGLITTLE(*n++,*--n)) % d);
+ } while (--len);
+
+ return r;
+}
+#elif 32 >= 0x20
+/*
+ * If the single word size can hold 65535*65536, then this function
+ * is avilable.
+ */
+#ifndef highhalf
+#define highhalf(x) ( (x) >> 32/2 )
+#define lowhalf(x) ( (x) & ((1 << 32/2)-1) )
+#endif
+unsigned
+lbnModQ_32(BNWORD32 const *n, unsigned len, unsigned d)
+{
+ BNWORD32 r, x;
+
+ BIGLITTLE(n -= len,n += len);
+
+ r = BIGLITTLE(*n++,*--n);
+ while (--len) {
+ x = BIGLITTLE(*n++,*--n);
+ r = (r%d << 32/2) | highhalf(x);
+ r = (r%d << 32/2) | lowhalf(x);
+ }
+
+ return r%d;
+}
+#else
+/* Default case - use lbnDiv21_32 */
+unsigned
+lbnModQ_32(BNWORD32 const *n, unsigned len, unsigned d)
+{
+ unsigned i, shift;
+ BNWORD32 r;
+ BNWORD32 q;
+
+ assert(len > 0);
+
+ shift = 0;
+ r = d;
+ i = 32;
+ while (i /= 2) {
+ if (r >> i)
+ r >>= i;
+ else
+ shift += i;
+ }
+ assert(d >> (32-1-shift) == 1);
+ d <<= shift;
+
+ BIGLITTLE(n -= len,n += len);
+
+ r = BIGLITTLE(*n++,*--n);
+ if (r >= d)
+ r %= d;
+
+ while (--len)
+ r = lbnDiv21_32(&q, r, BIGLITTLE(*n++,*--n), d);
+
+ /*
+ * Final correction for shift - shift the quotient up "shift"
+ * bits, and merge in the extra bits of quotient. Then reduce
+ * the final remainder mod the real d.
+ */
+ if (shift)
+ r %= d >> shift;
+
+ return r;
+}
+#endif
+#endif /* lbnModQ_32 */
+
+/*
+ * Reduce n mod d and return the quotient. That is, find:
+ * q = n / d;
+ * n = n % d;
+ * d is altered during the execution of this subroutine by normalizing it.
+ * It must already have its most significant word non-zero; it is shifted
+ * so its most significant bit is non-zero.
+ *
+ * The quotient q is nlen-dlen+1 words long. To make it possible to
+ * overlap the quptient with the input (you can store it in the high dlen
+ * words), the high word of the quotient is *not* stored, but is returned.
+ * (If all you want is the remainder, you don't care about it, anyway.)
+ *
+ * This uses algorithm D from Knuth (4.3.1), except that we do binary
+ * (shift) normalization of the divisor. WARNING: This is hairy!
+ *
+ * This function is used for some modular reduction, but it is not used in
+ * the modular exponentiation loops; they use Montgomery form and the
+ * corresponding, more efficient, Montgomery reduction. This code
+ * is needed for the conversion to Montgomery form, however, so it
+ * has to be here and it might as well be reasonably efficient.
+ *
+ * The overall operation is as follows ("top" and "up" refer to the
+ * most significant end of the number; "bottom" and "down", the least):
+ *
+ * - Shift the divisor up until the most significant bit is set.
+ * - Shift the dividend up the same amount. This will produce the
+ * correct quotient, and the remainder can be recovered by shifting
+ * it back down the same number of bits. This may produce an overflow
+ * word, but the word is always strictly less than the most significant
+ * divisor word.
+ * - Estimate the first quotient digit qhat:
+ * - First take the top two words (one of which is the overflow) of the
+ * dividend and divide by the top word of the divisor:
+ * qhat = (nh,nm)/dh. This qhat is >= the correct quotient digit
+ * and, since dh is normalized, it is at most two over.
+ * - Second, correct by comparing the top three words. If
+ * (dh,dl) * qhat > (nh,nm,ml), decrease qhat and try again.
+ * The second iteration can be simpler because there can't be a third.
+ * The computation can be simplified by subtracting dh*qhat from
+ * both sides, suitably shifted. This reduces the left side to
+ * dl*qhat. On the right, (nh,nm)-dh*qhat is simply the
+ * remainder r from (nh,nm)%dh, so the right is (r,nl).
+ * This produces qhat that is almost always correct and at
+ * most (prob ~ 2/2^32) one too high.
+ * - Subtract qhat times the divisor (suitably shifted) from the dividend.
+ * If there is a borrow, qhat was wrong, so decrement it
+ * and add the divisor back in (once).
+ * - Store the final quotient digit qhat in the quotient array q.
+ *
+ * Repeat the quotient digit computation for successive digits of the
+ * quotient until the whole quotient has been computed. Then shift the
+ * divisor and the remainder down to correct for the normalization.
+ *
+ * TODO: Special case 2-word divisors.
+ * TODO: Use reciprocals rather than dividing.
+ */
+#ifndef divn_32
+BNWORD32
+lbnDiv_32(BNWORD32 *q, BNWORD32 *n, unsigned nlen, BNWORD32 *d, unsigned dlen)
+{
+ BNWORD32 nh,nm,nl; /* Top three words of the dividend */
+ BNWORD32 dh,dl; /* Top two words of the divisor */
+ BNWORD32 qhat; /* Extimate of quotient word */
+ BNWORD32 r; /* Remainder from quotient estimate division */
+ BNWORD32 qhigh; /* High word of quotient */
+ unsigned i; /* Temp */
+ unsigned shift; /* Bits shifted by normalization */
+ unsigned qlen = nlen-dlen; /* Size of quotient (less 1) */
+#ifdef mul32_ppmm
+ BNWORD32 t32;
+#elif defined(BNWORD64)
+ BNWORD64 t64;
+#else /* use lbnMulN1_32 */
+ BNWORD32 t2[2];
+#define t2high BIGLITTLE(t2[0],t2[1])
+#define t2low BIGLITTLE(t2[1],t2[0])
+#endif
+
+ assert(dlen);
+ assert(nlen >= dlen);
+
+ /*
+ * Special cases for short divisors. The general case uses the
+ * top top 2 digits of the divisor (d) to estimate a quotient digit,
+ * so it breaks if there are fewer digits available. Thus, we need
+ * special cases for a divisor of length 1. A divisor of length
+ * 2 can have a *lot* of administrivia overhead removed removed,
+ * so it's probably worth special-casing that case, too.
+ */
+ if (dlen == 1)
+ return lbnDiv1_32(q, BIGLITTLE(n-1,n), n, nlen,
+ BIGLITTLE(d[-1],d[0]));
+
+#if 0
+ /*
+ * @@@ This is not yet written... The general loop will do,
+ * albeit less efficiently
+ */
+ if (dlen == 2) {
+ /*
+ * divisor two digits long:
+ * use the 3/2 technique from Knuth, but we know
+ * it's exact.
+ */
+ dh = BIGLITTLE(d[-1],d[0]);
+ dl = BIGLITTLE(d[-2],d[1]);
+ shift = 0;
+ if ((sh & ((BNWORD32)1 << 32-1-shift)) == 0) {
+ do {
+ shift++;
+ } while (dh & (BNWORD32)1<<32-1-shift) == 0);
+ dh = dh << shift | dl >> (32-shift);
+ dl <<= shift;
+
+
+ }
+
+
+ for (shift = 0; (dh & (BNWORD32)1 << 32-1-shift)) == 0; shift++)
+ ;
+ if (shift) {
+ }
+ dh = dh << shift | dl >> (32-shift);
+ shift = 0;
+ while (dh
+ }
+#endif
+
+ dh = BIGLITTLE(*(d-dlen),*(d+(dlen-1)));
+ assert(dh);
+
+ /* Normalize the divisor */
+ shift = 0;
+ r = dh;
+ i = 32/2;
+ do {
+ if (r >> i)
+ r >>= i;
+ else
+ shift += i;
+ } while ((i /= 2) != 0);
+
+ nh = 0;
+ if (shift) {
+ lbnLshift_32(d, dlen, shift);
+ dh = BIGLITTLE(*(d-dlen),*(d+(dlen-1)));
+ nh = lbnLshift_32(n, nlen, shift);
+ }
+
+ /* Assert that dh is now normalized */
+ assert(dh >> (32-1));
+
+ /* Also get the second-most significant word of the divisor */
+ dl = BIGLITTLE(*(d-(dlen-1)),*(d+(dlen-2)));
+
+ /*
+ * Adjust pointers: n to point to least significant end of first
+ * first subtract, and q to one the most-significant end of the
+ * quotient array.
+ */
+ BIGLITTLE(n -= qlen,n += qlen);
+ BIGLITTLE(q -= qlen,q += qlen);
+
+ /* Fetch the most significant stored word of the dividend */
+ nm = BIGLITTLE(*(n-dlen),*(n+(dlen-1)));
+
+ /*
+ * Compute the first digit of the quotient, based on the
+ * first two words of the dividend (the most significant of which
+ * is the overflow word h).
+ */
+ if (nh) {
+ assert(nh < dh);
+ r = lbnDiv21_32(&qhat, nh, nm, dh);
+ } else if (nm >= dh) {
+ qhat = nm/dh;
+ r = nm % dh;
+ } else { /* Quotient is zero */
+ qhigh = 0;
+ goto divloop;
+ }
+
+ /* Now get the third most significant word of the dividend */
+ nl = BIGLITTLE(*(n-(dlen-1)),*(n+(dlen-2)));
+
+ /*
+ * Correct qhat, the estimate of quotient digit.
+ * qhat can only be high, and at most two words high,
+ * so the loop can be unrolled and abbreviated.
+ */
+#ifdef mul32_ppmm
+ mul32_ppmm(nm, t32, qhat, dl);
+ if (nm > r || (nm == r && t32 > nl)) {
+ /* Decrement qhat and adjust comparison parameters */
+ qhat--;
+ if ((r += dh) >= dh) {
+ nm -= (t32 < dl);
+ t32 -= dl;
+ if (nm > r || (nm == r && t32 > nl))
+ qhat--;
+ }
+ }
+#elif defined(BNWORD64)
+ t64 = (BNWORD64)qhat * dl;
+ if (t64 > ((BNWORD64)r << 32) + nl) {
+ /* Decrement qhat and adjust comparison parameters */
+ qhat--;
+ if ((r += dh) > dh) {
+ t64 -= dl;
+ if (t64 > ((BNWORD64)r << 32) + nl)
+ qhat--;
+ }
+ }
+#else /* Use lbnMulN1_32 */
+ lbnMulN1_32(BIGLITTLE(t2+2,t2), &dl, 1, qhat);
+ if (t2high > r || (t2high == r && t2low > nl)) {
+ /* Decrement qhat and adjust comparison parameters */
+ qhat--;
+ if ((r += dh) >= dh) {
+ t2high -= (t2low < dl);
+ t2low -= dl;
+ if (t2high > r || (t2high == r && t2low > nl))
+ qhat--;
+ }
+ }
+#endif
+
+ /* Do the multiply and subtract */
+ r = lbnMulSub1_32(n, d, dlen, qhat);
+ /* If there was a borrow, add back once. */
+ if (r > nh) { /* Borrow? */
+ (void)lbnAddN_32(n, d, dlen);
+ qhat--;
+ }
+
+ /* Remember the first quotient digit. */
+ qhigh = qhat;
+
+ /* Now, the main division loop: */
+divloop:
+ while (qlen--) {
+
+ /* Advance n */
+ nh = BIGLITTLE(*(n-dlen),*(n+(dlen-1)));
+ BIGLITTLE(++n,--n);
+ nm = BIGLITTLE(*(n-dlen),*(n+(dlen-1)));
+
+ if (nh == dh) {
+ qhat = ~(BNWORD32)0;
+ /* Optimized computation of r = (nh,nm) - qhat * dh */
+ r = nh + nm;
+ if (r < nh)
+ goto subtract;
+ } else {
+ assert(nh < dh);
+ r = lbnDiv21_32(&qhat, nh, nm, dh);
+ }
+
+ nl = BIGLITTLE(*(n-(dlen-1)),*(n+(dlen-2)));
+#ifdef mul32_ppmm
+ mul32_ppmm(nm, t32, qhat, dl);
+ if (nm > r || (nm == r && t32 > nl)) {
+ /* Decrement qhat and adjust comparison parameters */
+ qhat--;
+ if ((r += dh) >= dh) {
+ nm -= (t32 < dl);
+ t32 -= dl;
+ if (nm > r || (nm == r && t32 > nl))
+ qhat--;
+ }
+ }
+#elif defined(BNWORD64)
+ t64 = (BNWORD64)qhat * dl;
+ if (t64 > ((BNWORD64)r<<32) + nl) {
+ /* Decrement qhat and adjust comparison parameters */
+ qhat--;
+ if ((r += dh) >= dh) {
+ t64 -= dl;
+ if (t64 > ((BNWORD64)r << 32) + nl)
+ qhat--;
+ }
+ }
+#else /* Use lbnMulN1_32 */
+ lbnMulN1_32(BIGLITTLE(t2+2,t2), &dl, 1, qhat);
+ if (t2high > r || (t2high == r && t2low > nl)) {
+ /* Decrement qhat and adjust comparison parameters */
+ qhat--;
+ if ((r += dh) >= dh) {
+ t2high -= (t2low < dl);
+ t2low -= dl;
+ if (t2high > r || (t2high == r && t2low > nl))
+ qhat--;
+ }
+ }
+#endif
+
+ /*
+ * As a point of interest, note that it is not worth checking
+ * for qhat of 0 or 1 and installing special-case code. These
+ * occur with probability 2^-32, so spending 1 cycle to check
+ * for them is only worth it if we save more than 2^15 cycles,
+ * and a multiply-and-subtract for numbers in the 1024-bit
+ * range just doesn't take that long.
+ */
+subtract:
+ /*
+ * n points to the least significant end of the substring
+ * of n to be subtracted from. qhat is either exact or
+ * one too large. If the subtract gets a borrow, it was
+ * one too large and the divisor is added back in. It's
+ * a dlen+1 word add which is guaranteed to produce a
+ * carry out, so it can be done very simply.
+ */
+ r = lbnMulSub1_32(n, d, dlen, qhat);
+ if (r > nh) { /* Borrow? */
+ (void)lbnAddN_32(n, d, dlen);
+ qhat--;
+ }
+ /* Store the quotient digit */
+ BIGLITTLE(*q++,*--q) = qhat;
+ }
+ /* Tah dah! */
+
+ if (shift) {
+ lbnRshift_32(d, dlen, shift);
+ lbnRshift_32(n, dlen, shift);
+ }
+
+ return qhigh;
+}
+#endif
+
+/*
+ * Find the negative multiplicative inverse of x (x must be odd!) modulo 2^32.
+ *
+ * This just performs Newton's iteration until it gets the
+ * inverse. The initial estimate is always correct to 3 bits, and
+ * sometimes 4. The number of valid bits doubles each iteration.
+ * (To prove it, assume x * y == 1 (mod 2^n), and introduce a variable
+ * for the error mod 2^2n. x * y == 1 + k*2^n (mod 2^2n) and follow
+ * the iteration through.)
+ */
+#ifndef lbnMontInv1_32
+BNWORD32
+lbnMontInv1_32(BNWORD32 const x)
+{
+ BNWORD32 y = x, z;
+
+ assert(x & 1);
+
+ while ((z = x*y) != 1)
+ y *= 2 - z;
+ return -y;
+}
+#endif /* !lbnMontInv1_32 */
+
+#if defined(BNWORD64) && PRODUCT_SCAN
+/*
+ * Test code for product-scanning Montgomery reduction.
+ * This seems to slow the C code down rather than speed it up.
+ *
+ * The first loop computes the Montgomery multipliers, storing them over
+ * the low half of the number n.
+ *
+ * The second half multiplies the upper half, adding in the modulus
+ * times the Montgomery multipliers. The results of this multiply
+ * are stored.
+ */
+void
+lbnMontReduce_32(BNWORD32 *n, BNWORD32 const *mod, unsigned mlen, BNWORD32 inv)
+{
+ BNWORD64 x, y;
+ BNWORD32 const *pm;
+ BNWORD32 *pn;
+ BNWORD32 t;
+ unsigned carry;
+ unsigned i, j;
+
+ /* Special case of zero */
+ if (!mlen)
+ return;
+
+ /* Pass 1 - compute Montgomery multipliers */
+ /* First iteration can have certain simplifications. */
+ t = BIGLITTLE(n[-1],n[0]);
+ x = t;
+ t *= inv;
+ BIGLITTLE(n[-1], n[0]) = t;
+ x += (BNWORD64)t * BIGLITTLE(mod[-1],mod[0]); /* Can't overflow */
+ assert((BNWORD32)x == 0);
+ x = x >> 32;
+
+ for (i = 1; i < mlen; i++) {
+ carry = 0;
+ pn = n;
+ pm = BIGLITTLE(mod-i-1,mod+i+1);
+ for (j = 0; j < i; j++) {
+ y = (BNWORD64)BIGLITTLE(*--pn * *pm++, *pn++ * *--pm);
+ x += y;
+ carry += (x < y);
+ }
+ assert(BIGLITTLE(pn == n-i, pn == n+i));
+ y = t = BIGLITTLE(pn[-1], pn[0]);
+ x += y;
+ carry += (x < y);
+ BIGLITTLE(pn[-1], pn[0]) = t = inv * (BNWORD32)x;
+ assert(BIGLITTLE(pm == mod-1, pm == mod+1));
+ y = (BNWORD64)t * BIGLITTLE(pm[0],pm[-1]);
+ x += y;
+ carry += (x < y);
+ assert((BNWORD32)x == 0);
+ x = x >> 32 | (BNWORD64)carry << 32;
+ }
+
+ BIGLITTLE(n -= mlen, n += mlen);
+
+ /* Pass 2 - compute upper words and add to n */
+ for (i = 1; i < mlen; i++) {
+ carry = 0;
+ pm = BIGLITTLE(mod-i,mod+i);
+ pn = n;
+ for (j = i; j < mlen; j++) {
+ y = (BNWORD64)BIGLITTLE(*--pm * *pn++, *pm++ * *--pn);
+ x += y;
+ carry += (x < y);
+ }
+ assert(BIGLITTLE(pm == mod-mlen, pm == mod+mlen));
+ assert(BIGLITTLE(pn == n+mlen-i, pn == n-mlen+i));
+ y = t = BIGLITTLE(*(n-i),*(n+i-1));
+ x += y;
+ carry += (x < y);
+ BIGLITTLE(*(n-i),*(n+i-1)) = (BNWORD32)x;
+ x = (x >> 32) | (BNWORD64)carry << 32;
+ }
+
+ /* Last round of second half, simplified. */
+ t = BIGLITTLE(*(n-mlen),*(n+mlen-1));
+ x += t;
+ BIGLITTLE(*(n-mlen),*(n+mlen-1)) = (BNWORD32)x;
+ carry = (unsigned)(x >> 32);
+
+ while (carry)
+ carry -= lbnSubN_32(n, mod, mlen);
+ while (lbnCmp_32(n, mod, mlen) >= 0)
+ (void)lbnSubN_32(n, mod, mlen);
+}
+#define lbnMontReduce_32 lbnMontReduce_32
+#endif
+
+/*
+ * Montgomery reduce n, modulo mod. This reduces modulo mod and divides by
+ * 2^(32*mlen). Returns the result in the *top* mlen words of the argument n.
+ * This is ready for another multiplication using lbnMul_32.
+ *
+ * Montgomery representation is a very useful way to encode numbers when
+ * you're doing lots of modular reduction. What you do is pick a multiplier
+ * R which is relatively prime to the modulus and very easy to divide by.
+ * Since the modulus is odd, R is closen as a power of 2, so the division
+ * is a shift. In fact, it's a shift of an integral number of words,
+ * so the shift can be implicit - just drop the low-order words.
+ *
+ * Now, choose R *larger* than the modulus m, 2^(32*mlen). Then convert
+ * all numbers a, b, etc. to Montgomery form M(a), M(b), etc using the
+ * relationship M(a) = a*R mod m, M(b) = b*R mod m, etc. Note that:
+ * - The Montgomery form of a number depends on the modulus m.
+ * A fixed modulus m is assumed throughout this discussion.
+ * - Since R is relaitvely prime to m, multiplication by R is invertible;
+ * no information about the numbers is lost, they're just scrambled.
+ * - Adding (and subtracting) numbers in this form works just as usual.
+ * M(a+b) = (a+b)*R mod m = (a*R + b*R) mod m = (M(a) + M(b)) mod m
+ * - Multiplying numbers in this form produces a*b*R*R. The problem
+ * is to divide out the excess factor of R, modulo m as well as to
+ * reduce to the given length mlen. It turns out that this can be
+ * done *faster* than a normal divide, which is where the speedup
+ * in Montgomery division comes from.
+ *
+ * Normal reduction chooses a most-significant quotient digit q and then
+ * subtracts q*m from the number to be reduced. Choosing q is tricky
+ * and involved (just look at lbnDiv_32 to see!) and is usually
+ * imperfect, requiring a check for correction after the subtraction.
+ *
+ * Montgomery reduction *adds* a multiple of m to the *low-order* part
+ * of the number to be reduced. This multiple is chosen to make the
+ * low-order part of the number come out to zero. This can be done
+ * with no trickery or error using a precomputed inverse of the modulus.
+ * In this code, the "part" is one word, but any width can be used.
+ *
+ * Repeating this step sufficiently often results in a value which
+ * is a multiple of R (a power of two, remember) but is still (since
+ * the additions were to the low-order part and thus did not increase
+ * the value of the number being reduced very much) still not much
+ * larger than m*R. Then implicitly divide by R and subtract off
+ * m until the result is in the correct range.
+ *
+ * Since the low-order part being cancelled is less than R, the
+ * multiple of m added must have a multiplier which is at most R-1.
+ * Assuming that the input is at most m*R-1, the final number is
+ * at most m*(2*R-1)-1 = 2*m*R - m - 1, so subtracting m once from
+ * the high-order part, equivalent to subtracting m*R from the
+ * while number, produces a result which is at most m*R - m - 1,
+ * which divided by R is at most m-1.
+ *
+ * To convert *to* Montgomery form, you need a regular remainder
+ * routine, although you can just compute R*R (mod m) and do the
+ * conversion using Montgomery multiplication. To convert *from*
+ * Montgomery form, just Montgomery reduce the number to
+ * remove the extra factor of R.
+ *
+ * TODO: Change to a full inverse and use Karatsuba's multiplication
+ * rather than this word-at-a-time.
+ */
+#ifndef lbnMontReduce_32
+void
+lbnMontReduce_32(BNWORD32 *n, BNWORD32 const *mod, unsigned const mlen,
+ BNWORD32 inv)
+{
+ BNWORD32 t;
+ BNWORD32 c = 0;
+ unsigned len = mlen;
+
+ /* inv must be the negative inverse of mod's least significant word */
+ assert((BNWORD32)(inv * BIGLITTLE(mod[-1],mod[0])) == (BNWORD32)-1);
+
+ assert(len);
+
+ do {
+ t = lbnMulAdd1_32(n, mod, mlen, inv * BIGLITTLE(n[-1],n[0]));
+ c += lbnAdd1_32(BIGLITTLE(n-mlen,n+mlen), len, t);
+ BIGLITTLE(--n,++n);
+ } while (--len);
+
+ /*
+ * All that adding can cause an overflow past the modulus size,
+ * but it's unusual, and never by much, so a subtraction loop
+ * is the right way to deal with it.
+ * This subtraction happens infrequently - I've only ever seen it
+ * invoked once per reduction, and then just under 22.5% of the time.
+ */
+ while (c)
+ c -= lbnSubN_32(n, mod, mlen);
+ while (lbnCmp_32(n, mod, mlen) >= 0)
+ (void)lbnSubN_32(n, mod, mlen);
+}
+#endif /* !lbnMontReduce_32 */
+
+/*
+ * A couple of helpers that you might want to implement atomically
+ * in asm sometime.
+ */
+#ifndef lbnMontMul_32
+/*
+ * Multiply "num1" by "num2", modulo "mod", all of length "len", and
+ * place the result in the high half of "prod". "inv" is the inverse
+ * of the least-significant word of the modulus, modulo 2^32.
+ * This uses numbers in Montgomery form. Reduce using "len" and "inv".
+ *
+ * This is implemented as a macro to win on compilers that don't do
+ * inlining, since it's so trivial.
+ */
+#define lbnMontMul_32(prod, n1, n2, mod, len, inv) \
+ (lbnMulX_32(prod, n1, n2, len), lbnMontReduce_32(prod, mod, len, inv))
+#endif /* !lbnMontMul_32 */
+
+#ifndef lbnMontSquare_32
+/*
+ * Square "num", modulo "mod", both of length "len", and place the result
+ * in the high half of "prod". "inv" is the inverse of the least-significant
+ * word of the modulus, modulo 2^32.
+ * This uses numbers in Montgomery form. Reduce using "len" and "inv".
+ *
+ * This is implemented as a macro to win on compilers that don't do
+ * inlining, since it's so trivial.
+ */
+#define lbnMontSquare_32(prod, n, mod, len, inv) \
+ (lbnSquare_32(prod, n, len), lbnMontReduce_32(prod, mod, len, inv))
+
+#endif /* !lbnMontSquare_32 */
+
+/*
+ * Convert a number to Montgomery form - requires mlen + nlen words
+ * of memory in "n".
+ */
+void
+lbnToMont_32(BNWORD32 *n, unsigned nlen, BNWORD32 *mod, unsigned mlen)
+{
+ /* Move n up "mlen" words */
+ lbnCopy_32(BIGLITTLE(n-mlen,n+mlen), n, nlen);
+ lbnZero_32(n, mlen);
+ /* Do the division - dump the quotient in the high-order words */
+ (void)lbnDiv_32(BIGLITTLE(n-mlen,n+mlen), n, mlen+nlen, mod, mlen);
+}
+
+/*
+ * Convert from Montgomery form. Montgomery reduction is all that is
+ * needed.
+ */
+void
+lbnFromMont_32(BNWORD32 *n, BNWORD32 *mod, unsigned len)
+{
+ /* Zero the high words of n */
+ lbnZero_32(BIGLITTLE(n-len,n+len), len);
+ lbnMontReduce_32(n, mod, len, lbnMontInv1_32(BIGLITTLE(mod[-1],mod[0])));
+ /* Move n down len words */
+ lbnCopy_32(n, BIGLITTLE(n-len,n+len), len);
+}
+
+/*
+ * The windowed exponentiation algorithm, precomputes a table of odd
+ * powers of n up to 2^k. It takes 2^(k-1)-1 multiplies to compute
+ * the table, and (e-1)/(k+1) multiplies (on average) to perform the
+ * exponentiation. To minimize the sum, k must vary with e.
+ * The optimal window sizes vary with the exponent length. Here are
+ * some selected values and the boundary cases.
+ * (An underscore _ has been inserted into some of the numbers to ensure
+ * that magic strings like 32 do not appear in this table. It should be
+ * ignored.)
+ *
+ * At e = 1 bits, k=1 (0.000000) is best.
+ * At e = 2 bits, k=1 (0.500000) is best.
+ * At e = 4 bits, k=1 (1.500000) is best.
+ * At e = 8 bits, k=2 (3.333333) < k=1 (3.500000)
+ * At e = 1_6 bits, k=2 (6.000000) is best.
+ * At e = 26 bits, k=3 (9.250000) < k=2 (9.333333)
+ * At e = 3_2 bits, k=3 (10.750000) is best.
+ * At e = 6_4 bits, k=3 (18.750000) is best.
+ * At e = 82 bits, k=4 (23.200000) < k=3 (23.250000)
+ * At e = 128 bits, k=4 (3_2.400000) is best.
+ * At e = 242 bits, k=5 (55.1_66667) < k=4 (55.200000)
+ * At e = 256 bits, k=5 (57.500000) is best.
+ * At e = 512 bits, k=5 (100.1_66667) is best.
+ * At e = 674 bits, k=6 (127.142857) < k=5 (127.1_66667)
+ * At e = 1024 bits, k=6 (177.142857) is best.
+ * At e = 1794 bits, k=7 (287.125000) < k=6 (287.142857)
+ * At e = 2048 bits, k=7 (318.875000) is best.
+ * At e = 4096 bits, k=7 (574.875000) is best.
+ *
+ * The numbers in parentheses are the expected number of multiplications
+ * needed to do the computation. The normal russian-peasant modular
+ * exponentiation technique always uses (e-1)/2. For exponents as
+ * small as 192 bits (below the range of current factoring algorithms),
+ * half of the multiplies are eliminated, 45.2 as opposed to the naive
+ * 95.5. Counting the 191 squarings as 3/4 a multiply each (squaring
+ * proper is just over half of multiplying, but the Montgomery
+ * reduction in each case is also a multiply), that's 143.25
+ * multiplies, for totals of 188.45 vs. 238.75 - a 21% savings.
+ * For larger exponents (like 512 bits), it's 483.92 vs. 639.25, a
+ * 24.3% savings. It asymptotically approaches 25%.
+ *
+ * Given that exponents for which k>7 are useful are uncommon,
+ * a fixed size table for k <= 7 is used for simplicity.
+ * k = 8 is uzeful at 4610 bits, k = 9 at 11522 bits.
+ *
+ * The basic number of squarings needed is e-1, although a k-bit
+ * window (for k > 1) can save, on average, k-2 of those, too.
+ * That savings currently isn't counted here. It would drive the
+ * crossover points slightly lower.
+ * (Actually, this win is also reduced in the DoubleExpMod case,
+ * meaning we'd have to split the tables. Except for that, the
+ * multiplies by powers of the two bases are independent, so
+ * the same logic applies to each as the single case.)
+ *
+ * Table entry i is the largest number of bits in an exponent to
+ * process with a window size of i+1. So the window never goes above 7
+ * bits, requiring 2^(7-1) = 0x40 precomputed multiples.
+ */
+#define BNEXPMOD_MAX_WINDOW 7
+static unsigned const bnExpModThreshTable[BNEXPMOD_MAX_WINDOW] = {
+ 7, 25, 81, 241, 673, 1793, (unsigned)-1
+};
+
+/*
+ * Perform modular exponentiation, as fast as possible! This uses
+ * Montgomery reduction, optimized squaring, and windowed exponentiation.
+ * The modulus "mod" MUST be odd!
+ *
+ * This returns 0 on success, -1 on out of memory.
+ *
+ * The window algorithm:
+ * The idea is to keep a running product of b1 = n^(high-order bits of exp),
+ * and then keep appending exponent bits to it. The following patterns
+ * apply to a 3-bit window (k = 3):
+ * To append 0: square
+ * To append 1: square, multiply by n^1
+ * To append 10: square, multiply by n^1, square
+ * To append 11: square, square, multiply by n^3
+ * To append 100: square, multiply by n^1, square, square
+ * To append 101: square, square, square, multiply by n^5
+ * To append 110: square, square, multiply by n^3, square
+ * To append 111: square, square, square, multiply by n^7
+ *
+ * Since each pattern involves only one multiply, the longer the pattern
+ * the better, except that a 0 (no multiplies) can be appended directly.
+ * We precompute a table of odd powers of n, up to 2^k, and can then
+ * multiply k bits of exponent at a time. Actually, assuming random
+ * exponents, there is on average one zero bit between needs to
+ * multiply (1/2 of the time there's none, 1/4 of the time there's 1,
+ * 1/8 of the time, there's 2, 1/32 of the time, there's 3, etc.), so
+ * you have to do one multiply per k+1 bits of exponent.
+ *
+ * The loop walks down the exponent, squaring the result buffer as
+ * it goes. There is a wbits+1 bit lookahead buffer, buf, that is
+ * filled with the upcoming exponent bits. (What is read after the
+ * end of the exponent is unimportant, but it is filled with zero here.)
+ * When the most-significant bit of this buffer becomes set, i.e.
+ * (buf & tblmask) != 0, we have to decide what pattern to multiply
+ * by, and when to do it. We decide, remember to do it in future
+ * after a suitable number of squarings have passed (e.g. a pattern
+ * of "100" in the buffer requires that we multiply by n^1 immediately;
+ * a pattern of "110" calls for multiplying by n^3 after one more
+ * squaring), clear the buffer, and continue.
+ *
+ * When we start, there is one more optimization: the result buffer
+ * is implcitly one, so squaring it or multiplying by it can be
+ * optimized away. Further, if we start with a pattern like "100"
+ * in the lookahead window, rather than placing n into the buffer
+ * and then starting to square it, we have already computed n^2
+ * to compute the odd-powers table, so we can place that into
+ * the buffer and save a squaring.
+ *
+ * This means that if you have a k-bit window, to compute n^z,
+ * where z is the high k bits of the exponent, 1/2 of the time
+ * it requires no squarings. 1/4 of the time, it requires 1
+ * squaring, ... 1/2^(k-1) of the time, it reqires k-2 squarings.
+ * And the remaining 1/2^(k-1) of the time, the top k bits are a
+ * 1 followed by k-1 0 bits, so it again only requires k-2
+ * squarings, not k-1. The average of these is 1. Add that
+ * to the one squaring we have to do to compute the table,
+ * and you'll see that a k-bit window saves k-2 squarings
+ * as well as reducing the multiplies. (It actually doesn't
+ * hurt in the case k = 1, either.)
+ *
+ * n must have mlen words allocated. Although fewer may be in use
+ * when n is passed in, all are in use on exit.
+ */
+int
+lbnExpMod_32(BNWORD32 *result, BNWORD32 const *n, unsigned nlen,
+ BNWORD32 const *e, unsigned elen, BNWORD32 *mod, unsigned mlen)
+{
+ BNWORD32 *table[1 << (BNEXPMOD_MAX_WINDOW-1)];
+ /* Table of odd powers of n */
+ unsigned ebits; /* Exponent bits */
+ unsigned wbits; /* Window size */
+ unsigned tblmask; /* Mask of exponentiation window */
+ BNWORD32 bitpos; /* Mask of current look-ahead bit */
+ unsigned buf; /* Buffer of exponent bits */
+ unsigned multpos; /* Where to do pending multiply */
+ BNWORD32 const *mult; /* What to multiply by */
+ unsigned i; /* Loop counter */
+ int isone; /* Flag: accum. is implicitly one */
+ BNWORD32 *a, *b; /* Working buffers/accumulators */
+ BNWORD32 *t; /* Pointer into the working buffers */
+ BNWORD32 inv; /* mod^-1 modulo 2^32 */
+
+ assert(mlen);
+ assert(nlen <= mlen);
+
+ /* First, a couple of trivial cases. */
+ elen = lbnNorm_32(e, elen);
+ if (!elen) {
+ /* x ^ 0 == 1 */
+ lbnZero_32(result, mlen);
+ BIGLITTLE(result[-1],result[0]) = 1;
+ return 0;
+ }
+ ebits = lbnBits_32(e, elen);
+ if (ebits == 1) {
+ /* x ^ 1 == x */
+ if (n != result)
+ lbnCopy_32(result, n, nlen);
+ if (mlen > nlen)
+ lbnZero_32(BIGLITTLE(result-nlen,result+nlen),
+ mlen-nlen);
+ return 0;
+ }
+
+ /* Okay, now move the exponent pointer to the most-significant word */
+ e = BIGLITTLE(e-elen, e+elen-1);
+
+ /* Look up appropriate k-1 for the exponent - tblmask = 1<<(k-1) */
+ wbits = 0;
+ while (ebits > bnExpModThreshTable[wbits])
+ wbits++;
+
+ /* Allocate working storage: two product buffers and the tables. */
+ LBNALLOC(a, 2*mlen);
+ if (!a)
+ return -1;
+ LBNALLOC(b, 2*mlen);
+ if (!b) {
+ LBNFREE(a, 2*mlen);
+ return -1;
+ }
+
+ /* Convert to the appropriate table size: tblmask = 1<<(k-1) */
+ tblmask = 1u << wbits;
+
+ /* We have the result buffer available, so use it. */
+ table[0] = result;
+
+ /*
+ * Okay, we now have a minimal-sized table - expand it.
+ * This is allowed to fail! If so, scale back the table size
+ * and proceed.
+ */
+ for (i = 1; i < tblmask; i++) {
+ LBNALLOC(t, mlen);
+ if (!t) /* Out of memory! Quit the loop. */
+ break;
+ table[i] = t;
+ }
+
+ /* If we stopped, with i < tblmask, shrink the tables appropriately */
+ while (tblmask > i) {
+ wbits--;
+ tblmask >>= 1;
+ }
+ /* Free up our overallocations */
+ while (--i > tblmask)
+ LBNFREE(table[i], mlen);
+
+ /* Okay, fill in the table */
+
+ /* Compute the necessary modular inverse */
+ inv = lbnMontInv1_32(mod[BIGLITTLE(-1,0)]); /* LSW of modulus */
+
+ /* Convert n to Montgomery form */
+
+ /* Move n up "mlen" words into a */
+ t = BIGLITTLE(a-mlen, a+mlen);
+ lbnCopy_32(t, n, nlen);
+ lbnZero_32(a, mlen);
+ /* Do the division - lose the quotient into the high-order words */
+ (void)lbnDiv_32(t, a, mlen+nlen, mod, mlen);
+ /* Copy into first table entry */
+ lbnCopy_32(table[0], a, mlen);
+
+ /* Square a into b */
+ lbnMontSquare_32(b, a, mod, mlen, inv);
+
+ /* Use high half of b to initialize the table */
+ t = BIGLITTLE(b-mlen, b+mlen);
+ for (i = 1; i < tblmask; i++) {
+ lbnMontMul_32(a, t, table[i-1], mod, mlen, inv);
+ lbnCopy_32(table[i], BIGLITTLE(a-mlen, a+mlen), mlen);
+ }
+
+ /* We might use b = n^2 later... */
+
+ /* Initialze the fetch pointer */
+ bitpos = (BNWORD32)1 << ((ebits-1) & (32-1)); /* Initialize mask */
+
+ /* This should point to the msbit of e */
+ assert((*e & bitpos) != 0);
+
+ /*
+ * Pre-load the window. Becuase the window size is
+ * never larger than the exponent size, there is no need to
+ * detect running off the end of e in here.
+ *
+ * The read-ahead is controlled by elen and the bitpos mask.
+ * Note that this is *ahead* of ebits, which tracks the
+ * most significant end of the window. The purpose of this
+ * initialization is to get the two wbits+1 bits apart,
+ * like they should be.
+ *
+ * Note that bitpos and e1len together keep track of the
+ * lookahead read pointer in the exponent that is used here.
+ */
+ buf = 0;
+ for (i = 0; i <= wbits; i++) {
+ buf = (buf << 1) | ((*e & bitpos) != 0);
+ bitpos >>= 1;
+ if (!bitpos) {
+ BIGLITTLE(e++,e--);
+ bitpos = (BNWORD32)1 << (32-1);
+ elen--;
+ }
+ }
+ assert(buf & tblmask);
+
+ /*
+ * Set the pending multiply positions to a location that will
+ * never be encountered, thus ensuring that nothing will happen
+ * until the need for a multiply appears and one is scheduled.
+ */
+ multpos = ebits; /* A NULL value */
+ mult = 0; /* Force a crash if we use these */
+
+ /*
+ * Okay, now begins the real work. The first step is
+ * slightly magic, so it's done outside the main loop,
+ * but it's very similar to what's inside.
+ */
+ ebits--; /* Start processing the first bit... */
+ isone = 1;
+
+ /*
+ * This is just like the multiply in the loop, except that
+ * - We know the msbit of buf is set, and
+ * - We have the extra value n^2 floating around.
+ * So, do the usual computation, and if the result is that
+ * the buffer should be multiplied by n^1 immediately
+ * (which we'd normally then square), we multiply it
+ * (which reduces to a copy, which reduces to setting a flag)
+ * by n^2 and skip the squaring. Thus, we do the
+ * multiply and the squaring in one step.
+ */
+ assert(buf & tblmask);
+ multpos = ebits - wbits;
+ while ((buf & 1) == 0) {
+ buf >>= 1;
+ multpos++;
+ }
+ /* Intermediates can wrap, but final must NOT */
+ assert(multpos <= ebits);
+ mult = table[buf>>1];
+ buf = 0;
+
+ /* Special case: use already-computed value sitting in buffer */
+ if (multpos == ebits)
+ isone = 0;
+
+ /*
+ * At this point, the buffer (which is the high half of b) holds
+ * either 1 (implicitly, as the "isone" flag is set), or n^2.
+ */
+
+ /*
+ * The main loop. The procedure is:
+ * - Advance the window
+ * - If the most-significant bit of the window is set,
+ * schedule a multiply for the appropriate time in the
+ * future (may be immediately)
+ * - Perform any pending multiples
+ * - Check for termination
+ * - Square the buffer
+ *
+ * At any given time, the acumulated product is held in
+ * the high half of b.
+ */
+ for (;;) {
+ ebits--;
+
+ /* Advance the window */
+ assert(buf < tblmask);
+ buf <<= 1;
+ /*
+ * This reads ahead of the current exponent position
+ * (controlled by ebits), so we have to be able to read
+ * past the lsb of the exponents without error.
+ */
+ if (elen) {
+ buf |= ((*e & bitpos) != 0);
+ bitpos >>= 1;
+ if (!bitpos) {
+ BIGLITTLE(e++,e--);
+ bitpos = (BNWORD32)1 << (32-1);
+ elen--;
+ }
+ }
+
+ /* Examine the window for pending multiplies */
+ if (buf & tblmask) {
+ multpos = ebits - wbits;
+ while ((buf & 1) == 0) {
+ buf >>= 1;
+ multpos++;
+ }
+ /* Intermediates can wrap, but final must NOT */
+ assert(multpos <= ebits);
+ mult = table[buf>>1];
+ buf = 0;
+ }
+
+ /* If we have a pending multiply, do it */
+ if (ebits == multpos) {
+ /* Multiply by the table entry remembered previously */
+ t = BIGLITTLE(b-mlen, b+mlen);
+ if (isone) {
+ /* Multiply by 1 is a trivial case */
+ lbnCopy_32(t, mult, mlen);
+ isone = 0;
+ } else {
+ lbnMontMul_32(a, t, mult, mod, mlen, inv);
+ /* Swap a and b */
+ t = a; a = b; b = t;
+ }
+ }
+
+ /* Are we done? */
+ if (!ebits)
+ break;
+
+ /* Square the input */
+ if (!isone) {
+ t = BIGLITTLE(b-mlen, b+mlen);
+ lbnMontSquare_32(a, t, mod, mlen, inv);
+ /* Swap a and b */
+ t = a; a = b; b = t;
+ }
+ } /* for (;;) */
+
+ assert(!isone);
+ assert(!buf);
+
+ /* DONE! */
+
+ /* Convert result out of Montgomery form */
+ t = BIGLITTLE(b-mlen, b+mlen);
+ lbnCopy_32(b, t, mlen);
+ lbnZero_32(t, mlen);
+ lbnMontReduce_32(b, mod, mlen, inv);
+ lbnCopy_32(result, t, mlen);
+ /*
+ * Clean up - free intermediate storage.
+ * Do NOT free table[0], which is the result
+ * buffer.
+ */
+ while (--tblmask)
+ LBNFREE(table[tblmask], mlen);
+ LBNFREE(b, 2*mlen);
+ LBNFREE(a, 2*mlen);
+
+ return 0; /* Success */
+}
+
+/*
+ * Compute and return n1^e1 * n2^e2 mod "mod".
+ * result may be either input buffer, or something separate.
+ * It must be "mlen" words long.
+ *
+ * There is a current position in the exponents, which is kept in e1bits.
+ * (The exponents are swapped if necessary so e1 is the longer of the two.)
+ * At any given time, the value in the accumulator is
+ * n1^(e1>>e1bits) * n2^(e2>>e1bits) mod "mod".
+ * As e1bits is counted down, this is updated, by squaring it and doing
+ * any necessary multiplies.
+ * To decide on the necessary multiplies, two windows, each w1bits+1 bits
+ * wide, are maintained in buf1 and buf2, which read *ahead* of the
+ * e1bits position (with appropriate handling of the case when e1bits
+ * drops below w1bits+1). When the most-significant bit of either window
+ * becomes set, indicating that something needs to be multiplied by
+ * the accumulator or it will get out of sync, the window is examined
+ * to see which power of n1 or n2 to multiply by, and when (possibly
+ * later, if the power is greater than 1) the multiply should take
+ * place. Then the multiply and its location are remembered and the
+ * window is cleared.
+ *
+ * If we had every power of n1 in the table, the multiply would always
+ * be w1bits steps in the future. But we only keep the odd powers,
+ * so instead of waiting w1bits squarings and then multiplying
+ * by n1^k, we wait w1bits-k squarings and multiply by n1.
+ *
+ * Actually, w2bits can be less than w1bits, but the window is the same
+ * size, to make it easier to keep track of where we're reading. The
+ * appropriate number of low-order bits of the window are just ignored.
+ */
+int
+lbnDoubleExpMod_32(BNWORD32 *result,
+ BNWORD32 const *n1, unsigned n1len,
+ BNWORD32 const *e1, unsigned e1len,
+ BNWORD32 const *n2, unsigned n2len,
+ BNWORD32 const *e2, unsigned e2len,
+ BNWORD32 *mod, unsigned mlen)
+{
+ BNWORD32 *table1[1 << (BNEXPMOD_MAX_WINDOW-1)];
+ /* Table of odd powers of n1 */
+ BNWORD32 *table2[1 << (BNEXPMOD_MAX_WINDOW-1)];
+ /* Table of odd powers of n2 */
+ unsigned e1bits, e2bits; /* Exponent bits */
+ unsigned w1bits, w2bits; /* Window sizes */
+ unsigned tblmask; /* Mask of exponentiation window */
+ BNWORD32 bitpos; /* Mask of current look-ahead bit */
+ unsigned buf1, buf2; /* Buffer of exponent bits */
+ unsigned mult1pos, mult2pos; /* Where to do pending multiply */
+ BNWORD32 const *mult1, *mult2; /* What to multiply by */
+ unsigned i; /* Loop counter */
+ int isone; /* Flag: accum. is implicitly one */
+ BNWORD32 *a, *b; /* Working buffers/accumulators */
+ BNWORD32 *t; /* Pointer into the working buffers */
+ BNWORD32 inv; /* mod^-1 modulo 2^32 */
+
+ assert(mlen);
+ assert(n1len <= mlen);
+ assert(n2len <= mlen);
+
+ /* First, a couple of trivial cases. */
+ e1len = lbnNorm_32(e1, e1len);
+ e2len = lbnNorm_32(e2, e2len);
+
+ /* Ensure that the first exponent is the longer */
+ e1bits = lbnBits_32(e1, e1len);
+ e2bits = lbnBits_32(e2, e2len);
+ if (e1bits < e2bits) {
+ i = e1len; e1len = e2len; e2len = i;
+ i = e1bits; e1bits = e2bits; e2bits = i;
+ t = (BNWORD32 *)n1; n1 = n2; n2 = t;
+ t = (BNWORD32 *)e1; e1 = e2; e2 = t;
+ }
+ assert(e1bits >= e2bits);
+
+ /* Handle a trivial case */
+ if (!e2len)
+ return lbnExpMod_32(result, n1, n1len, e1, e1len, mod, mlen);
+ assert(e2bits);
+
+ /* The code below breaks if the exponents aren't at least 2 bits */
+ if (e1bits == 1) {
+ assert(e2bits == 1);
+
+ LBNALLOC(a, n1len+n2len);
+ if (!a)
+ return -1;
+
+ lbnMul_32(a, n1, n1len, n2, n2len);
+ /* Do a direct modular reduction */
+ if (n1len + n2len >= mlen)
+ (void)lbnDiv_32(a+mlen, a, n1len+n2len, mod, mlen);
+ lbnCopy_32(result, a, mlen);
+ LBNFREE(a, n1len+n2len);
+ return 0;
+ }
+
+ /* Okay, now move the exponent pointers to the most-significant word */
+ e1 = BIGLITTLE(e1-e1len, e1+e1len-1);
+ e2 = BIGLITTLE(e2-e2len, e2+e2len-1);
+
+ /* Look up appropriate k-1 for the exponent - tblmask = 1<<(k-1) */
+ w1bits = 0;
+ while (e1bits > bnExpModThreshTable[w1bits])
+ w1bits++;
+ w2bits = 0;
+ while (e2bits > bnExpModThreshTable[w2bits])
+ w2bits++;
+
+ assert(w1bits >= w2bits);
+
+ /* Allocate working storage: two product buffers and the tables. */
+ LBNALLOC(a, 2*mlen);
+ if (!a)
+ return -1;
+ LBNALLOC(b, 2*mlen);
+ if (!b) {
+ LBNFREE(a, 2*mlen);
+ return -1;
+ }
+
+ /* Convert to the appropriate table size: tblmask = 1<<(k-1) */
+ tblmask = 1u << w1bits;
+ /* Use buf2 for its size, temporarily */
+ buf2 = 1u << w2bits;
+
+ LBNALLOC(t, mlen);
+ if (!t) {
+ LBNFREE(b, 2*mlen);
+ LBNFREE(a, 2*mlen);
+ return -1;
+ }
+ table1[0] = t;
+ table2[0] = result;
+
+ /*
+ * Okay, we now have some minimal-sized tables - expand them.
+ * This is allowed to fail! If so, scale back the table sizes
+ * and proceed. We allocate both tables at the same time
+ * so if it fails partway through, they'll both be a reasonable
+ * size rather than one huge and one tiny.
+ * When i passes buf2 (the number of entries in the e2 window,
+ * which may be less than the number of entries in the e1 window),
+ * stop allocating e2 space.
+ */
+ for (i = 1; i < tblmask; i++) {
+ LBNALLOC(t, mlen);
+ if (!t) /* Out of memory! Quit the loop. */
+ break;
+ table1[i] = t;
+ if (i < buf2) {
+ LBNALLOC(t, mlen);
+ if (!t) {
+ LBNFREE(table1[i], mlen);
+ break;
+ }
+ table2[i] = t;
+ }
+ }
+
+ /* If we stopped, with i < tblmask, shrink the tables appropriately */
+ while (tblmask > i) {
+ w1bits--;
+ tblmask >>= 1;
+ }
+ /* Free up our overallocations */
+ while (--i > tblmask) {
+ if (i < buf2)
+ LBNFREE(table2[i], mlen);
+ LBNFREE(table1[i], mlen);
+ }
+ /* And shrink the second window too, if needed */
+ if (w2bits > w1bits) {
+ w2bits = w1bits;
+ buf2 = tblmask;
+ }
+
+ /*
+ * From now on, use the w2bits variable for the difference
+ * between w1bits and w2bits.
+ */
+ w2bits = w1bits-w2bits;
+
+ /* Okay, fill in the tables */
+
+ /* Compute the necessary modular inverse */
+ inv = lbnMontInv1_32(mod[BIGLITTLE(-1,0)]); /* LSW of modulus */
+
+ /* Convert n1 to Montgomery form */
+
+ /* Move n1 up "mlen" words into a */
+ t = BIGLITTLE(a-mlen, a+mlen);
+ lbnCopy_32(t, n1, n1len);
+ lbnZero_32(a, mlen);
+ /* Do the division - lose the quotient into the high-order words */
+ (void)lbnDiv_32(t, a, mlen+n1len, mod, mlen);
+ /* Copy into first table entry */
+ lbnCopy_32(table1[0], a, mlen);
+
+ /* Square a into b */
+ lbnMontSquare_32(b, a, mod, mlen, inv);
+
+ /* Use high half of b to initialize the first table */
+ t = BIGLITTLE(b-mlen, b+mlen);
+ for (i = 1; i < tblmask; i++) {
+ lbnMontMul_32(a, t, table1[i-1], mod, mlen, inv);
+ lbnCopy_32(table1[i], BIGLITTLE(a-mlen, a+mlen), mlen);
+ }
+
+ /* Convert n2 to Montgomery form */
+
+ t = BIGLITTLE(a-mlen, a+mlen);
+ /* Move n2 up "mlen" words into a */
+ lbnCopy_32(t, n2, n2len);
+ lbnZero_32(a, mlen);
+ /* Do the division - lose the quotient into the high-order words */
+ (void)lbnDiv_32(t, a, mlen+n2len, mod, mlen);
+ /* Copy into first table entry */
+ lbnCopy_32(table2[0], a, mlen);
+
+ /* Square it into a */
+ lbnMontSquare_32(a, table2[0], mod, mlen, inv);
+ /* Copy to b, low half */
+ lbnCopy_32(b, t, mlen);
+
+ /* Use b to initialize the second table */
+ for (i = 1; i < buf2; i++) {
+ lbnMontMul_32(a, b, table2[i-1], mod, mlen, inv);
+ lbnCopy_32(table2[i], t, mlen);
+ }
+
+ /*
+ * Okay, a recap: at this point, the low part of b holds
+ * n2^2, the high part holds n1^2, and the tables are
+ * initialized with the odd powers of n1 and n2 from 1
+ * through 2*tblmask-1 and 2*buf2-1.
+ *
+ * We might use those squares in b later, or we might not.
+ */
+
+ /* Initialze the fetch pointer */
+ bitpos = (BNWORD32)1 << ((e1bits-1) & (32-1)); /* Initialize mask */
+
+ /* This should point to the msbit of e1 */
+ assert((*e1 & bitpos) != 0);
+
+ /*
+ * Pre-load the windows. Becuase the window size is
+ * never larger than the exponent size, there is no need to
+ * detect running off the end of e1 in here.
+ *
+ * The read-ahead is controlled by e1len and the bitpos mask.
+ * Note that this is *ahead* of e1bits, which tracks the
+ * most significant end of the window. The purpose of this
+ * initialization is to get the two w1bits+1 bits apart,
+ * like they should be.
+ *
+ * Note that bitpos and e1len together keep track of the
+ * lookahead read pointer in the exponent that is used here.
+ * e2len is not decremented, it is only ever compared with
+ * e1len as *that* is decremented.
+ */
+ buf1 = buf2 = 0;
+ for (i = 0; i <= w1bits; i++) {
+ buf1 = (buf1 << 1) | ((*e1 & bitpos) != 0);
+ if (e1len <= e2len)
+ buf2 = (buf2 << 1) | ((*e2 & bitpos) != 0);
+ bitpos >>= 1;
+ if (!bitpos) {
+ BIGLITTLE(e1++,e1--);
+ if (e1len <= e2len)
+ BIGLITTLE(e2++,e2--);
+ bitpos = (BNWORD32)1 << (32-1);
+ e1len--;
+ }
+ }
+ assert(buf1 & tblmask);
+
+ /*
+ * Set the pending multiply positions to a location that will
+ * never be encountered, thus ensuring that nothing will happen
+ * until the need for a multiply appears and one is scheduled.
+ */
+ mult1pos = mult2pos = e1bits; /* A NULL value */
+ mult1 = mult2 = 0; /* Force a crash if we use these */
+
+ /*
+ * Okay, now begins the real work. The first step is
+ * slightly magic, so it's done outside the main loop,
+ * but it's very similar to what's inside.
+ */
+ isone = 1; /* Buffer is implicitly 1, so replace * by copy */
+ e1bits--; /* Start processing the first bit... */
+
+ /*
+ * This is just like the multiply in the loop, except that
+ * - We know the msbit of buf1 is set, and
+ * - We have the extra value n1^2 floating around.
+ * So, do the usual computation, and if the result is that
+ * the buffer should be multiplied by n1^1 immediately
+ * (which we'd normally then square), we multiply it
+ * (which reduces to a copy, which reduces to setting a flag)
+ * by n1^2 and skip the squaring. Thus, we do the
+ * multiply and the squaring in one step.
+ */
+ assert(buf1 & tblmask);
+ mult1pos = e1bits - w1bits;
+ while ((buf1 & 1) == 0) {
+ buf1 >>= 1;
+ mult1pos++;
+ }
+ /* Intermediates can wrap, but final must NOT */
+ assert(mult1pos <= e1bits);
+ mult1 = table1[buf1>>1];
+ buf1 = 0;
+
+ /* Special case: use already-computed value sitting in buffer */
+ if (mult1pos == e1bits)
+ isone = 0;
+
+ /*
+ * The first multiply by a power of n2. Similar, but
+ * we might not even want to schedule a multiply if e2 is
+ * shorter than e1, and the window might be shorter so
+ * we have to leave the low w2bits bits alone.
+ */
+ if (buf2 & tblmask) {
+ /* Remember low-order bits for later */
+ i = buf2 & ((1u << w2bits) - 1);
+ buf2 >>= w2bits;
+ mult2pos = e1bits - w1bits + w2bits;
+ while ((buf2 & 1) == 0) {
+ buf2 >>= 1;
+ mult2pos++;
+ }
+ assert(mult2pos <= e1bits);
+ mult2 = table2[buf2>>1];
+ buf2 = i;
+
+ if (mult2pos == e1bits) {
+ t = BIGLITTLE(b-mlen, b+mlen);
+ if (isone) {
+ lbnCopy_32(t, b, mlen); /* Copy low to high */
+ isone = 0;
+ } else {
+ lbnMontMul_32(a, t, b, mod, mlen, inv);
+ t = a; a = b; b = t;
+ }
+ }
+ }
+
+ /*
+ * At this point, the buffer (which is the high half of b)
+ * holds either 1 (implicitly, as the "isone" flag is set),
+ * n1^2, n2^2 or n1^2 * n2^2.
+ */
+
+ /*
+ * The main loop. The procedure is:
+ * - Advance the windows
+ * - If the most-significant bit of a window is set,
+ * schedule a multiply for the appropriate time in the
+ * future (may be immediately)
+ * - Perform any pending multiples
+ * - Check for termination
+ * - Square the buffers
+ *
+ * At any given time, the acumulated product is held in
+ * the high half of b.
+ */
+ for (;;) {
+ e1bits--;
+
+ /* Advance the windows */
+ assert(buf1 < tblmask);
+ buf1 <<= 1;
+ assert(buf2 < tblmask);
+ buf2 <<= 1;
+ /*
+ * This reads ahead of the current exponent position
+ * (controlled by e1bits), so we have to be able to read
+ * past the lsb of the exponents without error.
+ */
+ if (e1len) {
+ buf1 |= ((*e1 & bitpos) != 0);
+ if (e1len <= e2len)
+ buf2 |= ((*e2 & bitpos) != 0);
+ bitpos >>= 1;
+ if (!bitpos) {
+ BIGLITTLE(e1++,e1--);
+ if (e1len <= e2len)
+ BIGLITTLE(e2++,e2--);
+ bitpos = (BNWORD32)1 << (32-1);
+ e1len--;
+ }
+ }
+
+ /* Examine the first window for pending multiplies */
+ if (buf1 & tblmask) {
+ mult1pos = e1bits - w1bits;
+ while ((buf1 & 1) == 0) {
+ buf1 >>= 1;
+ mult1pos++;
+ }
+ /* Intermediates can wrap, but final must NOT */
+ assert(mult1pos <= e1bits);
+ mult1 = table1[buf1>>1];
+ buf1 = 0;
+ }
+
+ /*
+ * Examine the second window for pending multiplies.
+ * Window 2 can be smaller than window 1, but we
+ * keep the same number of bits in buf2, so we need
+ * to ignore any low-order bits in the buffer when
+ * computing what to multiply by, and recompute them
+ * later.
+ */
+ if (buf2 & tblmask) {
+ /* Remember low-order bits for later */
+ i = buf2 & ((1u << w2bits) - 1);
+ buf2 >>= w2bits;
+ mult2pos = e1bits - w1bits + w2bits;
+ while ((buf2 & 1) == 0) {
+ buf2 >>= 1;
+ mult2pos++;
+ }
+ assert(mult2pos <= e1bits);
+ mult2 = table2[buf2>>1];
+ buf2 = i;
+ }
+
+
+ /* If we have a pending multiply for e1, do it */
+ if (e1bits == mult1pos) {
+ /* Multiply by the table entry remembered previously */
+ t = BIGLITTLE(b-mlen, b+mlen);
+ if (isone) {
+ /* Multiply by 1 is a trivial case */
+ lbnCopy_32(t, mult1, mlen);
+ isone = 0;
+ } else {
+ lbnMontMul_32(a, t, mult1, mod, mlen, inv);
+ /* Swap a and b */
+ t = a; a = b; b = t;
+ }
+ }
+
+ /* If we have a pending multiply for e2, do it */
+ if (e1bits == mult2pos) {
+ /* Multiply by the table entry remembered previously */
+ t = BIGLITTLE(b-mlen, b+mlen);
+ if (isone) {
+ /* Multiply by 1 is a trivial case */
+ lbnCopy_32(t, mult2, mlen);
+ isone = 0;
+ } else {
+ lbnMontMul_32(a, t, mult2, mod, mlen, inv);
+ /* Swap a and b */
+ t = a; a = b; b = t;
+ }
+ }
+
+ /* Are we done? */
+ if (!e1bits)
+ break;
+
+ /* Square the buffer */
+ if (!isone) {
+ t = BIGLITTLE(b-mlen, b+mlen);
+ lbnMontSquare_32(a, t, mod, mlen, inv);
+ /* Swap a and b */
+ t = a; a = b; b = t;
+ }
+ } /* for (;;) */
+
+ assert(!isone);
+ assert(!buf1);
+ assert(!buf2);
+
+ /* DONE! */
+
+ /* Convert result out of Montgomery form */
+ t = BIGLITTLE(b-mlen, b+mlen);
+ lbnCopy_32(b, t, mlen);
+ lbnZero_32(t, mlen);
+ lbnMontReduce_32(b, mod, mlen, inv);
+ lbnCopy_32(result, t, mlen);
+
+ /* Clean up - free intermediate storage */
+ buf2 = tblmask >> w2bits;
+ while (--tblmask) {
+ if (tblmask < buf2)
+ LBNFREE(table2[tblmask], mlen);
+ LBNFREE(table1[tblmask], mlen);
+ }
+ t = table1[0];
+ LBNFREE(t, mlen);
+ LBNFREE(b, 2*mlen);
+ LBNFREE(a, 2*mlen);
+
+ return 0; /* Success */
+}
+
+/*
+ * 2^exp (mod mod). This is an optimized version for use in Fermat
+ * tests. The input value of n is ignored; it is returned with
+ * "mlen" words valid.
+ */
+int
+lbnTwoExpMod_32(BNWORD32 *n, BNWORD32 const *exp, unsigned elen,
+ BNWORD32 *mod, unsigned mlen)
+{
+ unsigned e; /* Copy of high words of the exponent */
+ unsigned bits; /* Assorted counter of bits */
+ BNWORD32 const *bitptr;
+ BNWORD32 bitword, bitpos;
+ BNWORD32 *a, *b, *a1;
+ BNWORD32 inv;
+
+ assert(mlen);
+
+ bitptr = BIGLITTLE(exp-elen, exp+elen-1);
+ bitword = *bitptr;
+ assert(bitword);
+
+ /* Clear n for future use. */
+ lbnZero_32(n, mlen);
+
+ bits = lbnBits_32(exp, elen);
+
+ /* First, a couple of trivial cases. */
+ if (bits <= 1) {
+ /* 2 ^ 0 == 1, 2 ^ 1 == 2 */
+ BIGLITTLE(n[-1],n[0]) = (BNWORD32)1<<elen;
+ return 0;
+ }
+
+ /* Set bitpos to the most significant bit */
+ bitpos = (BNWORD32)1 << ((bits-1) & (32-1));
+
+ /* Now, count the bits in the modulus. */
+ bits = lbnBits_32(mod, mlen);
+ assert(bits > 1); /* a 1-bit modulus is just stupid... */
+
+ /*
+ * We start with 1<<e, where "e" is as many high bits of the
+ * exponent as we can manage without going over the modulus.
+ * This first loop finds "e".
+ */
+ e = 1;
+ while (elen) {
+ /* Consume the first bit */
+ bitpos >>= 1;
+ if (!bitpos) {
+ if (!--elen)
+ break;
+ bitword = BIGLITTLE(*++bitptr,*--bitptr);
+ bitpos = (BNWORD32)1<<(32-1);
+ }
+ e = (e << 1) | ((bitpos & bitword) != 0);
+ if (e >= bits) { /* Overflow! Back out. */
+ e >>= 1;
+ break;
+ }
+ }
+ /*
+ * The bit in "bitpos" being examined by the bit buffer has NOT
+ * been consumed yet. This may be past the end of the exponent,
+ * in which case elen == 1.
+ */
+
+ /* Okay, now, set bit "e" in n. n is already zero. */
+ inv = (BNWORD32)1 << (e & (32-1));
+ e /= 32;
+ BIGLITTLE(n[-e-1],n[e]) = inv;
+ /*
+ * The effective length of n in words is now "e+1".
+ * This is used a little bit later.
+ */
+
+ if (!elen)
+ return 0; /* That was easy! */
+
+ /*
+ * We have now processed the first few bits. The next step
+ * is to convert this to Montgomery form for further squaring.
+ */
+
+ /* Allocate working storage: two product buffers */
+ LBNALLOC(a, 2*mlen);
+ if (!a)
+ return -1;
+ LBNALLOC(b, 2*mlen);
+ if (!b) {
+ LBNFREE(a, 2*mlen);
+ return -1;
+ }
+
+ /* Convert n to Montgomery form */
+ inv = BIGLITTLE(mod[-1],mod[0]); /* LSW of modulus */
+ assert(inv & 1); /* Modulus must be odd */
+ inv = lbnMontInv1_32(inv);
+ /* Move n (length e+1, remember?) up "mlen" words into b */
+ /* Note that we lie about a1 for a bit - it's pointing to b */
+ a1 = BIGLITTLE(b-mlen,b+mlen);
+ lbnCopy_32(a1, n, e+1);
+ lbnZero_32(b, mlen);
+ /* Do the division - dump the quotient into the high-order words */
+ (void)lbnDiv_32(a1, b, mlen+e+1, mod, mlen);
+ /*
+ * Now do the first squaring and modular reduction to put
+ * the number up in a1 where it belongs.
+ */
+ lbnMontSquare_32(a, b, mod, mlen, inv);
+ /* Fix up a1 to point to where it should go. */
+ a1 = BIGLITTLE(a-mlen,a+mlen);
+
+ /*
+ * Okay, now, a1 holds the number being accumulated, and
+ * b is a scratch register. Start working:
+ */
+ for (;;) {
+ /*
+ * Is the bit set? If so, double a1 as well.
+ * A modular doubling like this is very cheap.
+ */
+ if (bitpos & bitword) {
+ /*
+ * Double the number. If there was a carry out OR
+ * the result is greater than the modulus, subract
+ * the modulus.
+ */
+ if (lbnDouble_32(a1, mlen) ||
+ lbnCmp_32(a1, mod, mlen) > 0)
+ (void)lbnSubN_32(a1, mod, mlen);
+ }
+
+ /* Advance to the next exponent bit */
+ bitpos >>= 1;
+ if (!bitpos) {
+ if (!--elen)
+ break; /* Done! */
+ bitword = BIGLITTLE(*++bitptr,*--bitptr);
+ bitpos = (BNWORD32)1<<(32-1);
+ }
+
+ /*
+ * The elen/bitword/bitpos bit buffer is known to be
+ * non-empty, i.e. there is at least one more unconsumed bit.
+ * Thus, it's safe to square the number.
+ */
+ lbnMontSquare_32(b, a1, mod, mlen, inv);
+ /* Rename result (in b) back to a (a1, really). */
+ a1 = b; b = a; a = a1;
+ a1 = BIGLITTLE(a-mlen,a+mlen);
+ }
+
+ /* DONE! Just a little bit of cleanup... */
+
+ /*
+ * Convert result out of Montgomery form... this is
+ * just a Montgomery reduction.
+ */
+ lbnCopy_32(a, a1, mlen);
+ lbnZero_32(a1, mlen);
+ lbnMontReduce_32(a, mod, mlen, inv);
+ lbnCopy_32(n, a1, mlen);
+
+ /* Clean up - free intermediate storage */
+ LBNFREE(b, 2*mlen);
+ LBNFREE(a, 2*mlen);
+
+ return 0; /* Success */
+}
+
+
+/*
+ * Returns a substring of the big-endian array of bytes representation
+ * of the bignum array based on two parameters, the least significant
+ * byte number (0 to start with the least significant byte) and the
+ * length. I.e. the number returned is a representation of
+ * (bn / 2^(8*lsbyte)) % 2 ^ (8*buflen).
+ *
+ * It is an error if the bignum is not at least buflen + lsbyte bytes
+ * long.
+ *
+ * This code assumes that the compiler has the minimal intelligence
+ * neded to optimize divides and modulo operations on an unsigned data
+ * type with a power of two.
+ */
+void
+lbnExtractBigBytes_32(BNWORD32 const *n, unsigned char *buf,
+ unsigned lsbyte, unsigned buflen)
+{
+ BNWORD32 t = 0; /* Needed to shut up uninitialized var warnings */
+ unsigned shift;
+
+ lsbyte += buflen;
+
+ shift = (8 * lsbyte) % 32;
+ lsbyte /= (32/8); /* Convert to word offset */
+ BIGLITTLE(n -= lsbyte, n += lsbyte);
+
+ if (shift)
+ t = BIGLITTLE(n[-1],n[0]);
+
+ while (buflen--) {
+ if (!shift) {
+ t = BIGLITTLE(*n++,*--n);
+ shift = 32;
+ }
+ shift -= 8;
+ *buf++ = (unsigned char)(t>>shift);
+ }
+}
+
+/*
+ * Merge a big-endian array of bytes into a bignum array.
+ * The array had better be big enough. This is
+ * equivalent to extracting the entire bignum into a
+ * large byte array, copying the input buffer into the
+ * middle of it, and converting back to a bignum.
+ *
+ * The buf is "len" bytes long, and its *last* byte is at
+ * position "lsbyte" from the end of the bignum.
+ *
+ * Note that this is a pain to get right. Fortunately, it's hardly
+ * critical for efficiency.
+ */
+void
+lbnInsertBigBytes_32(BNWORD32 *n, unsigned char const *buf,
+ unsigned lsbyte, unsigned buflen)
+{
+ BNWORD32 t = 0; /* Shut up uninitialized varibale warnings */
+
+ lsbyte += buflen;
+
+ BIGLITTLE(n -= lsbyte/(32/8), n += lsbyte/(32/8));
+
+ /* Load up leading odd bytes */
+ if (lsbyte % (32/8)) {
+ t = BIGLITTLE(*--n,*n++);
+ t >>= (lsbyte * 8) % 32;
+ }
+
+ /* The main loop - merge into t, storing at each word boundary. */
+ while (buflen--) {
+ t = (t << 8) | *buf++;
+ if ((--lsbyte % (32/8)) == 0)
+ BIGLITTLE(*n++,*--n) = t;
+ }
+
+ /* Merge odd bytes in t into last word */
+ lsbyte = (lsbyte * 8) % 32;
+ if (lsbyte) {
+ t <<= lsbyte;
+ t |= (((BNWORD32)1 << lsbyte) - 1) & BIGLITTLE(n[0],n[-1]);
+ BIGLITTLE(n[0],n[-1]) = t;
+ }
+
+ return;
+}
+
+/*
+ * Returns a substring of the little-endian array of bytes representation
+ * of the bignum array based on two parameters, the least significant
+ * byte number (0 to start with the least significant byte) and the
+ * length. I.e. the number returned is a representation of
+ * (bn / 2^(8*lsbyte)) % 2 ^ (8*buflen).
+ *
+ * It is an error if the bignum is not at least buflen + lsbyte bytes
+ * long.
+ *
+ * This code assumes that the compiler has the minimal intelligence
+ * neded to optimize divides and modulo operations on an unsigned data
+ * type with a power of two.
+ */
+void
+lbnExtractLittleBytes_32(BNWORD32 const *n, unsigned char *buf,
+ unsigned lsbyte, unsigned buflen)
+{
+ BNWORD32 t = 0; /* Needed to shut up uninitialized var warnings */
+
+ BIGLITTLE(n -= lsbyte/(32/8), n += lsbyte/(32/8));
+
+ if (lsbyte % (32/8)) {
+ t = BIGLITTLE(*--n,*n++);
+ t >>= (lsbyte % (32/8)) * 8 ;
+ }
+
+ while (buflen--) {
+ if ((lsbyte++ % (32/8)) == 0)
+ t = BIGLITTLE(*--n,*n++);
+ *buf++ = (unsigned char)t;
+ t >>= 8;
+ }
+}
+
+/*
+ * Merge a little-endian array of bytes into a bignum array.
+ * The array had better be big enough. This is
+ * equivalent to extracting the entire bignum into a
+ * large byte array, copying the input buffer into the
+ * middle of it, and converting back to a bignum.
+ *
+ * The buf is "len" bytes long, and its first byte is at
+ * position "lsbyte" from the end of the bignum.
+ *
+ * Note that this is a pain to get right. Fortunately, it's hardly
+ * critical for efficiency.
+ */
+void
+lbnInsertLittleBytes_32(BNWORD32 *n, unsigned char const *buf,
+ unsigned lsbyte, unsigned buflen)
+{
+ BNWORD32 t = 0; /* Shut up uninitialized varibale warnings */
+
+ /* Move to most-significant end */
+ lsbyte += buflen;
+ buf += buflen;
+
+ BIGLITTLE(n -= lsbyte/(32/8), n += lsbyte/(32/8));
+
+ /* Load up leading odd bytes */
+ if (lsbyte % (32/8)) {
+ t = BIGLITTLE(*--n,*n++);
+ t >>= (lsbyte * 8) % 32;
+ }
+
+ /* The main loop - merge into t, storing at each word boundary. */
+ while (buflen--) {
+ t = (t << 8) | *--buf;
+ if ((--lsbyte % (32/8)) == 0)
+ BIGLITTLE(*n++,*--n) = t;
+ }
+
+ /* Merge odd bytes in t into last word */
+ lsbyte = (lsbyte * 8) % 32;
+ if (lsbyte) {
+ t <<= lsbyte;
+ t |= (((BNWORD32)1 << lsbyte) - 1) & BIGLITTLE(n[0],n[-1]);
+ BIGLITTLE(n[0],n[-1]) = t;
+ }
+
+ return;
+}
+
+#ifdef DEADCODE /* This was a precursor to the more flexible lbnExtractBytes */
+/*
+ * Convert a big-endian array of bytes to a bignum.
+ * Returns the number of words in the bignum.
+ * Note the expression "32/8" for the number of bytes per word.
+ * This is so the word-size adjustment will work.
+ */
+unsigned
+lbnFromBytes_32(BNWORD32 *a, unsigned char const *b, unsigned blen)
+{
+ BNWORD32 t;
+ unsigned alen = (blen + (32/8-1))/(32/8);
+ BIGLITTLE(a -= alen, a += alen);
+
+ while (blen) {
+ t = 0;
+ do {
+ t = t << 8 | *b++;
+ } while (--blen & (32/8-1));
+ BIGLITTLE(*a++,*--a) = t;
+ }
+ return alen;
+}
+#endif
+
+/*
+ * Computes the GCD of a and b. Modifies both arguments;
+ * when it returns, one of them is the GCD and the other is trash.
+ * The return value is the length of the GCD, with the sign telling
+ * whether it is in a (+ve) or b (-ve). Both inputs must have
+ * one extra word of precision. alen must be >= blen.
+ *
+ * TODO: use the binary algorithm (Knuth section 4.5.2, algorithm B).
+ * This is based on taking out common powers of 2, then repeatedly:
+ * gcd(2*u,v) = gcd(u,2*v) = gcd(u,v) - isolated powers of 2 can be deleted.
+ * gcd(u,v) = gcd(u-v,v) - the numbers can be easily reduced.
+ * It gets less reduction per step, but the steps are much faster than
+ * the division case.
+ */
+int
+lbnGcd_32(BNWORD32 *a, unsigned alen, BNWORD32 *b, unsigned blen)
+{
+ assert(alen >= blen);
+
+ while (blen != 0) {
+ (void)lbnDiv_32(BIGLITTLE(a-blen,a+blen), a, alen, b, blen);
+ alen = lbnNorm_32(a, blen);
+ if (alen == 0)
+ return -(int)blen;
+ (void)lbnDiv_32(BIGLITTLE(b-alen,b+alen), b, blen, a, alen);
+ blen = lbnNorm_32(b, alen);
+ }
+ return alen;
+}
+
+/*
+ * Invert "a" modulo "mod" using the extended Euclidean algorithm.
+ * Note that this only computes one of the cosequences, and uses the
+ * theorem that the signs flip every step and the absolute value of
+ * the cosequence values are always bounded by the modulus to avoid
+ * having to work with negative numbers.
+ * gcd(a,mod) had better equal 1. Returns 1 if the GCD is NOT 1.
+ * a must be one word longer than "mod". It is overwritten with the
+ * result.
+ * TODO: Use Richard Schroeppel's *much* faster algorithm.
+ */
+int
+lbnInv_32(BNWORD32 *a, unsigned alen, BNWORD32 const *mod, unsigned mlen)
+{
+ BNWORD32 *b; /* Hold a copy of mod during GCD reduction */
+ BNWORD32 *p; /* Temporary for products added to t0 and t1 */
+ BNWORD32 *t0, *t1; /* Inverse accumulators */
+ BNWORD32 cy;
+ unsigned blen, t0len, t1len, plen;
+
+ alen = lbnNorm_32(a, alen);
+ if (!alen)
+ return 1; /* No inverse */
+
+ mlen = lbnNorm_32(mod, mlen);
+
+ assert (alen <= mlen);
+
+ /* Inverse of 1 is 1 */
+ if (alen == 1 && BIGLITTLE(a[-1],a[0]) == 1) {
+ lbnZero_32(BIGLITTLE(a-alen,a+alen), mlen-alen);
+ return 0;
+ }
+
+ /* Allocate a pile of space */
+ LBNALLOC(b, mlen+1);
+ if (b) {
+ /*
+ * Although products are guaranteed to always be less than the
+ * modulus, it can involve multiplying two 3-word numbers to
+ * get a 5-word result, requiring a 6th word to store a 0
+ * temporarily. Thus, mlen + 1.
+ */
+ LBNALLOC(p, mlen+1);
+ if (p) {
+ LBNALLOC(t0, mlen);
+ if (t0) {
+ LBNALLOC(t1, mlen);
+ if (t1)
+ goto allocated;
+ LBNFREE(t0, mlen);
+ }
+ LBNFREE(p, mlen+1);
+ }
+ LBNFREE(b, mlen+1);
+ }
+ return -1;
+
+allocated:
+
+ /* Set t0 to 1 */
+ t0len = 1;
+ BIGLITTLE(t0[-1],t0[0]) = 1;
+
+ /* b = mod */
+ lbnCopy_32(b, mod, mlen);
+ /* blen = mlen (implicitly) */
+
+ /* t1 = b / a; b = b % a */
+ cy = lbnDiv_32(t1, b, mlen, a, alen);
+ *(BIGLITTLE(t1-(mlen-alen)-1,t1+(mlen-alen))) = cy;
+ t1len = lbnNorm_32(t1, mlen-alen+1);
+ blen = lbnNorm_32(b, alen);
+
+ /* while (b > 1) */
+ while (blen > 1 || BIGLITTLE(b[-1],b[0]) != (BNWORD32)1) {
+ /* q = a / b; a = a % b; */
+ if (alen < blen || (alen == blen && lbnCmp_32(a, a, alen) < 0))
+ assert(0);
+ cy = lbnDiv_32(BIGLITTLE(a-blen,a+blen), a, alen, b, blen);
+ *(BIGLITTLE(a-alen-1,a+alen)) = cy;
+ plen = lbnNorm_32(BIGLITTLE(a-blen,a+blen), alen-blen+1);
+ assert(plen);
+ alen = lbnNorm_32(a, blen);
+ if (!alen)
+ goto failure; /* GCD not 1 */
+
+ /* t0 += q * t1; */
+ assert(plen+t1len <= mlen+1);
+ lbnMul_32(p, BIGLITTLE(a-blen,a+blen), plen, t1, t1len);
+ plen = lbnNorm_32(p, plen + t1len);
+ assert(plen <= mlen);
+ if (plen > t0len) {
+ lbnZero_32(BIGLITTLE(t0-t0len,t0+t0len), plen-t0len);
+ t0len = plen;
+ }
+ cy = lbnAddN_32(t0, p, plen);
+ if (cy) {
+ if (t0len > plen) {
+ cy = lbnAdd1_32(BIGLITTLE(t0-plen,t0+plen),
+ t0len-plen, cy);
+ }
+ if (cy) {
+ BIGLITTLE(t0[-t0len-1],t0[t0len]) = cy;
+ t0len++;
+ }
+ }
+
+ /* if (a <= 1) return a ? t0 : FAIL; */
+ if (alen <= 1 && BIGLITTLE(a[-1],a[0]) == (BNWORD32)1) {
+ if (alen == 0)
+ goto failure; /* FAIL */
+ assert(t0len <= mlen);
+ lbnCopy_32(a, t0, t0len);
+ lbnZero_32(BIGLITTLE(a-t0len, a+t0len), mlen-t0len);
+ goto success;
+ }
+
+ /* q = b / a; b = b % a; */
+ if (blen < alen || (blen == alen && lbnCmp_32(b, a, alen) < 0))
+ assert(0);
+ cy = lbnDiv_32(BIGLITTLE(b-alen,b+alen), b, blen, a, alen);
+ *(BIGLITTLE(b-blen-1,b+blen)) = cy;
+ plen = lbnNorm_32(BIGLITTLE(b-alen,b+alen), blen-alen+1);
+ assert(plen);
+ blen = lbnNorm_32(b, alen);
+ if (!blen)
+ goto failure; /* GCD not 1 */
+
+ /* t1 += q * t0; */
+ assert(plen+t0len <= mlen+1);
+ lbnMul_32(p, BIGLITTLE(b-alen,b+alen), plen, t0, t0len);
+ plen = lbnNorm_32(p, plen + t0len);
+ assert(plen <= mlen);
+ if (plen > t1len) {
+ lbnZero_32(BIGLITTLE(t1-t1len,t1+t1len), plen-t1len);
+ t1len = plen;
+ }
+ cy = lbnAddN_32(t1, p, plen);
+ if (cy) {
+ if (t1len > plen) {
+ cy = lbnAdd1_32(BIGLITTLE(t1-plen,t0+plen),
+ t1len-plen, cy);
+ }
+ if (cy) {
+ BIGLITTLE(t1[-t1len-1],t1[t1len]) = cy;
+ t1len++;
+ }
+ }
+ }
+
+ if (!blen)
+ goto failure; /* gcd(a, mod) != 1 -- FAIL */
+
+ /* return mod-t1 */
+ lbnCopy_32(a, mod, mlen);
+ assert(t1len <= mlen);
+ cy = lbnSubN_32(a, t1, t1len);
+ if (cy) {
+ assert(mlen > t1len);
+ cy = lbnSub1_32(BIGLITTLE(a-t1len, a+t1len), mlen-t1len, cy);
+ assert(!cy);
+ }
+
+success:
+ LBNFREE(t1, mlen);
+ LBNFREE(t0, mlen);
+ LBNFREE(p, mlen+1);
+ LBNFREE(b, mlen+1);
+
+ return 0;
+
+failure:
+ LBNFREE(t1, mlen);
+ LBNFREE(t0, mlen);
+ LBNFREE(p, mlen+1);
+ LBNFREE(b, mlen+1);
+
+ return 1;
+}
diff --git a/usr/src/lib/libresolv2/common/cylink/lbn32.h b/usr/src/lib/libresolv2/common/cylink/lbn32.h
new file mode 100644
index 0000000000..d0347390c2
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbn32.h
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef LBN32_H
+#define LBN32_H
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "lbn.h"
+
+#ifndef BNWORD32
+#error 32-bit bignum library requires a 32-bit data type
+#endif
+
+#ifndef lbnCopy_32
+void lbnCopy_32(BNWORD32 *dest, BNWORD32 const *src, unsigned len);
+#endif
+#ifndef lbnZero_32
+void lbnZero_32(BNWORD32 *num, unsigned len);
+#endif
+#ifndef lbnNeg_32
+void lbnNeg_32(BNWORD32 *num, unsigned len);
+#endif
+
+#ifndef lbnAdd1_32
+BNWORD32 lbnAdd1_32(BNWORD32 *num, unsigned len, BNWORD32 carry);
+#endif
+#ifndef lbnSub1_32
+BNWORD32 lbnSub1_32(BNWORD32 *num, unsigned len, BNWORD32 borrow);
+#endif
+
+#ifndef lbnAddN_32
+BNWORD32 lbnAddN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len);
+#endif
+#ifndef lbnSubN_32
+BNWORD32 lbnSubN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len);
+#endif
+
+#ifndef lbnCmp_32
+int lbnCmp_32(BNWORD32 const *num1, BNWORD32 const *num2, unsigned len);
+#endif
+
+#ifndef lbnMulN1_32
+void lbnMulN1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k);
+#endif
+#ifndef lbnMulAdd1_32
+BNWORD32
+lbnMulAdd1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k);
+#endif
+#ifndef lbnMulSub1_32
+BNWORD32 lbnMulSub1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k);
+#endif
+
+#ifndef lbnLshift_32
+BNWORD32 lbnLshift_32(BNWORD32 *num, unsigned len, unsigned shift);
+#endif
+#ifndef lbnDouble_32
+BNWORD32 lbnDouble_32(BNWORD32 *num, unsigned len);
+#endif
+#ifndef lbnRshift_32
+BNWORD32 lbnRshift_32(BNWORD32 *num, unsigned len, unsigned shift);
+#endif
+
+#ifndef lbnMul_32
+void lbnMul_32(BNWORD32 *prod, BNWORD32 const *num1, unsigned len1,
+ BNWORD32 const *num2, unsigned len2);
+#endif
+#ifndef lbnSquare_32
+void lbnSquare_32(BNWORD32 *prod, BNWORD32 const *num, unsigned len);
+#endif
+
+#ifndef lbnNorm_32
+unsigned lbnNorm_32(BNWORD32 const *num, unsigned len);
+#endif
+#ifndef lbnBits_32
+unsigned lbnBits_32(BNWORD32 const *num, unsigned len);
+#endif
+
+#ifndef lbnExtractBigBytes_32
+void lbnExtractBigBytes_32(BNWORD32 const *bn, unsigned char *buf,
+ unsigned lsbyte, unsigned buflen);
+#endif
+#ifndef lbnInsertBigytes_32
+void lbnInsertBigBytes_32(BNWORD32 *n, unsigned char const *buf,
+ unsigned lsbyte, unsigned buflen);
+#endif
+#ifndef lbnExtractLittleBytes_32
+void lbnExtractLittleBytes_32(BNWORD32 const *bn, unsigned char *buf,
+ unsigned lsbyte, unsigned buflen);
+#endif
+#ifndef lbnInsertLittleBytes_32
+void lbnInsertLittleBytes_32(BNWORD32 *n, unsigned char const *buf,
+ unsigned lsbyte, unsigned buflen);
+#endif
+
+#ifndef lbnDiv21_32
+BNWORD32 lbnDiv21_32(BNWORD32 *q, BNWORD32 nh, BNWORD32 nl, BNWORD32 d);
+#endif
+#ifndef lbnDiv1_32
+BNWORD32 lbnDiv1_32(BNWORD32 *q, BNWORD32 *rem,
+ BNWORD32 const *n, unsigned len, BNWORD32 d);
+#endif
+#ifndef lbnModQ_32
+unsigned lbnModQ_32(BNWORD32 const *n, unsigned len, unsigned d);
+#endif
+#ifndef lbnDiv_32
+BNWORD32
+lbnDiv_32(BNWORD32 *q, BNWORD32 *n, unsigned nlen, BNWORD32 *d, unsigned dlen);
+#endif
+
+#ifndef lbnMontInv1_32
+BNWORD32 lbnMontInv1_32(BNWORD32 const x);
+#endif
+#ifndef lbnMontReduce_32
+void lbnMontReduce_32(BNWORD32 *n, BNWORD32 const *mod, unsigned const mlen,
+ BNWORD32 inv);
+#endif
+#ifndef lbnToMont_32
+void lbnToMont_32(BNWORD32 *n, unsigned nlen, BNWORD32 *mod, unsigned mlen);
+#endif
+#ifndef lbnFromMont_32
+void lbnFromMont_32(BNWORD32 *n, BNWORD32 *mod, unsigned len);
+#endif
+
+#ifndef lbnExpMod_32
+int lbnExpMod_32(BNWORD32 *result, BNWORD32 const *n, unsigned nlen,
+ BNWORD32 const *exp, unsigned elen, BNWORD32 *mod, unsigned mlen);
+#endif
+#ifndef lbnDoubleExpMod_32
+int lbnDoubleExpMod_32(BNWORD32 *result,
+ BNWORD32 const *n1, unsigned n1len, BNWORD32 const *e1, unsigned e1len,
+ BNWORD32 const *n2, unsigned n2len, BNWORD32 const *e2, unsigned e2len,
+ BNWORD32 *mod, unsigned mlen);
+#endif
+#ifndef lbnTwoExpMod_32
+int lbnTwoExpMod_32(BNWORD32 *n, BNWORD32 const *exp, unsigned elen,
+ BNWORD32 *mod, unsigned mlen);
+#endif
+#ifndef lbnGcd_32
+int lbnGcd_32(BNWORD32 *a, unsigned alen, BNWORD32 *b, unsigned blen);
+#endif
+#ifndef lbnInv_32
+int lbnInv_32(BNWORD32 *a, unsigned alen, BNWORD32 const *mod, unsigned mlen);
+#endif
+
+#endif /* LBN32_H */
diff --git a/usr/src/lib/libresolv2/common/cylink/lbn68000.c b/usr/src/lib/libresolv2/common/cylink/lbn68000.c
new file mode 100644
index 0000000000..96404d674f
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbn68000.c
@@ -0,0 +1,507 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/*
+ * lbn68000.c - 16-bit bignum primitives for the 68000 (or 68010) processors.
+ *
+ * Copyright (c) 1995 Colin Plumb. All rights reserved.
+ * For licensing and other legal details, see the file legal.c.
+ *
+ * This was written for Metrowerks C, and while it should be reasonably
+ * portable, NOTE that Metrowerks lets a callee trash a0, a1, d0, d1, and d2.
+ * Some 680x0 compilers make d2 callee-save, so instructions to save it
+ * will have to be added.
+ *
+ * This code supports 16 or 32-bit ints, based on UINT_MAX.
+ * Regardless of UINT_MAX, only bignums up to 64K words (1 million bits)
+ * are supported. (68k hackers will recognize this as a consequence of
+ * using dbra.)
+ *
+ * These primitives use little-endian word order.
+ * (The order of bytes within words is irrelevant to this issue.)
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <limits.h>
+
+#include "lbn.h" /* Should include lbn68000.h */
+
+/*
+ * The Metrowerks C compiler (1.2.2) produces bad 68k code for the
+ * following input, which happens to be the inner loop of lbnSub1,
+ * so a few less than critical routines have been recoded in assembly
+ * to avoid the bug. (Optimizer on or off does not matter.)
+ *
+ * unsigned
+ * decrement(unsigned *num, unsigned len)
+ * {
+ * do {
+ * if ((*num++)-- != 0)
+ * return 0;
+ * } while (--len);
+ * return 1;
+ * }
+ */
+asm BNWORD16
+lbnSub1_16(BNWORD16 *num, unsigned len, BNWORD16 borrow)
+{
+ movea.l 4(sp),a0 /* num */
+#if UINT_MAX == 0xffff
+ move.w 10(sp),d0 /* borrow */
+#else
+ move.w 12(sp),d0 /* borrow */
+#endif
+ sub.w d0,(a0)+
+ bcc done
+#if UINT_MAX == 0xffff
+ move.w 8(sp),d0 /* len */
+#else
+ move.w 10(sp),d0 /* len */
+#endif
+ subq.w #2,d0
+ bcs done
+loop:
+ subq.w #1,(a0)+
+ dbcc d0,loop
+done:
+ moveq.l #0,d0
+ addx.w d0,d0
+ rts
+}
+
+asm BNWORD16
+lbnAdd1_16(BNWORD16 *num, unsigned len, BNWORD16 carry)
+{
+ movea.l 4(sp),a0 /* num */
+#if UINT_MAX == 0xffff
+ move.w 10(sp),d0 /* carry */
+#else
+ move.w 12(sp),d0 /* carry */
+#endif
+ add.w d0,(a0)+
+ bcc done
+#if UINT_MAX == 0xffff
+ move.w 8(sp),d0 /* len */
+#else
+ move.w 10(sp),d0 /* len */
+#endif
+ subq.w #2,d0
+ bcs done
+loop:
+ addq.w #1,(a0)+
+ dbcc d0,loop
+done:
+ moveq.l #0,d0
+ addx.w d0,d0
+ rts
+}
+
+asm void
+lbnMulN1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k)
+{
+ move.w d3,-(sp) /* 2 bytes of stack frame */
+ move.l 2+4(sp),a1 /* out */
+ move.l 2+8(sp),a0 /* in */
+#if UINT_MAX == 0xffff
+ move.w 2+12(sp),d3 /* len */
+ move.w 2+14(sp),d2 /* k */
+#else
+ move.w 2+14(sp),d3 /* len (low 16 bits) */
+ move.w 2+16(sp),d2 /* k */
+#endif
+
+ move.w (a0)+,d1 /* First multiply */
+ mulu.w d2,d1
+ move.w d1,(a1)+
+ clr.w d1
+ swap d1
+
+ subq.w #1,d3 /* Setup for loop unrolling */
+ lsr.w #1,d3
+ bcs.s m16_even
+ beq.s m16_short
+
+ subq.w #1,d3 /* Set up software pipeline properly */
+ move.l d1,d0
+
+m16_loop:
+ move.w (a0)+,d1
+ mulu.w d2,d1
+ add.l d0,d1
+ move.w d1,(a1)+
+ clr.w d1
+ swap d1
+m16_even:
+
+ move.w (a0)+,d0
+ mulu.w d2,d0
+ add.l d1,d0
+ move.w d0,(a1)+
+ clr.w d0
+ swap d0
+
+ dbra d3,m16_loop
+
+ move.w d0,(a1)
+ move.w (sp)+,d3
+ rts
+m16_short:
+ move.w d1,(a1)
+ move.w (sp)+,d3
+ rts
+}
+
+
+asm BNWORD16
+lbnMulAdd1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k)
+{
+ move.w d4,-(sp)
+ clr.w d4
+ move.w d3,-(sp) /* 4 bytes of stack frame */
+ move.l 4+4(sp),a1 /* out */
+ move.l 4+8(sp),a0 /* in */
+#if UINT_MAX == 0xffff
+ move.w 4+12(sp),d3 /* len */
+ move.w 4+14(sp),d2 /* k */
+#else
+ move.w 4+14(sp),d3 /* len (low 16 bits) */
+ move.w 4+16(sp),d2 /* k */
+#endif
+
+ move.w (a0)+,d1 /* First multiply */
+ mulu.w d2,d1
+ add.w d1,(a1)+
+ clr.w d1
+ swap d1
+ addx.w d4,d1
+
+ subq.w #1,d3 /* Setup for loop unrolling */
+ lsr.w #1,d3
+ bcs.s ma16_even
+ beq.s ma16_short
+
+ subq.w #1,d3 /* Set up software pipeline properly */
+ move.l d1,d0
+
+ma16_loop:
+ move.w (a0)+,d1
+ mulu.w d2,d1
+ add.l d0,d1
+ add.w d1,(a1)+
+ clr.w d1
+ swap d1
+ addx.w d4,d1
+ma16_even:
+
+ move.w (a0)+,d0
+ mulu.w d2,d0
+ add.l d1,d0
+ add.w d0,(a1)+
+ clr.w d0
+ swap d0
+ addx.w d4,d0
+
+ dbra d3,ma16_loop
+
+ move.w (sp)+,d3
+ move.w (sp)+,d4
+ rts
+ma16_short:
+ move.w (sp)+,d3
+ move.l d1,d0
+ move.w (sp)+,d4
+ rts
+}
+
+
+
+asm BNWORD16
+lbnMulSub1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k)
+{
+ move.w d4,-(sp)
+ clr.w d4
+ move.w d3,-(sp) /* 4 bytes of stack frame */
+ move.l 4+4(sp),a1 /* out */
+ move.l 4+8(sp),a0 /* in */
+#if UINT_MAX == 0xffff
+ move.w 4+12(sp),d3 /* len */
+ move.w 4+14(sp),d2 /* k */
+#else
+ move.w 4+14(sp),d3 /* len (low 16 bits) */
+ move.w 4+16(sp),d2 /* k */
+#endif
+
+ move.w (a0)+,d1 /* First multiply */
+ mulu.w d2,d1
+ sub.w d1,(a1)+
+ clr.w d1
+ swap d1
+ addx.w d4,d1
+
+ subq.w #1,d3 /* Setup for loop unrolling */
+ lsr.w #1,d3
+ bcs.s ms16_even
+ beq.s ms16_short
+
+ subq.w #1,d3 /* Set up software pipeline properly */
+ move.l d1,d0
+
+ms16_loop:
+ move.w (a0)+,d1
+ mulu.w d2,d1
+ add.l d0,d1
+ sub.w d1,(a1)+
+ clr.w d1
+ swap d1
+ addx.w d4,d1
+ms16_even:
+
+ move.w (a0)+,d0
+ mulu.w d2,d0
+ add.l d1,d0
+ sub.w d0,(a1)+
+ clr.w d0
+ swap d0
+ addx.w d4,d0
+
+ dbra d3,ms16_loop
+
+ move.w (sp)+,d3
+ move.w (sp)+,d4
+ rts
+ms16_short:
+ move.w (sp)+,d3
+ move.l d1,d0
+ move.w (sp)+,d4
+ rts
+}
+
+/* The generic long/short divide doesn't know that nh < d */
+asm BNWORD16
+lbnDiv21_16(BNWORD16 *q, BNWORD16 nh, BNWORD16 nl, BNWORD16 d)
+{
+ move.l 8(sp),d0 /* nh *and* nl */
+ divu.w 12(sp),d0
+ move.l 4(sp),a0
+ move.w d0,(a0)
+ clr.w d0
+ swap d0
+ rts
+}
+
+asm unsigned
+lbnModQ_16(BNWORD16 const *n, unsigned len, BNWORD16 d)
+{
+ move.l 4(sp),a0 /* n */
+ moveq.l #0,d1
+#if UINT_MAX == 0xffff
+ move.w 8(sp),d1 /* len */
+ move.w 10(sp),d2 /* d */
+#else
+ move.w 10(sp),d1 /* len (low 16 bits) */
+ move.w 12(sp),d2 /* d */
+#endif
+
+ add.l d1,a0
+ add.l d1,a0 /* n += len */
+ moveq.l #0,d0
+ subq.w #1,d1
+
+mq16_loop:
+ move.w -(a0),d0 /* Assemble remainder and new word */
+ divu.w d2,d0 /* Put remainder in high half of d0 */
+ dbra d1,mq16_loop
+
+mq16_done:
+ clr.w d0
+ swap d0
+ rts
+}
+
+/*
+ * Detect if this is a 32-bit processor (68020+ *or* CPU32).
+ * Both the 68020+ and CPU32 processors (which have 32x32->64-bit
+ * multiply, what the 32-bit math library wants) support scaled indexed
+ * addressing. The 68000 and 68010 ignore the scale selection
+ * bits, treating it as *1 all the time. So a 32-bit processor
+ * will evaluate -2(a0,a0.w*2) as 1+1*2-2 = 1.
+ * A 16-bit processor will compute 1+1-2 = 0.
+ *
+ * Thus, the return value will indicate whether the chip this is
+ * running on supports 32x32->64-bit multiply (mulu.l).
+ */
+asm int
+is68020(void)
+{
+ machine 68020
+ lea 1,a0
+#if 0
+ lea -2(a0,a0.w*2),a0 /* Metrowerks won't assemble this, arrgh */
+#else
+ dc.w 0x41f0, 0x82fe
+#endif
+ move.l a0,d0
+ rts
+}
+/*
+ * Since I had to hand-assemble that fancy addressing mode, I had to study
+ * up on 680x0 addressing modes.
+ * A summary of 680x0 addressing modes.
+ * A 68000 effective address specifies an operand on an instruction, which
+ * may be a register or in memory. It is made up of a 3-bit mode and a
+ * 3-bit register specifier. The meanings of the various modes are:
+ *
+ * 000 reg - Dn, n specified by "reg"
+ * 001 reg - An, n specified by "reg"
+ * 010 reg - (An)
+ * 011 reg - (An)+
+ * 100 reg - -(An)
+ * 101 reg - d16(An), one 16-bit displacement word follows, sign-extended
+ * 110 reg - Fancy addressing mode off of An, see extension word below
+ * 111 000 - abs.W, one 16-bit signed absolute address follows
+ * 111 001 - abs.L, one 32-bit absolute address follows
+ * 111 010 - d16(PC), one 16-bit displacemnt word follows, sign-extended
+ * 111 011 - Fancy addressing mode off of PC, see extension word below
+ * 111 100 - #immediate, followed by 16 or 32 bits of immediate value
+ * 111 101 - unused, reserved
+ * 111 110 - unused, reserved
+ * 111 111 - unused, reserved
+ *
+ * Memory references are to data space, except that PC-relative references
+ * are to program space, and are read-only.
+ *
+ * Fancy addressing modes are followed by a 16-bit extension word, and come
+ * in "brief" and "full" forms.
+ * The "brief" form looks like this. Bit 8 is 0 to indicate this form:
+ *
+ * 1 1 1 1 1 1 1
+ * 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ * |A/D| register |L/W| scale | 0 | 8-bit signed displacement |
+ * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ *
+ * The basic effective address specifies a 32-bit base register - A0 through
+ * A7 or PC (the address of the following instruction).
+ * The A/D and register fields specify an index register. A/D is 1 for
+ * address registers, and 0 for data registers. L/W specifies the length
+ * of the index register, 1 for 32 bits, and 0 for 16 bits (sign-extended).
+ * The scale field is a left shift amount (0 to 3 bits) to apply to the
+ * sign-extended index register. The final address is d8(An,Rn.X*SCALE),
+ * also written (d8,An,Rn.X*SCALE). X is "W" or "L", SCALE is 1, 2, 4 or 8.
+ * "*1" may be omitted, as may a d8 of 0.
+ *
+ * The 68000 supports this form, but only with a scale field of 0.
+ * It does NOT (says the MC68030 User's Manual MC68030UM/AD, section 2.7)
+ * decode the scale field and the following format bit. They are treated
+ * as 0.
+ * I recall (I don't have the data book handy) that the CPU32 processor
+ * core used in the 683xx series processors supports variable scales,
+ * but only the brief extension word form. I suspect it decodes the
+ * format bit and traps if it is not zero, but I don't recall.
+ *
+ * The "full" form (680x0, x >= 2 processors only) looks like this:
+ *
+ * 1 1 1 1 1 1 1
+ * 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ * |A/D| register |L/W| scale | 1 | BS| IS|BD size| 0 | P |OD size|
+ * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ *
+ * The first 8 bits are interpreted the same way as in the brief form,
+ * except that bit 8 is set to 1 to indicate the full form.
+ * BS, Base Suppress, if set, causes a value of 0 to be used in place of
+ * the base register value. If this is set, the base register
+ * specified is irrelevant, except that if it is the PC, the fetch is
+ * still done from program space. The specifier "ZPC" can be used in
+ * place of "PC" in the effective address mnemonic to represent this
+ * case.
+ * IS, Index Suppress, if set, causes a value of 0 to be used in place
+ * of the scaled index register. In this case, the first 7 bits of the
+ * extension word are irrelevant.
+ * BD size specifies the base displacement size. A value of 00
+ * in this field is illegal, while 01, 10 and 11 indicate that the
+ * extension word is followed by 0, 1 or 2 16-bit words of base displacement
+ * (zero, sign-extended to 32 bits, and most-significant word first,
+ * respectively) to add to the base register value.
+ * Bit 3 is unused.
+ * The P bit is the pre/post indexing bit, and only applies if an outer
+ * displacement is used. This is explained later.
+ * OD size specifies the size of an outer displacement. In the simple
+ * case, this field is set to 00 and the effective address is
+ * (disp,An,Rn.X*SCALE) or (disp,PC,Rn.X*SCALE).
+ * In this case the P bit must be 0. Any of those compnents may be
+ * suppressed, with a BD size of 01, the BS bit, or the IS bit.
+ * If the OD size is not 00, it encodes an outer displacement in the same
+ * manner as the BD size, and 0, 1 or 2 16-bit words of outer displacement
+ * follow the base displacement in the instruction stream. In this case,
+ * this is a double-indirect addressing mode. The base, base displacement,
+ * and possibly the index, specify a 32-bit memory word which holds a value
+ * which is fetched, and the outer displacement and possibly the index are
+ * added to produce the address of the operand.
+ * If the P bit is 0, this is pre-indexed, and the index value is added
+ * before the fetch of the indirect word, producing an effective address
+ * of ([disp,An,Rn.X*SCALE],disp). If the P bit is 1, the post-indexed case,
+ * the memory word is fectched from base+base displacement, then the index
+ * and outer displacement are added to compute the address of the operand.
+ * This effective address is written ([disp,An],Rn.X*SCALE,disp).
+ * (In both cases, "An" may also be "PC" or "ZPC".)
+ * Any of the components may be omitted. If the index is omitted (using the
+ * IS bit), the P bit is irrelevant, but must be written as 0.
+ * Thus, legal combinations of IS, P and OD size are:
+ * 0 0 00 - (disp,An,Rn.X*SCALE), also written disp(An,Rn.X*SCALE)
+ * 0 0 01 - ([disp,An,Rn.X*SCALE])
+ * 0 0 10 - ([disp,An,Rn.X*SCALE],d16)
+ * 0 0 11 - ([disp,An,Rn.X*SCALE],d32)
+ * 0 1 01 - ([disp,An],Rn.X*SCALE)
+ * 0 1 10 - ([disp,An],Rn.X*SCALE,d16)
+ * 0 1 11 - ([disp,An],Rn.X*SCALE,d32)
+ * 1 0 00 - (disp,An), also written disp(An)
+ * 1 0 01 - ([disp,An])
+ * 1 0 10 - ([disp,An],d16)
+ * 1 0 11 - ([disp,An],d32)
+ */
+
+/* 45678901234567890123456789012345678901234567890123456789012345678901234567 */
diff --git a/usr/src/lib/libresolv2/common/cylink/lbn68000.h b/usr/src/lib/libresolv2/common/cylink/lbn68000.h
new file mode 100644
index 0000000000..ebd667d177
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbn68000.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/*
+ * lbn68000.h - 16-bit bignum primitives for the 68000 (or 68010) processors.
+ *
+ * These primitives use little-endian word order.
+ * (The order of bytes within words is irrelevant.)
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#define BN_LITTLE_ENDIAN 1
+
+typedef unsigned short bnword16
+#define BNWORD16 bnword16
+
+bnword16 lbnSub1_16(bnword16 *num, unsigned len, bnword16 borrow);
+bnword16 lbnAdd1_16(bnword16 *num, unsigned len, bnword16 carry);
+void lbnMulN1_16(bnword16 *out, bnword16 const *in, unsigned len, bnword16 k);
+bnword16
+lbnMulAdd1_16(bnword16 *out, bnword16 const *in, unsigned len, bnword16 k);
+bnword16
+lbnMulSub1_16(bnword16 *out, bnword16 const *in, unsigned len, bnword16 k);
+bnword16 lbnDiv21_16(bnword16 *q, bnword16 nh, bnword16 nl, bnword16 d);
+unsigned lbnModQ_16(bnword16 const *n, unsigned len, bnword16 d);
+
+int is68020(void);
+
+/* #define the values to exclude the C versions */
+#define lbnSub1_16 lbnSub1_16
+#define lbnAdd1_16 lbnAdd1_16
+#define lbnMulN1_16 lbnMulN1_16
+#define lbnMulAdd1_16 lbnMulAdd1_16
+#define lbnMulSub1_16 lbnMulSub1_16
+#define lbnDiv21_16 lbnDiv21_16
+#define lbnModQ_16 lbnModQ_16
+
+/* Also include the 68020 definitions for 16/32 bit switching versions. */
+#include <lbn68020.h>
diff --git a/usr/src/lib/libresolv2/common/cylink/lbn68020.c b/usr/src/lib/libresolv2/common/cylink/lbn68020.c
new file mode 100644
index 0000000000..f3562a3463
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbn68020.c
@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/*
+ * lbn68020.c - 32-bit bignum primitives for the 68020+ (0r 683xx) processors.
+ *
+ * Copyright (c) 1995 Colin Plumb. All rights reserved.
+ * For licensing and other legal details, see the file legal.c.
+ *
+ * This was written for Metrowerks C, and while it should be reasonably
+ * portable, NOTE that Metrowerks lets a callee trash a0, a1, d0, d1, and d2.
+ * Some 680x0 compilers make d2 callee-save, so instructions to save it
+ * will have to be added.
+ *
+ * This code supports 16 or 32-bit ints, based on UINT_MAX.
+ * Regardless of UINT_MAX, only bignums up to 64K words (2 million bits)
+ * are supported. (68k hackers will recognize this as a consequence of
+ * using dbra.)
+ *
+ * These primitives use little-endian word order.
+ * (The order of bytes within words is irrelevant to this issue.)
+ *
+ * TODO: Schedule this for the 68040's pipeline. (When I get a 68040 manual.)
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <limits.h>
+
+#include "lbn.h" /* Should include lbn68020.h */
+
+/*
+ * The Metrowerks C compiler (1.2.2) produces bad 68k code for the
+ * following input, which happens to be the inner loop of lbnSub1,
+ * so a few less than critical routines have been recoded in assembly
+ * to avoid the bug. (Optimizer on or off does not matter.)
+ *
+ * unsigned
+ * decrement(unsigned *num, unsigned len)
+ * {
+ * do {
+ * if ((*num++)-- != 0)
+ * return 0;
+ * } while (--len);
+ * return 1;
+ * }
+ */
+asm BNWORD32
+lbnSub1_32(BNWORD32 *num, unsigned len, BNWORD32 borrow)
+{
+ movea.l 4(sp),a0 /* num */
+#if UINT_MAX == 0xffff
+ move.l 10(sp),d0 /* borrow */
+#else
+ move.l 12(sp),d0 /* borrow */
+#endif
+ sub.l d0,(a0)+
+ bcc done
+#if UINT_MAX == 0xffff
+ move.w 8(sp),d0 /* len */
+#else
+ move.w 10(sp),d0 /* len */
+#endif
+ subq.w #2,d0
+ bcs done
+loop:
+ subq.l #1,(a0)+
+ dbcc d0,loop
+done:
+ moveq.l #0,d0
+ addx.w d0,d0
+ rts
+}
+
+asm BNWORD32
+lbnAdd1_32(BNWORD32 *num, unsigned len, BNWORD32 carry)
+{
+ movea.l 4(sp),a0 /* num */
+#if UINT_MAX == 0xffff
+ move.l 10(sp),d0 /* carry */
+#else
+ move.l 12(sp),d0 /* carry */
+#endif
+ add.l d0,(a0)+
+ bcc done
+#if UINT_MAX == 0xffff
+ move.w 8(sp),d0 /* len */
+#else
+ move.w 10(sp),d0 /* len */
+#endif
+ subq.w #2,d0
+ bcs done
+loop:
+ addq.l #1,(a0)+
+ dbcc d0,loop
+done:
+ moveq.l #0,d0
+ addx.w d0,d0
+ rts
+}
+
+asm void
+lbnMulN1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
+{
+ machine 68020
+
+ movem.l d3-d5,-(sp) /* 12 bytes of extra data */
+ moveq.l #0,d4
+ move.l 16(sp),a1 /* out */
+ move.l 20(sp),a0 /* in */
+#if UINT_MAX == 0xffff
+ move.w 24(sp),d5 /* len */
+ move.l 26(sp),d2 /* k */
+#else
+ move.w 26(sp),d5 /* len */
+ move.l 28(sp),d2 /* k */
+#endif
+
+ move.l (a0)+,d3 /* First multiply */
+ mulu.l d2,d1:d3 /* dc.w 0x4c02, 0x3401 */
+ move.l d3,(a1)+
+
+ subq.w #1,d5 /* Setup for loop unrolling */
+ lsr.w #1,d5
+ bcs.s m32_even
+ beq.s m32_short
+
+ subq.w #1,d5 /* Set up software pipeline properly */
+ move.l d1,d0
+
+m32_loop:
+ move.l (a0)+,d3
+ mulu.l d2,d1:d3 /* dc.w 0x4c02, 0x3401 */
+ add.l d0,d3
+ addx.l d4,d1
+ move.l d3,(a1)+
+m32_even:
+
+ move.l (a0)+,d3
+ mulu.l d2,d0:d3 /* dc.w 0x4c02, 0x3400 */
+ add.l d1,d3
+ addx.l d4,d0
+ move.l d3,(a1)+
+
+ dbra d5,m32_loop
+
+ move.l d0,(a1)
+ movem.l (sp)+,d3-d5
+ rts
+m32_short:
+ move.l d1,(a1)
+ movem.l (sp)+,d3-d5
+ rts
+}
+
+
+asm BNWORD32
+lbnMulAdd1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
+{
+ machine 68020
+ movem.l d3-d5,-(sp) /* 12 bytes of extra data */
+ moveq.l #0,d4
+ move.l 16(sp),a1 /* out */
+ move.l 20(sp),a0 /* in */
+#if UINT_MAX == 0xffff
+ move.w 24(sp),d5 /* len */
+ move.l 26(sp),d2 /* k */
+#else
+ move.w 26(sp),d5 /* len */
+ move.l 28(sp),d2 /* k */
+#endif
+
+ move.l (a0)+,d3 /* First multiply */
+ mulu.l d2,d1:d3 /* dc.w 0x4c02, 0x3401 */
+ add.l d3,(a1)+
+ addx.l d4,d1
+
+ subq.w #1,d5 /* Setup for loop unrolling */
+ lsr.w #1,d5
+ bcs.s ma32_even
+ beq.s ma32_short
+
+ subq.w #1,d5 /* Set up software pipeline properly */
+ move.l d1,d0
+
+ma32_loop:
+ move.l (a0)+,d3
+ mulu.l d2,d1:d3 /* dc.w 0x4c02, 0x3401 */
+ add.l d0,d3
+ addx.l d4,d1
+ add.l d3,(a1)+
+ addx.l d4,d1
+ma32_even:
+
+ move.l (a0)+,d3
+ mulu.l d2,d0:d3 /* dc.w 0x4c02, 0x3400 */
+ add.l d1,d3
+ addx.l d4,d0
+ add.l d3,(a1)+
+ addx.l d4,d0
+
+ dbra d5,ma32_loop
+
+ movem.l (sp)+,d3-d5
+ rts
+ma32_short:
+ move.l d1,d0
+ movem.l (sp)+,d3-d5
+ rts
+}
+
+
+asm BNWORD32
+lbnMulSub1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
+{
+ machine 68020
+ movem.l d3-d5,-(sp) /* 12 bytes of extra data */
+ moveq.l #0,d4
+ move.l 16(sp),a1 /* out */
+ move.l 20(sp),a0 /* in */
+#if UINT_MAX == 0xffff
+ move.w 24(sp),d5 /* len */
+ move.l 26(sp),d2 /* k */
+#else
+ move.w 26(sp),d5 /* len */
+ move.l 28(sp),d2 /* k */
+#endif
+
+ move.l (a0)+,d3 /* First multiply */
+ mulu.l d2,d1:d3 /* dc.w 0x4c02, 0x3401 */
+ sub.l d3,(a1)+
+ addx.l d4,d1
+
+ subq.w #1,d5 /* Setup for loop unrolling */
+ lsr.w #1,d5
+ bcs.s ms32_even
+ beq.s ms32_short
+
+ subq.w #1,d5 /* Set up software pipeline properly */
+ move.l d1,d0
+
+ms32_loop:
+ move.l (a0)+,d3
+ mulu.l d2,d1:d3 /* dc.w 0x4c02, 0x3401 */
+ add.l d0,d3
+ addx.l d4,d1
+ sub.l d3,(a1)+
+ addx.l d4,d1
+ms32_even:
+
+ move.l (a0)+,d3
+ mulu.l d2,d0:d3 /* dc.w 0x4c02, 0x3400 */
+ add.l d1,d3
+ addx.l d4,d0
+ sub.l d3,(a1)+
+ addx.l d4,d0
+
+ dbra d5,ms32_loop
+
+ movem.l (sp)+,d3-d5
+ rts
+
+ms32_short:
+ move.l d1,d0
+ movem.l (sp)+,d3-d5
+ rts
+}
+
+
+asm BNWORD32
+lbnDiv21_32(BNWORD32 *q, BNWORD32 nh, BNWORD32 nl, BNWORD32 d)
+{
+ machine 68020
+ move.l 8(sp),d0
+ move.l 12(sp),d1
+ move.l 4(sp),a0
+ divu.l 16(sp),d0:d1 /* dc.w 0x4c6f, 0x1400, 16 */
+ move.l d1,(a0)
+ rts
+}
+
+asm unsigned
+lbnModQ_32(BNWORD32 const *n, unsigned len, unsigned d)
+{
+ machine 68020
+ move.l 4(sp),a0 /* n */
+ move.l d3,a1
+#if UINT_MAX == 0xffff
+ moveq.l #0,d2
+ move.w 8(sp),d1 /* len */
+ move.w 10(sp),d2 /* d */
+#else
+ move.w 10(sp),d1 /* len */
+ move.l 12(sp),d2 /* d */
+#endif
+ dc.w 0x41f0, 0x1cfc /* lea -4(a0,d1.L*4),a0 */
+
+ /* First time, divide 32/32 - may be faster than 64/32 */
+ move.l (a0),d3
+ divul.l d2,d0:d3 /* dc.w 0x4c02, 0x3000 */
+ subq.w #2,d1
+ bmi mq32_done
+
+mq32_loop:
+ move.l -(a0),d3
+ divu.l d2,d0:d3 /* dc.w 0x4c02,0x3400 */
+ dbra d1,mq32_loop
+
+mq32_done:
+ move.l a1,d3
+ rts
+}
+
+/* 45678901234567890123456789012345678901234567890123456789012345678901234567 */
diff --git a/usr/src/lib/libresolv2/common/cylink/lbn68020.h b/usr/src/lib/libresolv2/common/cylink/lbn68020.h
new file mode 100644
index 0000000000..4aff67f5ed
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbn68020.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/*
+ * lbn68020.h - 32-bit bignum primitives for the 68020 (or 683xx) processors.
+ *
+ * These primitives use little-endian word order.
+ * (The order of bytes within words is irrelevant.)
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#define BN_LITTLE_ENDIAN 1
+
+typedef unsigned long bnword32
+#define BNWORD32 bnword32
+
+bnword32 lbnSub1_32(bnword32 *num, unsigned len, bnword32 borrow);
+bnword32 lbnAdd1_32(bnword32 *num, unsigned len, bnword32 carry);
+void lbnMulN1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k);
+bnword32
+lbnMulAdd1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k);
+bnword32
+lbnMulSub1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k);
+bnword32 lbnDiv21_32(bnword32 *q, bnword32 nh, bnword32 nl, bnword32 d);
+unsigned lbnModQ_32(bnword32 const *n, unsigned len, unsigned d);
+
+/* #define the values to exclude the C versions */
+#define lbnSub1_32 lbnSub1_32
+#define lbnAdd1_32 lbnAdd1_32
+#define lbnMulN1_32 lbnMulN1_32
+#define lbnMulAdd1_32 lbnMulAdd1_32
+#define lbnMulSub1_32 lbnMulSub1_32
+#define lbnDiv21_32 lbnDiv21_32
+#define lbnModQ_32 lbnModQ_32
diff --git a/usr/src/lib/libresolv2/common/cylink/lbn80386.h b/usr/src/lib/libresolv2/common/cylink/lbn80386.h
new file mode 100644
index 0000000000..10e10e10a5
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbn80386.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/*
+ * lbn80386.h - This file defines the interfaces to the 80386
+ * assembly primitives. It is intended to be included in "lbn.h"
+ * via the "#include BNINCLUDE" mechanism.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#define BN_LITTLE_ENDIAN 1
+
+typedef unsigned long bnword32;
+#define BNWORD32 bnword32
+
+/* MS-DOS needs the calling convention described to it. */
+#ifndef MSDOS
+#ifdef __MSDOS__
+#define MSDOS 1
+#endif
+#endif
+
+#ifdef MSDOS
+#define CDECL __cdecl
+#else
+#define CDECL /*nothing*/
+#endif
+
+#ifdef __cplusplus
+/* These assembly-language primitives use C names */
+extern "C" {
+#endif
+
+/* Function prototypes for the asm routines */
+void CDECL
+lbnMulN1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k);
+#define lbnMulN1_32 lbnMulN1_32
+
+bnword32 CDECL
+lbnMulAdd1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k);
+#define lbnMulAdd1_32 lbnMulAdd1_32
+
+bnword32 CDECL
+lbnMulSub1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k);
+#define lbnMulSub1_32 lbnMulSub1_32
+
+bnword32 CDECL
+lbnDiv21_32(bnword32 *q, bnword32 nh, bnword32 nl, bnword32 d);
+#define lbnDiv21_32 lbnDiv21_32
+
+unsigned CDECL
+lbnModQ_32(bnword32 const *n, unsigned len, bnword32 d);
+#define lbnModQ_32 lbnModQ_32
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#if __GNUC__
+/*
+ * Use the (massively cool) GNU inline-assembler extension to define
+ * inline expansions for various operations.
+ *
+ * The massively cool part is that the assembler can have inputs
+ * and outputs, and you specify the operands and which effective
+ * addresses are legal and they get substituted into the code.
+ * (For example, some of the code requires a zero. Rather than
+ * specify an immediate constant, the expansion specifies an operand
+ * of zero which can be in various places. This lets GCC use an
+ * immediate zero, or a register which contains zero if it's available.)
+ *
+ * The syntax is asm("asm_code" : outputs : inputs : trashed)
+ * %0, %1 and so on in the asm code are substituted by the operands
+ * in left-to-right order (outputs, then inputs).
+ * The operands contain constraint strings and values to use.
+ * Outputs must be lvalues, inputs may be rvalues. In the constraints:
+ * "a" means that the operand must be in eax.
+ * "d" means that the operand must be in edx.
+ * "g" means that the operand may be any effective address.
+ * "=" means that the operand is assigned to.
+ * "%" means that this operand and the following one may be
+ * interchanged if desirable.
+ * "bcDSmn" means that the operand must be in ebx, ecx, esi, edi, memory,
+ * or an immediate constant. (This is almost the same as "g"
+ * but allowing it in eax wouldn't help because x is already
+ * assigned there, and it must not be in edx, since edx is
+ * overwritten by the multiply before a and b are read.)
+ *
+ * Note that GCC uses AT&T assembler syntax, which is rather
+ * different from Intel syntax. The length (b, w or l) of the
+ * operation is appended to the opcode, and the *second* operand
+ * is the destination, not the first. Finally, the register names
+ * are all preceded with "%". (Doubled here because % is a
+ * magic character.)
+ */
+
+/* (ph<<32) + pl = x*y */
+#define mul32_ppmm(ph,pl,x,y) \
+ __asm__("mull %3" : "=d"(ph), "=a"(pl) : "%a"(x), "g"(y))
+
+/* (ph<<32) + pl = x*y + a */
+#define mul32_ppmma(ph,pl,x,y,a) \
+ __asm__("mull %3\n\t" \
+ "addl %4,%%eax\n\t" \
+ "adcl %5,%%edx" \
+ : "=&d"(ph), "=a"(pl) \
+ : "%a"(x), "g"(y), "bcDSmn"(a), "bcDSmn"(0))
+
+/* (ph<<32) + pl = x*y + a + b */
+#define mul32_ppmmaa(ph,pl,x,y,a,b) \
+ __asm__("mull %3\n\t" \
+ "addl %4,%%eax\n\t" \
+ "adcl %6,%%edx\n\t" \
+ "addl %5,%%eax\n\t" \
+ "adcl %6,%%edx" \
+ : "=&d"(ph), "=a"(pl) \
+ : "%a"(x), "g"(y), "%bcDSmn"(a), "bcDSmn"(b), "bcDSmn"(0))
+
+/* q = ((nh<<32) + nl) / d, return remainder. nh guaranteed < d. */
+#undef lbnDiv21_32
+#define lbnDiv21_32(q,nh,nl,d) \
+ ({unsigned _; \
+ __asm__("divl %4" : "=d"(_), "=a"(*q) : "d"(nh), "a"(nl), "g"(d)); \
+ _;})
+
+/* No quotient, just return remainder ((nh<<32) + nl) % d */
+#define lbnMod21_32(nh,nl,d) \
+ ({unsigned _; \
+ __asm__("divl %3" : "=d"(_) : "d"(nh), "a"(nl), "g"(d) : "ax"); \
+ _;})
+
+#endif /* __GNUC__ */
diff --git a/usr/src/lib/libresolv2/common/cylink/lbn8086.h b/usr/src/lib/libresolv2/common/cylink/lbn8086.h
new file mode 100644
index 0000000000..be9c2fab27
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbn8086.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/*
+ * lbn8086.h - This file defines the interfaces to the 8086
+ * assembly primitives for 16-bit MS-DOS environments.
+ * It is intended to be included in "lbn.h"
+ * via the "#include BNINCLUDE" mechanism.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#define BN_LITTLE_ENDIAN 1
+
+#ifdef __cplusplus
+/* These assembly-language primitives use C names */
+extern "C" {
+#endif
+
+/* Set up the appropriate types */
+typedef unsigned short bnword16;
+#define BNWORD16 bnword16
+typedef unsigned long bnword32;
+#define BNWORD32 bnword32
+
+void __cdecl __far
+lbnMulN1_16(bnword16 __far *out, bnword16 const __far *in,
+ unsigned len, bnword16 k);
+#define lbnMulN1_16 lbnMulN1_16
+
+bnword16 __cdecl __far
+lbnMulAdd1_16(bnword16 __far *out, bnword16 const __far *in,
+ unsigned len, bnword16 k);
+#define lbnMulAdd1_16 lbnMulAdd1_16
+
+bnword16 __cdecl __far
+lbnMulSub1_16(bnword16 __far *out, bnword16 const __far *in,
+ unsigned len, bnword16 k);
+#define lbnMulSub1_16 lbnMulSub1_16
+
+bnword16 __cdecl __far
+lbnDiv21_16(bnword16 __far *q, bnword16 nh, bnword16 nl, bnword16 d);
+#define lbnDiv21_16 lbnDiv21_16
+
+bnword16 __cdecl __far
+lbnModQ_16(bnword16 const __far *n, unsigned len, bnword16 d);
+#define lbnModQ_16 lbnModQ_16
+
+
+
+void __cdecl __far
+lbnMulN1_32(bnword32 __far *out, bnword32 const __far *in,
+ unsigned len, bnword32 k);
+#define lbnMulN1_32 lbnMulN1_32
+
+bnword32 __cdecl __far
+lbnMulAdd1_32(bnword32 __far *out, bnword32 const __far *in,
+ unsigned len, bnword32 k);
+#define lbnMulAdd1_32 lbnMulAdd1_32
+
+bnword32 __cdecl __far
+lbnMulSub1_32(bnword32 __far *out, bnword32 const __far *in,
+ unsigned len, bnword32 k);
+#define lbnMulSub1_32 lbnMulSub1_32
+
+bnword32 __cdecl __far
+lbnDiv21_32(bnword32 __far *q, bnword32 nh, bnword32 nl, bnword32 d);
+#define lbnDiv21_32 lbnDiv21_32
+
+bnword16 __cdecl __far
+lbnModQ_32(bnword32 const __far *n, unsigned len, bnword32 d);
+#define lbnModQ_32 lbnModQ_32
+
+int __cdecl __far not386(void);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/usr/src/lib/libresolv2/common/cylink/lbnmem.c b/usr/src/lib/libresolv2/common/cylink/lbnmem.c
new file mode 100644
index 0000000000..ebb44a2aae
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbnmem.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/*
+ * lbnmem.c - low-level bignum memory handling.
+ *
+ * Copyright (c) 1995 Colin Plumb. All rights reserved.
+ * For licensing and other legal details, see the file legal.c.
+ *
+ * Note that in all cases, the pointers passed around
+ * are pointers to the *least* significant end of the word.
+ * On big-endian machines, these are pointers to the *end*
+ * of the allocated range.
+ *
+ * BNSECURE is a simple level of security; for more security
+ * change these function to use locked unswappable memory.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "port_before.h"
+
+#ifndef HAVE_CONFIG_H
+#define HAVE_CONFIG_H 0
+#endif
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * Some compilers complain about #if FOO if FOO isn't defined,
+ * so do the ANSI-mandated thing explicitly...
+ */
+#ifndef NO_STDLIB_H
+#define NO_STDLIB_H 0
+#endif
+#ifndef NO_STRING_H
+#define NO_STRING_H 0
+#endif
+#ifndef HAVE_STRINGS_H
+#define HAVE_STRINGS_H 0
+#endif
+#ifndef NEED_MEMORY_H
+#define NEED_MEMORY_H 0
+#endif
+
+#if !NO_STDLIB_H
+#include <stdlib.h> /* For malloc() & co. */
+#else
+void *malloc();
+void *realloc();
+void free();
+#endif
+
+#if !NO_STRING_H
+#include <string.h> /* For memset */
+#elif HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#if NEED_MEMORY_H
+#include <memory.h>
+#endif
+
+#ifndef DBMALLOC
+#define DBMALLOC 0
+#endif
+#if DBMALLOC
+/* Development debugging */
+#include "../dbmalloc/malloc.h"
+#endif
+
+#include "lbn.h"
+#include "lbnmem.h"
+
+#include "kludge.h"
+
+#ifndef lbnMemWipe
+void
+lbnMemWipe(void *ptr, unsigned bytes)
+{
+ memset(ptr, 0, bytes);
+}
+#define lbnMemWipe(ptr, bytes) memset(ptr, 0, bytes)
+#endif
+
+#ifndef lbnMemAlloc
+void *
+lbnMemAlloc(unsigned bytes)
+{
+ return malloc(bytes);
+}
+#define lbnMemAlloc(bytes) malloc(bytes)
+#endif
+
+#ifndef lbnMemFree
+void
+lbnMemFree(void *ptr, unsigned bytes)
+{
+ lbnMemWipe(ptr, bytes);
+ free(ptr);
+}
+#endif
+
+#ifndef lbnRealloc
+#if defined(lbnMemRealloc) || !BNSECURE
+void *
+lbnRealloc(void *ptr, unsigned oldbytes, unsigned newbytes)
+{
+ if (ptr) {
+ BIG(ptr = (char *)ptr - oldbytes;)
+ if (newbytes < oldbytes)
+ memmove(ptr, (char *)ptr + oldbytes-newbytes, oldbytes);
+ }
+#ifdef lbnMemRealloc
+ ptr = lbnMemRealloc(ptr, oldbytes, newbytes);
+#else
+ ptr = realloc(ptr, newbytes);
+#endif
+ if (ptr) {
+ if (newbytes > oldbytes)
+ memmove((char *)ptr + newbytes-oldbytes, ptr, oldbytes);
+ BIG(ptr = (char *)ptr + newbytes;)
+ }
+
+ return ptr;
+}
+
+#else /* BNSECURE */
+
+void *
+lbnRealloc(void *oldptr, unsigned oldbytes, unsigned newbytes)
+{
+ void *newptr = lbnMemAlloc(newbytes);
+
+ if (!newptr)
+ return newptr;
+ if (!oldptr)
+ return BIGLITTLE((char *)newptr+newbytes, newptr);
+
+ /*
+ * The following copies are a bit non-obvious in the big-endian case
+ * because one of the pointers points to the *end* of allocated memory.
+ */
+ if (newbytes > oldbytes) { /* Copy all of old into part of new */
+ BIG(newptr = (char *)newptr + newbytes;)
+ BIG(oldptr = (char *)oldptr - oldbytes;)
+ memcpy(BIGLITTLE((char *)newptr-oldbytes, newptr), oldptr,
+ oldbytes);
+ } else { /* Copy part of old into all of new */
+ memcpy(newptr, BIGLITTLE((char *)oldptr-newbytes, oldptr),
+ newbytes);
+ BIG(newptr = (char *)newptr + newbytes;)
+ BIG(oldptr = (char *)oldptr - oldbytes;)
+ }
+
+ lbnMemFree(oldptr, oldbytes);
+ return newptr;
+}
+#endif /* BNSECURE */
+#endif /* !lbnRealloc */
diff --git a/usr/src/lib/libresolv2/common/cylink/lbnmem.h b/usr/src/lib/libresolv2/common/cylink/lbnmem.h
new file mode 100644
index 0000000000..8a86eeaf0e
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbnmem.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Operations on the usual buffers of bytes
+ */
+#ifndef BNSECURE
+#define BNSECURE 1
+#endif
+
+/*
+ * These operations act on buffers of memory, just like malloc & free.
+ * One exception: it is not legal to pass a NULL pointer to lbnMemFree.
+ */
+
+#ifndef lbnMemAlloc
+void *lbnMemAlloc(unsigned bytes);
+#endif
+
+#ifndef lbnMemFree
+void lbnMemFree(void *ptr, unsigned bytes);
+#endif
+
+/* This wipes out a buffer of bytes if necessary needed. */
+
+#ifndef lbnMemWipe
+#if BNSECURE
+void lbnMemWipe(void *ptr, unsigned bytes);
+#else
+#define lbnMemWipe(ptr, bytes) (void)(ptr,bytes)
+#endif
+#endif /* !lbnMemWipe */
+
+/*
+ * lbnRealloc is NOT like realloc(); it's endian-sensitive!
+ * If lbnMemRealloc is #defined, lbnRealloc will be defined in terms of it.
+ * It is legal to pass a NULL pointer to lbnRealloc, although oldbytes
+ * will always be sero.
+ */
+#ifndef lbnRealloc
+void *lbnRealloc(void *ptr, unsigned oldbytes, unsigned newbytes);
+#endif
+
+
+/*
+ * These macros are the ones actually used most often in the math library.
+ * They take and return pointers to the *end* of the given buffer, and
+ * take sizes in terms of words, not bytes.
+ *
+ * Note that LBNALLOC takes the pointer as an argument instead of returning
+ * the value.
+ *
+ * Note also that these macros are only useable if you have included
+ * lbn.h (for the BIG and BIGLITTLE macros), which this file does NOT include.
+ */
+
+#define LBNALLOC(p,words) BIGLITTLE( \
+ if ( ((p) = lbnMemAlloc((words)*sizeof*(p))) != 0) (p) += (words), \
+ (p) = lbnMemAlloc((words) * sizeof*(p)) \
+ )
+#define LBNFREE(p,words) lbnMemFree((p) BIG(-(words)), (words) * sizeof*(p))
+#define LBNREALLOC(p,old,new) \
+ lbnRealloc(p, (old) * sizeof*(p), (new) * sizeof*(p))
+#define LBNWIPE(p,words) lbnMemWipe((p) BIG(-(words)), (words) * sizeof*(p))
+
diff --git a/usr/src/lib/libresolv2/common/cylink/lbnppc.c b/usr/src/lib/libresolv2/common/cylink/lbnppc.c
new file mode 100644
index 0000000000..15eef0e28e
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbnppc.c
@@ -0,0 +1,365 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "lbnppc.h"
+
+/*
+ * lbnppc.c - Assembly primitives for the bignum library, PowerPC version.
+ *
+ * Copyright (c) 1995 Colin Plumb. All rights reserved.
+ * For licensing and other legal details, see the file legal.c
+ *
+ * Register usage during function calls is:
+ * r0 - volatile
+ * r1 - stack pointer, preserved
+ * r2 - TOC pointer, preserved
+ * r3 - First argument and return value register
+ * r4-r10 - More argument registers, volatile
+ * r11-r12 - Volatile
+ * r13-r31 - Preserved
+ * LR, CTR, XER and MQ are all volatile.
+ * LR holds return address on entry.
+ *
+ * On the PPC 601, unrolling the loops more doesn't seem to speed things
+ * up at all. I'd be curious if other chips differed.
+ */
+#if __MWERKS__ < 0x800
+
+#include "ppcasm.h" /* PowerPC assembler */
+
+/*
+ * MulN1 expects (*out, *in, len, k), count >= 1
+ * r3 r4 r5 r6
+ */
+static const unsigned mulN1[] = {
+ PPC_LWZ(7,4,0), /* Load first word of in in r7 */
+ PPC_MULLW(8,7,6), /* Low half of multiply in r8 */
+ PPC_MTCTR(5), /* Move len into CTR */
+ PPC_ADDIC(0,0,0), /* Clear carry bit for loop */
+ PPC_MULHWU(5,7,6), /* High half of multiply in r5 */
+ PPC_STW(8,3,0),
+ PPC_BC(18,31,7), /* Branch to Label if --ctr == 0 */
+/* Loop: */
+ PPC_LWZU(7,4,4), /* r7 = *++in */
+ PPC_MULLW(8,7,6), /* r8 = low word of product */
+ PPC_ADDE(8,8,5), /* Add carry word r5 and bit CF to r8 */
+ PPC_STWU(8,3,4), /* *++out = r8 */
+ PPC_MULHWU(5,7,6), /* r5 is high word of product, for carry word */
+ PPC_BC(16,31,-5), /* Branch to Loop if --ctr != 0 */
+/* Label: */
+ PPC_ADDZE(5,5), /* Add carry flag to r5 */
+ PPC_STW(5,3,4), /* out[1] = r5 */
+ PPC_BLR()
+};
+
+/*
+ * MulAdd1 expects (*out, *in, len, k), count >= 1
+ * r3 r4 r5 r6
+ */
+static unsigned const mulAdd1[] = {
+ PPC_LWZ(7,4,0), /* Load first word of in in r7 */
+ PPC_LWZ(0,3,0), /* Load first word of out into r0 */
+ PPC_MULLW(8,7,6), /* Low half of multiply in r8 */
+ PPC_MTCTR(5), /* Move len into CTR */
+ PPC_MULHWU(5,7,6), /* High half of multiply in r5 */
+ PPC_ADDC(8,8,0), /* r8 = r8 + r0 */
+ PPC_STW(8,3,0), /* Store result to memory */
+ PPC_BC(18,31,10), /* Branch to Label if --ctr == 0 */
+/* Loop: */
+ PPC_LWZU(7,4,4), /* r7 = *++in */
+ PPC_LWZU(0,3,4), /* r0 = *++out */
+ PPC_MULLW(8,7,6), /* r8 = low word of product */
+ PPC_ADDE(8,8,5), /* Add carry word r5 and carry bit CF to r8 */
+ PPC_MULHWU(5,7,6), /* r5 is high word of product, for carry word */
+ PPC_ADDZE(5,5), /* Add carry bit from low add to r5 */
+ PPC_ADDC(8,8,0), /* r8 = r8 + r0 */
+ PPC_STW(8,3,0), /* *out = r8 */
+ PPC_BC(16,31,-8), /* Branch to Loop if --ctr != 0 */
+/* Label: */
+ PPC_ADDZE(3,5), /* Add carry flag to r5 and move to r3 */
+ PPC_BLR()
+};
+
+/*
+ * MulSub1 expects (*out, *in, len, k), count >= 1
+ * r3 r4 r5 r6
+ *
+ * Multiply and subtract is rather a pain. If the subtract of the
+ * low word of the product from out[i] generates a borrow, we want to
+ * increment the carry word (initially in the range 0..0xfffffffe).
+ * However, the PPC's carry bit CF is *clear* after a subtract, so
+ * we want to add (1-CF) to the carry word. This is done using two
+ * instructions:
+ *
+ * SUBFME, subtract from minus one extended. This computes
+ * rD = ~rS + 0xffffffff + CF. Since rS is from 0 to 0xfffffffe,
+ * ~rS is from 1 through 0xffffffff, and the sum with 0xffffffff+CF is
+ * from 0 through 0xfffffffff, setting the carry flag unconditionally, and
+ * NOR, which is used as a bitwise invert NOT instruction.
+ *
+ * The SUBFME performs the computation rD = ~rS + 0xffffffff + CF,
+ * = (-rS - 1) + (CF - 1) = -(rS - CF + 1) - 1 = ~(rS + 1-CF),
+ * which is the bitwise complement of the value we want.
+ * We want to add the complement of that result to the low word of the
+ * product, which is just what a subtract would do, if only we could get
+ * the carry flag clear. But it's always set, except for SUBFE, and the
+ * operation we just performed unconditionally *sets* the carry flag. Ugh.
+ * So find the complement in a separate instruction.
+ */
+static unsigned const mulSub1[] = {
+ PPC_LWZ(7,4,0), /* Load first word of in in r7 */
+ PPC_LWZ(0,3,0), /* Load first word of out into r0 */
+ PPC_MTCTR(5), /* Move len into CTR */
+ PPC_MULLW(8,7,6), /* Low half of multiply in r8 */
+ PPC_MULHWU(5,7,6), /* High half of multiply in r5 */
+ PPC_SUBFC(8,8,0), /* r8 = r0 - r8, setting CF */
+ PPC_STW(8,3,0), /* Store result to memory */
+ PPC_SUBFME(5,5), /* First of two insns to add (1-CF) to r5 */
+ PPC_BC(18,31,12), /* Branch to Label if --ctr == 0 */
+/* Loop: */
+ PPC_LWZU(7,4,4), /* r7 = *++in */
+ PPC_LWZU(0,3,4), /* r0 = *++out */
+ PPC_NOR(5,5,5), /* Second of two insns to add (1-CF) to r5 */
+ PPC_MULLW(8,7,6), /* r8 = low word of product */
+ PPC_ADDC(8,8,5), /* Add carry word r5 to r8 */
+ PPC_MULHWU(5,7,6), /* r5 is high word of product, for carry word */
+ PPC_ADDZE(5,5), /* Add carry bit from low add to r5 */
+ PPC_SUBFC(8,8,0), /* r8 = r0 - r8, setting CF */
+ PPC_STW(8,3,0), /* *out = r8 */
+ PPC_SUBFME(5,5), /* First of two insns to add (1-CF) to r5 */
+ PPC_BC(16,31,-10), /* Branch to Loop if --ctr != 0 */
+/* Label: */
+ PPC_NOR(3,5,5), /* Finish adding (1-CF) to r5, store in r3 */
+ PPC_BLR()
+};
+
+#if 0
+/*
+ * Args: BNWORD32 *n, BNWORD32 const *mod, unsigned mlen, BNWORD32 inv)
+ * r3 r4 r5 r6
+ * r7, r8 and r9 are the triple-width accumulator.
+ * r0 and r10 are temporary registers.
+ * r11 and r12 are temporary pointers into n and mod, respectively.
+ * r2 (!) is another temporary register.
+ */
+static unsigned const montReduce[] = {
+ PPC_MTCTR(5), /* ??? */
+ PPC_LWZ(7,3,0), /* Load low word of n into r7 */
+ PPC_LWZ(10,4,0), /* Fetch low word of mod */
+ PPC_MULLW(0,7,6), /* Invert r7 into r0 */
+ PPC_STW(0,3,0), /* Store back for future use */
+ PPC_MULHWU(8,10,7), /* Get high word of whatnot */
+ PPC_MULLW(10,10,7), /* Get low word of it */
+ PPC_ADDC(7,7,10), /* Add low word of product to r7 */
+ PPC_ADDZE(8,8), /* Add carry to high word */
+ PPC_
+
+
+ PPC_MULHW(8,7,6),
+ PPC_ADDC(7,7,0), /* Add inverse back to r7 */
+ PPC_ADDZE(8,8),
+ PPC_
+
+ PPC_LWZU(
+/* Loop: */
+ PPC_LWZU(0,11,4),
+ PPC_LWZU(10,23,-4),
+ PPC_MULLW(2,0,10),
+ PPC_ADDC(7,7,2),
+ PPC_MULHWU(0,0,10),
+ PPC_ADDE(8,8,0),
+ PPC_ADDZE(9,9),
+ PPC_BC(16,31,-7), /* Branch to Loop if --ctr != 0 */
+
+ PPC_ADDIC_(count,-1),
+ PPC_LWZU(0,x,4),
+ PPC_ADDC(0,7,0),
+ PPC_STW(0,x,0),
+ PPC_ADDZE(7,8),
+ PPC_ADDZE(8,9),
+ PPC_LI(9,0),
+ PPC_BC(xx,2,yy),
+
+};
+#endif
+
+/*
+ * Three overlapped transition vectors for three functions.
+ * A PowerPC transition vector for a (potentially) inter-module
+ * jump or call consists of two words, an instruction address
+ * and a Table Of Contents (TOC) pointer, which is loaded into
+ * r1. Since none of the routines here have global variables,
+ * they don't need a TOC pointer, so the value is unimportant.
+ * This array places an unintersting 32-bit value after each address.
+ */
+unsigned const * const lbnPPC_tv[] = {
+ mulN1,
+ mulAdd1,
+ mulSub1,
+ 0
+};
+
+#else /* __MWERKS >= 0x800 */
+
+/*
+ * MulN1 expects (*out, *in, len, k), count >= 1
+ * r3 r4 r5 r6
+ */
+asm void
+lbnMulN1_32(register unsigned *out, register unsigned const *in,
+ register unsigned len, register unsigned k)
+{
+ lwz r7,0(in) /* Load first word of in in r7 */
+ mtctr len /* Move len into CTR */
+ mullw r8,r7,k /* Low half of multiply in r8 */
+ addic r0,r0,0 /* Clear carry bit for loop */
+ mulhwu len,r7,k /* High half of multiply in len */
+ stw r8,0(out) /* *out = r8 */
+ mulhwu len,r7,k /* len is high word of product, for carry */
+ bdz- label /* Branch to Label if --ctr == 0 */
+loop:
+ lwzu r7,4(in) /* r7 = *++in */
+ mullw r8,r7,k /* Low half of multiply in r8 */
+ adde r8,r8,len /* Add carry word len and bit CF to r8 */
+ stwu r8,4(out) /* *++out = r8 */
+ mulhwu len,r7,k /* len is high word of product, for carry */
+ bdnz+ loop /* Branch to Loop if --ctr != 0 */
+label:
+ addze len,len /* Add carry flag to carry word */
+ stw len,4(out)
+ blr
+}
+
+/*
+ * MulAdd1 expects (*out, *in, len, k), count >= 1
+ * r3 r4 r5 r6
+ */
+asm unsigned
+lbnMulAdd1_32(register unsigned *out, register unsigned const *in,
+ register unsigned len, register unsigned k)
+{
+ lwz r7,0(in) /* Load first word of in in r7 */
+ lwz r0,0(out) /* Load first word of out into r0 */
+ mullw r8,r7,k /* Low half of multiply in r8 */
+ mtctr len /* Move len into CTR */
+ mulhwu len,r7,k /* High half of multiply in len */
+ addc r8,r8,r0 /* r8 = r8 + r0 */
+ stw r8,0(out) /* Store result to memory */
+ bdz- label /* Branch to Label if --ctr == 0 */
+loop:
+ lwzu r7,4(in) /* r7 = *++in */
+ lwzu r0,4(out) /* r0 = *++out */
+ mullw r8,r7,k /* r8 = low word of product */
+ adde r8,r8,len /* Add carry word len and carry bit CF to r8 */
+ mulhwu len,r7,k /* len is high word of product, for carry */
+ addze len,len /* Add carry bit from low add to r5 */
+ addc r8,r8,r0 /* r8 = r8 + r0 */
+ stw r8,0(out) /* *out = r8 */
+ bdnz+ loop /* Branch to Loop if --ctr != 0 */
+label:
+ addze r3,r5 /* Add carry flag to r5 and move to r3 */
+ blr
+}
+
+/*
+ * MulSub1 expects (*out, *in, len, k), count >= 1
+ * r3 r4 r5 r6
+ *
+ * Multiply and subtract is rather a pain. If the subtract of the
+ * low word of the product from out[i] generates a borrow, we want to
+ * increment the carry word (initially in the range 0..0xfffffffe).
+ * However, the PPC's carry bit CF is *clear* after a subtract, so
+ * we want to add (1-CF) to the carry word. This is done using two
+ * instructions:
+ *
+ * SUBFME, subtract from minus one extended. This computes
+ * rD = ~rS + 0xffffffff + CF. Since rS is from 0 to 0xfffffffe,
+ * ~rS is from 1 through 0xffffffff, and the sum with 0xffffffff+CF is
+ * from 0 through 0xfffffffff, setting the carry flag unconditionally, and
+ * NOR, which is used as a bitwise invert NOT instruction.
+ *
+ * The SUBFME performs the computation rD = ~rS + 0xffffffff + CF,
+ * = (-rS - 1) + (CF - 1) = -(rS - CF + 1) - 1 = ~(rS + 1-CF),
+ * which is the bitwise complement of the value we want.
+ * We want to add the complement of that result to the low word of the
+ * product, which is just what a subtract would do, if only we could get
+ * the carry flag clear. But it's always set, except for SUBFE, and the
+ * operation we just performed unconditionally *sets* the carry flag. Ugh.
+ * So find the complement in a separate instruction.
+ */
+asm unsigned
+lbnMulSub1_32(register unsigned *out, register unsigned const *in,
+ register unsigned len, register unsigned k)
+{
+ lwz r7,0(in) /* Load first word of in in r7 */
+ lwz r0,0(out) /* Load first word of out into r0 */
+ mtctr len /* Move len into CTR */
+ mullw r8,r7,k /* Low half of multiply in r8 */
+ mulhwu len,r7,k /* High half of multiply in len */
+ subfc r8,r8,r0 /* r8 = r0 - r8, setting CF */
+ stw r8,0(out) /* Store result to memory */
+ subfme len,len /* First of two insns to add (1-CF) to len */
+ bdz- label /* Branch to Label if --ctr == 0 */
+loop:
+ lwzu r7,4(in) /* r7 = *++in */
+ lwzu r0,4(out) /* r0 = *++out */
+ nor len,len,len /* Second of two insns to add (1-CF) to len */
+ mullw r8,r7,k /* r8 = low word of product */
+ addc r8,r8,len /* Add carry word len to r8 */
+ mulhwu len,r7,k /* len is high word of product, for carry */
+ addze len,len /* Add carry bit from low add to len */
+ subfc r8,r8,r0 /* r8 = r0 - r8 */
+ stw r8,0(out) /* *out = r8 */
+ subfme len,len /* First of two insns to add (1-CF) to len */
+ bdnz+ loop /* Branch to Loop if --ctr != 0 */
+label:
+ nor r3,r5,r5 /* Finish adding (1-CF) to len, store in r3 */
+ blr
+}
+
+#endif /* __MWERKS >= 0x800 */
+/* 45678901234567890123456789012345678901234567890123456789012345678901234567 */
diff --git a/usr/src/lib/libresolv2/common/cylink/lbnppc.h b/usr/src/lib/libresolv2/common/cylink/lbnppc.h
new file mode 100644
index 0000000000..1d9d6e5418
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/lbnppc.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef LBNPPC_H
+#define LBNPPC_H
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Assembly-language routines for the Power PC processor.
+ * Annoyingly, the Power PC does not have 64/32->32 bit divide,
+ * so the C code should be reasonably fast. But it does have
+ * 32x32->64-bit multiplies, and these routines provide access
+ * to that.
+ *
+ * In versions of CodeWarrior before 8.0, there was no PPC assembler,
+ * so a kludged-up one in CPP is used. This requires casting an
+ * array of unsigneds to function pointer type, and a function pointer
+ * is not a pointer to the code, but rather a pointer to a (code,TOC)
+ * pointer pair which we fake up.
+ *
+ * CodeWarrior 8.0 supports PCC assembly, which is used directly.
+ */
+
+/*
+ * Bignums are stored in arrays of 32-bit words, and the least
+ * significant 32-bit word has the lowest address, thus "little-endian".
+ * The C code is slightly more efficient this way, so unless the
+ * processor cares (the PowerPC, like most RISCs, doesn't), it is
+ * best to use BN_LITTLE_ENDIAN.
+ * Note that this has NOTHING to do with the order of bytes within a 32-bit
+ * word; the math library is insensitive to that.
+ */
+#define BN_LITTLE_ENDIAN 1
+
+typedef unsigned bnword32;
+#define BNWORD32 bnword32
+
+#if __MWERKS__ < 0x800
+
+/* Shared transition vector array */
+extern unsigned const * const lbnPPC_tv[];
+
+/* A function pointer on the PowerPC is a pointer to a transition vector */
+#define lbnMulN1_32 \
+((void (*)(bnword32 *, bnword32 const *, unsigned, bnword32))(lbnPPC_tv+0))
+#define lbnMulAdd1_32 \
+((bnword32 (*)(bnword32 *, bnword32 const *, unsigned, bnword32))(lbnPPC_tv+1))
+#define lbnMulSub1_32 \
+((bnword32 (*)(bnword32 *, bnword32 const *, unsigned, bnword32))(lbnPPC_tv+2))
+
+#else /* __MWERKS__ >= 0x800 */
+
+void lbnMulN1_32(bnword32 *, bnword32 const *, unsigned, bnword32);
+#define lbnMulN1_32 lbnMulN1_32
+bnword32 lbnMulAdd1_32(bnword32 *, bnword32 const *, unsigned, bnword32);
+#define lbnMulAdd1_32 lbnMulAdd1_32
+bnword32 lbnMulSub1_32(bnword32 *, bnword32 const *, unsigned, bnword32);
+#define lbnMulSub1_32 lbnMulSub1_32
+
+#endif /* __MWERKS__ >= 0x800 */
+
+#endif /* LBNPPC_H */
diff --git a/usr/src/lib/libresolv2/common/cylink/legal.c b/usr/src/lib/libresolv2/common/cylink/legal.c
new file mode 100644
index 0000000000..09447c8d3c
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/legal.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* Force inclusion of this... */
+#include "legal.h"
+volatile const char bnCopyright[] =
+ "bnlib 1.0.1 Copyright (c) 1995,1996 Colin Plumb.";
diff --git a/usr/src/lib/libresolv2/common/cylink/legal.h b/usr/src/lib/libresolv2/common/cylink/legal.h
new file mode 100644
index 0000000000..49c7c163bd
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/legal.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * ANSI C standard, section 3.5.3: "An object that has volatile-qualified
+ * type may be modified in ways unknown to the implementation or have
+ * other unknown side effects." Yes, we can't expect a compiler to
+ * understand law...
+ */
+extern volatile const char bnCopyright[];
diff --git a/usr/src/lib/libresolv2/common/cylink/math.c b/usr/src/lib/libresolv2/common/cylink/math.c
new file mode 100644
index 0000000000..4c7b0e6a5e
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/math.c
@@ -0,0 +1,1158 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/****************************************************************************
+* FILENAME: math.c PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT
+*
+* FILE STATUS:
+*
+* DESCRIPTION: Math Routines for the ToolKit
+*
+* PUBLIC FUNCTIONS:
+*
+* int Sum_big (ord *X,
+* ord *Y,
+* ord *Z,
+* u_int16_t len_X )
+*
+* int Sub_big (ord *X,
+* ord *Y,
+* ord *Z,
+* u_int16_t len_X )
+*
+* void Mul_big( ord *X, ord *Y,ord *XY,
+* u_int16_t lx, u_int16_t ly)
+*
+*
+* PRIVATE FUNCTIONS:
+*
+* REVISION HISTORY:
+*
+* 14 Oct 94 GKL Initial release
+* 26 Oct 94 GKL (alignment for big endian support )
+*
+****************************************************************************/
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/****************************************************************************
+* INCLUDE FILES
+****************************************************************************/
+/* bn files */
+#include "port_before.h"
+#include "bn.h"
+/* system files */
+#ifdef VXD
+#include <vtoolsc.h>
+#else
+#include <stdlib.h>
+#include <string.h>
+#endif
+/* program files */
+#include "cylink.h"
+#include "ctk_endian.h"
+#include "toolkit.h"
+#include "port_after.h"
+
+/****************************************************************************
+* NAME: void BigNumInit( void )
+*
+*
+* DESCRIPTION: Initialize BigNum
+*
+* INPUTS:
+* PARAMETERS:
+* OUTPUT:
+* PARAMETERS:
+*
+* RETURN:
+*
+*
+* REVISION HISTORY:
+*
+* 29 Sep 96 Initial release
+*
+****************************************************************************/
+
+void BigNumInit()
+{
+static int bignuminit = 0;
+if(!bignuminit){
+ bnInit();
+ bignuminit = 1;
+ }
+}
+/****************************************************************************
+* NAME: int Sum_big (ord *X,
+* ord *Y,
+* ord *Z,
+* u_int16_t len_X )
+*
+* DESCRIPTION: Compute addition.
+*
+* INPUTS:
+* PARAMETERS:
+* ord *X Pointer to first array
+* ord *Y Pointer to second array
+* int len_X Number of longs in X_l
+* OUTPUT:
+* PARAMETERS:
+* ord *Z Pointer to result arrray
+*
+* RETURN:
+* Carry bit
+*
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 14 Oct 94 GKL Second version (big endian support)
+*
+****************************************************************************/
+
+ int Sum_big (ord *X,
+ ord *Y,
+ ord *Z,
+ u_int16_t len_X )
+{
+
+struct BigNum src2,temp_bn;
+ord *temp;
+BigNumInit();
+
+/*bnInit();
+bnBegin(&src2);
+bnBegin(&temp_bn);
+*/
+temp = (ord *) malloc((len_X*sizeof(ord)) + sizeof(ord));
+temp_bn.size = len_X;
+temp_bn.ptr = temp;
+temp_bn.allocated = len_X + 1;
+
+src2.ptr = Y;
+src2.size = len_X;
+src2.allocated = len_X;
+
+memcpy(temp,X,len_X*sizeof(ord));
+bnAdd(&temp_bn,&src2);
+memcpy(Z,temp_bn.ptr,len_X*sizeof(ord));
+/*bn package increments the size of dest by 1 if the carry bit is 1*/
+free(temp);
+if (temp_bn.size > len_X)
+ return 1;
+else
+ return 0;
+}
+
+ int Sum (ord *X, ord *Y, u_int16_t len_X )
+{
+
+struct BigNum dest,src;
+/*ord *temp;*/
+BigNumInit();
+#if 0
+bnInit();
+bnBegin(&src2);
+bnBegin(&temp_bn);
+
+temp = (ord *) malloc((len_X*sizeof(ord)) + sizeof(ord));
+temp_bn.size = len_X;
+temp_bn.ptr = temp;
+temp_bn.allocated = len_X + 1;
+#endif
+
+dest.ptr = X;
+dest.size = len_X-1;
+dest.allocated = len_X;
+
+src.ptr = Y;
+src.size = len_X;
+src.allocated = len_X;
+
+/*memcpy(temp,X,len_X*sizeof(ord));*/
+bnAdd(&dest,&src);
+/*memcpy(Z,temp_bn.ptr,len_X*sizeof(ord));*/
+/*bn package increments the size of dest by 1 if the carry bit is 1*/
+/*free(temp);*/
+if (dest.size > (u_int16_t)(len_X -1))
+ return 1;
+else
+ return 0;
+}
+
+
+/****************************************************************************
+* NAME: int Sum_Q(ord *X,
+* u_int16_t src,
+* u_int16_t len_X )
+* DESCRIPTION: Compute addition X += src.
+*
+* INPUTS:
+* PARAMETERS:
+* ord *X Pointer to first array
+* u_int16_t src Second operand must be <65535
+* int len_X Number of ords in X_l
+* OUTPUT:
+* PARAMETERS:
+* ord *X Pointer to result arrray
+*
+* RETURN:
+* SUCCESS or -1
+*
+* REVISION HISTORY:
+*
+* 21 Sep 96 AAB Initial release
+****************************************************************************/
+ int Sum_Q(ord *X, u_int16_t src, u_int16_t len_X )
+ {
+ int status = SUCCESS;
+ struct BigNum des;
+ BigNumInit();
+ /*bnInit();*/
+ des.ptr = X;
+ des.size = len_X;
+ des.allocated = len_X;
+ status = bnAddQ(&des, src);
+ return status;
+ }
+
+
+/****************************************************************************
+* NAME: int Sub_big (ord *X,
+* ord *Y,
+* ord *Z,
+* u_int16_t len_X )
+*
+*
+* DESCRIPTION: Compute subtraction.
+*
+* INPUTS:
+* PARAMETERS:
+* ord *X Pointer to first array
+* ord *Y Pointer to second array
+* u_int16_t len_X Number of longs in X_l
+* OUTPUT:
+* PARAMETERS:
+* ord *Z Pointer to result arrray
+*
+* RETURN:
+* Carry bit
+*
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 14 Oct 94 GKL Second version (big endian support)
+*
+****************************************************************************/
+
+int Sub_big (ord *X,
+ ord *Y,
+ ord *Z,
+ u_int16_t len_X )
+{
+/* carry is not returned in bn version */
+struct BigNum dest, src;
+int status;
+ord *temp;
+BigNumInit();
+/*bnInit();
+bnBegin(&dest);
+bnBegin(&src);
+*/
+src.ptr = Y;
+src.size = len_X;
+src.allocated = len_X;
+
+temp = (ord*)malloc(len_X*sizeof(ord));
+dest.ptr = temp;
+dest.size = len_X;
+dest.allocated = len_X;
+memcpy(dest.ptr,X,len_X*sizeof(ord));
+
+status = bnSub(&dest,&src);
+memcpy(Z,dest.ptr,len_X*sizeof(ord));
+free(temp);
+return status;
+}
+
+#if 0
+/****************************************************************************
+* NAME: void Mul_big( ord *X, ord *Y, ord *XY,
+* u_int16_t lx, u_int16_t ly)
+*
+*
+*
+* DESCRIPTION: Compute a product.
+*
+* INPUTS:
+* PARAMETERS:
+* ord *X Pointer to first long array
+* ord *Y Pointer to second long array
+* u_int16_t lx Leftmost non zero element of first array
+* u_int16_t ly Leftmost non zero element of second array
+* OUTPUT:
+* PARAMETERS:
+* ord *XY Pointer to result
+*
+* RETURN:
+*
+*
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 14 Oct 94 GKL Second version (big endian support)
+* 08 Sep 95 AAB Comment out calloc and discard the elements_in_X,
+* elements_in_Y
+****************************************************************************/
+void Mul_big( ord *X, ord *Y, ord *XY,
+ u_int16_t lx, u_int16_t ly )
+{
+struct BigNum dest, src1, src2;
+BigNumInit();
+/*bnInit();*/
+bnBegin(&dest);
+/*
+bnBegin(&src1);
+bnBegin(&src2);
+*/
+src1.size = lx + 1;
+src1.ptr = X;
+src1.allocated = lx + 1;
+
+src2.ptr = Y;
+src2.size = ly + 1;
+src2.allocated = ly + 1;
+
+dest.ptr = XY;
+dest.size = lx + ly + 2;
+dest.allocated = lx + ly + 2;
+
+/* Call bn routine */
+bnMul(&dest, &src1,&src2);
+}
+
+#endif
+/****************************************************************************
+* NAME: void Mul_big_1( ord X, ord *Y, ord *XY,
+* u_int16_t lx, u_int16_t ly )
+*
+*
+*
+* DESCRIPTION: Compute a product.
+*
+* INPUTS:
+* PARAMETERS:
+* ord X Number
+* ord *Y Pointer to long array
+* u_int16_t ly Leftmost non zero element of second array
+* OUTPUT:
+* PARAMETERS:
+* ord *XY Pointer to result
+*
+* RETURN:
+*
+*
+* REVISION HISTORY:
+*
+* 08 Oct 95 AAB Initial relaese
+*
+****************************************************************************/
+void Mul_big_1( ord X, ord *Y, ord *XY,
+ u_int16_t ly )
+{
+struct BigNum dest, src;
+BigNumInit();
+/*bnInit();
+bnBegin(&dest);
+bnBegin(&src);
+*/
+src.ptr = Y;
+src.size = ly + 1;
+src.allocated = ly + 1;
+
+dest.ptr = XY;
+dest.size = ly + 2;
+dest.allocated = ly + 2;
+
+bnMulQ(&dest, &src, (unsigned)X);
+
+}
+
+/****************************************************************************
+* NAME: int Mul( u_int16_t X_bytes,
+* ord *X,
+* u_int16_t Y_bytes,
+* ord *Y,
+* u_int16_t P_bytes,
+* ord *P,
+* ord *Z )
+*
+* DESCRIPTION: Compute a modulo product
+*
+* INPUTS:
+* PARAMETERS:
+* ord *X Pointer to first operand
+* u_int16_t X_bytes Number of bytes in X
+* ord *Y Pointer to second operand
+* u_int16_t Y_bytes Number of bytes in Y
+* ord *P Pointer to modulo
+* u_int16_t P_bytes Number of bytes in P
+*
+* OUTPUT:
+* PARAMETERS:
+* ord *Z Pointer to result
+*
+* RETURN:
+* SUCCESS No errors
+* ERR_INPUT_LEN Invalid length for input data (zero bytes)
+*
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 14 Oct 94 GKL Second version (big endian support)
+*
+****************************************************************************/
+
+int Mul( u_int16_t X_bytes,
+ ord *X,
+ u_int16_t Y_bytes,
+ ord *Y,
+ u_int16_t P_bytes,
+ ord *P,
+ ord *Z )
+
+{
+ int status = SUCCESS; /*function return status*/
+ u_int16_t X_longs; /*number of longs in X*/
+ u_int16_t Y_longs; /*number of longs in Y*/
+ ord *XY; /*pointer to product (temporary)*/
+
+
+struct BigNum dest, src1,src2, mod;
+BigNumInit();
+/*bnInit();
+bnBegin(&dest);
+bnBegin(&src1);
+bnBegin(&src2);
+bnBegin(&mod);
+*/
+
+src1.size = X_bytes/sizeof(ord);
+src1.ptr = X;
+src1.allocated = X_bytes/sizeof(ord);
+
+src2.size = Y_bytes/sizeof(ord);
+src2.ptr = Y;
+src2.allocated =Y_bytes/sizeof(ord);
+
+mod.size = P_bytes/sizeof(ord);
+mod.ptr = P;
+mod.allocated = P_bytes/sizeof(ord);
+
+ if ( P_bytes == 0 || X_bytes == 0 || Y_bytes == 0 )
+ {
+ status = ERR_INPUT_LEN;
+ return status;
+ }
+ if ( (X_bytes % sizeof(ord) != 0) ||
+ (Y_bytes % sizeof(ord) != 0) ||
+ (P_bytes % sizeof(ord) != 0) )
+ {
+ status = ERR_INPUT_LEN;
+ return status;
+ }
+ X_longs = (u_int16_t) (X_bytes / sizeof(ord));
+ Y_longs = (u_int16_t) (Y_bytes / sizeof(ord));
+ XY = (ord *)calloc( X_longs + Y_longs, sizeof(ord) );
+ if( !XY )
+ {
+ return ERR_ALLOC;
+ }
+dest.size = X_longs + Y_longs;
+dest.ptr = XY;
+dest.allocated = X_longs + Y_longs;
+
+bnMul (&dest,&src1,&src2);
+
+status = bnMod(&dest, &dest, &mod);
+memcpy(Z, dest.ptr, P_bytes);
+free( XY );
+ return status;
+}
+
+/****************************************************************************
+* NAME: int Square( u_int16_t X_bytes,
+* ord *X,
+* u_int16_t P_bytes,
+* ord *P,
+* ord *Z )
+*
+* DESCRIPTION: Compute a modulo square
+*
+* INPUTS:
+* PARAMETERS:
+* ord *X Pointer to array to be squared
+* u_int16_t X_bytes Number of bytes in X
+* ord *P Pointer to modulo
+* u_int16_t P_bytes Number of bytes in P
+*
+* OUTPUT:
+* PARAMETERS:
+* ord *Z Pointer to result
+*
+* RETURN:
+* SUCCESS No errors
+* ERR_INPUT_LEN Invalid length for input data (zero bytes)
+*
+* REVISION HISTORY:
+*
+* 1 Sep 95 AAB Initial release
+****************************************************************************/
+
+int Square( u_int16_t X_bytes,
+ ord *X,
+ u_int16_t P_bytes,
+ ord *P,
+ ord *Z )
+
+{
+ int status = SUCCESS; /*function return status*/
+
+ord *XY;
+struct BigNum dest, src, mod;
+BigNumInit();
+/*bnInit();
+bnBegin(&dest);
+bnBegin(&src);
+bnBegin(&mod);
+*/
+ if ( P_bytes == 0 || X_bytes == 0 )
+ {
+ status = ERR_INPUT_LEN;
+ return status;
+ }
+ if ( (X_bytes % sizeof(ord) != 0) ||
+ (P_bytes % sizeof(ord) != 0) )
+ {
+ status = ERR_INPUT_LEN;
+ return status;
+ }
+ XY = (ord *)malloc( 2*X_bytes );
+ if( !XY )
+ {
+ return ERR_ALLOC;
+ }
+
+src.size = X_bytes/sizeof(ord);
+src.ptr = X;
+src.allocated = X_bytes/sizeof(ord);
+
+dest.size = 2*X_bytes/sizeof(ord);
+dest.ptr = XY;
+dest.allocated = 2*X_bytes/sizeof(ord);
+
+mod.size = P_bytes/sizeof(ord);
+mod.ptr = P;
+mod.allocated = P_bytes/sizeof(ord);
+
+status = bnSquare(&dest, &src);
+status = bnMod(&dest, &dest, &mod);
+memcpy(Z, dest.ptr, P_bytes);
+free(XY);
+return status;
+}
+
+
+/****************************************************************************
+* NAME: int PartReduct( u_int16_t X_bytes,
+* ord *X,
+* u_int16_t P_bytes,
+* ord *P,
+* ord *Z )
+*
+* DESCRIPTION: Compute a modulo
+*
+* INPUTS:
+* PARAMETERS:
+* ord *X Pointer to array
+* u_int16_t X_bytes Number of bytes in X
+* ord *P Pointer to modulo
+* u_int16_t P_bytes Number of bytes in P
+*
+* OUTPUT:
+* PARAMETERS:
+* ord *Z Pointer to result
+*
+* RETURN:
+* SUCCESS No errors
+* ERR_INPUT_LEN Invalid length for input data (zero bytes)
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 14 Oct 94 GKL Second version (big endian support)
+*
+****************************************************************************/
+
+int PartReduct( u_int16_t X_bytes,
+ ord *X,
+ u_int16_t P_bytes,
+ ord *P,
+ ord *Z )
+{
+ int status = SUCCESS; /*function return status */
+
+
+struct BigNum dest, /*src,*/ d;
+ord *temp;
+BigNumInit();
+/*bnInit();
+bnBegin(&dest);
+bnBegin(&src);
+bnBegin(&d);
+
+src.size = X_bytes/sizeof(ord);
+src.ptr = X;
+src.allocated = X_bytes/sizeof(ord);
+*/
+d.size = P_bytes/sizeof(ord);
+d.ptr = P;
+d.allocated = P_bytes/sizeof(ord);
+
+temp = (ord*)malloc(X_bytes);
+dest.size = X_bytes/sizeof(ord);
+dest.ptr = temp;
+dest.allocated = X_bytes/sizeof(ord);
+memcpy(dest.ptr, X, X_bytes);
+
+status = bnMod(&dest, &dest, &d);
+
+memcpy(Z, dest.ptr, P_bytes);
+free(temp);
+
+return status;
+
+}
+
+/****************************************************************************
+* NAME: int Expo( u_int16_t X_bytes,
+* ord *X,
+* u_int16_t Y_bytes,
+* ord *Y,
+* u_int16_t P_bytes,
+* ord *P,
+* ord *Z,
+* YIELD_context *yield_cont )
+*
+* DESCRIPTION: Compute a modulo exponent
+*
+* INPUTS:
+* PARAMETERS:
+* ord *X Pointer to base array
+* u_int16_t X_bytes Number of bytes in base
+* ord *Y Pointer to exponent array
+* u_int16_t Y_bytes Number of bytes in exponent
+* ord *P Pointer to modulo
+* u_int16_t P_bytes Number of bytes in P
+* YIELD_context *yield_cont Pointer to yield_cont structure (NULL if not used)
+*
+* OUTPUT:
+* PARAMETERS:
+* ord *Z Pointer to result
+*
+* RETURN:
+* SUCCESS No errors
+* ERR_INPUT_LEN Invalid length for input data(zero bytes)
+*
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 14 Oct 94 GKL Second version (big endian support)
+* 08 Dec 94 GKL Added YIELD_context
+* 01 Sep 95 Fast exponentation algorithm
+****************************************************************************/
+
+int Expo( u_int16_t X_bytes, ord *X,
+ u_int16_t Y_bytes, ord *Y,
+ u_int16_t P_bytes, ord *P,
+ ord *Z )
+{
+
+int status = SUCCESS; /*function return status*/
+
+struct BigNum dest, n, exp, mod;
+BigNumInit();
+#if 0
+/*bnInit();*/
+bnBegin(&dest);
+bnBegin(&n);
+bnBegin(&exp);
+bnBegin(&mod);
+#endif
+
+n.size = X_bytes/sizeof(ord);
+n.ptr = X;
+n.allocated = X_bytes/sizeof(ord);
+
+exp.ptr = Y;
+exp.size = Y_bytes/sizeof(ord);
+exp.allocated = Y_bytes/sizeof(ord);
+
+mod.ptr = P;
+mod.size = P_bytes/sizeof(ord);
+mod.allocated = P_bytes/sizeof(ord);
+
+dest.ptr = Z;
+dest.size = P_bytes/sizeof(ord);
+dest.allocated = P_bytes/sizeof(ord);
+
+/* Call bn routine */
+
+status = bnExpMod(&dest, &n,
+ &exp, &mod);
+
+return status;
+}
+
+
+/****************************************************************************
+* NAME: int DoubleExpo( u_int16_t X1_bytes,
+* ord *X1,
+* u_int16_t Y1_bytes,
+* ord *Y1,
+* u_int16_t X2_bytes,
+* ord *X2,
+* u_int16_t Y2_bytes,
+* ord *Y2,
+* u_int16_t P_bytes,
+* ord *P,
+* ord *Z)
+*
+* DESCRIPTION: Compute a modulo exponent
+*
+* INPUTS:
+* PARAMETERS:
+* ord *X1 Pointer to first base array
+* u_int16_t X1_bytes Number of bytes in first base
+* ord *Y1 Pointer to first exponent array
+* u_int16_t Y1_bytes Number of bytes in first exponent
+* ord *X2 Pointer to second base array
+* u_int16_t X2_bytes Number of bytes in second base
+* ord *Y2 Pointer to second exponent array
+* u_int16_t Y2_bytes Number of bytes in second exponent ord *P Pointer to modulo
+* ord *P Pointer to modulo
+* u_int16_t P_bytes Number of bytes in
+*
+* OUTPUT:
+* PARAMETERS:
+* ord *Z Pointer to result
+*
+* RETURN:
+* SUCCESS No errors
+* ERR_INPUT_LEN Invalid length for input data(zero bytes)
+*
+* REVISION HISTORY:
+*
+* 21 Aug 96 AAB Initial release
+****************************************************************************/
+
+
+int DoubleExpo( u_int16_t X1_bytes,ord *X1,
+ u_int16_t Y1_bytes,ord *Y1,
+ u_int16_t X2_bytes,ord *X2,
+ u_int16_t Y2_bytes,ord *Y2,
+ u_int16_t P_bytes,ord *P,
+ ord *Z)
+{
+int status = SUCCESS; /*function return status*/
+struct BigNum res, n1, e1, n2, e2, mod;
+BigNumInit();
+
+n1.size = X1_bytes/sizeof(ord);
+n1.ptr = X1;
+n1.allocated = X1_bytes/sizeof(ord);
+
+e1.size = Y1_bytes/sizeof(ord);
+e1.ptr = Y1;
+e1.allocated = Y1_bytes/sizeof(ord);
+
+n2.size = X2_bytes/sizeof(ord);
+n2.ptr = X2;
+n2.allocated = X2_bytes/sizeof(ord);
+
+e2.size = Y2_bytes/sizeof(ord);
+e2.ptr = Y2;
+e2.allocated = Y2_bytes/sizeof(ord);
+
+mod.ptr = P;
+mod.size = P_bytes/sizeof(ord);
+mod.allocated = P_bytes/sizeof(ord);
+
+res.ptr = Z;
+res.size = P_bytes/sizeof(ord);
+res.allocated = P_bytes/sizeof(ord);
+status = bnDoubleExpMod(&res, &n1, &e1, &n2, &e2, &mod);
+return status;
+}
+
+/****************************************************************************
+* NAME: int Inverse( u_int16_t X_bytes,
+* ord *X,
+* u_int16_t P_bytes,
+* ord *P,
+* ord *Z )
+*
+*
+*
+*
+* DESCRIPTION: Compute a modulo inverse element
+*
+* INPUTS:
+* PARAMETERS:
+* ord *X Pointer to array
+* u_int16_t X_bytes Number of bytes in array
+* ord *P Pointer to modulo
+* u_int16_t P_bytes Number of bytes in P
+*
+* OUTPUT:
+* PARAMETERS:
+* ord *Z Pointer to result
+*
+* RETURN:
+* SUCCESS No errors
+* ERR_INPUT_LEN Invalid length for input data(zero bytes)
+* ERR_INPUT_VALUE Invalid input value
+*
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 14 Oct 94 GKL Second version (big endian support)
+* 08 Nov 94 GKL Added input parameters check
+* 01 Sep 95 Improve fuction
+****************************************************************************/
+
+int Inverse( u_int16_t X_bytes,
+ ord *X,
+ u_int16_t P_bytes,
+ ord *P,
+ ord *Z )
+{
+int status = SUCCESS; /* function return status */
+
+struct BigNum dest, src, mod;
+BigNumInit();
+/*bnInit();
+bnBegin(&dest);
+bnBegin(&src);
+bnBegin(&mod);
+*/
+src.size = X_bytes/sizeof(ord);
+src.ptr = X;
+src.allocated = X_bytes/sizeof(ord);
+
+mod.ptr = P;
+mod.size = P_bytes/sizeof(ord);
+mod.allocated = P_bytes/sizeof(ord);
+
+dest.ptr = Z;
+dest.size = (P_bytes/sizeof(ord)) ;
+dest.allocated = (P_bytes/sizeof(ord)) + 1;
+status = bnInv(&dest,&src,&mod);
+return status;
+}
+
+
+/****************************************************************************
+* NAME: void Add( ord *X,
+* ord *Y,
+* u_int16_t P_len,
+* ord *P,
+* ord *Z )
+
+*
+* DESCRIPTION: Compute modulo addition
+*
+* INPUTS:
+* PARAMETERS:
+* ord *X Pointer to first operand
+* ord *Y Pointer to second operand
+* u_int16_t P_len Length of modulo
+* ord *P Pointer to modulo
+* OUTPUT:
+* ord *Z Pointer to result
+* RETURN:
+*
+* REVISION HISTORY:
+*
+* 24 sep 94 KPZ Initial release
+* 10 Oct 94 KPZ Fixed bugs
+* 14 Oct 94 GKL Second version (big endian support)
+*
+****************************************************************************/
+ /*
+ int Add( ord *X,
+ ord *Y,
+ u_int16_t P_len,
+ ord *P,
+ ord *Z )
+{
+ int status = SUCCESS;
+ ord *temp;
+ struct BigNum dest, src, mod;
+
+bnInit();
+bnBegin(&dest);
+bnBegin(&src);
+bnBegin(&mod);
+
+temp = (ord*)malloc(P_len + sizeof(ord));
+memcpy(temp, X, P_len);
+
+dest.size = P_len/sizeof(ord);
+dest.ptr = temp;
+dest.allocated = P_len/sizeof(ord) + 1;
+
+src.ptr = Y;
+src.size = P_len/sizeof(ord);
+src.allocated = P_len/sizeof(ord);
+
+mod.ptr = P;
+mod.size = P_len/sizeof(ord);
+mod.allocated = P_len/sizeof(ord);
+
+status = bnAdd(&dest,&src);
+status = bnMod(&dest,&dest,&mod);
+memcpy(Z,temp,P_len);
+free(temp);
+return status;
+}
+ */
+ int Add( ord *X,
+ ord *Y,
+ u_int16_t P_len,
+ ord *P)
+{
+ int status = SUCCESS;
+/* ord *temp;*/
+ struct BigNum dest, src, mod;
+
+BigNumInit();
+/*bnInit();
+bnBegin(&dest);
+bnBegin(&src);
+bnBegin(&mod);
+*/
+/*
+temp = (ord*)malloc(P_len + sizeof(ord));
+memcpy(temp, X, P_len);
+*/
+dest.size = P_len/sizeof(ord);
+/*dest.ptr = temp;*/
+dest.ptr = X;
+dest.allocated = P_len/sizeof(ord) + 1;
+
+src.ptr = Y;
+src.size = P_len/sizeof(ord);
+src.allocated = P_len/sizeof(ord);
+
+mod.ptr = P;
+mod.size = P_len/sizeof(ord);
+mod.allocated = P_len/sizeof(ord);
+
+status = bnAdd(&dest,&src);
+status = bnMod(&dest,&dest,&mod);
+/*
+memcpy(Z,temp,P_len);
+free(temp);
+*/
+return status;
+}
+
+
+
+
+/****************************************************************************
+* NAME: int SteinGCD( ord *m,
+* ord *b
+* u_int16_t len )
+*
+* DESCRIPTION: Compute great common divisor
+*
+* INPUTS:
+* PARAMETERS:
+* ord *m Pointer to first number
+* ord *b Pointer to second number
+* u_int16_t len Number of elements in number
+* OUTPUT:
+*
+* RETURN:
+* TRUE if gcd != 1
+* FALSE if gcd == 1
+* REVISION HISTORY:
+*
+*
+* 24 Sep 94 KPZ Initial release
+* 14 Oct 94 GKL Second version (big endian support)
+* 01 Sep 95 AAB Speed up
+*
+****************************************************************************/
+
+
+/* test if GCD equal 1 */
+int SteinGCD ( ord *m,
+ ord *n,
+ u_int16_t len )
+{
+
+int status;
+struct BigNum dest, a, b;
+ord *temp;
+BigNumInit();
+/*bnInit();
+bnBegin(&dest);
+bnBegin(&a);
+bnBegin(&b);
+*/
+a.size = len;
+a.ptr = m;
+a.allocated = len;
+
+b.size = len;
+b.ptr = n;
+b.allocated = len;
+
+temp = (ord*)malloc((len+1)*sizeof(ord));
+dest.size = len;
+dest.ptr = temp;
+dest.allocated = len+1;
+
+status = bnGcd(&dest, &a, &b);
+
+if (*(ord *)(dest.ptr) == 0x01 && dest.size == 1)
+ status = 0;
+else
+ status = 1;
+
+free(temp);
+
+return status;
+
+}
+
+
+/****************************************************************************
+* NAME: int DivRem( u_int16_t X_bytes,
+* ord *X,
+* u_int16_t P_bytes,
+* ord *P,
+* ord *Z,
+* ord *D)
+*
+* DESCRIPTION: Compute a modulo and quotient
+*
+* INPUTS:
+* PARAMETERS:
+* ord *X Pointer to array
+* u_int16_t X_bytes Number of bytes in X
+* ord *P Pointer to modulo
+* u_int16_t P_bytes Number of bytes in P
+*
+* OUTPUT:
+* PARAMETERS:
+* ord *Z Pointer to result
+* ord *D Pointer to quotient
+* RETURN:
+* SUCCESS No errors
+* ERR_INPUT_LEN Invalid length for input data (zero bytes)
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 10 Oct 94 KPZ Fixed bugs
+* 14 Oct 94 GKL Second version (big endian support)
+*
+****************************************************************************/
+
+int DivRem( u_int16_t X_bytes,
+ ord *X,
+ u_int16_t P_bytes,
+ ord *P,
+ ord *Z,
+ ord *D)
+{
+ int status = SUCCESS; /* function return status */
+
+struct BigNum q, r, /*n,*/ d;
+ord *temp;
+BigNumInit();
+/*bnInit();
+bnBegin(&q);
+bnBegin(&r);
+bnBegin(&n);
+bnBegin(&d);
+
+n.size = X_bytes/sizeof(ord);
+n.ptr = X;
+n.allocated = X_bytes/sizeof(ord);
+*/
+d.size = P_bytes/sizeof(ord);
+d.ptr = P;
+d.allocated = P_bytes/sizeof(ord);
+
+q.size = (X_bytes/sizeof(ord)) - (P_bytes/sizeof(ord)) + 1;
+q.ptr = D;
+q.allocated = (X_bytes/sizeof(ord)) - (P_bytes/sizeof(ord)) + 1;
+
+temp = (ord *)malloc(X_bytes);
+r.size = X_bytes/sizeof(ord);
+r.ptr = temp;
+r.allocated = X_bytes/sizeof(ord);
+memcpy(r.ptr, X, X_bytes);
+
+status = bnDivMod(&q, &r, &r, &d);
+
+memcpy(Z, r.ptr, P_bytes);
+free(temp);
+
+return status;
+
+}
diff --git a/usr/src/lib/libresolv2/common/cylink/ppcasm.h b/usr/src/lib/libresolv2/common/cylink/ppcasm.h
new file mode 100644
index 0000000000..23e1b28341
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/ppcasm.h
@@ -0,0 +1,582 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef PPCASM_H
+#define PPCASM_H
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * A PowerPC assembler in the C preprocessor.
+ * This assumes that ints are 32 bits, and uses them for the values.
+ *
+ * An assembly-language routine is simply an array of unsigned ints,
+ * initialized with the macros defined here.
+ *
+ * In the PowerPC, a generic function pointer does *not* point to the
+ * first word of code, but to a two (or possibly more) word "transition
+ * vector." The first word of the TV points to the function's code.
+ * The second word is the function's TOC (Table Of Contents) pointer,
+ * which is loaded into r2. The function's global variables are
+ * accessed via the TOC pointed to by r2. TOC pointers are changed,
+ * for example, when a dynamically linked library is called, so the
+ * library can have private global variables.
+ *
+ * Saving r2 and reloading r2 each function call is a hassle that
+ * I'd really rather avoid, since a lot of useful assembly language routines
+ * can be written without global variables at all, so they don't need a TOC
+ * pointer. But I haven't figured out how to persuade CodeWarrior 7 to
+ * generate an intra-TOC call to an array. (CodeWarrior 8 supports
+ * PowerPC asm, which obviates the need to do the cast-to-function-pointer
+ * trick, which obviates the need for cross-TOC calls.)
+ *
+ * The basic PowerPC calling conventions for integers are:
+ * r0 - scratch. May be modified by function calls.
+ * r1 - stack pointer. Must be preserved across function calls.
+ * See IMPORTANT notes on stack frame format below.
+ * This must *ALWAYS*, at every instruction boundary, be 16-byte
+ * aligned and point to a valid stack frame. If a procedure
+ * needs to create a stack frame, the recommended way is to do:
+ * stwu r1,-frame_size(r1)
+ * and on exit, recover with one of:
+ * addi r1,r1,frame_size, OR
+ * lwz r1,0(r1)
+ * r2 - TOC pointer. Points to the current table of contents.
+ * Must be preserved across function calls.
+ * r3 - First argument register and return value register.
+ * Arguments are passed in r3 through r10, and values returned in
+ * r3 through r6, as needed. (Usually only r3 for single word.)
+ * r4-r10 - More argument registers
+ * r11 - Scratch, may be modified by function calls.
+ * On entry to indirect function calls, this points to the
+ * transition vector, and additional words may be loaded
+ * at offsets from it. Some conventions use r12 instead.
+ * r12 - Scratch, may be modified by function calls.
+ * r13-r31 - Callee-save registers, may not be modified by function
+ * calls.
+ * The LR, CTR and XER may be modified by function calls, as may the MQ
+ * register, on those processors for which it is implemented.
+ * CR fields 0, 1, 5, 6 and 7 are scratch and may be modified by function
+ * calls. CR fields 2, 3 and 4 must be preserved across function calls.
+ *
+ * Stack frame format - READ
+ *
+ * r1 points to a stack frame, which must *ALWAYS*, meaning after each and
+ * every instruction, without excpetion, point to a valid 16-byte-aligned
+ * stack frame, defined as follows:
+ * - The 296 bytes below r1 (from -296(r1) to -1(r1)) are the so-called Red
+ * Zone reserved for leaf procedures, which may use it without allocating
+ * a stack frame and without decrementing r1. The size comes from the room
+ * needed to store all the callee-save registers: 19 64-bit integer registers
+ * and 18 64-bit floating-point registers. (18+19)*8 = 296. So any
+ * procedure can save all the registers it needs to save before creating
+ * a stack frame and moving r1.
+ * The bytes at -297(r1) and below may be used by interrupt and exception
+ * handlers *at any time*. Anything placed there may disappear before
+ * the next instruction.
+ * The word at 0(r1) is the previous r1, and so on in a linked list.
+ * This is the minimum needed to be a valid stack frame, but some other
+ * offsets from r1 are preallocated by the calling procedure for the called
+ * procedure's use. These are:
+ * Offset 0: Link to previous stack frame - saved r1, if the called
+ * procedure alters it.
+ * Offset 4: Saved CR, if the called procedure alters the callee-save
+ * fields. There's no important reason to save it here,
+ * but the space is reserved and you might as well use it
+ * for its intended purpose unless you have good reason to
+ * do otherwise. (This may help some debuggers.)
+ * Offset 8: Saved LR, if the called procedure needs to save it for
+ * later function return. Saving the LR here helps a debugger
+ * track the chain of return addresses on the stack.
+ * Note that a called procedure does not need to preserve the
+ * LR for it's caller's sake, but it uually wants to preserve
+ * the value for its own sake until it finishes and it's
+ * time to return. At that point, this is usually loaded
+ * back into the LR and the branch accomplished with BLR.
+ * However, if you want to be preverse, you could load it
+ * into the CTR and use BCTR instead.
+ * Offset 12: Reserved to compiler. I can't find what this is for.
+ * Offset 16: Reserved to compiler. I can't find what this is for.
+ * Offset 20: Saved TOC pointer. In a cross-TOC call, the old TOC (r2)
+ * is saved here before r2 is loaded with the new TOC value.
+ * Again, it's not important to use this slot for this, but
+ * you might as well.
+ * Beginning at offset 24 is the argument area. This area is at least 8 words
+ * (32 bytes; I don't know what happens with 64 bits) long, and may be longer,
+ * up to the length of the longest argument list in a function called by
+ * the function which allocated this stack frame. Generally, arguments
+ * to functions are passed in registers, but if those functions notice
+ * the address of the arguments being taken, the registers are stored
+ * into the space reserved for them in this area and then used from memory.
+ * Additional arguments that will not fit into registers are also stored
+ * here. Variadic functions (like printf) generally start by saving
+ * all the integer argument registers from the "..." onwards to this space.
+ * For that reason, the space must be large enough to store all the argument
+ * registers, even if they're never used.
+ * (It could probably be safely shrunk if you're not calling any variadic
+ * functions, but be careful!)
+ *
+ * Offsets above that are private to the calling function and shouldn't
+ * be messed with. Generally, what appears there is locals, then saved
+ * registers.
+ *
+ *
+ * The floating-point instruction set isn't implemented yet (I'm too
+ * lazy, as I don't need it yet), but for when it is, the register
+ * usage convention is:
+ * FPSCR - Scratch, except for floating point exception enable fields,
+ * which should only be modified by functions defined to do so.
+ * fr0 - scratch
+ * fr1 - first floating point parameter and return value, scratch
+ * fr2 - second floating point parameter and return value (if needed), scratch
+ * fr3 - third floating point parameter and return value (if needed), scratch
+ * fr4 - fourth floating point parameter and return value (if needed), scratch
+ * fr5-fr13 - More floating point argument registers, scratch
+ * fr14-fr31 - Callee-save registers, may not be modified across a function call
+ *
+ * Complex values store the real part in the lower-numberd register of a pair.
+ * When mixing floating-point and integer arguments, reserve space (one register
+ * for single-precision, two for double-precision values) in the integer
+ * argument list for the floating-point values. Those integer registers
+ * generally have undefined values, UNLESS there is no prototype for the call,
+ * in which case they should contain a copy of the floating-point value's
+ * bit pattern to cope with wierd software.
+ * If the floating point arguments go past the end of the integer registers,
+ * they are stored in the argument area as well as being passed in here.
+ *
+ * After the argument area comes the calling function's private storage.
+ * Typically, there are locals, followed by saved GP rgisters, followed
+ * by saved FP registers.
+ *
+ * Suggested instruction for allocating a stack frame:
+ * stwu r1,-frame_size(r1)
+ * Suggested instructions for deallocating a stack frame:
+ * addi r1,r1,frame_size
+ * or
+ * lwz r1,0(r1)
+ * If frame_size is too big, you'll have to load the offset into a temp
+ * register, but be sure that r1 is updated atomically.
+ *
+ *
+ * Basic PowerPC instructions look like this:
+ *
+ * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Opcode | | | | | | | | | | | | | | | | | | | | | | | | | | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * Branch instructions look like this:
+ *
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Opcode | Branch offset |A|L|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * The L, or LK, or Link bit indicates that the return address for the
+ * branch should be copied to the link register (LR).
+ * The A, or AA, or absolute address bit, indicates that the address
+ * of the current instruction (NOTE: not next instruction!) should NOT
+ * be added to the branch offset; it is relative to address 0.
+ *
+ * Conditional branches looks like this:
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Opcode | BO | BI | Branch offset |A|L|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * The BI field specifies the condition bit of interest (from the CR).
+ * The BO field specifies what's interesting. You can branch on a
+ * combination of a bit of the condition register and --ctr, the CTR
+ * register. Two bits encode the branch condition to use:
+ * BRANCH IF
+ * 00--- = Bit BI is 0
+ * 01--- = Bit BI is 1
+ * 1z--- = don't care about bit BI (always true)
+ * AND
+ * --00- = --ctr != 0
+ * --01- = --ctr == 0
+ * --1z- = don't decrement ctr (always true)
+ * The last bit us used as a branch prediction bit. If set, it reverses
+ * the usual backward-branch-taken heuristic.
+ *
+ * y = branch prediction bit. z = unused, must be 0
+ * 0000y - branch if --ctr != 0 && BI == 0
+ * don't branch if --ctr == 0 || BI != 0
+ * 0001y - branch if --ctr == 0 && BI == 0
+ * don't branch if --ctr != 0 || BI != 0
+ * 001zy - branch if BI == 0
+ * don't branch if BI != 0
+ * 0100y - branch if --ctr != 0 && BI != 0
+ * don't branch if --ctr == 0 || BI == 0
+ * 0101y - branch if --ctr == 0 && BI != 0
+ * don't branch if --ctr != 0 || BI == 0
+ * 011zy - branch if BI != 0
+ * don't branch if BI == 0
+ * 1z00y - branch if --ctr != 0
+ * don't branch if --ctr == 0
+ * 1z01y - branch if --ctr == 0
+ * don't branch if --ctr != 0
+ * 1z1zz - branch always
+ * If y is 1, the usual branch prediction (usually not taken, taken for
+ * backwards branches with immediate offsets) is reversed.
+ *
+ * Instructions with 2 operands and a 16-bit immediate field look like this:
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Opcode | D | A | 16-bit immediate value |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * Now, there are three variations of note. In some instructions, the 16-bit
+ * value is sign-extended. In others, it's zero-extended. These are noted
+ * below as "simm" (signed immediate) and "uimm", respectively. Also, which
+ * field is the destination and which is the source sometimes switches.
+ * Sometimes it's d = a OP imm, and sometimes it's a = s OP imm. In the
+ * latter cases, the "d" field is referred to as "s" ("source" instead of
+ * "destination". These are logical and shift instructions. (Store also
+ * refers to the s register, but that's the source of the value to be stored.)
+ * The assembly mnemonics, however, always lists the destination first,
+ * swapping the order in the instruction if necessary.
+ * Third, quite often, if r0 is specified for the source a, then the constant
+ * value 0 is used instead. Thus, r0 is of limited use - it can be used for
+ * some things, but not all.
+ *
+ * Instructions with three register operands look like this:
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Opcode | D | A | B | Subopcode |C|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * For most of the instructions of interest the Opcode is 31 and the subopcode
+ * determines what the instruction does. For a few instructions (mostly loads
+ * and stores), if the A field is 0, the constant 0 is used. The "C"
+ * bit (also known as the "RC" bit) controls whether or not the condition
+ * codes are updated. If it is set (indicated by a "." suffix on the official
+ * PowerPC opcodes, and a "_" suffix on these macros), condition code register
+ * field 0 (for integer instructions; field 1 for floating point) is updated
+ * to reflect the result of the operation.
+ * Some arithmetic instructions use the most significant bit of the subopcode
+ * field as an overflow enable bit (o suffix).
+ *
+ * Then there are the rotate and mask instructions, which have 5 operands, and
+ * fill the subopcode field with 2 more 5-bit fields. See below for them.
+ *
+ * NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
+ * These macros fully parenthesize their arguments, but are not themselves
+ * fully parenthesized. They are intended to be used for initializer lists,
+ * and if you want to do tricks with their numeric values, wrap them in
+ * parentheses.
+ */
+
+#define PPC_MAJOR(x) ((x)<<26) /* Major opcode (0..63) */
+#define PPC_MINOR(x) ((x)<<1) /* Minor opcode (0..1023) */
+#define PPC_RC 1 /* Record carry (. suffix, represented as _) */
+#define PPC_OE 1024 /* Overflow enable (o suffix) */
+#define PPC_DEST(reg) ((reg)<<21) /* Dest register field */
+#define PPC_SRCA(reg) ((reg)<<16) /* First source register field */
+#define PPC_SRCB(reg) ((reg)<<11) /* Second source register field */
+#define PPC_AA 2 /* Branch is absolute, relative to address 0 */
+#define PPC_LK 1 /* Branch with link (L suffix) */
+
+/* Unconditional branch (dest is 26 bits, +/- 2^25 bytes) */
+#define PPC_B(dest) PPC_MAJOR(18)|(((dest)<<2) & 0x03fffffc)
+#define PPC_BA(dest) PPC_B(dest)|PPC_AA
+#define PPC_BL(dest) PPC_B(dest)|PPC_LK
+#define PPC_BLA(dest) PPC_B(dest)|PPC_AA|PPC_LK
+
+/* Three-operand instructions */
+#define PPC_TYPE31(minor,d,a,b) \
+ PPC_MAJOR(31)|PPC_DEST(d)|PPC_SRCA(a)|PPC_SRCB(b)|PPC_MINOR(minor)
+#define PPC_ADD(d,a,b) PPC_TYPE31(266,d,a,b)
+#define PPC_ADD_(d,a,b) PPC_TYPE31(266,d,a,b)|PPC_RC
+#define PPC_ADDO(d,a,b) PPC_TYPE31(266,d,a,b)|PPC_OE
+#define PPC_ADDO_(d,a,b) PPC_TYPE31(266,d,a,b)|PPC_OE|PPC_RC
+#define PPC_ADDC(d,a,b) PPC_TYPE31(10,d,a,b)
+#define PPC_ADDC_(d,a,b) PPC_TYPE31(10,d,a,b)|PPC_RC
+#define PPC_ADDCO(d,a,b) PPC_TYPE31(10,d,a,b)|PPC_OE
+#define PPC_ADDCO_(d,a,b) PPC_TYPE31(10,d,a,b)|PPC_OE|PPC_RC
+#define PPC_ADDE(d,a,b) PPC_TYPE31(138,d,a,b)
+#define PPC_ADDE_(d,a,b) PPC_TYPE31(138,d,a,b)|PPC_RC
+#define PPC_ADDEO(d,a,b) PPC_TYPE31(138,d,a,b)|PPC_OE
+#define PPC_ADDEO_(d,a,b) PPC_TYPE31(138,d,a,b)|PPC_OE|PPC_RC
+#define PPC_ADDME(d,a) PPC_TYPE31(234,d,a,0)
+#define PPC_ADDME_(d,a) PPC_TYPE31(234,d,a,0)|PPC_RC
+#define PPC_ADDMEO(d,a) PPC_TYPE31(234,d,a,0)|PPC_OE
+#define PPC_ADDMEO_(d,a) PPC_TYPE31(234,d,a,0)|PPC_OE|PPC_RC
+#define PPC_ADDZE(d,a) PPC_TYPE31(202,d,a,0)
+#define PPC_ADDZE_(d,a) PPC_TYPE31(202,d,a,0)|PPC_RC
+#define PPC_ADDZEO(d,a) PPC_TYPE31(202,d,a,0)|PPC_OE
+#define PPC_ADDZEO_(d,a) PPC_TYPE31(202,d,a,0)|PPC_OE|PPC_RC
+#define PPC_AND(a,s,b) PPC_TYPE31(28,s,a,b)
+#define PPC_AND_(a,s,b) PPC_TYPE31(28,s,a,b)|PPC_RC
+#define PPC_ANDC(a,s,b) PPC_TYPE31(60,s,a,b)
+#define PPC_ANDC_(a,s,b) PPC_TYPE31(60,s,a,b)|PPC_RC
+#define PPC_CMP(cr,a,b) PPC_TYPE31(0,(cr)<<2,a,b)
+#define PPC_CMPL(cr,a,b) PPC_TYPE31(32,(cr)<<2,a,b)
+#define PPC_CNTLZW(a,s) PPC_TYPE31(26,s,a,0)
+#define PPC_CNTLZW_(a,s) PPC_TYPE31(26,s,a,0)|PPC_RC
+#define PPC_DCBF(a,b) PPC_TYPE31(86,0,a,b)
+#define PPC_DCBI(a,b) PPC_TYPE31(470,0,a,b)
+#define PPC_DCBST(a,b) PPC_TYPE31(54,0,a,b)
+#define PPC_DCBT(a,b) PPC_TYPE31(278,0,a,b)
+#define PPC_DCBTST(a,b) PPC_TYPE31(246,0,a,b)
+#define PPC_DCBZ(a,b) PPC_TYPE31(1014,0,a,b)
+#define PPC_DIVW(d,a,b) PPC_TYPE31(491,d,a,b)
+#define PPC_DIVW_(d,a,b) PPC_TYPE31(491,d,a,b)|PPC_RC
+#define PPC_DIVWO(d,a,b) PPC_TYPE31(491,d,a,b)|PPC_OE
+#define PPC_DIVWO_(d,a,b) PPC_TYPE31(491,d,a,b)|PPC_OE|PPC_RC
+#define PPC_DIVWU(d,a,b) PPC_TYPE31(459,d,a,b)
+#define PPC_DIVWU_(d,a,b) PPC_TYPE31(459,d,a,b)|PPC_RC
+#define PPC_DIVWUO(d,a,b) PPC_TYPE31(459,d,a,b)|PPC_OE
+#define PPC_DIVWUO_(d,a,b) PPC_TYPE31(459,d,a,b)|PPC_OE|PPC_RC
+#define PPC_EIEIO() PPC_TYPE31(854,0,0,0)
+#define PPC_EQV(a,s,b) PPC_TYPE31(284,s,a,b)
+#define PPC_EQV_(a,s,b) PPC_TYPE31(284,s,a,b)|PPC_RC
+#define PPC_EXTSB(a,s,b) PPC_TYPE31(954,s,a,b)
+#define PPC_EXTSB_(a,s,b) PPC_TYPE31(954,s,a,b)|PPC_RC
+#define PPC_EXTSH(a,s,b) PPC_TYPE31(922,s,a,b)
+#define PPC_EXTSH_(a,s,b) PPC_TYPE31(922,s,a,b)|PPC_RC
+#define PPC_ICBI(a,b) PPC_TYPE31(982,0,a,b)
+#define PPC_ISYNC() PPC_TYPE31(150,0,0,0)
+#define PPC_LBZUX(d,a,b) PPC_TYPE31(119,d,a,b)
+#define PPC_LBZX(d,a,b) PPC_TYPE31(87,d,a,b)
+#define PPC_LHAUX(d,a,b) PPC_TYPE31(375,d,a,b)
+#define PPC_LHAX(d,a,b) PPC_TYPE31(343,d,a,b)
+#define PPC_LHBRX(d,a,b) PPC_TYPE31(790,d,a,b)
+#define PPC_LHZUX(d,a,b) PPC_TYPE31(311,d,a,b)
+#define PPC_LHZX(d,a,b) PPC_TYPE31(279,d,a,b)
+#define PPC_LSWI(d,a,nb) PPC_TYPE31(597,d,a,nb)
+#define PPC_LSWX(d,a,b) PPC_TYPE31(533,d,a,b)
+#define PPC_LSARX(d,a,b) PPC_TYPE31(20,d,a,b)
+#define PPC_LSBRX(d,a,b) PPC_TYPE31(534,d,a,b)
+#define PPC_MCRXR(crd) PPC_TYPE31(512,(crd)<<2,0,0)
+#define PPC_MFCR(d) PPC_TYPE31(19,d,0,0)
+#define PPC_MFSPR(d,spr) PPC_TYPE31(339,d,(spr)&31,(spr)>>5)
+#define PPC_MFTB(d) PPC_TYPE31(371,d,12,8)
+#define PPC_MFTBU(d) PPC_TYPE31(371,d,13,8)
+#define PPC_MTCRF(mask,s) PPC_TYPE31(144,s,0,(mask)&0xff)
+#define PPC_MTSPR(s,spr) PPC_TYPE31(467,s,(spr)&31,(spr)>>5)
+#define PPC_MULHW(d,a,b) PPC_TYPE31(75,d,a,b)
+#define PPC_MULHW_(d,a,b) PPC_TYPE31(75,d,a,b)|PPC_RC
+#define PPC_MULHWU(d,a,b) PPC_TYPE31(11,d,a,b)
+#define PPC_MULHWU_(d,a,b) PPC_TYPE31(11,d,a,b)|PPC_RC
+#define PPC_MULLW(d,a,b) PPC_TYPE31(235,d,a,b)
+#define PPC_MULLW_(d,a,b) PPC_TYPE31(235,d,a,b)|PPC_RC
+#define PPC_MULLWO(d,a,b) PPC_TYPE31(235,d,a,b)|PPC_OE
+#define PPC_MULLWO_(d,a,b) PPC_TYPE31(235,d,a,b)|PPC_OE|PPC_RC
+#define PPC_NAND(a,s,b) PPC_TYPE31(476,s,a,b)
+#define PPC_NAND_(a,s,b) PPC_TYPE31(476,s,a,b)|PPC_RC
+#define PPC_NEG(d,a) PPC_TYPE31(104,d,a,b)
+#define PPC_NEG_(d,a) PPC_TYPE31(104,d,a,b)|PPC_RC
+#define PPC_NEGO(d,a) PPC_TYPE31(104,d,a,b)|PPC_OE
+#define PPC_NEGO_(d,a) PPC_TYPE31(104,d,a,b)|PPC_OE|PPC_RC
+#define PPC_NOR(a,s,b) PPC_TYPE31(124,s,a,b)
+#define PPC_NOR_(a,s,b) PPC_TYPE31(124,s,a,b)|PPC_RC
+#define PPC_OR(a,s,b) PPC_TYPE31(444,s,a,b)
+#define PPC_OR_(a,s,b) PPC_TYPE31(444,s,a,b)|PPC_RC
+#define PPC_ORC(a,s,b) PPC_TYPE31(412,s,a,b)
+#define PPC_ORC_(a,s,b) PPC_TYPE31(412,s,a,b)|PPC_RC
+#define PPC_SLW(a,s,b) PPC_TYPE31(24,s,a,b)
+#define PPC_SLW_(a,s,b) PPC_TYPE31(24,s,a,b)|PPC_RC
+#define PPC_SRAW(a,s,b) PPC_TYPE31(792,s,a,b)
+#define PPC_SRAW_(a,s,b) PPC_TYPE31(792,s,a,b)|PPC_RC
+#define PPC_SRAWI(a,s,sh) PPC_TYPE31(824,s,a,sh)
+#define PPC_SRAWI_(a,s,sh) PPC_TYPE31(824,s,a,sh)|PPC_RC
+#define PPC_SRW(a,s,b) PPC_TYPE31(536,s,a,b)
+#define PPC_SRW_(a,s,b) PPC_TYPE31(536,s,a,b)|PPC_RC
+#define PPC_STBUX(s,a,b) PPC_TYPE31(247,s,a,b)
+#define PPC_STBX(s,a,b) PPC_TYPE31(215,s,a,b)
+#define PPC_STHBRX(s,a,b) PPC_TYPE31(918,s,a,b)
+#define PPC_STHUX(s,a,b) PPC_TYPE31(439,s,a,b)
+#define PPC_STHX(s,a,b) PPC_TYPE31(407,s,a,b)
+#define PPC_STSWI(s,a,nb) PPC_TYPE31(725,s,a,nb)
+#define PPC_STSWX(s,a,b) PPC_TYPE31(661,s,a,b)
+#define PPC_STWBRX(s,a,b) PPC_TYPE31(662,s,a,b)
+#define PPC_STWCX_(s,a,b) PPC_TYPE31(150,s,a,b)|PPC_RC
+#define PPC_STWUX(s,a,b) PPC_TYPE31(183,s,a,b)
+#define PPC_STWX(s,a,b) PPC_TYPE31(151,s,a,b)
+#define PPC_SUBF(d,a,b) PPC_TYPE31(40,d,a,b)
+#define PPC_SUBF_(d,a,b) PPC_TYPE31(40,d,a,b)|PPC_RC
+#define PPC_SUBFO(d,a,b) PPC_TYPE31(40,d,a,b)|PPC_OE
+#define PPC_SUBFO_(d,a,b) PPC_TYPE31(40,d,a,b)|PPC_OE|PPC_RC
+#define PPC_SUB(d,b,a) PPC_SUBF(d,a,b)
+#define PPC_SUB_(d,b,a) PPC_SUBF_(d,a,b)
+#define PPC_SUBO(d,b,a) PPC_SUBFO(d,a,b)
+#define PPC_SUBO_(d,b,a) PPC_SUBFO_(d,a,b)
+#define PPC_SUBFC(d,a,b) PPC_TYPE31(8,d,a,b)
+#define PPC_SUBFC_(d,a,b) PPC_TYPE31(8,d,a,b)|PPC_RC
+#define PPC_SUBFCO(d,a,b) PPC_TYPE31(8,d,a,b)|PPC_OE
+#define PPC_SUBFCO_(d,a,b) PPC_TYPE31(8,d,a,b)|PPC_OE|PPC_RC
+#define PPC_SUBFE(d,a,b) PPC_TYPE31(136,d,a,b)
+#define PPC_SUBFE_(d,a,b) PPC_TYPE31(136,d,a,b)|PPC_RC
+#define PPC_SUBFEO(d,a,b) PPC_TYPE31(136,d,a,b)|PPC_OE
+#define PPC_SUBFEO_(d,a,b) PPC_TYPE31(136,d,a,b)|PPC_OE|PPC_RC
+#define PPC_SUBFME(d,a) PPC_TYPE31(232,d,a,0)
+#define PPC_SUBFME_(d,a) PPC_TYPE31(232,d,a,0)|PPC_RC
+#define PPC_SUBFMEO(d,a) PPC_TYPE31(232,d,a,0)|PPC_OE
+#define PPC_SUBFMEO_(d,a) PPC_TYPE31(232,d,a,0)|PPC_OE|PPC_RC
+#define PPC_SUBFZE(d,a) PPC_TYPE31(200,d,a,0)
+#define PPC_SUBFZE_(d,a) PPC_TYPE31(200,d,a,0)|PPC_RC
+#define PPC_SUBFZEO(d,a) PPC_TYPE31(200,d,a,0)|PPC_OE
+#define PPC_SUBFZEO_(d,a) PPC_TYPE31(200,d,a,0)|PPC_OE|PPC_RC
+#define PPC_SYNC() PPC_TYPE31(598,0,0,0)
+#define PPC_TW(to,a,b) PPC_TYPE31(4,to,a,b)
+#define PPC_XOR(a,s,b) PPC_TYPE31(316,s,a,b)
+
+/* Immediate-operand instructions. Take a 16-bit immediate operand */
+#define PPC_IMM(major,d,a,imm) \
+ PPC_MAJOR(major)|PPC_DEST(d)|PPC_SRCA(a)|((imm)&0xffff)
+/* Trap word immediate */
+#define PPV_TWI(to,a,simm) PPC_IMM(3,to,a,simm)
+/* Integer arithmetic */
+#define PPC_MULLI(d,a,simm) PPC_IMM(7,d,a,simm)
+#define PPC_SUBFIC(s,a,simm) PPC_IMM(8,s,a,simm)
+#define PPC_CMPLI(cr,a,uimm) PPC_IMM(10,(cr)<<2,a,uimm)
+#define PPC_CMPI(cr,a,simm) PPC_IMM(11,(cr)<<2,a,simm)
+#define PPC_ADDIC(d,a,simm) PPC_IMM(12,d,a,simm)
+#define PPC_ADDIC_(d,a,simm) PPC_IMM(13,d,a,simm)
+#define PPC_ADDI(d,a,simm) PPC_IMM(14,d,a,simm)
+#define PPC_ADDIS(d,a,simm) PPC_IMM(15,d,a,simm)
+
+/* Conditional branch (dest is 16 bits, +/- 2^15 bytes) */
+#define PPC_BC(bo,bi,dest) PPC_IMM(16,bo,bi,((dest)<<2)&0xfffc)
+#define PPC_BCA(bo,bi,dest) PPC_BC(bo,bi,dest)|PPC_AA
+#define PPC_BCL(bo,bi,dest) PPC_BC(bo,bi,dest)|PPC_LK
+#define PPC_BCLA(bo,bi,dest) PPC_BC(bo,bi,dest)|PPC_AA|PPC_LK
+
+/* Logical operations */
+#define PPC_ORI(a,s,uimm) PPC_IMM(24,s,a,uimm)
+#define PPC_ORIS(a,s,uimm) PPC_IMM(25,s,a,uimm)
+#define PPC_XORI(a,s,uimm) PPC_IMM(26,s,a,uimm)
+#define PPC_XORIS(a,s,uimm) PPC_IMM(27,s,a,uimm)
+#define PPC_ANDI_(a,s,uimm) PPC_IMM(28,s,a,uimm)
+#define PPC_ANDIS(a,s,uimm) PPC_IMM(29,s,a,uimm)
+
+/* Load/store */
+#define PPC_LWZ(d,a,simm) PPC_IMM(32,d,a,simm)
+#define PPC_LWZU(d,a,simm) PPC_IMM(33,d,a,simm)
+#define PPC_LBZ(d,a,simm) PPC_IMM(34,d,a,simm)
+#define PPC_LBZU(d,a,simm) PPC_IMM(35,d,a,simm)
+#define PPC_STW(s,a,simm) PPC_IMM(36,s,a,simm)
+#define PPC_STWU(s,a,simm) PPC_IMM(37,s,a,simm)
+#define PPC_STB(s,a,simm) PPC_IMM(38,s,a,simm)
+#define PPC_STBU(s,a,simm) PPC_IMM(39,s,a,simm)
+#define PPC_LHZ(d,a,simm) PPC_IMM(40,d,a,simm)
+#define PPC_LHZU(d,a,simm) PPC_IMM(41,d,a,simm)
+#define PPC_LHA(d,a,simm) PPC_IMM(42,d,a,simm)
+#define PPC_STH(s,a,simm) PPC_IMM(44,s,a,simm)
+#define PPC_STHU(s,a,simm) PPC_IMM(45,s,a,simm)
+#define PPC_LHAU(d,a,simm) PPC_IMM(43,d,a,simm)
+#define PPC_LMW(d,a,simm) PPC_IMM(46,d,a,simm)
+#define PPC_STMW(s,a,simm) PPC_IMM(47,s,a,simm)
+
+/* Major number = 19 - condition register operations. d, a and b are CR bits */
+#define PPC_TYPE19(minor,d,a,b) \
+ PPC_MAJOR(19)|PPC_DEST(d)|PPC_SRCA(a)|PPC_SRCB(b)|PPC_MINOR(minor)
+#define PPC_MCRF(d,s) PPC_TYPE19(0,(d)<<2,(s)<<2,0)
+#define PPC_CRNOR(d,a,b) PPC_TYPE19(33,d,a,b)
+#define PPC_CRANDC(d,a,b) PPC_TYPE19(129,d,a,b)
+#define PPC_CRXOR(d,a,b) PPC_TYPE19(193,d,a,b)
+#define PPC_CRNAND(d,a,b) PPC_TYPE19(225,d,a,b)
+#define PPC_CRAND(d,a,b) PPC_TYPE19(257,d,a,b)
+#define PPC_CREQV(d,a,b) PPC_TYPE19(289,d,a,b)
+#define PPC_CRORC(d,a,b) PPC_TYPE19(417,d,a,b)
+#define PPC_CROR(d,a,b) PPC_TYPE19(449,d,a,b)
+
+/* Indirect conditional branch */
+#define PPC_BCLR(bo,bi) PPC_TYPE19(16,bo,bi,0)
+#define PPC_BCLRL(bo,bi) PPC_TYPE19(16,bo,bi,0)|PPC_LK
+#define PPC_BCCTR(bo,bi) PPC_TYPE19(528,bo,bi,0)
+#define PPC_BCCTRL(bo,bi) PPC_TYPE19(528,bo,bi,0)|PPC_LK
+#define PPC_BLR() PPC_BCLR(20,31)
+#define PPC_BCTR() PPC_BCCTR(20,31)
+
+/* Other */
+#define PPC_RLWIMI(a,s,sh,mb,me) \
+ PPC_MAJOR(20)|PPC_DEST(s)|PPC_SRCA(A)|PPC_SRCB(sh)|(mb)<<6|(me)<<1
+#define PPC_RLWIMI_(a,s,sh,mb,me) PPC_RLWIMI(a,s,sh,mb,me)|PPC_RC
+#define PPC_RLWINM(a,s,sh,mb,me) \
+ PPC_MAJOR(21)|PPC_DEST(s)|PPC_SRCA(A)|PPC_SRCB(sh)|(mb)<<6|(me)<<1
+#define PPC_RLWINM_(a,s,sh,mb,me) PPC_RLWINM(a,s,sh,mb,me)|PPC_RC
+#define PPC_RLWNM(a,s,b,mb,me) \
+ PPC_MAJOR(23)|PPC_DEST(s)|PPC_SRCA(A)|PPC_SRCB(b)|(mb)<<6|(me)<<1
+#define PPC_RLWNM_(a,s,b,mb,me) PPC_RLWNM(a,s,b,mb,me)|PPC_RC
+
+#define PPC_SC() PPC_MAJOR(17)|2
+/* Major number = 63 Floating-point operations (not implemented for now) */
+
+/* Simplified Mnemonics */
+/* Fabricate immediate subtract out of add negative */
+#define PPC_SUBI(d,a,simm) PPC_ADDI(d,a,-(simm))
+#define PPC_SUBIS(d,a,simm) PPC_ADDIS(d,a,-(simm))
+#define PPC_SUBIC(d,a,simm) PPC_ADDIC(d,a,-(simm))
+#define PPC_SUBIC_(d,a,simm) PPC_ADDIC_(d,a,-(simm))
+/* Fabricate subtract out of subtract from */
+#define PPC_SUBC(d,b,a) PPC_SUBFC(d,a,b)
+#define PPC_SUBC_(d,b,a) PPC_SUBFC_(d,a,b)
+#define PPC_SUBCO(d,b,a) PPC_SUBFCO(d,a,b)
+#define PPC_SUBCO_(d,b,a) PPC_SUBFCO_(d,a,b)
+/* Messy compare bits omitted */
+/* Shift and rotate omitted */
+/* Branch coding omitted */
+#define PPC_CRSET(d) PPC_CREQV(d,d,d)
+#define PPC_CRCLR(d) PPC_CRXOR(d,d,d)
+#define PPC_CRMOVE(d,s) PPC_CROR(d,s,s)
+#define PPC_CRNOT(d,s) PPC_CRNOR(d,s,s)
+/* Trap menmonics omitted */
+/* Menmonics for user-accessible SPRs */
+#define PPC_MFXER(d) PPC_MFSPR(d,1)
+#define PPC_MFLR(d) PPC_MFSPR(d,8)
+#define PPC_MFCTR(d) PPC_MFSPR(d,9)
+#define PPC_MTXER(s) PPC_MTSPR(s,1)
+#define PPC_MTLR(s) PPC_MTSPR(s,8)
+#define PPC_MTCTR(s) PPC_MTSPR(s,9)
+/* Recommended mnemonics */
+#define PPC_NOP() PPC_ORI(0,0,0)
+#define PPC_LI(d,simm) PPC_ADDI(d,0,simm)
+#define PPC_LIS(d,simm) PPC_ADDIS(d,0,simm)
+#define PPC_LA(d,a,simm) PPC_ADDI(d,a,simm)
+#define PPC_MR(d,s) PPC_OR(d,s,s)
+#define PPC_NOT(d,s) PPC_NOR(d,s,s)
+#define PPC_MTCR(s) PPC_MTCRF(0xff,s)
+
+#endif /* PPCASM_H */
+
+/* 45678901234567890123456789012345678901234567890123456789012345678901234567 */
diff --git a/usr/src/lib/libresolv2/common/cylink/rand.c b/usr/src/lib/libresolv2/common/cylink/rand.c
new file mode 100644
index 0000000000..b2b6d6f85b
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/rand.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/****************************************************************************
+* FILENAME: rand.c PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT
+*
+* FILE STATUS:
+*
+* DESCRIPTION: Cryptographic Toolkit Functions File
+* Random Number Generation Files
+* PUBLIC FUNCTIONS:
+* int InitRand( u_int16_t SEED_bytes, uchar *SEED,
+* uchar *RVAL )
+* int GenRand( u_int16_t A_bytes, uchar *A,
+* uchar *RVAL )
+* int MyGenRand( u_int16_t A_bytes,
+* ord *A,
+* ord *RVAL )
+
+* Copyright (c) Cylink Corporation 1994. All rights reserved.
+*
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 10 Oct 94 KPZ Added Shamir Key Sharing functions
+* 10 Oct 94 KPZ Modified SHA functions for arbitrary message length
+* 12 Oct 94 KPZ Modified SHA functions (new standard)
+* 14 Oct 94 GKL Second version (big endian support)
+* 26 Oct 94 GKL (alignment for big endian support & ERR_ALLOC)
+*
+****************************************************************************/
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/****************************************************************************
+* INCLUDE FILES
+****************************************************************************/
+
+#include "port_before.h"
+
+/* system files */
+#ifdef VXD
+#include <vtoolsc.h>
+#else
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+/* program files */
+#ifdef VXD
+#include "tkvxd.h"
+#endif
+#include "cylink.h"
+#include "ctk_endian.h"
+#include "toolkit.h"
+#include "cencrint.h"
+#include "sha.h"
+
+#include "port_after.h"
+extern u_int16_t DataOrder;
+/****************************************************************************
+* PUBLIC FUNCTIONS DEFINITIONS
+****************************************************************************/
+
+/****************************************************************************
+* NAME: int InitRand( u_int16_t SEED_bytes,
+* uchar *SEED,
+* uchar *RVAL)
+*
+* DESCRIPTION: Initialize Random number Generator
+*
+* INPUTS:
+* PARAMETERS:
+* u_int16_t SEED_bytes Length of SEED
+* uchar *SEED Pointer to SEED value
+*
+* OUTPUT:
+* PARAMETERS:
+* uchar *RVAL Pointer to RVAL
+*
+* RETURN:
+* SUCCESS No errors
+* ERR_INPUT_LEN Invalid length for input data
+* ERR_DATA Generic data error
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+*
+****************************************************************************/
+
+int InitRand( u_int16_t SEED_bytes,
+ uchar *SEED,
+ uchar *RVAL )
+{
+ int status = SUCCESS; /* function return status */
+ if ( SEED_bytes == 0 )
+ {
+ status = ERR_INPUT_LEN;
+ return status;
+ }
+ if ( SEED_bytes < SHA_LENGTH )
+ {
+ status = ERR_DATA;
+ return status;
+ }
+ memcpy( RVAL, SEED, SHA_LENGTH);
+ return status;
+}
+
+
+/****************************************************************************
+* NAME: int GenRand( u_int16_t A_bytes,
+* uchar *A,
+* uchar *RVAL)
+*
+* DESCRIPTION: Generate random number.
+*
+* INPUTS:
+* PARAMETERS:
+* u_int16_t A_bytes Length of A
+* uchar *A Pointer to A value
+*
+* OUTPUT:
+* PARAMETERS:
+* uchar *RVAL Pointer to RVAL
+*
+* RETURN:
+* SUCCESS No errors
+* ERR_INPUT_LEN Invalid length for input data
+* ERR_DATA Generic data error
+* ERR_ALLOC Insufficient memory
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 14 Oct 94 GKL Second version (big endian support)
+* 26 Oct 94 GKL (alignment for big endian support & ERR_ALLOC)
+*
+****************************************************************************/
+int GenRand( u_int16_t A_bytes,
+ uchar *A,
+ uchar *RVAL )
+{
+ int status = SUCCESS; /* function return status */
+ ord *RVAL_a;
+ SHA_context hash_context; /* SHA context structure */
+ uchar M[DSS_LENGTH_MIN]; /* message block */
+ uchar hash_result[SHA_LENGTH];
+ u_int16_t i;
+ u_int16_t sha_block; /* number of sha blocks */
+ u_int16_t sha_rem; /* size of last block */
+ if ( A_bytes == 0 )
+ {
+ status = ERR_INPUT_LEN;
+ return status;
+ }
+ sha_block = (u_int16_t) (A_bytes / SHA_LENGTH); /* number of sha blocks */
+ sha_rem = (u_int16_t) (A_bytes % SHA_LENGTH); /* size of last block */
+ if ( sha_rem == 0 ) /* last block = SHA_LENGTH */
+ {
+ sha_block--;
+ }
+ for ( i = 0; i <= sha_block; i++)
+ {
+ SHAInit ( &hash_context );
+ memcpy( M, RVAL, SHA_LENGTH);
+ memset( M + SHA_LENGTH, 0, DSS_LENGTH_MIN - SHA_LENGTH );
+ if ( (status = SHAUpdate( &hash_context, M, DSS_LENGTH_MIN ))
+ != SUCCESS )
+ {
+ return status; /* error */
+ }
+ if ( (status=MySHAFinal (&hash_context, hash_result )) != SUCCESS )
+ {
+ return status; /* error */
+ }
+
+ BigSwap(RVAL, SHA_LENGTH);
+ ALIGN_CALLOC_COPY(RVAL, RVAL_a, SHA_LENGTH);
+ if ( status != SUCCESS )
+ {
+ ALIGN_COPY_FREE(RVAL_a,RVAL,SHA_LENGTH);
+ BigSwap(RVAL, SHA_LENGTH);
+ return status; /* ERR_ALLOC insufficient memory */
+ }
+ Sum_Q( RVAL_a, 1, SHA_LENGTH / sizeof(ord) );
+ Sum_big( RVAL_a, /* RVAL=RVAL+hash_result*/
+ (ord *)hash_result,
+ RVAL_a, SHA_LENGTH / sizeof(ord) );
+ ALIGN_COPY_FREE(RVAL_a,RVAL,SHA_LENGTH);
+ BigSwap(RVAL, SHA_LENGTH);
+#ifdef CTK_BIG_ENDIAN
+ ByteSwap(hash_result,SHA_LENGTH);
+#endif
+ BigSwap(hash_result, SHA_LENGTH);
+ if ( i == sha_block && sha_rem != 0 ) /* last block < SHA_LENGTH*/
+ {
+ memcpy( A + i * SHA_LENGTH, hash_result,
+ sha_rem * sizeof (uchar));
+ }
+ else /* last block = SHA_LENGTH*/
+ {
+ memcpy( A + i * SHA_LENGTH, hash_result,
+ SHA_LENGTH * sizeof (uchar));
+ }
+ }
+ return status;
+}
+
+
+
+/****************************************************************************
+* NAME: int MyGenRand( u_int16_t A_bytes,
+* ord *A,
+* ord *RVAL)
+*
+* DESCRIPTION: Generate random number.
+*
+* INPUTS:
+* PARAMETERS:
+* u_int16_t A_bytes Length of A
+* ord *A Pointer to A value
+*
+* OUTPUT:
+* PARAMETERS:
+* ord *RVAL Pointer to RVAL
+*
+* RETURN:
+* SUCCESS No errors
+* ERR_INPUT_LEN Invalid length for input data
+* ERR_DATA Generic data error
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 14 Oct 94 GKL Second version (big endian support)
+*
+****************************************************************************/
+int MyGenRand( u_int16_t A_bytes,
+ ord *A,
+ ord *RVAL )
+{
+ int status = SUCCESS; /* function return status */
+ SHA_context hash_context; /* SHA context structure */
+ uchar M[DSS_LENGTH_MIN]; /* message block */
+ uchar hash_result[SHA_LENGTH];
+ u_int16_t i;
+ u_int16_t sha_block; /* number of sha blocks */
+ u_int16_t sha_rem; /* size of last block */
+ if ( A_bytes == 0 )
+ {
+ status = ERR_INPUT_LEN;
+ return status;
+ }
+ sha_block = (u_int16_t) (A_bytes / SHA_LENGTH); /* number of sha blocks */
+ sha_rem = (u_int16_t) (A_bytes % SHA_LENGTH); /* size of last block */
+ if ( sha_rem == 0 ) /* last block = SHA_LENGTH */
+ {
+ sha_block--;
+ }
+ for ( i = 0; i <= sha_block; i++)
+ {
+ SHAInit ( &hash_context );
+ memcpy( M, RVAL, SHA_LENGTH);
+ memset( M + SHA_LENGTH, 0, DSS_LENGTH_MIN - SHA_LENGTH );
+ if ( (status = SHAUpdate( &hash_context, M, DSS_LENGTH_MIN ))
+ != SUCCESS )
+ {
+ return status; /* error */
+ }
+ if ( (status=MySHAFinal (&hash_context, hash_result )) != SUCCESS )
+ {
+ return status; /* error */
+ }
+#ifdef CTK_BIG_ENDIAN
+ ByteSwap((uchar*)RVAL,SHA_LENGTH);
+#endif
+ BigSwap((uchar*)RVAL, SHA_LENGTH);
+ Sum_Q(RVAL, 1,SHA_LENGTH / sizeof(ord));
+ Sum_big( RVAL, /* RVAL=RVAL+hash_result*/
+ (ord*)hash_result,
+ RVAL, SHA_LENGTH / sizeof(ord) );
+ BigSwap((uchar*)RVAL, SHA_LENGTH);
+#ifdef CTK_BIG_ENDIAN
+ ByteSwap((uchar*)RVAL,SHA_LENGTH);
+#endif
+ if ( i == sha_block && sha_rem != 0 ) /* last block < SHA_LENGTH*/
+ {
+ memcpy( &A[ i*SHA_LENGTH / sizeof(ord)], hash_result,
+ sha_rem * sizeof (uchar));
+ }
+ else /* last block = SHA_LENGTH*/
+ {
+ memcpy( &A[ i*SHA_LENGTH / sizeof(ord)], hash_result,
+ SHA_LENGTH * sizeof (uchar));
+ }
+ }
+ return status;
+}
+
diff --git a/usr/src/lib/libresolv2/common/cylink/sha.c b/usr/src/lib/libresolv2/common/cylink/sha.c
new file mode 100644
index 0000000000..bc67fcac79
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/sha.c
@@ -0,0 +1,706 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/****************************************************************************
+* FILENAME: cencrint.c PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT
+*
+* FILE STATUS:
+*
+* DESCRIPTION: Cryptographic Toolkit Internal Functions File
+*
+* PRIVATE FUNCTIONS:
+*
+*
+* void shaTransform( u_int32_t *state, uchar *block )
+* void SHAInitK( SHA_context *hash_context )
+* int MySHA( uchar *message, u_int16_t message_bytes,
+* uchar *hash_result )
+* int MySHAFinal( SHA_context *hash_context, uchar *hash_result )
+*
+*
+* Copyright (c) Cylink Corporation 1994. All rights reserved.
+*
+* REVISION HISTORY:
+*
+*
+* 24 Sep 94 KPZ Initial release
+* 10 Oct 94 KPZ Fixed bugs in Add(), DivRem()
+* 12 Oct 94 KPZ Modified shaTransform()
+* 14 Oct 94 GKL Second version (big endian support)
+* 26 Oct 94 GKL (alignment for big endian support & ERR_ALLOC)
+* 08 Nov 94 GKL Added input parameters check to Inverse
+* 08 Dec 94 GKL Added YIELD_context to Expo, VerPrime and GenPrime
+*
+****************************************************************************/
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/****************************************************************************
+* INCLUDE FILES
+****************************************************************************/
+
+#include "port_before.h"
+#include <sys/types.h>
+
+/* system files */
+#ifdef VXD
+#include <vtoolsc.h>
+#else
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#endif
+
+/* program files */
+#include "cylink.h"
+#include "ctk_endian.h"
+#include "toolkit.h"
+#include "cencrint.h"
+#include "sha.h"
+#include "port_after.h"
+extern u_int16_t DataOrder;
+
+/****************************************************************************
+* NAME: int SHA( uchar *message,
+* u_int16_t message_bytes,
+* uchar *hash_result )
+*
+* DESCRIPTION: Compute a Secure Hash Function.
+*
+* INPUTS:
+* PARAMETERS:
+* uchar *message Pointer to message
+* u_int16_t message_bytes Number of bytes in message
+* uchar *hash_result Pointer to message digest
+*
+* OUTPUT:
+* PARAMETERS:
+* uchar *hash_result Message digest
+*
+* RETURN:
+* SUCCESS No errors
+* ERR_INPUT_LEN Invalid length for input data(zero bytes)
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+*
+****************************************************************************/
+
+int SHA( uchar *message,
+ u_int16_t message_bytes,
+ uchar *hash_result )
+{
+ SHA_context hash_context; /* SHA context structure */
+ int status = SUCCESS; /* function return status */
+ if (message_bytes == 0 )
+ {
+ status = ERR_INPUT_LEN;
+ return status; /* invalid length for input data */
+ }
+ SHAInit ( &hash_context ); /* initialize SHA */
+ if ( (status = SHAUpdate( &hash_context, message, message_bytes ))
+ != SUCCESS )
+ {
+ return status; /* error */
+ }
+ if ((status=SHAFinal (&hash_context, hash_result)) != SUCCESS )
+ {
+ return status; /* error */
+ }
+
+ return status;
+}
+
+/****************************************************************************
+* PRIVATE FUNCTIONS DEFINITIONS
+****************************************************************************/
+
+
+/****************************************************************************
+* NAME: void shaTransform( u_int32_t *state,
+* uchar *block )
+*
+* DESCRIPTION: Perform SHS transformation.
+*
+* INPUTS:
+* PARAMETERS:
+* SHA_context *hash_context Pointer to SHA_context structure
+* OUTPUT:
+*
+* SHA_context *hash_context Pointer to SHA_context structure
+* (updated)
+* REVISION HISTORY:
+*
+* 24 sep 94 KPZ Initial release
+* 12 Oct 94 KPZ Modified buffers copy
+* 14 Oct 94 GKL Second version (big endian support)
+* 1 Sep 95 AAB Speedup the function
+****************************************************************************/
+
+ void shaTransform( u_int32_t *state,
+ const uchar *block )
+{
+ u_int32_t W[80];
+ u_int32_t A,B,C,D,E; /*,temp;*/
+ memcpy( W, block, 64); /*TKL00201*/
+#ifdef CTK_LITTLE_ENDIAN /*TKL00201*/
+ ByteSwap32( (uchar *)W, 64); /*TKL00201*/
+#endif /*TKL00201*/
+ /* Expand the 16 words into 80 words */
+ expand(16);expand(17);expand(18);expand(19);expand(20);expand(21);
+ expand(22);expand(23);expand(24);expand(25);expand(26);expand(27);
+ expand(28);expand(29);expand(30);expand(31);expand(32);expand(33);
+ expand(34);expand(35);expand(36);expand(37);expand(38);expand(39);
+ expand(40);expand(41);expand(42);expand(43);expand(44);expand(45);
+ expand(46);expand(47);expand(48);expand(49);expand(50);expand(51);
+ expand(52);expand(53);expand(54);expand(55);expand(56);expand(57);
+ expand(58);expand(59);expand(60);expand(61);expand(62);expand(63);
+ expand(64);expand(65);expand(66);expand(67);expand(68);expand(69);
+ expand(70);expand(71);expand(72);expand(73);expand(74);expand(75);
+ expand(76);expand(77);expand(78);expand(79);
+ /*Set up first buffer*/
+ A = state[0];
+ B = state[1];
+ C = state[2];
+ D = state[3];
+ E = state[4];
+
+ /* Heavy mangling, in 4 sub-rounds of 20 iterations each. */
+ subRound( A, B, C, D, E, f1, k1SHA, W[ 0] );
+ subRound( E, A, B, C, D, f1, k1SHA, W[ 1] );
+ subRound( D, E, A, B, C, f1, k1SHA, W[ 2] );
+ subRound( C, D, E, A, B, f1, k1SHA, W[ 3] );
+ subRound( B, C, D, E, A, f1, k1SHA, W[ 4] );
+ subRound( A, B, C, D, E, f1, k1SHA, W[ 5] );
+ subRound( E, A, B, C, D, f1, k1SHA, W[ 6] );
+ subRound( D, E, A, B, C, f1, k1SHA, W[ 7] );
+ subRound( C, D, E, A, B, f1, k1SHA, W[ 8] );
+ subRound( B, C, D, E, A, f1, k1SHA, W[ 9] );
+ subRound( A, B, C, D, E, f1, k1SHA, W[10] );
+ subRound( E, A, B, C, D, f1, k1SHA, W[11] );
+ subRound( D, E, A, B, C, f1, k1SHA, W[12] );
+ subRound( C, D, E, A, B, f1, k1SHA, W[13] );
+ subRound( B, C, D, E, A, f1, k1SHA, W[14] );
+ subRound( A, B, C, D, E, f1, k1SHA, W[15] );
+ subRound( E, A, B, C, D, f1, k1SHA, W[16] );
+ subRound( D, E, A, B, C, f1, k1SHA, W[17] );
+ subRound( C, D, E, A, B, f1, k1SHA, W[18] );
+ subRound( B, C, D, E, A, f1, k1SHA, W[19] );
+
+ subRound( A, B, C, D, E, f2, k2SHA, W[20]);
+ subRound( E, A, B, C, D, f2, k2SHA, W[21]);
+ subRound( D, E, A, B, C, f2, k2SHA, W[22]);
+ subRound( C, D, E, A, B, f2, k2SHA, W[23]);
+ subRound( B, C, D, E, A, f2, k2SHA, W[24]);
+ subRound( A, B, C, D, E, f2, k2SHA, W[25]);
+ subRound( E, A, B, C, D, f2, k2SHA, W[26]);
+ subRound( D, E, A, B, C, f2, k2SHA, W[27]);
+ subRound( C, D, E, A, B, f2, k2SHA, W[28]);
+ subRound( B, C, D, E, A, f2, k2SHA, W[29]);
+ subRound( A, B, C, D, E, f2, k2SHA, W[30]);
+ subRound( E, A, B, C, D, f2, k2SHA, W[31]);
+ subRound( D, E, A, B, C, f2, k2SHA, W[32]);
+ subRound( C, D, E, A, B, f2, k2SHA, W[33]);
+ subRound( B, C, D, E, A, f2, k2SHA, W[34]);
+ subRound( A, B, C, D, E, f2, k2SHA, W[35]);
+ subRound( E, A, B, C, D, f2, k2SHA, W[36]);
+ subRound( D, E, A, B, C, f2, k2SHA, W[37]);
+ subRound( C, D, E, A, B, f2, k2SHA, W[38]);
+ subRound( B, C, D, E, A, f2, k2SHA, W[39]);
+
+ subRound( A, B, C, D, E, f3, k3SHA, W[40]);
+ subRound( E, A, B, C, D, f3, k3SHA, W[41]);
+ subRound( D, E, A, B, C, f3, k3SHA, W[42]);
+ subRound( C, D, E, A, B, f3, k3SHA, W[43]);
+ subRound( B, C, D, E, A, f3, k3SHA, W[44]);
+ subRound( A, B, C, D, E, f3, k3SHA, W[45]);
+ subRound( E, A, B, C, D, f3, k3SHA, W[46]);
+ subRound( D, E, A, B, C, f3, k3SHA, W[47]);
+ subRound( C, D, E, A, B, f3, k3SHA, W[48]);
+ subRound( B, C, D, E, A, f3, k3SHA, W[49]);
+ subRound( A, B, C, D, E, f3, k3SHA, W[50]);
+ subRound( E, A, B, C, D, f3, k3SHA, W[51]);
+ subRound( D, E, A, B, C, f3, k3SHA, W[52]);
+ subRound( C, D, E, A, B, f3, k3SHA, W[53]);
+ subRound( B, C, D, E, A, f3, k3SHA, W[54]);
+ subRound( A, B, C, D, E, f3, k3SHA, W[55]);
+ subRound( E, A, B, C, D, f3, k3SHA, W[56]);
+ subRound( D, E, A, B, C, f3, k3SHA, W[57]);
+ subRound( C, D, E, A, B, f3, k3SHA, W[58]);
+ subRound( B, C, D, E, A, f3, k3SHA, W[59]);
+
+ subRound( A, B, C, D, E, f4, k4SHA, W[60]);
+ subRound( E, A, B, C, D, f4, k4SHA, W[61]);
+ subRound( D, E, A, B, C, f4, k4SHA, W[62]);
+ subRound( C, D, E, A, B, f4, k4SHA, W[63]);
+ subRound( B, C, D, E, A, f4, k4SHA, W[64]);
+ subRound( A, B, C, D, E, f4, k4SHA, W[65]);
+ subRound( E, A, B, C, D, f4, k4SHA, W[66]);
+ subRound( D, E, A, B, C, f4, k4SHA, W[67]);
+ subRound( C, D, E, A, B, f4, k4SHA, W[68]);
+ subRound( B, C, D, E, A, f4, k4SHA, W[69]);
+ subRound( A, B, C, D, E, f4, k4SHA, W[70]);
+ subRound( E, A, B, C, D, f4, k4SHA, W[71]);
+ subRound( D, E, A, B, C, f4, k4SHA, W[72]);
+ subRound( C, D, E, A, B, f4, k4SHA, W[73]);
+ subRound( B, C, D, E, A, f4, k4SHA, W[74]);
+ subRound( A, B, C, D, E, f4, k4SHA, W[75]);
+ subRound( E, A, B, C, D, f4, k4SHA, W[76]);
+ subRound( D, E, A, B, C, f4, k4SHA, W[77]);
+ subRound( C, D, E, A, B, f4, k4SHA, W[78]);
+ subRound( B, C, D, E, A, f4, k4SHA, W[79]);
+
+ state[0] += A;
+ state[1] += B;
+ state[2] += C;
+ state[3] += D;
+ state[4] += E;
+
+}
+
+
+
+
+/****************************************************************************
+* NAME: void SHAInitK( SHA_context *hash_context )
+*
+* DESCRIPTION: Initialize Secure Hash Function for generate
+* random number for DSS.
+*
+* INPUTS:
+* PARAMETERS:
+* SHA_context *hash_context SHA context structure
+* OUTPUT:
+* PARAMETERS:
+* SHA_context *hash_context Initialized SHA context structure
+*
+* RETURN:
+*
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 14 Oct 94 GKL Second version (big endian support)
+*
+****************************************************************************/
+
+void SHAInitK( SHA_context *hash_context )
+{
+/*Set up first buffer*/
+ /* on28 port: silence compiler warnings by changing 0x...L to 0x...U */
+ hash_context->state[0] = 0xEFCDAB89U;
+ hash_context->state[1] = 0x98BADCFEU;
+ hash_context->state[2] = 0x10325476U;
+ hash_context->state[3] = 0xC3D2E1F0U;
+ hash_context->state[4] = 0x67452301U;
+/*Initialise buffer */
+ memset( hash_context->buffer, 0, sizeof(hash_context->buffer));
+ memset( hash_context->count, 0, sizeof(hash_context->count));
+}
+
+
+/****************************************************************************
+* NAME: int MySHA( uchar *message,
+* u_int16_t message_bytes,
+* uchar *hash_result )
+*
+* DESCRIPTION: Compute a Secure Hash Function.
+*
+* INPUTS:
+* PARAMETERS:
+* uchar *message Pointer to message
+* u_int16_t message_bytes Number of bytes in message
+* uchar *hash_result Pointer to message digest
+*
+* OUTPUT:
+* PARAMETERS:
+* uchar *hash_result Message digest
+*
+* RETURN:
+* SUCCESS No errors
+* ERR_INPUT_LEN Invalid length for input data(zero bytes)
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+*
+****************************************************************************/
+int MySHA( uchar *message,
+ u_int16_t message_bytes,
+ uchar *hash_result )
+{
+ SHA_context hash_context; /* SHA context structure */
+ int status = SUCCESS; /* function return status */
+ if (message_bytes == 0 )
+ {
+ status = ERR_INPUT_LEN;
+ return status; /* invalid length for input data */
+ }
+ SHAInit ( &hash_context ); /* initialize SHA */
+#ifdef CTK_BIG_ENDIAN
+ ByteSwap(message,message_bytes);
+#endif
+ status = SHAUpdate( &hash_context, message, message_bytes );
+#ifdef CTK_BIG_ENDIAN
+ ByteSwap(message,message_bytes);
+#endif
+ if ( status != SUCCESS )
+ {
+ return status; /* error */
+ }
+ if ((status=MySHAFinal (&hash_context, hash_result)) != SUCCESS )
+ {
+ return status; /* error */
+ }
+ return status;
+}
+
+/****************************************************************************
+* NAME: int MySHAFinal( SHA_context *hash_context,
+* uchar *hash_result )
+* DESCRIPTION: Finalize Secure Hash Function
+*
+* INPUTS:
+* PARAMETERS:
+* SHA_context *hash_context SHA context structure
+* uchar *hash_result Pointer to hash
+* OUTPUT:
+* PARAMETERS:
+* uchar *hash_result Final value
+* RETURN:
+* SUCCESS No errors
+* ERR_INPUT_LEN Invalid length for input data (zero bytes)
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 10 Oct 94 KPZ Modified for arbitrary message length
+* 14 Oct 94 GKL Second version (big endian support)
+*
+****************************************************************************/
+ int MySHAFinal( SHA_context *hash_context,
+ uchar *hash_result )
+{
+ int status = SUCCESS; /* function return status */
+ uchar bits[8];
+ u_int16_t index, padLen;
+ u_int32_t ex;
+ uchar PADDING[64] = { /* padding string */
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ if ( hash_context->count[0] == 0 && hash_context->count[1] == 0 )
+ {
+ status= ERR_INPUT_LEN;
+ return status;
+ }
+ /* Save number of bits */
+ LongByte( &hash_context->count[1] , 4, bits );
+ LongByte( &hash_context->count[0] , 4, bits + 4 );
+ ByteSwap32( bits, 8 );
+ /* Pad out to 56 mod 64.*/
+ index = (u_int16_t )((hash_context->count[0] >> 3) & 0x3f);
+ padLen = (u_int16_t) ((index < 56) ? (56 - index) : (120 - index));
+ SHAUpdate( hash_context, PADDING, padLen );
+
+ /* Append length (before padding) */
+ SHAUpdate (hash_context, bits, 8);
+
+ /* Set order of hash_context */
+ ex = hash_context->state[0];
+ hash_context->state[0] = hash_context->state[4];
+ hash_context->state[4] = ex;
+ ex = hash_context->state[1];
+ hash_context->state[1] = hash_context->state[3];
+ hash_context->state[3] = ex;
+ /* Store state in digest */
+ memcpy(hash_result,hash_context->state,SHA_LENGTH);
+ /* Zeroize sensitive information.*/
+ memset( hash_context, 0, sizeof(hash_context) );
+#if defined ( ORD_16 ) && defined( CTK_BIG_ENDIAN )
+ WordSwap(hash_result,SHA_LENGTH);
+#endif
+ return status;
+}
+
+
+/****************************************************************************
+* NAME: int SHAUpdate( SHA_context *hash_context,
+* uchar *message,
+* u_int16_t message_bytes )
+* DESCRIPTION: Update Secure Hash Function
+*
+* INPUTS:
+* PARAMETERS:
+* SHA_context *hash_context SHA context structure
+* uchar *message Pointer to message
+* u_int16_t message_bytes Number of bytes
+* OUTPUT:
+* PARAMETERS:
+* SHA_context *hash_context Updated SHA context structure
+*
+* RETURN:
+* SUCCESS No errors
+* ERR_INPUT_LEN Invalid length for input data (zero bytes)
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 10 Oct 94 KPZ Modified for arbitrary message length
+*
+****************************************************************************/
+
+int SHAUpdate( SHA_context *hash_context,
+ const uchar *message,
+ u_int16_t message_bytes )
+
+{
+ int status = SUCCESS; /* function return status */
+ u_int16_t i, index, partLen;
+ if ( message_bytes == 0 )
+ {
+ status = ERR_INPUT_LEN; /*invalid length for input data (zero bytes)*/
+ return status;
+ }
+
+ /* Compute number of bytes mod 64 */
+ index = (u_int16_t)((hash_context->count[0] >> 3) & 0x3F);
+
+ /* Update number of bits */
+ if ( (hash_context->count[0] += ((u_int32_t )message_bytes << 3))
+ < ((u_int32_t )message_bytes << 3) )
+ {
+ hash_context->count[1]++;
+ }
+ hash_context->count[1] += ((u_int32_t )message_bytes >> 29);
+
+ partLen = (u_int16_t) (64 - index);
+ /* Transform as many times as possible.*/
+ if ( message_bytes >= partLen )
+ {
+ memcpy( &hash_context->buffer[index], message, partLen );
+ shaTransform( hash_context->state, hash_context->buffer );
+
+ for ( i = partLen; (u_int16_t)(i + 63) < message_bytes; i += 64 )
+ {
+ shaTransform ( hash_context->state, &message[i] );
+ }
+ index = 0;
+ }
+ else
+ {
+ i = 0;
+ }
+ /* Buffer remaining input */
+ memcpy( &hash_context->buffer[index], &message[i],
+ message_bytes - i );
+ return status;
+}
+
+
+/****************************************************************************
+* NAME: void SHAInit( SHA_context *hash_context )
+*
+* DESCRIPTION: Initialize Secure Hash Function
+*
+* INPUTS:
+* PARAMETERS:
+* SHA_context *hash_context SHA context structure
+* OUTPUT:
+* PARAMETERS:
+* SHA_context *hash_context Initialized SHA context structure
+*
+* RETURN:
+*
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+*
+****************************************************************************/
+
+void SHAInit( SHA_context *hash_context )
+{
+/*Set up first buffer*/
+ hash_context->state[0] = h0SHA;
+ hash_context->state[1] = h1SHA;
+ hash_context->state[2] = h2SHA;
+ hash_context->state[3] = h3SHA;
+ hash_context->state[4] = h4SHA;
+
+/* Initialise buffer */
+ memset( hash_context->buffer, 0, sizeof(hash_context->buffer));
+ /*Initialize bit count*/
+ hash_context->count[0] = hash_context->count[1] = 0;
+}
+
+/****************************************************************************
+* NAME: int SHAFinal( SHA_context *hash_context,
+* uchar *hash_result )
+* DESCRIPTION: Finalize Secure Hash Function
+*
+* INPUTS:
+* PARAMETERS:
+* SHA_context *hash_context SHA context structure
+* uchar *hash_result Pointer to hash
+* OUTPUT:
+* PARAMETERS:
+* uchar *hash_result Final value
+* RETURN:
+* SUCCESS No errors
+* ERR_INPUT_LEN Invalid length for input data (zero bytes)
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 10 Oct 94 KPZ Modified for arbitrary message length
+* 14 Oct 94 GKL Second version (big endian support)
+*
+****************************************************************************/
+
+
+int SHAFinal( SHA_context *hash_context,
+ uchar *hash_result )
+{
+ int status = SUCCESS; /* function return status */
+ status = MySHAFinal( hash_context, hash_result );
+#ifdef CTK_BIG_ENDIAN
+ if (status == SUCCESS)
+ {
+ ByteSwap(hash_result, SHA_LENGTH);
+ }
+#endif
+ if (DataOrder)
+ {
+ BigSwap(hash_result, SHA_LENGTH);
+ }
+ return status;
+}
+
+/****************************************************************************
+* NAME: int GetPasswordKeySHA( u_int16_t Password_bytes,
+* uchar *Password,
+* uchar *salt,
+* u_int16_t Count,
+* uchar *K,
+* uchar *IV )
+*
+* DESCRIPTION: Get Password-Based DES/KAPPA Key by SHA
+*
+* INPUTS:
+* PARAMETERS:
+* u_int16_t Password_bytes Number of bytes in password
+* uchar *Password Pointer to password
+* uchar *salt Pointer to salt(8-byte)
+* u_int16_t Count Number of iteration
+* OUTPUT:
+* PARAMETERS:
+* uchar *K Pointer to DES/KAPPA key
+* uchar *IV Pointer to initialization vector
+* RETURN:
+* SUCCESS No errors
+* ERR_COUNT Invalid iteration count (zero)
+* ERR_INPUT_LEN Invalid length for input data(zero bytes)
+* ERR_ALLOC Insufficient memory
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 26 Oct 94 GKL (ERR_ALLOC)
+*
+****************************************************************************/
+ int GetPasswordKeySHA( u_int16_t Password_bytes,
+ uchar *Password,
+ uchar *salt,
+ u_int16_t Count,
+ uchar *K,
+ uchar *IV )
+
+{
+ int status = SUCCESS; /* function return status */
+ uchar digest[SHA_LENGTH];
+ uchar *buf;
+ if ( Count == 0 ) /* invalid iteration count (zero) */
+ {
+ status = ERR_COUNT;
+ return status;
+ }
+ CALLOC(buf,uchar,Password_bytes + 8);
+ if ( status != SUCCESS )
+ {
+ return status; /* ERR_ALLOC insufficient memory */
+ }
+ if ( Password_bytes != 0 ) /* if number of bytes password non equals zero */
+ {
+ memcpy( buf, Password, Password_bytes );
+ }
+ memcpy( buf + Password_bytes, salt, 8);
+/* Compute message digest */
+ status = SHA( buf, (u_int16_t)(Password_bytes + 8), digest);
+ if (!DataOrder)
+ {
+ BigSwap(digest, SHA_LENGTH);
+ }
+
+ if ( status != SUCCESS )
+ {
+ free ( buf );
+ return status;
+ }
+ Count --; /* decrement Count */
+/* Count times compute message digest */
+ while ( Count != 0 )
+ {
+ if ( (status = SHA( digest, SHA_LENGTH, digest)) != SUCCESS )
+ {
+ free ( buf );
+ return status;
+ }
+ if (!DataOrder)
+ {
+ BigSwap(digest, SHA_LENGTH);
+ }
+ Count --;
+ }
+ memcpy( K, digest, 8 );
+ memcpy( IV, digest + SHA_LENGTH -8, 8 );
+ free ( buf );
+ return status;
+}
diff --git a/usr/src/lib/libresolv2/common/cylink/sha.h b/usr/src/lib/libresolv2/common/cylink/sha.h
new file mode 100644
index 0000000000..8442b3bfab
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/sha.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/****************************************************************************
+* FILENAME: sha.h PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT
+*
+* FILE STATUS:
+*
+* DESCRIPTION: Cryptographic Toolkit Internal Functions Header File
+*
+* USAGE: File should be included in Toolkit functions files
+*
+*
+* Copyright (c) Cylink Corporation 1994. All rights reserved.
+*
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+*
+****************************************************************************/
+#ifndef SHA_H
+#define SHA_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "cylink.h"
+
+#define SHS_BLOCKSIZE 64
+/*
+#define FSHA(x,y,z) ( ( x & y ) | ( ~x & z ) )
+#define GSHA(x,y,z) ( x ^ y ^ z )
+#define HSHA(x,y,z) ( ( x & y ) | ( x & z ) | ( y & z ) )
+#define ISHA(x,y,z) (x ^ y ^ z)
+*/
+/*#define f1(x,y,z) ( (x & y) | (~x & z) ) // Rounds 0-19 */
+#define f1(x,y,z) ( z ^ (x & (y ^ z) ) ) /* Rounds 0-19 */
+#define f2(x,y,z) ( x ^ y ^ z ) /* Rounds 20-39 */
+/*#define f3(x,y,z) ( (x & y) | (x & z) | (y & z) ) // Rounds 40-59 */
+#define f3(x,y,z) ( (x & y) | (z & (x | y) ) ) /* Rounds 40-59 */
+#define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */
+
+
+#define RotateLeft(x,n) (( x << n )|( x >> (32-n) ) ) /*Circular left shift operation*/
+
+/*
+ * Note: for on28 port, and to silence compiler warnings when the value is
+ * larger than or equal to 0x80000000, change constants to be U rather
+ * than L.
+ */
+
+/*SHS Constants */
+#define k1SHA 0x5a827999U
+#define k2SHA 0x6ed9eba1U
+#define k3SHA 0x8f1bbcdcU
+#define k4SHA 0xca62c1d6U
+
+/*SHS initial value */
+#define h0SHA 0x67452301U
+#define h1SHA 0xefcdab89U
+#define h2SHA 0x98badcfeU
+#define h3SHA 0x10325476U
+#define h4SHA 0xc3d2e1f0U
+
+/*The initial expanding function*/
+#define expand(count) \
+ {\
+ W[count] = W[count-3] ^ W[count-8] ^ W[count-14] ^ W[count-16];\
+ W[count] = RotateLeft( W[count], 1 );\
+ }
+
+/*New variant */
+#define subRound(a, b, c, d, e, f, k, data) \
+ ( e += RotateLeft(a,5) + f(b, c, d) + k + data, b = RotateLeft( b,30) )
+
+
+
+/*The four sub_rounds*/
+/*
+#define subR1(count) \
+ {\
+ temp=RotateLeft(A,5) + FSHA(B,C,D) + E +W[count] +k1SHA;\
+ E = D; \
+ D = C; \
+ C = RotateLeft(B,30); \
+ B = A; \
+ A = temp; \
+ }
+
+#define subR2(count) \
+ {\
+ temp=RotateLeft(A,5) + GSHA(B,C,D) + E +W[count] +k2SHA;\
+ E = D; \
+ D = C; \
+ C = RotateLeft(B,30);\
+ B = A; \
+ A = temp; \
+ }
+
+#define subR3(count) \
+ {\
+ temp=RotateLeft(A,5) + HSHA(B,C,D) + E +W[count] +k3SHA;\
+ E = D; \
+ D = C; \
+ C = RotateLeft(B,30);\
+ B = A; \
+ A = temp; \
+ }
+
+#define subR4(count) \
+ {\
+ temp=RotateLeft(A,5) + ISHA(B,C,D) + E + W[count] +k4SHA;\
+ E = D; \
+ D = C; \
+ C = RotateLeft(B,30);\
+ B = A; \
+ A = temp; \
+ }
+*/
+#endif /* SHA_H */
+
diff --git a/usr/src/lib/libresolv2/common/cylink/sizetest.c b/usr/src/lib/libresolv2/common/cylink/sizetest.c
new file mode 100644
index 0000000000..6fc9a9ee89
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/sizetest.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "bnsize00.h"
+
+#if BNSIZE16
+#error Using 16-bit math library
+#elif BNSIZE32
+#error Using 32-bit math library
+#elif BNSIZE64
+#error Using 64-bit math library
+#else
+#error No math library size defined
+#endif
diff --git a/usr/src/lib/libresolv2/common/cylink/swap.c b/usr/src/lib/libresolv2/common/cylink/swap.c
new file mode 100644
index 0000000000..6e4f33b967
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/swap.c
@@ -0,0 +1,218 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+
+/****************************************************************************
+* FILENAME: swap.c PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT
+*
+* FILE STATUS:
+*
+* DESCRIPTION: Byte and Word Swap functions
+*
+* PUBLIC FUNCTIONS:
+*
+*
+* PRIVATE FUNCTIONS:
+*
+* REVISION HISTORY:
+*
+* 14 Oct 94 GKL Initial release
+* 26 Oct 94 GKL (alignment for big endian support )
+*
+****************************************************************************/
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/****************************************************************************
+* INCLUDE FILES
+****************************************************************************/
+/* system files */
+
+#include "port_before.h"
+#ifdef VXD
+#include <vtoolsc.h>
+#else
+#include <stdlib.h>
+#include <string.h>
+#endif
+/* program files */
+#include "cylink.h"
+#include "ctk_endian.h"
+#include "toolkit.h"
+#include "port_after.h"
+
+u_int16_t DataOrder = 0;
+
+/*Reset bytes in long*/
+/*extern void ByteSwap32_asm( uchar *X, u_int16_t X_len );*/ /*kz*/
+
+/****************************************************************************
+* NAME: void ByteSwap32 (uchar *array,
+* u_int16_t X_len )
+*
+* DESCRIPTION: Perform byte reversal on an array of longword.
+*
+* INPUTS:
+* PARAMETERS:
+* uchar *X Pointer to array
+* u_int16_t X_len Number of bytes
+* OUTPUT:
+* uchar *X Pointer to array
+*
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 14 Oct 94 GKL Second version (big endian support)
+*
+****************************************************************************/
+
+
+void ByteSwap32( uchar *X, u_int16_t X_len )
+{
+ u_int16_t i; /*counter*/
+ uchar a; /*temporary char*/
+ for ( i = 0; i < X_len; i += 4)
+ {
+ a = X[i];
+ X[i] = X[i+3];
+ X[i+3] = a;
+ a = X[i+1];
+ X[i+1] = X[i+2];
+ X[i+2] = a;
+ }
+/*#endif*/ /*kz*/
+}
+
+
+/****************************************************************************
+* NAME: void ByteSwap (uchar *array,
+* u_int16_t X_len )
+*
+* DESCRIPTION: Perform byte reversal on an array of longword or shortword.
+*
+* INPUTS:
+* PARAMETERS:
+* uchar *X Pointer to array
+* u_int16_t X_len Number of bytes
+* OUTPUT:
+* uchar *X Pointer to array
+*
+* REVISION HISTORY:
+*
+* 24 Sep 94 KPZ Initial release
+* 14 Oct 94 GKL Second version (big endian support)
+*
+****************************************************************************/
+
+void ByteSwap( uchar *X,
+ u_int16_t X_len )
+{
+#ifdef ORD_16
+ u_int16_t i; /*counter*/
+ uchar a; /*tempriory char for revers*/
+ for ( i = 0; i < X_len; i += 2)
+ {
+ a = X[i];
+ X[i] = X[i+1];
+ X[i+1] = a;
+ }
+#endif
+#ifdef ORD_32
+ ByteSwap32(X,X_len);
+#endif
+}
+
+/*kz longbyte deleted */
+
+/****************************************************************************
+* NAME: void WordSwap (uchar *array,
+* u_int16_t X_len )
+*
+* DESCRIPTION: Perform short reversal on an array of longword.
+*
+* INPUTS:
+* PARAMETERS:
+* uchar *X Pointer to array
+* u_int16_t X_len Number of bytes
+* OUTPUT:
+* uchar *X Pointer to array
+*
+* REVISION HISTORY:
+*
+* 14 Oct 94 GKL Initial release
+*
+****************************************************************************/
+void WordSwap( uchar *X,
+ u_int16_t X_len )
+{
+ u_int16_t i; /*counter*/
+ u_int16_t a; /*tempriory u_int16_t*/
+
+ for ( i = 0; i < X_len; i += 4)
+ {
+ a = *(u_int16_t*)(&X[i]);
+ *(u_int16_t*)(&X[i])=*(u_int16_t*)(&X[i+2]);
+ *(u_int16_t*)(&X[i+2])=a;
+ }
+}
+
+void BigSwap( uchar *buffer,
+ u_int16_t bufferLength)
+{
+ uchar temp;
+ u_int16_t i;
+
+ for (i = 0; i < (u_int16_t)(bufferLength/2); i++)
+ {
+ temp = buffer[i];
+ buffer[i] = buffer[bufferLength - 1 - i];
+ buffer[bufferLength - 1 - i] = temp;
+ }
+}
+
+void SetDataOrder ( u_int16_t dataOrder)
+{
+ DataOrder = dataOrder;
+}
diff --git a/usr/src/lib/libresolv2/common/cylink/toolkit.h b/usr/src/lib/libresolv2/common/cylink/toolkit.h
new file mode 100644
index 0000000000..b9ba25ad57
--- /dev/null
+++ b/usr/src/lib/libresolv2/common/cylink/toolkit.h
@@ -0,0 +1,399 @@
+/*
+ * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Cylink Corporation © 1998
+ *
+ * This software is licensed by Cylink to the Internet Software Consortium to
+ * promote implementation of royalty free public key cryptography within IETF
+ * standards. Cylink wishes to expressly thank the contributions of Dr.
+ * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
+ * their contributions to Internet Security. In accordance with the terms of
+ * this license, ISC is authorized to distribute and sublicense this software
+ * for the practice of IETF standards.
+ *
+ * The software includes BigNum, written by Colin Plumb and licensed by Philip
+ * R. Zimmermann for royalty free use and distribution with Cylink's
+ * software. Use of BigNum as a stand alone product or component is
+ * specifically prohibited.
+ *
+ * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
+ * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
+ * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Cylink or its representatives shall not be liable for tort, indirect,
+ * special or consequential damages such as loss of profits or loss of
+ * goodwill from the use or inability to use the software for any purpose or
+ * for any reason whatsoever.
+ *
+ * EXPORT LAW: Export of the Foundations Suite may be subject to compliance
+ * with the rules and regulations promulgated from time to time by the Bureau
+ * of Export Administration, United States Department of Commerce, which
+ * restrict the export and re-export of certain products and technical data.
+ * If the export of the Foundations Suite is controlled under such rules and
+ * regulations, then the Foundations Suite shall not be exported or
+ * re-exported, directly or indirectly, (a) without all export or re-export
+ * licenses and governmental approvals required by any applicable laws, or (b)
+ * in violation of any applicable prohibition against the export or re-export
+ * of any part of the Foundations Suite. All export licenses for software
+ * containing the Foundations Suite are the sole responsibility of the licensee.
+ */
+
+/****************************************************************************
+* FILENAME: toolkit.h PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT
+*
+* FILE STATUS:
+*
+* DESCRIPTION: Cryptographic Toolkit Functions Header File
+*
+* USAGE: File should be included to use Toolkit Functions
+*
+*
+* Copyright (c) Cylink Corporation 1994. All rights reserved.
+*
+* REVISION HISTORY:
+*
+* 23 Aug 94 KPZ Initial release
+* 24 Sep 94 KPZ Added prototypes of Toolkit functions
+* 14 Oct 94 GKL Second version (big endian support)
+* 08 Dec 94 GKL Added YIELD_context to GenDSSParameters
+*
+****************************************************************************/
+
+#ifndef TOOLKIT_H /* Prevent multiple inclusions of same header file */
+#define TOOLKIT_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* Error types */
+
+#define SUCCESS 0 /* no errors */
+#define ERR_DATA -1 /* generic data error */
+#define ERR_ALLOC -2 /* insufficient memory */
+#define ERR_INPUT_LEN -3 /* invalid length for input data (zero bytes) */
+#define ERR_DSS_LEN -4 /* invalid length for dss_p */
+#define ERR_DH_LEN -5 /* invalid length for DH_modulus */
+#define ERR_BLOCK_LEN -7 /* invalid length for input block for ECB/CBC */
+#define ERR_HASH_LEN -8 /* invalid length for hash_result */
+#define ERR_MODE -9 /* invalid value of encryption mode */
+#define ERR_NUMBER -10 /* invalid number of testings (zero) */
+#define ERR_POSITION -11 /* invalid value of triplet_position */
+#define ERR_COUNT -12 /* invalid iteration count (zero) */
+#define ERR_SIGNATURE -21 /* signature is not valid */
+#define ERR_PRIME -22 /* number is not prime */
+#define ERR_WEAK -23 /* weak key */
+#define ERR_INPUT_VALUE -24 /* invalid input value */
+/* additional error types for CEPA */
+#define ERR_KEY_LENGTH -25 /* invalid value of key length */
+#define ERR_ROUNDS -26 /* invalid value of rounds number */
+#define ERR_CANCEL -30 /* canceled by user */
+#define ERR_MODULUS_ZERO -31 /* invalid modulo */
+#define ERR_UNSUPPORTED -40 /* unsupported crypto method */
+#define ERR_OP_CODE -41 /*invalid operation code*/
+
+
+
+/* Lengths of variables */
+#define DH_LENGTH_MIN 64 /* 512-bit minimal length for DH functions */
+#define DSS_LENGTH_MIN 64 /* 512-bit minimal length for DSS functions */
+#define DSS_LENGTH_MAX 128 /* 1024-bit maximal length for DSS functions */
+#define SHA_LENGTH 20 /* 160-bit length for SHA hash result */
+
+/* Number of random bases for Miller test */
+#define TEST_COUNT 40
+
+#define LITTLE_ORDER 0
+#define BIG_ORDER 1
+
+/* Key lengths */ /* add to toolkit.h */
+#define KEY_40BIT 40 /* 40-bit key */
+#define KEY_64BIT 64 /* 64-bit key */
+#define KEY_128BIT 128 /* 128-bit key */
+#define CEPA_MAX_ROUNDS 12
+
+/* Operation codes for MultiPrecArithm() */
+#define EXPO 0x21
+#define MUL 0x22
+/*#define ADD 0x23*/
+
+/****************************************************************************
+* INCLUDE FILES
+****************************************************************************/
+
+/* system files */
+#include "cylink.h"
+#include "ctk_endian.h"
+/* callback function */
+#ifdef VXD
+typedef int (* YIELD_PROC)( void );
+#else
+typedef int (* YIELD_PROC)(int ); /*TKL00601*/
+#endif
+
+typedef struct { /*TKL00601*/
+ YIELD_PROC yield_proc;
+ void * handle; /* Application specific information */
+}YIELD_context;
+
+
+/* Secure Hash Algorithm structure */
+typedef struct
+{
+ u_int32_t state[ 5 ]; /* state */
+ u_int32_t count[ 2 ]; /* number of bits */
+ uchar buffer[ 64 ]; /* input buffer */
+} SHA_context;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/* Copy Cylink DSS Common Parameters */ /*TKL01201*/
+ int GetDSSPQG(u_int16_t dss_p_bytes,
+ uchar *dss_p,
+ uchar *dss_q,
+ uchar *dss_g);
+
+/* Compute a Secure Hash Function */
+ int SHA( uchar *message, u_int16_t message_bytes,
+ uchar *hash_result );
+/* Initialize Secure Hash Function */
+ void SHAInit( SHA_context *hash_context );
+
+/* Update Secure Hash Function */
+ int SHAUpdate( SHA_context *hash_context,
+ const uchar *message,
+ u_int16_t message_bytes );
+/* Finalize Secure Hash Function */
+ int SHAFinal( SHA_context *hash_context,
+ uchar *hash_result );
+/* Compute a DSS Signature */
+ int GenDSSSignature( u_int16_t dss_p_bytes, uchar *dss_p,
+ uchar *dss_q, uchar *dss_g,
+ uchar *dss_x, uchar *dss_k,
+ uchar *r, uchar *s,
+ uchar *hash_result );
+/* Verify a DSS Signature */
+ int VerDSSSignature( u_int16_t dss_p_bytes, uchar *dss_p,
+ uchar *dss_q, uchar *dss_g,
+ uchar *dss_y, uchar *r,
+ uchar *s, uchar *hash_result);
+/* Initialize Random number Generator */
+ int InitRand( u_int16_t SEED_bytes, uchar *SEED,
+ uchar *RVAL );
+/* Generate random number */
+ int GenRand( u_int16_t A_bytes, uchar *A,
+ uchar *RVAL );
+/* Compute DSS public/secret number pair */
+ int GenDSSKey( u_int16_t dss_p_bytes, uchar *dss_p,
+ uchar *dss_q, uchar *dss_g,
+ uchar *dss_x, uchar *dss_y,
+ uchar *XKEY );
+/* Generate secret number */
+ int GenDSSNumber( uchar *dss_k, uchar *dss_q,
+ uchar *KKEY );
+
+/* Compute a Diffie-Hellman Shared number */
+ int GetDHSharedNumber( u_int16_t DH_modulus_bytes, uchar *DH_secret,
+ uchar *DH_public, uchar *DH_shared,
+ uchar *DH_modulus );
+/* Set Key by Diffie_Hellman shared number */
+ int SetDESKAPPAKey( u_int16_t DH_modulus_bytes, uchar *DH_shared,
+ uchar *K );
+/* Expand DES key */
+ void DESKeyExpand( uchar *key, uchar *K1 );
+
+/* Encrypt a block of data with single DES */
+ int DESEncrypt( uchar *des_iv, uchar *des_key,
+ u_int16_t des_mode, uchar *input_array,
+ uchar *output_array, u_int16_t input_array_bytes );
+
+/* Decrypt a block of data with single DES */
+ int DESDecrypt( uchar *des_iv, uchar *des_key,
+ u_int16_t des_mode, uchar *data_array,
+ u_int16_t data_array_bytes );
+
+/* One-Time-Pad Signature with a Diffie-Hellman shared number */
+ int DHOneTimePad( u_int16_t DH_modulus_bytes, uchar *DH_shared,
+ uchar *X, uchar *Y );
+
+/* Compute a Diffie-Hellman pair */
+ int GenDHPair( u_int16_t DH_modulus_bytes, uchar *DH_secret,
+ uchar *DH_public, uchar *DH_base,
+ uchar *DH_modulus, uchar *RVAL );
+
+ int GetPasswordKeySHA( u_int16_t Password_bytes, uchar *Password,
+ uchar *salt, u_int16_t Count,
+ uchar *K, uchar *IV );
+
+/* Generate DSS Common Parameters */
+ int GenDSSParameters( u_int16_t dss_p_bytes, uchar *dss_p,
+ uchar *dss_q, uchar *dss_g,
+ uchar *RVAL, YIELD_context *yield_cont ); /*TKL00701*/
+
+/* Produce a Shamir Key-Sharing Triplet for Secret Number */
+int GenShamirTriplet( u_int16_t SecretNumber_bytes, uchar *SecretNumber,
+ uchar *first_value, uchar *second_value,
+ uchar *third_value, uchar *RVAL );
+
+/* Reconstract a Secret Number from Shamir Key-Sharing Duplex */
+int GetNumberShamirDuplex( u_int16_t SecretNumber_bytes,
+ uchar *value_A,
+ u_int16_t A_position, uchar *value_B,
+ u_int16_t B_position,
+ uchar *SecretNumber );
+int SFDHEncrypt( u_int16_t DH_modulus_bytes,
+ uchar *DH_modulus,
+ uchar *DH_base,
+ uchar *DH_public,
+ uchar *DH_random_public,
+ uchar *DH_shared,
+ uchar *RVAL );
+int SFDHDecrypt( u_int16_t DH_modulus_bytes,
+ uchar *DH_modulus,
+ uchar *DH_secret,
+ uchar *DH_random_public,
+ uchar *DH_shared );
+/* Check DES key weakness */
+int CheckDESKeyWeakness( uchar *key );
+
+int SetCipherKey( u_int16_t DH_shared_bytes,
+ uchar *DH_shared,
+ uchar *Key,
+ u_int16_t cryptoMethod );
+/* Non-Pipelined Triple DES encrypt*/
+int TDESEncrypt( uchar *des_iv,
+ uchar *des_key1,uchar *des_key2, uchar *des_key3,
+ u_int16_t des_mode,
+ uchar *input_array,
+ uchar *output_array,
+ u_int16_t input_array_bytes );
+/* Non-Pipelined Triple DES decrypt*/
+int TDESDecrypt( uchar *des_iv,
+ uchar *des_key1,uchar *des_key2, uchar *des_key3,
+ u_int16_t des_mode,
+ uchar *data_array,
+ u_int16_t data_array_bytes );
+/*Pipeline Triple DES encrypt*/
+int PTDESEncrypt( uchar *iv1, uchar *iv2, uchar *iv3,
+ uchar *des_key1,uchar *des_key2, uchar *des_key3,
+ u_int16_t des_mode,
+ uchar *input_array,
+ uchar *output_array,
+ u_int16_t input_array_bytes );
+/*Pipeline Triple DES decrypt*/
+int PTDESDecrypt( uchar *iv1, uchar *iv2, uchar *iv3,
+ uchar *des_key1,uchar *des_key2, uchar *des_key3,
+ u_int16_t des_mode,
+ uchar *data_array,
+ u_int16_t input_array_bytes );
+ int PCBC1Encrypt( uchar *iv1, uchar *iv2, uchar *iv3,
+ uchar *des_key1,uchar *des_key2, uchar *des_key3,
+ uchar *msg1,uchar *msg2, uchar *msg3,
+ uchar *out1,uchar *out2, uchar *out3,
+ u_int16_t input_array_bytes );
+ int PCBC1Decrypt( uchar *iv1, uchar *iv2, uchar *iv3,
+ uchar *des_key1,uchar *des_key2, uchar *des_key3,
+ uchar *out1,uchar *out2, uchar *out3,
+ u_int16_t input_array_bytes );
+
+/*CEPA enc/dec */
+int CepaKeyExpand( uchar *key,
+ u_int16_t key_length,
+ u_int16_t number_of_rounds,
+ uchar *expanded_key );
+
+int CepaCsp( u_int16_t key_length,
+ uchar *csp);
+
+int CepaEncrypt( uchar *iv,
+ uchar *key,
+ u_int16_t mode,
+ uchar *csp,
+ u_int16_t r,
+ uchar *input_array,
+ uchar *output_array,
+ u_int16_t input_array_bytes );
+
+int CepaDecrypt( uchar *iv,
+ uchar *key,
+ u_int16_t mode,
+ uchar *csp,
+ u_int16_t r,
+ uchar *data_array,
+ u_int16_t data_array_bytes );
+void BigNumInit(void);
+void SetDataOrder ( u_int16_t dataOrder);
+
+int GetDHSecretShared( u_int16_t DH_modulus_bytes, u_int16_t DH_secret_bytes, uchar *DH_secret,
+ uchar *DH_public, uchar *DH_shared,
+ uchar *DH_modulus);
+int GenDHKey( u_int16_t DH_modulus_bytes, u_int16_t DH_secret_bytes, uchar *DH_secret,
+ uchar *DH_public, uchar *DH_base,
+ uchar *DH_modulus, uchar *RVAL );
+int SFDHInitiate( u_int16_t DH_modulus_bytes, u_int16_t DH_secret_bytes,
+ uchar *DH_modulus, uchar *DH_base,
+ uchar *DH_public, uchar *DH_random_public,
+ uchar *DH_shared, uchar *RVAL );
+int SFDHComplete( u_int16_t DH_modulus_bytes, u_int16_t DH_secret_bytes,
+ uchar *DH_modulus,
+ uchar *DH_secret, uchar *DH_random_public,
+ uchar *DH_shared );
+
+int SplitKey( u_int16_t Secretnumber_bytes, uchar *SecretNumber,
+ uchar *first_value, uchar *second_value,
+ uchar *third_value, uchar *RVAL );
+int UnsplitKey( u_int16_t Secretnumber_bytes, uchar *value_A,
+ u_int16_t A_position, uchar *value_B,
+ u_int16_t B_position, uchar *SecretNumber );
+int SAFERKeyExpand( uchar *key, u_int16_t key_length,
+ uchar *expanded_key );
+int SAFEREncrypt( uchar *iv, uchar *key, u_int16_t mode, u_int16_t key_length,
+ uchar *input_array, uchar *output_array, u_int16_t input_array_bytes );
+int SAFERDecrypt( uchar *iv, uchar *key, u_int16_t mode, u_int16_t r_length,
+ uchar *data_array, u_int16_t data_array_bytes );
+
+
+ void ByteSwap( uchar *X, u_int16_t X_len);
+ void ByteSwap32( uchar *X, u_int16_t X_len);
+ void WordSwap( uchar *X, u_int16_t X_len);
+ void BigSwap( uchar *buffer, u_int16_t bufferLength);
+ int Sum_big (ord *X, ord *Y, ord *Z, u_int16_t len_X);
+ int Sum_Q(ord *X, u_int16_t src, u_int16_t len_X);
+ void LShiftL_big( ord *X, u_int32_t len_X, u_int32_t n_bit );
+ int Sub_big (ord *X, ord *Y, ord *Z, u_int16_t len_X);
+ int DivRem( u_int16_t X_bytes, ord *X, u_int16_t P_bytes, ord *P,
+ ord *Z, ord *D);
+ int SteinGCD (ord *m, ord *n, u_int16_t len);
+ int Add( ord *X, ord *Y, u_int16_t P_len, ord *P);
+ int Inverse(u_int16_t X_bytes, ord *X, u_int16_t P_bytes, ord *P,
+ ord *Z);
+ int DoubleExpo(u_int16_t X1_bytes, ord *X1, u_int16_t Y1_bytes,
+ ord *Y1, u_int16_t X2_bytes, ord *X2,
+ u_int16_t Y2_bytes, ord *Y2, u_int16_t P_bytes,
+ ord *P, ord *Z);
+ int Sum (ord *X, ord *Y, u_int16_t len_X);
+ void Mul_big_1( ord X, ord *Y, ord *XY, u_int16_t ly);
+ int Mul( u_int16_t X_bytes, ord *X, u_int16_t Y_bytes, ord *Y,
+ u_int16_t P_bytes, ord *P, ord *Z );
+
+ int Square(u_int16_t X_bytes, ord *X, u_int16_t P_bytes, ord *P,
+ ord *Z);
+
+ int PartReduct(u_int16_t X_bytes, ord *X, u_int16_t P_bytes, ord *P,
+ ord *Z);
+ int Expo(u_int16_t X_bytes, ord *X, u_int16_t Y_bytes, ord *Y,
+ u_int16_t P_bytes, ord *P, ord *Z);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* TOOLKIT_H */
+