diff options
| author | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
|---|---|---|
| committer | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
| commit | 7c478bd95313f5f23a4c958a745db2134aa03244 (patch) | |
| tree | c871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/libresolv2/common/cylink | |
| download | illumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz | |
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/libresolv2/common/cylink')
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 */ + |
