--- /dev/null
+/* $Header$ */
+
+#define have_subdirs
+SUBDIRS = lib
+
+all::
+
+gdss_test: lib/libgdss.a
+ $(CC) $(CFLAGS) -I./include -o $@ $@.c lib/libgdss.a $(LLIB) -lkrb -ldes -lhesiod $(OSLIBS)
+
+clean::
+ rm -f gdss_test
+
--- /dev/null
+/*
+ * Test program for GDSS.
+ *
+ */
+
+#include <krb.h>
+#include <gdss.h>
+
+char TestMessage[] = "This is a test message. This is only a test.";
+
+unsigned char OldSig[] = { 0x44, 0x6a, 0x69, 0x73, 0x20, 0x21, 0x20,
+0x21, 0x41, 0x54, 0x48, 0x45, 0x4e, 0x41, 0x2e, 0x4d, 0x49, 0x54,
+0x2e, 0x45, 0x44, 0x55, 0x20, 0x21, 0x2a, 0x13, 0x28, 0x97, 0x2b,
+0x47, 0xad, 0xcc, 0xb0, 0xe1, 0x11, 0x71, 0xc1, 0x48, 0xa5, 0xd1,
+0x1e, 0xa6, 0x20, 0x20, 0x97, 0x3d, 0xcb, 0x73, 0xf3, 0x63, 0x52,
+0x3b, 0x2c, 0x7f, 0x05, 0x30, 0xe0, 0x03, 0x75, 0x9e, 0x0c, 0xa7,
+0xdc, 0xf2, 0x41, 0x89, 0x95, 0xb1, 0x4e, 0xe1, 0x11, 0xba, 0x05,
+0x39, 0xd1, 0xf1, 0x74, 0x96, 0x7f, 0xa2, 0xaf, 0x40, 0xc3, 0x70,
+0x5a, 0x39, 0xa0, 0xce, 0x8a, 0xfd, 0x1c, 0xed, 0xcc, 0x00 };
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+ char Signature[1000];
+ int status;
+ SigInfo aSigInfo;
+
+ printf("Performing Test Signature....");
+ status = GDSS_Sign(TestMessage, strlen(TestMessage), Signature);
+ if (status != GDSS_SUCCESS) {
+ printf("FAILED\n");
+ if (status == GDSS_E_TIMEDOUT)
+ printf("Signature Server Request timed out (is it running?)!\n");
+ else printf("GDSS_Sign Error number: %d\n", status);
+ exit (1);
+ } else {
+ printf("SUCCESS\n");
+ }
+
+ memset(&aSigInfo, 0, sizeof(aSigInfo));
+
+ printf("Attempting to Verify signature...");
+ status = GDSS_Verify(TestMessage, strlen(TestMessage), Signature,
+ &aSigInfo);
+ if (status != GDSS_SUCCESS) {
+ printf("FAILED\n");
+ printf("GDSS_Verify Error number: %d\n", status);
+ exit (1);
+ } else {
+ printf("SUCCESS\n");
+ printf("Signature by: %s.%s@%s at %s\n",
+ aSigInfo.pname, aSigInfo.pinst, aSigInfo.prealm,
+ ctime(&aSigInfo.timestamp));
+ }
+
+ printf("Purposely damaging data...test: ");
+
+ TestMessage[0] = 'S';
+
+ status = GDSS_Verify(TestMessage, strlen(TestMessage), Signature,
+ &aSigInfo);
+ if (status == GDSS_SUCCESS) {
+ printf("FAILED\n");
+ printf("Signature succeeded when it should *not* have!\n");
+ exit (1);
+ } else if (status != GDSS_E_BADSIG) {
+ printf("FAILED\n");
+ printf("Signature failed, but returned error code %d\n", status);
+ exit (1);
+ } else {
+ printf("PASSED\n");
+ }
+
+ printf("Fixing data...\n");
+
+ TestMessage[0] = 'T';
+
+ printf("Attempting to Verify signature...");
+ status = GDSS_Verify(TestMessage, strlen(TestMessage), Signature,
+ &aSigInfo);
+ if (status != GDSS_SUCCESS) {
+ printf("FAILED\n");
+ printf("GDSS_Verify Error number: %d\n", status);
+ exit (1);
+ } else {
+ printf("SUCCESS\n");
+ printf("Signature by: %s.%s@%s at %s\n",
+ aSigInfo.pname, aSigInfo.pinst, aSigInfo.prealm,
+ ctime(&aSigInfo.timestamp));
+ }
+
+ printf("Testing Builtin Signature...\n");
+
+ printf("Attempting to Verify signature...");
+
+ status = GDSS_Verify(TestMessage, strlen(TestMessage), OldSig,
+ &aSigInfo);
+ if (status != GDSS_SUCCESS) {
+ printf("FAILED\n");
+ printf("GDSS_Verify Error number: %d\n", status);
+ exit (1);
+ } else {
+ printf("SUCCESS\n");
+ printf("Signature by: %s.%s@%s at %s\n",
+ aSigInfo.pname, aSigInfo.pinst, aSigInfo.prealm,
+ ctime(&aSigInfo.timestamp));
+ }
+
+ printf("All Test Passed.\n");
+ exit (0);
+}
+
+
+
+
+
+
--- /dev/null
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+#define assert(x) ((x)?0:dumpcore("x",__FILE__,__LINE__))
+
+#define PRINT_LEVEL1
+#define DigitLim 50
+
+extern unsigned BnnDyCanon();
+extern void BnnDyRaise();
+extern void BnnMPInit();
+extern void BnnModularProduct();
+
+extern BigNum muB();
+#define assert(x) ((x)?0:dumpcore("x",__FILE__,__LINE__))
+#define BnnCfMultiplyDigit(p,pl,m,ml,d) assert(BnnMultiplyDigit(p,pl,m,ml,d) == 0)
--- /dev/null
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+/* BigN.h - Types and structures for clients of BigNum */
+
+
+
+ /******** representation of a bignum ******/
+/*
+** <--------------------------- nl ---------------------------->
+** | Least Most |
+** |Significant| | | |Significant|
+** |BigNumDigit| | | |BigNumDigit|
+** |___________|___________|___________|___________|___________|
+** ^ (sometimes
+** | is zero)
+** nn
+*/
+
+/* signals BigNum.h already included */
+#define BIGNUM
+
+ /*************** sizes ********************/
+
+#define BN_BYTE_SIZE 8
+#define BN_WORD_SIZE (sizeof (int) * BN_BYTE_SIZE)
+#define BN_DIGIT_SIZE (sizeof (BigNumDigit) * BN_BYTE_SIZE)
+
+/* notes: */
+/* BN_BYTE_SIZE: number of bits in a byte */
+/* BN_WORD_SIZE: number of bits in an "int" in the target language */
+/* BN_DIGIT_SIZE: number of bits in a digit of a BigNum */
+
+
+ /****** results of compare functions ******/
+
+ /* Note: we don't use "enum" to interface with Modula2+, Lisp, ... */
+#define BN_LT -1
+#define BN_EQ 0
+#define BN_GT 1
+
+
+ /*************** boolean ******************/
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+typedef short Boolean;
+
+
+ /* if DIGITon16BITS is defined, a single digit is on 16 bits */
+ /* otherwise (by default) a single digit is on 32 bits *****/
+
+#ifdef DIGITon16BITS
+typedef unsigned short BigNumDigit;
+#else
+typedef unsigned int BigNumDigit;
+#endif
+
+
+ /* bignum types: digits, big numbers, carries ... */
+
+typedef BigNumDigit * BigNum; /* A big number is a digit pointer */
+typedef unsigned short BigNumCarry; /* Either 0 or 1 */
+typedef unsigned long BigNumProduct; /* The product of two digits */
+typedef unsigned long BigNumLength; /* The length of a bignum */
+typedef short BigNumCmp; /* result of comparison */
+
+/*\f*/
+
+
+ /************ functions of bn.c ***********/
+
+extern void BnnInit ();
+extern void BnnClose ();
+
+extern Boolean BnnIsZero ();
+extern BigNumCarry BnnMultiply ();
+extern void BnnDivide ();
+extern BigNumCmp BnnCompare ();
+
+
+ /*********** functions of KerN.c **********/
+
+extern void BnnSetToZero ();
+extern void BnnAssign ();
+extern void BnnSetDigit ();
+extern BigNumDigit BnnGetDigit ();
+extern BigNumLength BnnNumDigits ();
+extern BigNumDigit BnnNumLeadingZeroBitsInDigit ();
+extern Boolean BnnDoesDigitFitInWord ();
+extern Boolean BnnIsDigitZero ();
+extern Boolean BnnIsDigitNormalized ();
+extern Boolean BnnIsDigitOdd ();
+extern BigNumCmp BnnCompareDigits ();
+extern void BnnComplement ();
+extern void BnnAndDigits ();
+extern void BnnOrDigits ();
+extern void BnnXorDigits ();
+extern BigNumDigit BnnShiftLeft ();
+extern BigNumDigit BnnShiftRight ();
+extern BigNumCarry BnnAddCarry ();
+extern BigNumCarry BnnAdd ();
+extern BigNumCarry BnnSubtractBorrow ();
+extern BigNumCarry BnnSubtract ();
+extern BigNumCarry BnnMultiplyDigit ();
+extern BigNumDigit BnnDivideDigit ();
+
+/*\f*/
+
+ /* some functions can be written with macro-procedures */
+
+
+#ifndef BNNMACROS_OFF
+/* the functions BnnIsZero and BnnCompareDigits are not macro procedures
+since they use parameters twice, and that can produce some bugs if
+you pass a parameter like x++, the increment will be executed twice ! */
+#define BnnSetToZero(nn,nl) memset (nn, 0, (nl)*BN_DIGIT_SIZE/BN_BYTE_SIZE)
+#define BnnSetDigit(nn,d) (*(nn) = (d))
+#define BnnGetDigit(nn) ((unsigned)(*(nn)))
+#define BnnDoesDigitFitInWord(d) (BN_DIGIT_SIZE > BN_WORD_SIZE ? ((d) >= 1 << BN_WORD_SIZE ? FALSE : TRUE) : TRUE)
+#define BnnIsDigitZero(d) ((d) == 0)
+#define BnnIsDigitNormalized(d) ((d) & (1 << (BN_DIGIT_SIZE - 1)) ? TRUE : FALSE)
+#define BnnIsDigitOdd(d) ((d) & 1 ? TRUE : FALSE)
+#define BnnAndDigits(nn, d) (*(nn) &= (d))
+#define BnnOrDigits(nn, d) (*(nn) |= (d))
+#define BnnXorDigits(nn, d) (*(nn) ^= (d))
+
+#endif
+
+
--- /dev/null
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+#ifndef SPHINX_BIGRSA
+#define SPHINX_BIGRSA
+
+/* DigitLim is general buffer allocation size */
+
+#ifndef DigitLim
+#define DigitLim 50
+#endif
+
+#define PrimeSize 20
+#define MaxPrimeBits PrimeSize*BN_DIGIT_SIZE-2
+#define MaxModulusBits 2*MaxPrimeBits-8
+
+typedef struct {
+ int nl,el,pl,ql,dpl,dql;
+
+ BigNumDigit n[PrimeSize*2];
+ BigNumDigit e[PrimeSize*2];
+ BigNumDigit nINV[PrimeSize*2];
+ BigNumDigit beta2n[PrimeSize*2];
+
+ BigNumDigit p[PrimeSize];
+ BigNumDigit q[PrimeSize];
+ BigNumDigit dp[PrimeSize];
+ BigNumDigit dq[PrimeSize];
+ BigNumDigit cr[PrimeSize];
+ BigNumDigit pINV[PrimeSize];
+ BigNumDigit qINV[PrimeSize];
+ BigNumDigit beta3p[PrimeSize];
+ BigNumDigit beta3q[PrimeSize];
+ BigNumDigit beta2p[PrimeSize];
+ } RSAKeyStorage ;
+
+typedef struct {
+ int nl,el,pl,ql,dpl,dql;
+
+ BigNumDigit n[PrimeSize*2];
+ BigNumDigit e[PrimeSize*2];
+ BigNumDigit nINV[PrimeSize*2];
+ BigNumDigit beta2n[PrimeSize*2];
+ } RSAPublicKeyStorage ;
+
+#define PRIVATE_KEY_SIZE sizeof(RSAKeyStorage)
+#define PUBLIC_KEY_SIZE sizeof(RSAPublicKeyStorage)
+
+#endif
+
--- /dev/null
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+#ifndef SPHINX_BIGKEYGEN
+#define SPHINX_BIGKEYGEN
+
+
+int newRSAKey ();
+int Finishkey (); /* fills in key structure based on primes, etc. */
+int TestRSAKeys();
+int recover_private(); /* recover_private( deskey, input, len, rsakey) */
+int hide_private(); /* hide_private( deskey, **output, *len, rsakey) */
+int hide_privateP(); /* hide_privateP( deskey, **output, *len, rsakey) */
+int PrintTestKey();
+int PrintPubKey();
+#endif
+
--- /dev/null
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+#ifndef SPHINX_BIGRSACODE
+#define SPHINX_BIGRSACODE
+
+int NumEncodeLengthOctets ();
+unsigned char *EncodeLength ();
+int NumEncodeValueOctets();
+unsigned char *EncodeBigIntegerValue ();
+unsigned char *EncodePublic();
+void FreePublic();
+unsigned char *EncodePrivate();
+unsigned char *EncodePrivateP();
+void FreePrivate();
+int DecodeValueLength ();
+int DecodeHeaderLength ();
+int DecodeTypeLength ();
+int DecodeTotalLength ();
+unsigned char *DecodeBigInteger ();
+unsigned char *DecodePublic ();
+unsigned char *DecodePrivate ();
+unsigned char *DecodePrivateP ();
+
+#endif
+
--- /dev/null
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+#ifndef SPHINX_BIGSIGNVERIFY
+#define SPHINX_BIGSIGNVERIFY
+
+#include "random.h"
+#include "BigZ.h"
+#include "BigRSA.h"
+
+int RSASign ();
+/*
+int RSASign (toBeSigned, datalen, key, signature, siglen)
+RSAKeyStorage *key;
+unsigned char *toBeSigned, *signature;
+int datalen, *siglen;
+*/
+
+int RSAVerify ();
+/*
+int RSAVerify (allegedSigned, datalen, key, signature, siglen)
+RSAKeyStorage *key;
+char *allegedSigned, *signature;
+int datalen, siglen;
+*/
+
+#define MAX_INIT_AUTH 2*DigitLim*sizeof(BigNumDigit)
+
+int InitAuthenticationKey ();
+int AcceptAuthenticationKey ();
+
+#endif
+
--- /dev/null
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
--- /dev/null
+/*
+ * Include file for GDSS The Generic Digital Signature Service.
+ *
+ */
+#ifdef SOLARIS
+#include <string.h>
+#endif
+
+/* Structures Needed */
+
+typedef struct {
+ int SigInfoVersion;
+ char pname[ANAME_SZ];
+ char pinst[INST_SZ];
+ char prealm[REALM_SZ];
+ unsigned int timestamp;
+ unsigned char *rawsig; /* Raw Signature Bytes */
+} SigInfo;
+
+/* GDSS Errors */
+
+#define GDSS_SUCCESS 0 /* No error */
+#define GDSS_E_BADSIG -1 /* Signature failed to verify */
+#define GDSS_E_NOPUBKEY -2 /* Couldn't find public key file */
+#define GDSS_E_KRBFAIL -3 /* Generic Kerberos error during sign */
+#define GDSS_E_NOSOCKET -4 /* socket() call failed during sign */
+#define GDSS_E_NOCONNECT -5 /* connect() call failed during sign */
+#define GDSS_E_TIMEDOUT -6 /* timed out contacting gdss sign server */
+#define GDSS_E_PADTOOMANY -7 /* Padding required to much space */
+#define GDSS_E_ALLOC -8 /* malloc() failed to allocate memory */
+#define GDSS_E_BVERSION -9 /* Bad version ID in signature */
+#define GDSS_E_BADINPUT -10 /* Bad input value to Recompose */
+
+/* GDSS Constants */
+
+#define GDSS_PAD 10 /* Maximum number of nulls to pad */
+#define GDSS_ESCAPE 0x20 /* Escape character for padding */
+#define GDSS_NULL 0x21 /* Psuedo Null character */
--- /dev/null
+/* hashes.h */
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+
+/*
+ * Externally Callable Routines. All arguments are character pointers
+ * or integer lengths.
+ */
+
+#ifndef SPHINX_HASHES
+#define SPHINX_HASHES
+
+void RSA_MD2(); /* RSA_MD2(input_buffer, length, hash_result) */
+void RSA_MD4(); /* RSA_MD4(input_buffer, length, hash_result) */
+void RSA_MAC(); /* RSA_MAC(input_buffer, length, mac, output_length) */
+void RSA_MD(); /* RSA_MD(input_buffer, length, hash_result) */
+
+int H1(); /* H1(username, password, hash_result) */
+int H2(); /* H2(username, password, hash_result) */
+
+/*
+ * Common data structures
+ */
+#define MAC_BLOCK_SIZE 8
+#define MD_BLOCK_SIZE 16
+
+
+#endif
+
--- /dev/null
+/* This file is automatically generated. Do not edit it. */
+static int const key_perm[16][48] = {
+ /* ks permutation iteration = 1 */
+ 14, 53, 38, 60, 55, 23, 39, 63,
+ 6, 15, 21, 46, 5, 37, 30, 31,
+ 44, 62, 61, 7, 36, 29, 22, 47,
+ 18, 28, 33, 50, 35, 4, 41, 26,
+ 3, 51, 17, 27, 59, 19, 34, 57,
+ 9, 20, 43, 10, 11, 58, 49, 25, /* ks permutation iteration = 2 */
+ 6, 45, 30, 52, 47, 15, 31, 55,
+ 61, 7, 13, 38, 60, 29, 22, 23,
+ 36, 54, 53, 62, 63, 21, 14, 39,
+ 10, 20, 25, 42, 27, 57, 33, 18,
+ 28, 43, 9, 19, 51, 11, 26, 49,
+ 1, 12, 35, 2, 3, 50, 41, 17, /* ks permutation iteration = 3 */
+ 53, 29, 14, 36, 31, 62, 15, 39,
+ 45, 54, 60, 22, 44, 13, 6, 7,
+ 55, 38, 37, 46, 47, 5, 61, 23,
+ 59, 4, 9, 26, 11, 41, 17, 2,
+ 12, 27, 58, 3, 35, 28, 10, 33,
+ 50, 57, 19, 51, 20, 34, 25, 1, /* ks permutation iteration = 4 */
+ 37, 13, 61, 55, 15, 46, 62, 23,
+ 29, 38, 44, 6, 63, 60, 53, 54,
+ 39, 22, 21, 30, 31, 52, 45, 7,
+ 43, 49, 58, 10, 28, 25, 1, 51,
+ 57, 11, 42, 20, 19, 12, 59, 17,
+ 34, 41, 3, 35, 4, 18, 9, 50, /* ks permutation iteration = 5 */
+ 21, 60, 45, 39, 62, 30, 46, 7,
+ 13, 22, 63, 53, 47, 44, 37, 38,
+ 23, 6, 5, 14, 15, 36, 29, 54,
+ 27, 33, 42, 59, 12, 9, 50, 35,
+ 41, 28, 26, 4, 3, 57, 43, 1,
+ 18, 25, 20, 19, 49, 2, 58, 34, /* ks permutation iteration = 6 */
+ 5, 44, 29, 23, 46, 14, 30, 54,
+ 60, 6, 47, 37, 31, 63, 21, 22,
+ 7, 53, 52, 61, 62, 55, 13, 38,
+ 11, 17, 26, 43, 57, 58, 34, 19,
+ 25, 12, 10, 49, 20, 41, 27, 50,
+ 2, 9, 4, 3, 33, 51, 42, 18, /* ks permutation iteration = 7 */
+ 52, 63, 13, 7, 30, 61, 14, 38,
+ 44, 53, 31, 21, 15, 47, 5, 6,
+ 54, 37, 36, 45, 46, 39, 60, 22,
+ 28, 1, 10, 27, 41, 42, 18, 3,
+ 9, 57, 59, 33, 4, 25, 11, 34,
+ 51, 58, 49, 20, 17, 35, 26, 2, /* ks permutation iteration = 8 */
+ 36, 47, 60, 54, 14, 45, 61, 22,
+ 63, 37, 15, 5, 62, 31, 52, 53,
+ 38, 21, 55, 29, 30, 23, 44, 6,
+ 12, 50, 59, 11, 25, 26, 2, 20,
+ 58, 41, 43, 17, 49, 9, 28, 18,
+ 35, 42, 33, 4, 1, 19, 10, 51, /* ks permutation iteration = 9 */
+ 63, 39, 52, 46, 6, 37, 53, 14,
+ 55, 29, 7, 60, 54, 23, 44, 45,
+ 30, 13, 47, 21, 22, 15, 36, 61,
+ 4, 42, 51, 3, 17, 18, 59, 12,
+ 50, 33, 35, 9, 41, 1, 20, 10,
+ 27, 34, 25, 57, 58, 11, 2, 43, /* ks permutation iteration = 10 */
+ 47, 23, 36, 30, 53, 21, 37, 61,
+ 39, 13, 54, 44, 38, 7, 63, 29,
+ 14, 60, 31, 5, 6, 62, 55, 45,
+ 49, 26, 35, 20, 1, 2, 43, 57,
+ 34, 17, 19, 58, 25, 50, 4, 59,
+ 11, 18, 9, 41, 42, 28, 51, 27, /* ks permutation iteration = 11 */
+ 31, 7, 55, 14, 37, 5, 21, 45,
+ 23, 60, 38, 63, 22, 54, 47, 13,
+ 61, 44, 15, 52, 53, 46, 39, 29,
+ 33, 10, 19, 4, 50, 51, 27, 41,
+ 18, 1, 3, 42, 9, 34, 49, 43,
+ 28, 2, 58, 25, 26, 12, 35, 11, /* ks permutation iteration = 12 */
+ 15, 54, 39, 61, 21, 52, 5, 29,
+ 7, 44, 22, 47, 6, 38, 31, 60,
+ 45, 63, 62, 36, 37, 30, 23, 13,
+ 17, 59, 3, 49, 34, 35, 11, 25,
+ 2, 50, 20, 26, 58, 18, 33, 27,
+ 12, 51, 42, 9, 10, 57, 19, 28, /* ks permutation iteration = 13 */
+ 62, 38, 23, 45, 5, 36, 52, 13,
+ 54, 63, 6, 31, 53, 22, 15, 44,
+ 29, 47, 46, 55, 21, 14, 7, 60,
+ 1, 43, 20, 33, 18, 19, 28, 9,
+ 51, 34, 4, 10, 42, 2, 17, 11,
+ 57, 35, 26, 58, 59, 41, 3, 12, /* ks permutation iteration = 14 */
+ 46, 22, 7, 29, 52, 55, 36, 60,
+ 38, 47, 53, 15, 37, 6, 62, 63,
+ 13, 31, 30, 39, 5, 61, 54, 44,
+ 50, 27, 4, 17, 2, 3, 12, 58,
+ 35, 18, 49, 59, 26, 51, 1, 28,
+ 41, 19, 10, 42, 43, 25, 20, 57, /* ks permutation iteration = 15 */
+ 30, 6, 54, 13, 36, 39, 55, 44,
+ 22, 31, 37, 62, 21, 53, 46, 47,
+ 60, 15, 14, 23, 52, 45, 38, 63,
+ 34, 11, 49, 1, 51, 20, 57, 42,
+ 19, 2, 33, 43, 10, 35, 50, 12,
+ 25, 3, 59, 26, 27, 9, 4, 41, /* ks permutation iteration = 16 */
+ 22, 61, 46, 5, 63, 31, 47, 36,
+ 14, 23, 29, 54, 13, 45, 38, 39,
+ 52, 7, 6, 15, 44, 37, 30, 55,
+ 26, 3, 41, 58, 43, 12, 49, 34,
+ 11, 59, 25, 35, 2, 27, 42, 4,
+ 17, 28, 51, 18, 19, 1, 57, 33
+};
--- /dev/null
+/* This file is automatically generated. Do not edit it. */
+static unsigned char const odd_parity[256] = {
+ 1,
+ 1, 2, 2, 4, 4, 7, 7, 8,
+ 8, 11, 11, 13, 13, 14, 14, 16,
+ 16, 19, 19, 21, 21, 22, 22, 25,
+ 25, 26, 26, 28, 28, 31, 31, 32,
+ 32, 35, 35, 37, 37, 38, 38, 41,
+ 41, 42, 42, 44, 44, 47, 47, 49,
+ 49, 50, 50, 52, 52, 55, 55, 56,
+ 56, 59, 59, 61, 61, 62, 62, 64,
+ 64, 67, 67, 69, 69, 70, 70, 73,
+ 73, 74, 74, 76, 76, 79, 79, 81,
+ 81, 82, 82, 84, 84, 87, 87, 88,
+ 88, 91, 91, 93, 93, 94, 94, 97,
+ 97, 98, 98, 100, 100, 103, 103, 104,
+104, 107, 107, 109, 109, 110, 110, 112,
+112, 115, 115, 117, 117, 118, 118, 121,
+121, 122, 122, 124, 124, 127, 127, 128,
+128, 131, 131, 133, 133, 134, 134, 137,
+137, 138, 138, 140, 140, 143, 143, 145,
+145, 146, 146, 148, 148, 151, 151, 152,
+152, 155, 155, 157, 157, 158, 158, 161,
+161, 162, 162, 164, 164, 167, 167, 168,
+168, 171, 171, 173, 173, 174, 174, 176,
+176, 179, 179, 181, 181, 182, 182, 185,
+185, 186, 186, 188, 188, 191, 191, 193,
+193, 194, 194, 196, 196, 199, 199, 200,
+200, 203, 203, 205, 205, 206, 206, 208,
+208, 211, 211, 213, 213, 214, 214, 217,
+217, 218, 218, 220, 220, 223, 223, 224,
+224, 227, 227, 229, 229, 230, 230, 233,
+233, 234, 234, 236, 236, 239, 239, 241,
+241, 242, 242, 244, 244, 247, 247, 248,
+248, 251, 251, 253, 253, 254, 254};
--- /dev/null
+/* This file is automatically generated. Do not edit it. */
+
+ static unsigned long const P_prime[4][256] = {
+
+
+0x00000000, 0x00000100, 0x00010000, 0x00010100,
+0x00400000, 0x00400100, 0x00410000, 0x00410100,
+0x40000000, 0x40000100, 0x40010000, 0x40010100,
+0x40400000, 0x40400100, 0x40410000, 0x40410100,
+0x00001000, 0x00001100, 0x00011000, 0x00011100,
+0x00401000, 0x00401100, 0x00411000, 0x00411100,
+0x40001000, 0x40001100, 0x40011000, 0x40011100,
+0x40401000, 0x40401100, 0x40411000, 0x40411100,
+0x08000000, 0x08000100, 0x08010000, 0x08010100,
+0x08400000, 0x08400100, 0x08410000, 0x08410100,
+0x48000000, 0x48000100, 0x48010000, 0x48010100,
+0x48400000, 0x48400100, 0x48410000, 0x48410100,
+0x08001000, 0x08001100, 0x08011000, 0x08011100,
+0x08401000, 0x08401100, 0x08411000, 0x08411100,
+0x48001000, 0x48001100, 0x48011000, 0x48011100,
+0x48401000, 0x48401100, 0x48411000, 0x48411100,
+0x00000002, 0x00000102, 0x00010002, 0x00010102,
+0x00400002, 0x00400102, 0x00410002, 0x00410102,
+0x40000002, 0x40000102, 0x40010002, 0x40010102,
+0x40400002, 0x40400102, 0x40410002, 0x40410102,
+0x00001002, 0x00001102, 0x00011002, 0x00011102,
+0x00401002, 0x00401102, 0x00411002, 0x00411102,
+0x40001002, 0x40001102, 0x40011002, 0x40011102,
+0x40401002, 0x40401102, 0x40411002, 0x40411102,
+0x08000002, 0x08000102, 0x08010002, 0x08010102,
+0x08400002, 0x08400102, 0x08410002, 0x08410102,
+0x48000002, 0x48000102, 0x48010002, 0x48010102,
+0x48400002, 0x48400102, 0x48410002, 0x48410102,
+0x08001002, 0x08001102, 0x08011002, 0x08011102,
+0x08401002, 0x08401102, 0x08411002, 0x08411102,
+0x48001002, 0x48001102, 0x48011002, 0x48011102,
+0x48401002, 0x48401102, 0x48411002, 0x48411102,
+0x00020000, 0x00020100, 0x00030000, 0x00030100,
+0x00420000, 0x00420100, 0x00430000, 0x00430100,
+0x40020000, 0x40020100, 0x40030000, 0x40030100,
+0x40420000, 0x40420100, 0x40430000, 0x40430100,
+0x00021000, 0x00021100, 0x00031000, 0x00031100,
+0x00421000, 0x00421100, 0x00431000, 0x00431100,
+0x40021000, 0x40021100, 0x40031000, 0x40031100,
+0x40421000, 0x40421100, 0x40431000, 0x40431100,
+0x08020000, 0x08020100, 0x08030000, 0x08030100,
+0x08420000, 0x08420100, 0x08430000, 0x08430100,
+0x48020000, 0x48020100, 0x48030000, 0x48030100,
+0x48420000, 0x48420100, 0x48430000, 0x48430100,
+0x08021000, 0x08021100, 0x08031000, 0x08031100,
+0x08421000, 0x08421100, 0x08431000, 0x08431100,
+0x48021000, 0x48021100, 0x48031000, 0x48031100,
+0x48421000, 0x48421100, 0x48431000, 0x48431100,
+0x00020002, 0x00020102, 0x00030002, 0x00030102,
+0x00420002, 0x00420102, 0x00430002, 0x00430102,
+0x40020002, 0x40020102, 0x40030002, 0x40030102,
+0x40420002, 0x40420102, 0x40430002, 0x40430102,
+0x00021002, 0x00021102, 0x00031002, 0x00031102,
+0x00421002, 0x00421102, 0x00431002, 0x00431102,
+0x40021002, 0x40021102, 0x40031002, 0x40031102,
+0x40421002, 0x40421102, 0x40431002, 0x40431102,
+0x08020002, 0x08020102, 0x08030002, 0x08030102,
+0x08420002, 0x08420102, 0x08430002, 0x08430102,
+0x48020002, 0x48020102, 0x48030002, 0x48030102,
+0x48420002, 0x48420102, 0x48430002, 0x48430102,
+0x08021002, 0x08021102, 0x08031002, 0x08031102,
+0x08421002, 0x08421102, 0x08431002, 0x08431102,
+0x48021002, 0x48021102, 0x48031002, 0x48031102,
+0x48421002, 0x48421102, 0x48431002, 0x48431102,
+
+0x00000000, 0x00800000, 0x00008000, 0x00808000,
+0x20000000, 0x20800000, 0x20008000, 0x20808000,
+0x00000020, 0x00800020, 0x00008020, 0x00808020,
+0x20000020, 0x20800020, 0x20008020, 0x20808020,
+0x02000000, 0x02800000, 0x02008000, 0x02808000,
+0x22000000, 0x22800000, 0x22008000, 0x22808000,
+0x02000020, 0x02800020, 0x02008020, 0x02808020,
+0x22000020, 0x22800020, 0x22008020, 0x22808020,
+0x00080000, 0x00880000, 0x00088000, 0x00888000,
+0x20080000, 0x20880000, 0x20088000, 0x20888000,
+0x00080020, 0x00880020, 0x00088020, 0x00888020,
+0x20080020, 0x20880020, 0x20088020, 0x20888020,
+0x02080000, 0x02880000, 0x02088000, 0x02888000,
+0x22080000, 0x22880000, 0x22088000, 0x22888000,
+0x02080020, 0x02880020, 0x02088020, 0x02888020,
+0x22080020, 0x22880020, 0x22088020, 0x22888020,
+0x00000200, 0x00800200, 0x00008200, 0x00808200,
+0x20000200, 0x20800200, 0x20008200, 0x20808200,
+0x00000220, 0x00800220, 0x00008220, 0x00808220,
+0x20000220, 0x20800220, 0x20008220, 0x20808220,
+0x02000200, 0x02800200, 0x02008200, 0x02808200,
+0x22000200, 0x22800200, 0x22008200, 0x22808200,
+0x02000220, 0x02800220, 0x02008220, 0x02808220,
+0x22000220, 0x22800220, 0x22008220, 0x22808220,
+0x00080200, 0x00880200, 0x00088200, 0x00888200,
+0x20080200, 0x20880200, 0x20088200, 0x20888200,
+0x00080220, 0x00880220, 0x00088220, 0x00888220,
+0x20080220, 0x20880220, 0x20088220, 0x20888220,
+0x02080200, 0x02880200, 0x02088200, 0x02888200,
+0x22080200, 0x22880200, 0x22088200, 0x22888200,
+0x02080220, 0x02880220, 0x02088220, 0x02888220,
+0x22080220, 0x22880220, 0x22088220, 0x22888220,
+0x00000001, 0x00800001, 0x00008001, 0x00808001,
+0x20000001, 0x20800001, 0x20008001, 0x20808001,
+0x00000021, 0x00800021, 0x00008021, 0x00808021,
+0x20000021, 0x20800021, 0x20008021, 0x20808021,
+0x02000001, 0x02800001, 0x02008001, 0x02808001,
+0x22000001, 0x22800001, 0x22008001, 0x22808001,
+0x02000021, 0x02800021, 0x02008021, 0x02808021,
+0x22000021, 0x22800021, 0x22008021, 0x22808021,
+0x00080001, 0x00880001, 0x00088001, 0x00888001,
+0x20080001, 0x20880001, 0x20088001, 0x20888001,
+0x00080021, 0x00880021, 0x00088021, 0x00888021,
+0x20080021, 0x20880021, 0x20088021, 0x20888021,
+0x02080001, 0x02880001, 0x02088001, 0x02888001,
+0x22080001, 0x22880001, 0x22088001, 0x22888001,
+0x02080021, 0x02880021, 0x02088021, 0x02888021,
+0x22080021, 0x22880021, 0x22088021, 0x22888021,
+0x00000201, 0x00800201, 0x00008201, 0x00808201,
+0x20000201, 0x20800201, 0x20008201, 0x20808201,
+0x00000221, 0x00800221, 0x00008221, 0x00808221,
+0x20000221, 0x20800221, 0x20008221, 0x20808221,
+0x02000201, 0x02800201, 0x02008201, 0x02808201,
+0x22000201, 0x22800201, 0x22008201, 0x22808201,
+0x02000221, 0x02800221, 0x02008221, 0x02808221,
+0x22000221, 0x22800221, 0x22008221, 0x22808221,
+0x00080201, 0x00880201, 0x00088201, 0x00888201,
+0x20080201, 0x20880201, 0x20088201, 0x20888201,
+0x00080221, 0x00880221, 0x00088221, 0x00888221,
+0x20080221, 0x20880221, 0x20088221, 0x20888221,
+0x02080201, 0x02880201, 0x02088201, 0x02888201,
+0x22080201, 0x22880201, 0x22088201, 0x22888201,
+0x02080221, 0x02880221, 0x02088221, 0x02888221,
+0x22080221, 0x22880221, 0x22088221, 0x22888221,
+
+0x00000000, 0x00000080, 0x00002000, 0x00002080,
+0x01000000, 0x01000080, 0x01002000, 0x01002080,
+0x00000004, 0x00000084, 0x00002004, 0x00002084,
+0x01000004, 0x01000084, 0x01002004, 0x01002084,
+0x00000008, 0x00000088, 0x00002008, 0x00002088,
+0x01000008, 0x01000088, 0x01002008, 0x01002088,
+0x0000000C, 0x0000008C, 0x0000200C, 0x0000208C,
+0x0100000C, 0x0100008C, 0x0100200C, 0x0100208C,
+0x10000000, 0x10000080, 0x10002000, 0x10002080,
+0x11000000, 0x11000080, 0x11002000, 0x11002080,
+0x10000004, 0x10000084, 0x10002004, 0x10002084,
+0x11000004, 0x11000084, 0x11002004, 0x11002084,
+0x10000008, 0x10000088, 0x10002008, 0x10002088,
+0x11000008, 0x11000088, 0x11002008, 0x11002088,
+0x1000000C, 0x1000008C, 0x1000200C, 0x1000208C,
+0x1100000C, 0x1100008C, 0x1100200C, 0x1100208C,
+0x00000400, 0x00000480, 0x00002400, 0x00002480,
+0x01000400, 0x01000480, 0x01002400, 0x01002480,
+0x00000404, 0x00000484, 0x00002404, 0x00002484,
+0x01000404, 0x01000484, 0x01002404, 0x01002484,
+0x00000408, 0x00000488, 0x00002408, 0x00002488,
+0x01000408, 0x01000488, 0x01002408, 0x01002488,
+0x0000040C, 0x0000048C, 0x0000240C, 0x0000248C,
+0x0100040C, 0x0100048C, 0x0100240C, 0x0100248C,
+0x10000400, 0x10000480, 0x10002400, 0x10002480,
+0x11000400, 0x11000480, 0x11002400, 0x11002480,
+0x10000404, 0x10000484, 0x10002404, 0x10002484,
+0x11000404, 0x11000484, 0x11002404, 0x11002484,
+0x10000408, 0x10000488, 0x10002408, 0x10002488,
+0x11000408, 0x11000488, 0x11002408, 0x11002488,
+0x1000040C, 0x1000048C, 0x1000240C, 0x1000248C,
+0x1100040C, 0x1100048C, 0x1100240C, 0x1100248C,
+0x00040000, 0x00040080, 0x00042000, 0x00042080,
+0x01040000, 0x01040080, 0x01042000, 0x01042080,
+0x00040004, 0x00040084, 0x00042004, 0x00042084,
+0x01040004, 0x01040084, 0x01042004, 0x01042084,
+0x00040008, 0x00040088, 0x00042008, 0x00042088,
+0x01040008, 0x01040088, 0x01042008, 0x01042088,
+0x0004000C, 0x0004008C, 0x0004200C, 0x0004208C,
+0x0104000C, 0x0104008C, 0x0104200C, 0x0104208C,
+0x10040000, 0x10040080, 0x10042000, 0x10042080,
+0x11040000, 0x11040080, 0x11042000, 0x11042080,
+0x10040004, 0x10040084, 0x10042004, 0x10042084,
+0x11040004, 0x11040084, 0x11042004, 0x11042084,
+0x10040008, 0x10040088, 0x10042008, 0x10042088,
+0x11040008, 0x11040088, 0x11042008, 0x11042088,
+0x1004000C, 0x1004008C, 0x1004200C, 0x1004208C,
+0x1104000C, 0x1104008C, 0x1104200C, 0x1104208C,
+0x00040400, 0x00040480, 0x00042400, 0x00042480,
+0x01040400, 0x01040480, 0x01042400, 0x01042480,
+0x00040404, 0x00040484, 0x00042404, 0x00042484,
+0x01040404, 0x01040484, 0x01042404, 0x01042484,
+0x00040408, 0x00040488, 0x00042408, 0x00042488,
+0x01040408, 0x01040488, 0x01042408, 0x01042488,
+0x0004040C, 0x0004048C, 0x0004240C, 0x0004248C,
+0x0104040C, 0x0104048C, 0x0104240C, 0x0104248C,
+0x10040400, 0x10040480, 0x10042400, 0x10042480,
+0x11040400, 0x11040480, 0x11042400, 0x11042480,
+0x10040404, 0x10040484, 0x10042404, 0x10042484,
+0x11040404, 0x11040484, 0x11042404, 0x11042484,
+0x10040408, 0x10040488, 0x10042408, 0x10042488,
+0x11040408, 0x11040488, 0x11042408, 0x11042488,
+0x1004040C, 0x1004048C, 0x1004240C, 0x1004248C,
+0x1104040C, 0x1104048C, 0x1104240C, 0x1104248C,
+
+0x00000000, 0x80000000, 0x00000800, 0x80000800,
+0x00200000, 0x80200000, 0x00200800, 0x80200800,
+0x00000040, 0x80000040, 0x00000840, 0x80000840,
+0x00200040, 0x80200040, 0x00200840, 0x80200840,
+0x00000010, 0x80000010, 0x00000810, 0x80000810,
+0x00200010, 0x80200010, 0x00200810, 0x80200810,
+0x00000050, 0x80000050, 0x00000850, 0x80000850,
+0x00200050, 0x80200050, 0x00200850, 0x80200850,
+0x04000000, 0x84000000, 0x04000800, 0x84000800,
+0x04200000, 0x84200000, 0x04200800, 0x84200800,
+0x04000040, 0x84000040, 0x04000840, 0x84000840,
+0x04200040, 0x84200040, 0x04200840, 0x84200840,
+0x04000010, 0x84000010, 0x04000810, 0x84000810,
+0x04200010, 0x84200010, 0x04200810, 0x84200810,
+0x04000050, 0x84000050, 0x04000850, 0x84000850,
+0x04200050, 0x84200050, 0x04200850, 0x84200850,
+0x00004000, 0x80004000, 0x00004800, 0x80004800,
+0x00204000, 0x80204000, 0x00204800, 0x80204800,
+0x00004040, 0x80004040, 0x00004840, 0x80004840,
+0x00204040, 0x80204040, 0x00204840, 0x80204840,
+0x00004010, 0x80004010, 0x00004810, 0x80004810,
+0x00204010, 0x80204010, 0x00204810, 0x80204810,
+0x00004050, 0x80004050, 0x00004850, 0x80004850,
+0x00204050, 0x80204050, 0x00204850, 0x80204850,
+0x04004000, 0x84004000, 0x04004800, 0x84004800,
+0x04204000, 0x84204000, 0x04204800, 0x84204800,
+0x04004040, 0x84004040, 0x04004840, 0x84004840,
+0x04204040, 0x84204040, 0x04204840, 0x84204840,
+0x04004010, 0x84004010, 0x04004810, 0x84004810,
+0x04204010, 0x84204010, 0x04204810, 0x84204810,
+0x04004050, 0x84004050, 0x04004850, 0x84004850,
+0x04204050, 0x84204050, 0x04204850, 0x84204850,
+0x00100000, 0x80100000, 0x00100800, 0x80100800,
+0x00300000, 0x80300000, 0x00300800, 0x80300800,
+0x00100040, 0x80100040, 0x00100840, 0x80100840,
+0x00300040, 0x80300040, 0x00300840, 0x80300840,
+0x00100010, 0x80100010, 0x00100810, 0x80100810,
+0x00300010, 0x80300010, 0x00300810, 0x80300810,
+0x00100050, 0x80100050, 0x00100850, 0x80100850,
+0x00300050, 0x80300050, 0x00300850, 0x80300850,
+0x04100000, 0x84100000, 0x04100800, 0x84100800,
+0x04300000, 0x84300000, 0x04300800, 0x84300800,
+0x04100040, 0x84100040, 0x04100840, 0x84100840,
+0x04300040, 0x84300040, 0x04300840, 0x84300840,
+0x04100010, 0x84100010, 0x04100810, 0x84100810,
+0x04300010, 0x84300010, 0x04300810, 0x84300810,
+0x04100050, 0x84100050, 0x04100850, 0x84100850,
+0x04300050, 0x84300050, 0x04300850, 0x84300850,
+0x00104000, 0x80104000, 0x00104800, 0x80104800,
+0x00304000, 0x80304000, 0x00304800, 0x80304800,
+0x00104040, 0x80104040, 0x00104840, 0x80104840,
+0x00304040, 0x80304040, 0x00304840, 0x80304840,
+0x00104010, 0x80104010, 0x00104810, 0x80104810,
+0x00304010, 0x80304010, 0x00304810, 0x80304810,
+0x00104050, 0x80104050, 0x00104850, 0x80104850,
+0x00304050, 0x80304050, 0x00304850, 0x80304850,
+0x04104000, 0x84104000, 0x04104800, 0x84104800,
+0x04304000, 0x84304000, 0x04304800, 0x84304800,
+0x04104040, 0x84104040, 0x04104840, 0x84104840,
+0x04304040, 0x84304040, 0x04304840, 0x84304840,
+0x04104010, 0x84104010, 0x04104810, 0x84104810,
+0x04304010, 0x84304010, 0x04304810, 0x84304810,
+0x04104050, 0x84104050, 0x04104850, 0x84104850,
+0x04304050, 0x84304050, 0x04304850, 0x84304850
+};
--- /dev/null
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+#define rword(num,i) (8*num+i)
+#define R_m 31
+#define R_mINV 30
+#define R_mbeta 29
+
+#define R_0 16
+#define R_sq 17
+#define R_j 18
+#define R_a 19
+#define R_x 20
+#define R_q 21
+#define R_s0 22
+#define R_s1 23
+
+/* multiply read at odd halfword address */
+/* charge write at odd halfword address */
+#define charge(ra,rs0,rp1) (1 | ra << 1 | rs0 << 6 | rp1 << 11)
+#define mult(rb,rs1,rp0) (1 | rb << 1 | rs1 << 6 | rp0 << 11)
--- /dev/null
+/* random.h */
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+#ifndef SPHINX_RANDOM
+#define SPHINX_RANDOM
+
+typedef unsigned long INT32; /* 32-bit unsigned integer */
+
+typedef union
+{ /* data type for the DES blocks */
+ unsigned char bytes[8]; /* for access as bytes */
+ INT32 longwords[2]; /* for access as longwords */
+} DESblock;
+
+#define DES_BLOCK_SIZE sizeof(DESblock)
+
+typedef struct {
+ int count ;
+ DESblock seed , key , current;
+ } RNGState ;
+
+#define RNG_STATE_SIZE sizeof(RNGState)
+
+void read_rng_state ();
+void restore_rng_state ();
+void initialize_rng_state ();
+void random_bytes ();
+void DES_X9_MAC(); /* DES_X9_MAC(key,input_buffer, length, hash_result) */
+
+#endif
+
--- /dev/null
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+#ifndef SPHINX_READ_PASSWORD
+#define SPHINX_READ_PASSWORD
+
+#include "hashes.h"
+
+int DES_read_password();
+int DES_read_password_hash();
+
+#endif
--- /dev/null
+/* $Header$ */
+
+SUBDIRS = crypto
+
+OBJS = gdss.o rgdss.o
+COBJS = crypto/hashes.o crypto/read_password.o crypto/crypto_util.o \
+ crypto/dumphex.o crypto/read_privkey.o crypto/read_pubkey.o \
+ crypto/write_pubkey.o crypto/KeyFromPQ.o
+BOBJS = crypto/bignum/o/KerN.o crypto/bignum/o/bnCmp.o \
+ crypto/bignum/o/bnDivide.o crypto/bignum/o/bnInit.o \
+ crypto/bignum/o/bnMult.o crypto/bignum/o/bz.o crypto/bignum/o/bzf.o
+AOBJS = crypto/algorithm/random.o crypto/algorithm/random_BigNum.o \
+ crypto/algorithm/bigrsacode.o crypto/algorithm/bigkeygen.o \
+ crypto/algorithm/bigsignverify.o
+
+DEFINES = -I. -I../include -I./crypto/bignum/h -I./crypto/algorithm
+
+do_subdirs($(SUBDIRS))
+
+library_obj_rule()
+install_library_target(gdss,$(OBJS) $(COBJS) $(BOBJS) $(AOBJS),)
--- /dev/null
+/* $Header$ */
+
+#define have_subdirs
+SUBDIRS = algorithm bignum
+
+OBJS = hashes.o \
+ read_password.o \
+ crypto_util.o \
+ dumphex.o \
+ read_privkey.o \
+ read_pubkey.o \
+ write_pubkey.o \
+ KeyFromPQ.o
+
+DEFINES = -I. -I../../include -Ibignum/h
+
+all:: $(OBJS)
--- /dev/null
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#include "BigNum.h"
+#include "BigRSA.h"
+#include "bigrsacode.h"
+#include "bigkeygen.h"
+
+/*
+#ifdef DEBUG
+#undef DEBUG
+#endif
+*/
+
+/* given two primes in msb-lsg order, initialize the key structure */
+
+int KeyFromPQ ( P, PL, Q, QL, keys )
+char *P, *Q;
+int PL, QL;
+RSAKeyStorage *keys ;
+{
+ BigNum p = keys->p, q = keys->q ;
+ int i;
+ char *x, *y;
+ unsigned pl, ql;
+
+ memset(keys,0,sizeof(RSAKeyStorage));
+ BnnInit();
+
+ DecodeBigInteger(P, p, PL);
+ DecodeBigInteger(Q, q, QL);
+
+ pl = BnnNumDigits(p, (PL+sizeof(BigNumDigit))/sizeof(BigNumDigit));
+ ql = BnnNumDigits(q, (QL+sizeof(BigNumDigit))/sizeof(BigNumDigit));
+
+ if (BnnCompare(p, pl, q, ql) == -1) {
+ unsigned tpl = pl;
+ BigNumDigit tp[DigitLim];
+ BnnSetToZero(tp,DigitLim);
+ BnnAssign(tp,p,pl);
+ BnnSetToZero(p,pl);
+ BnnAssign(p,q,ql);
+ BnnAssign(q,tp,pl);
+ pl = ql;
+ ql = tpl;
+ }
+
+ keys->pl = pl;
+ keys->ql = ql;
+
+ BnnSetDigit(keys->e, (BigNumDigit) ((1<<16)+1));
+ keys->el = 1;
+
+ BnnMultiply(keys->n, pl+ql, p, pl, q, ql),
+ keys->nl = pl+ql;
+
+#ifdef DEBUG
+PrintTestKey(keys);
+#endif
+
+ if (FinishKey(keys)==0) return (0);
+
+ if (TestRSAKeys(keys)!=1) {
+#ifdef DEBUG
+printf("\nFailed.\n");
+#endif
+ return(0);
+ }
+
+ BnnClose();
+ return(1);
+}
+
+
--- /dev/null
+/* DEScrypto.h */
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+/* In-line include file for DES routines */
+
+#ifndef SPHINX_DESCRYPTO
+#define SPHINX_DESCRYPTO
+
+/*
+ *********************************************************************
+ *********************************************************************
+ ** **
+ ** W A R N I N G **
+ ** **
+ ** This software is subject to export restrictions under the **
+ ** U.S. Department of State's International Traffic in Arms **
+ ** Regulations (ITAR). This software must not be transmitted **
+ ** in source form outside the United States or to a foreign **
+ ** national in the United States without a valid U.S. State **
+ ** Department export license. **
+ ** **
+ *********************************************************************
+ *********************************************************************
+*/
+
+#ifndef SPHINX_ITAR
+#define SPHINX_ITAR
+static char copyright[] = "\n Copyright, 1989, 1990, Digital Equipment Corporation \n";
+static char warning[]= "\n This software is subject to export restrictions under \
+\n the U.S. Department of State's International Traffic in Arms \
+\n Regulations (ITAR). This software must not be transmitted \
+\n in source form outside the United States or to a foreign \
+\n national in the United States without a valid U.S. State \
+\n Department export license. ";
+#endif
+
+#include "endian.h"
+#include "hashes.h"
+#include "random.h"
+#include "tables.h"
+
+static DESdecrypt_local();
+static DESencrypt_local();
+static void DES_load_key_local();
+static int DES_CBC_encrypt_local ();
+static int DES_CBC_decrypt_local ();
+
+typedef struct
+{ /* DES key schedule */
+ unsigned char subkey[16][8]; /* 8 6-bit subkeys per round */
+} KEYschedule;
+
+/*
+ * The following macros perform the initial and final permutations on a
+ * DES block. The output is accessed as 32-bit units and the input as 8-bit
+ * units.
+ *
+ * Note: These macros reference 2 permutation arrays (iperm and fperm) which
+ * are machine generated and must be included with any program using
+ * these macros.
+ */
+
+#define INITIAL(out, in) \
+ out[0] = iperma[in[0]] \
+ | (iperma[in[1]] << 1) \
+ | (iperma[in[2]] << 2) \
+ | (iperma[in[3]] << 3) \
+ | (iperma[in[4]] << 4) \
+ | (iperma[in[5]] << 5) \
+ | (iperma[in[6]] << 6) \
+ | (iperma[in[7]] << 7); \
+ out[1] = ipermb[in[0]] \
+ | (ipermb[in[1]] << 1) \
+ | (ipermb[in[2]] << 2) \
+ | (ipermb[in[3]] << 3) \
+ | (ipermb[in[4]] << 4) \
+ | (ipermb[in[5]] << 5) \
+ | (ipermb[in[6]] << 6) \
+ | (ipermb[in[7]] << 7)
+
+#if SPHINX_ENDIAN
+#define FINAL(out, in) \
+ out[0] = fperma[in[0]] \
+ | (fperma[in[4]] << 1) \
+ | (fperma[in[1]] << 2) \
+ | (fperma[in[5]] << 3) \
+ | (fperma[in[2]] << 4) \
+ | (fperma[in[6]] << 5) \
+ | (fperma[in[3]] << 6) \
+ | (fperma[in[7]] << 7); \
+ out[1] = fpermb[in[0]] \
+ | (fpermb[in[4]] << 1) \
+ | (fpermb[in[1]] << 2) \
+ | (fpermb[in[5]] << 3) \
+ | (fpermb[in[2]] << 4) \
+ | (fpermb[in[6]] << 5) \
+ | (fpermb[in[3]] << 6) \
+ | (fpermb[in[7]] << 7);
+#else
+#define FINAL(out, in) \
+ out[0] = fperma[in[3]] \
+ | (fperma[in[7]] << 1) \
+ | (fperma[in[2]] << 2) \
+ | (fperma[in[6]] << 3) \
+ | (fperma[in[1]] << 4) \
+ | (fperma[in[5]] << 5) \
+ | (fperma[in[0]] << 6) \
+ | (fperma[in[4]] << 7); \
+ out[1] = fpermb[in[3]] \
+ | (fpermb[in[7]] << 1) \
+ | (fpermb[in[2]] << 2) \
+ | (fpermb[in[6]] << 3) \
+ | (fpermb[in[1]] << 4) \
+ | (fpermb[in[5]] << 5) \
+ | (fpermb[in[0]] << 6) \
+ | (fpermb[in[4]] << 7);
+
+#endif /* SPHINX_ENDIAN */
+
+/*
+ * The following tables are taken directly from FIPS PUB 46 (Specifications
+ * for the Data Encryption Standard).
+ */
+
+/*
+ * Number of left rotations of pc1
+ */
+static char totrot[] = {
+ 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28
+};
+
+/*
+ * Permuted choice key (table)
+ */
+static char pc2[] = {
+ 14, 17, 11, 24, 1, 5,
+ 3, 28, 15, 6, 21, 10,
+ 23, 19, 12, 4, 26, 8,
+ 16, 7, 27, 20, 13, 2,
+ 41, 52, 31, 37, 47, 55,
+ 30, 40, 51, 45, 33, 48,
+ 44, 49, 39, 56, 34, 53,
+ 46, 42, 50, 36, 29, 32
+};
+
+/*
+ * Note that the Standard is written in Big Endian terms so bit 1 is the
+ * high bit of the byte.
+ */
+static int bytebit[] = {
+ 0200, 0100, 040, 020, 010, 04, 02, 01
+};
+
+/*
+ * Declare external and forward routines.
+ */
+
+\f
+/*
+ *
+ * Functional Description:
+ *
+ * Perform a DES decryption of a single 8-byte block producing
+ * another 8-byte block.
+ *
+ * Inputs:
+ *
+ * indata - Pointer to the input data
+ *
+ * Outputs:
+ *
+ * outdata - Pointer to the output data
+ *
+ * Return Value:
+ *
+ * None
+ *
+ */
+static DESdecrypt_local( indata,outdata,key_schedule )
+KEYschedule *key_schedule ;
+DESblock *indata,*outdata;
+{
+ register int i;
+ register INT32 er,out;
+ register unsigned char *subkey;
+ INT32 index;
+ DESblock temp;
+
+ /*
+ * Perform the initial transformation.
+ */
+ INITIAL(temp.longwords, indata->bytes);
+
+ /*
+ * Now swap halves of the working block.
+ */
+ out = temp.longwords[0];
+ temp.longwords[0] = temp.longwords[1];
+ temp.longwords[1] = out;
+
+ /*
+ * Perform the decryption operation.
+ */
+ for (i = 15; i >= 0; i--)
+ {
+ /*
+ * Select the subkey for this round.
+ */
+ subkey = key_schedule->subkey[i];
+
+ /*
+ * Compute the index value to be used for the first 7 subkeys.
+ */
+ index = temp.longwords[1 - (i & 1)];
+ er = (index >> 1) | ((index & 1) ? 0x80000000 : 0);
+
+ /*
+ * Perform one round of E(input) ^ K through the combined S and
+ * P boxes.
+ */
+ out = sp[0][((er >> 26) & 0x3F) ^ *subkey++];
+ out |= sp[1][((er >> 22) & 0x3F) ^ *subkey++];
+ out |= sp[2][((er >> 18) & 0x3F) ^ *subkey++];
+ out |= sp[3][((er >> 14) & 0x3F) ^ *subkey++];
+ out |= sp[4][((er >> 10) & 0x3F) ^ *subkey++];
+ out |= sp[5][((er >> 6) & 0x3F) ^ *subkey++];
+ out |= sp[6][((er >> 2) & 0x3F) ^ *subkey++];
+ er = (index << 1) | ((index & 0x80000000) ? 1 : 0);
+ out |= sp[7][(er & 0x3F) ^ *subkey];
+
+ temp.longwords[i & 1] ^= out;
+ }
+
+ /*
+ * Perform the final transformation.
+ */
+ FINAL(outdata->longwords, temp.bytes);
+}
+
+\f
+/*
+ *
+ * Functional Description:
+ *
+ * Perform a DES encryption of a single 8-byte block producing
+ * another 8-byte block.
+ *
+ * Inputs:
+ *
+ * indata - Pointer to the input data
+ *
+ * Outputs:
+ *
+ * outdata - Pointer to the output data
+ *
+ * Return Value:
+ *
+ * None
+ *
+ */
+static DESencrypt_local( indata,outdata,key_schedule )
+DESblock *indata,*outdata;
+KEYschedule *key_schedule ;
+{
+ register int i;
+ register INT32 er,out;
+ register unsigned char *subkey;
+ INT32 index;
+ DESblock temp;
+
+ /*
+ * Perform the initial transformation.
+ */
+ INITIAL(temp.longwords, indata->bytes);
+
+ /*
+ * Perform the encryption operation.
+ */
+ for (i = 0; i < 16; i++)
+ {
+ /*
+ * Select the subkey for this round.
+ */
+ subkey = key_schedule->subkey[i];
+
+ /*
+ * Compute the index value to be used for the first 7 subkeys.
+ */
+ index = temp.longwords[1 - (i & 1)];
+ er = (index >> 1) | ((index & 1) ? 0x80000000 : 0);
+
+ /*
+ * Perform one round of E(input) ^ K through the combined S and
+ * P boxes.
+ */
+ out = sp[0][((er >> 26) & 0x3F) ^ *subkey++];
+ out |= sp[1][((er >> 22) & 0x3F) ^ *subkey++];
+ out |= sp[2][((er >> 18) & 0x3F) ^ *subkey++];
+ out |= sp[3][((er >> 14) & 0x3F) ^ *subkey++];
+ out |= sp[4][((er >> 10) & 0x3F) ^ *subkey++];
+ out |= sp[5][((er >> 6) & 0x3F) ^ *subkey++];
+ out |= sp[6][((er >> 2) & 0x3F) ^ *subkey++];
+ er = (index << 1) | ((index & 0x80000000) ? 1 : 0);
+ out |= sp[7][(er & 0x3F) ^ *subkey];
+
+ temp.longwords[i & 1] ^= out;
+ }
+
+ /*
+ * Now swap halves of the working block.
+ */
+ out = temp.longwords[0];
+ temp.longwords[0] = temp.longwords[1];
+ temp.longwords[1] = out;
+
+ /*
+ * Perform the final transformation.
+ */
+ FINAL(outdata->longwords, temp.bytes);
+}
+\f
+/*
+ *
+ * Functional Description:
+ *
+ * Expand a DES key from an 8-byte array into a key schedule. This
+ * expansion allows the later encryption routines to operate faster.
+ *
+ * Inputs:
+ *
+ * inkey - Pointer to an 8-byte input key
+ *
+ * Outputs:
+ *
+ * Return Value:
+ *
+ * None
+ *
+ */
+static void DES_load_key_local( key, key_schedule )
+register unsigned char *key;
+KEYschedule *key_schedule ;
+{
+ register int i,j,k;
+ unsigned char k1[56],k2[56];
+
+ /*
+ * Clear out the key schedule, in case it isn't already
+ */
+ memset(key_schedule, 0, sizeof(KEYschedule));
+
+ /*
+ * Compute the key for the first round as an array of 56 bits (k1).
+ */
+ for (i = 0; i < 56; i++)
+ k1[i] = (key[pc1byte[i]] & pc1bit[i]) ? 1 : 0;
+
+ /*
+ * Build the subkeys by rotating and selecting the bits from each
+ * iteration.
+ */
+ for (i = 0; i < 16; i++)
+ {
+ /*
+ * Rotate the initial key permutation the correct amount for
+ * this subkey, rotating each half independently.
+ */
+ for (j = 0; j < 56; j++)
+ k2[j] = k1[(k = j + totrot[i]) < (j < 28 ? 28 : 56) ? k : k - 28];
+
+ /*
+ * Select the final values for each subkey.
+ */
+ for (j = 0; j < 48; j++)
+ if (k2[pc2[j] - 1] != 0)
+ key_schedule->subkey[i][j/6] |= bytebit[j % 6] >> 2;
+ }
+}
+
+
+\f
+/*
+ *
+ * D E S _ C B C _ e n c r y p t
+ *
+ * Encrypt a buffer using DES in Cipher Block Chaining mode.
+ *
+ * Inputs:
+ * iv - Pointer to initialization vector or zero
+ * inbuf - Pointer to the input buffer
+ * isize - Size of the input buffer
+ * outbuf - Pointer to the output buffer (can be same as input)
+ *
+ * Outputs:
+ * outbuf - contains encrypted data
+ *
+ * Return Value:
+ * 0 - Buffer is not a multiple of 8 bytes
+ * 1 - Success
+ */
+static int DES_CBC_encrypt_local (iv , inbuf, isize, outbuf,key_schedule)
+unsigned char * iv, * inbuf, * outbuf ;
+int isize;
+KEYschedule *key_schedule ;
+{
+ unsigned long temp1[2] ;
+ unsigned long * inptr = (unsigned long *) inbuf;
+ unsigned long * outptr = (unsigned long *) outbuf;
+
+ /*
+ * Check that we have a good buffer size.
+ */
+ if ((isize & 0x7) != 0) return (0);
+
+ if (iv!=0) memcpy(temp1,iv,sizeof(temp1)); /* copy over initialization vector */
+ else memset(temp1,0,sizeof(temp1));
+
+ while (isize > 0) {
+
+ temp1[0] ^= * inptr ++ ; /* XOR previous ciphertext with next data */
+ temp1[1] ^= * inptr ++ ;
+
+ DESencrypt_local(temp1,temp1,key_schedule); /* encrypt */
+
+ * outptr ++ = temp1 [0]; /* copy out data */
+ * outptr ++ = temp1 [1];
+
+ isize -= 8;
+ }
+ return(1);
+}
+\f
+/*
+ *
+ * D E S _ C B C _ d e c r y p t
+ *
+ * Decrypt a buffer using DES in Cipher Block Chaining mode.
+ *
+ * Inputs:
+ * iv - Pointer to initialization vector or zero
+ * inbuf - Pointer to the input buffer
+ * isize - Size of the input buffer
+ * outbuf - Pointer to the output buffer (can be same as input)
+ *
+ * Outputs:
+ * outbuf - contains encrypted data
+ *
+ * Return Value:
+ * 0 - Buffer is not a multiple of 8 bytes
+ * 1 - Success
+ */
+static int DES_CBC_decrypt_local (iv , inbuf, isize, outbuf,key_schedule)
+char * iv, * inbuf, * outbuf ;
+int isize;
+KEYschedule *key_schedule ;
+{
+ unsigned long temp1[2], temp2[2];
+ unsigned long * inptr = (unsigned long *) inbuf;
+ unsigned long * outptr = (unsigned long *) outbuf;
+
+ /*
+ * Check that we have a good buffer size.
+ */
+ if ((isize & 0x7) != 0) return (0);
+
+ if (iv!=0) memcpy(temp1,iv,sizeof(temp1)); /* copy over initialization vector */
+ else memset(temp1,0,sizeof(temp1));
+
+ while (isize > 0) {
+ DESdecrypt_local(inptr,temp2,key_schedule); /* decrypt to temporary */
+
+ temp2[0] ^= temp1 [0]; /* XOR previous ciphertext with data */
+ temp2[1] ^= temp1 [1];
+
+ temp1[0] = * inptr ++ ; /* copy in ciphertext for next block XOR */
+ temp1[1] = * inptr ++ ;
+
+ * outptr ++ = temp2 [0]; /* copy out data */
+ * outptr ++ = temp2 [1];
+
+ isize -= 8;
+ }
+ return(1);
+}
+
+#endif
--- /dev/null
+/* $Header$ */
+
+OBJS = random.o \
+ random_BigNum.o \
+ bigrsacode.o \
+ bigkeygen.o \
+ bigsignverify.o
+
+DEFINES = -I. -I../../../include -I../bignum/h
+
+
+depend:: tables.h
+
+all:: tables.h $(OBJS)
+
+genutil(gentables,gentables.o,,)
+
+endian.h tables.h: gentables
+ ./gentables
+
+clean::
+ $(RM) tables.h endian.h
--- /dev/null
+/* RSAcrypto.h */
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+/* This code was derived in large part from Mark Shand's PRL Montgomery code. */
+
+/* In-line code for basic RSA routines */
+
+static void rsaencrypt_1();
+static void rsadecrypt_1();
+static void BnnModularProduct_1();
+static void BnnDyRaise_1 ();
+static unsigned BnnDyCanon_1 ();
+
+/*
+ *********************************************************************
+ *********************************************************************
+ ** **
+ ** W A R N I N G **
+ ** **
+ ** This software is subject to export restrictions under the **
+ ** U.S. Department of State's International Traffic in Arms **
+ ** Regulations (ITAR). This software must not be transmitted **
+ ** IN SOURCE FORM outside the United States or to a foreign **
+ ** national in the United States without a valid U.S. State **
+ ** Department export license. **
+ ** **
+ *********************************************************************
+ *********************************************************************
+*/
+
+#ifndef SPHINX_RSACRYPTO
+#define SPHINX_RSACRYPTO
+
+#ifndef SPHINX_ITAR
+#define SPHINX_ITAR
+static char copyright[] = "\n Copyright, 1989, 1990, Digital Equipment Corporation ";
+static char warning[]= "\n This software is subject to export restrictions under \
+\n the U.S. Department of State's International Traffic in Arms \
+\n Regulations (ITAR). This software must not be transmitted \
+\n in source form outside the United States or to a foreign \
+\n national in the United States without a valid U.S. State \
+\n Department export license. ";
+#endif
+
+#define assert(x) ((x)?0:dumpcore("x",__FILE__,__LINE__))
+#define TopBitInWord ((BigNumDigit)(1<<(BN_DIGIT_SIZE-1)))
+
+static BigNumDigit one[2*2*DigitLim] = { 1 };
+
+static int dumpcore(s,f,n)
+char *s,*f;
+int n;
+{
+ fflush(stdout);
+ fclose(stdout);
+ fprintf(stderr, "\nassertion failed file %s line %d: %s\n", f, n, s);
+ fclose(stderr);
+ abort();
+}
+
+static void rsaencrypt_1(inblk,outblk,keys)
+BigNum inblk, outblk;
+RSAKeyStorage * keys;
+{
+ static BigNumDigit x[1] ;
+ char *charp;
+ register int shift = 0;
+ BigNum n = keys->n, e = keys->e;
+ int nl = keys->nl, el = keys->el;
+ int nTop = BnnNumDigits(n,nl) ;
+ int BLOCKLEN = nTop*BN_DIGIT_SIZE - BnnNumLeadingZeroBitsInDigit(n[nTop-1]) - 1;
+ int BLOCKBYTES = BLOCKLEN/8;
+ int BLOCKWDS = BLOCKLEN/BN_DIGIT_SIZE + 1;
+ BnnInit();
+ x[0] = 0;
+ charp = (char *) x;
+ *charp = 1;
+ if (x[0] != (BigNumDigit) 1 && BLOCKBYTES % sizeof(BigNumDigit) != 0)
+ {
+ /* This machine is big-endian */
+ shift = ((sizeof(BigNumDigit) * BLOCKWDS) - BLOCKBYTES) * 8;
+ }
+ *charp = 0;
+
+ inblk[nl-1] >>= shift;
+ BnnDyRaise_1 (outblk, inblk, e, el, n, keys->beta2n, keys->nINV, nl);
+ BnnClose();
+}
+
+static void rsadecrypt_1(inblk, outblk,keys)
+BigNum inblk, outblk;
+RSAKeyStorage * keys ;
+{
+ static BigNumDigit x[3*DigitLim], xp[2*DigitLim], xq[2*DigitLim] ;
+ char *charp;
+ register int shift = 0;
+ BigNum n = keys->n, p = keys->p, q = keys->q ,
+ pINV = keys->pINV, qINV = keys->qINV;
+ int nl = keys->nl, pl = keys->pl, ql = keys->ql ;
+ int nTop = BnnNumDigits(n,nl) ;
+ int BLOCKLEN = nTop*BN_DIGIT_SIZE - BnnNumLeadingZeroBitsInDigit(n[nTop-1]) - 1;
+ int BLOCKBYTES = BLOCKLEN/8;
+ int BLOCKWDS = BLOCKLEN/BN_DIGIT_SIZE + 1;
+
+ BnnInit();
+ x[nl]=0;
+ charp = (char *) (x+nl);
+ *charp = 1;
+ if (x[nl] != (BigNumDigit) 1)
+ {
+ /* This machine is big-endian */
+ shift = ((sizeof(BigNumDigit) * BLOCKWDS) - BLOCKBYTES) * 8;
+ }
+ {
+ /* xp <- inblk/B^PL [p] */
+ BnnSetToZero(xp, 2*pl);
+ BnnAssign(xp+pl, inblk+pl, nl-pl);
+ BnnModularProduct_1 (xp, pl+pl, inblk, pl, one, pl, p, pl, pINV);
+ /* xq <- inblk/B^QL [q] */
+ BnnSetToZero(xq, 2*ql);
+ BnnAssign(xq+ql, inblk+ql, nl-ql);
+ BnnModularProduct_1 (xq, ql+ql, inblk, ql, one, ql, q, ql, qINV);
+ /* pass beta3[pq] coeff. to compensate for prediv by B^[PQ]L */
+ BnnDyRaise_1 (xp, xp+pl, keys->dp, keys->dpl, p, keys->beta3p, pINV, pl);
+ BnnDyRaise_1 (xq, xq+ql, keys->dq, keys->dql, q, keys->beta3q, qINV, ql);
+ BnnSetToZero(xp+pl, nl-pl);
+ BnnSetToZero(xq+ql, nl-ql);
+ BnnSubtract(xp,pl,xq,ql,1);
+ while((BnnGetDigit(xp+(pl-1))&TopBitInWord)!=0) BnnAdd(xp,pl,p,pl,0);
+ BnnSetToZero(x,3*pl);
+ BnnModularProduct_1 (x+pl,pl+pl,xp,pl,keys->cr,pl,p,pl,pINV);
+ BnnModularProduct_1 (x,pl+pl,keys->beta2p,pl,x+pl+pl,pl,p,pl,pINV);
+ BnnDyCanon_1 (x+pl, p, pl);
+ BnnMultiply(xq, nl, x+pl, pl, q , ql);
+ xq[2*pl-1] <<= shift;
+ }
+ BnnClose();
+ BnnAssign(outblk, xq, nl);
+}
+
+
+static void BnnModularProduct_1 (p,pl,a,al,b,bl,m,ml,mu)
+BigNum p,b,a,m,mu;
+unsigned pl,al,bl,ml;
+{
+ /* p is length pl */
+ /* a has length al, b has length bl, m has length ml, mu has length >= 2 */
+ /* mu is -m[0..1..] mod BN_DIGIT_SIZE*2 */
+ /* after computation
+ p[0..bl-1] = 0
+ (p[bl..pl-1] * beta^bl) mod m = p+(a*b) mod m
+ */
+ BigNumDigit qt[2*DigitLim];
+ assert(pl <= 2*DigitLim);
+
+ BnnMultiply(p, pl, a, al, b, bl);
+ BnnSetToZero(qt, pl);
+ BnnMultiply(qt, pl, p, pl-ml, mu, ml);
+ BnnMultiply(p, pl, m, ml, qt, pl-ml);
+}
+
+static unsigned BnnDyCanon_1 (x, m, ml)
+BigNum x, m;
+unsigned ml;
+{
+ int redcount = 0;
+ while (BnnCompare(x, ml, m, ml) > 0)
+ {
+ BnnSubtract(x, ml, m, ml, 1);
+ redcount++;
+ }
+ return redcount;
+}
+
+#define MAX_LN2PWR 4
+#define MAXPWR (1<<MAX_LN2PWR)
+
+static void BnnDyRaise_1 (x, a, e, el, m, beta2ml, mu, ml)
+BigNum x, a, e, m, beta2ml;
+BigNum mu;
+unsigned ml, el;
+{
+ static BigNumDigit sBUF[DigitLim];
+ static BigNumDigit tBUF[DigitLim*10];
+ register BigNum s = sBUF, t = tBUF;
+ static BigNum aCache[MAXPWR];
+ BigNumDigit ed;
+ BigNumDigit mask;
+ int eindex, eoffset, nibble, i;
+ static BigNumDigit aCacheBUF[MAXPWR*2*DigitLim];
+ int pwr,ln2pwr;
+
+ /* Exponentiate: x = a^e mod m */
+ if (BnnNumDigits(e, el) > 1)
+ ln2pwr = MAX_LN2PWR;
+ else
+ ln2pwr = 1;
+ pwr = (1<<ln2pwr);
+ /* We work high to low in the exponent and make a special case
+ of the topmost bit in e */
+ /* check that m is within range */
+ assert((m[ml-1] & (3<<(BN_DIGIT_SIZE-2))) == 0);
+
+ /* prime the aCache */
+ t = aCacheBUF+2*DigitLim-ml;
+ aCache[1] = s = aCacheBUF+2*DigitLim;
+ BnnSetToZero(t, 2*ml);
+ BnnModularProduct_1 (t, ml+ml, a, ml, beta2ml, ml, m, ml, mu);
+ for (i = 2; i < pwr; i++)
+ {
+ t += 2*DigitLim;
+ BnnSetToZero(t, 2*ml);
+ BnnModularProduct_1 (t, ml+ml, s, ml, aCache[1], ml, m, ml, mu);
+ aCache[i] = (s += 2*DigitLim);
+ }
+
+ eindex = BnnNumDigits(e, el)-1;
+ ed = e[eindex];
+ eoffset = ((BN_DIGIT_SIZE-BnnNumLeadingZeroBitsInDigit(ed)-1) & ~(ln2pwr-1));
+ mask = (pwr-1) << eoffset;
+ nibble = (ed&mask)>>eoffset;
+ mask >>= ln2pwr;
+ eoffset -= ln2pwr;
+ s = aCache[nibble];
+
+ while (eindex >= 0)
+ {
+ ed = e[eindex--];
+ while (mask)
+ {
+ /* Square ln2pwr times */
+ t = tBUF;
+ BnnSetToZero(t, 2*(ln2pwr+1)*ml);
+ for (i = 0; i < ln2pwr; i++)
+ {
+ BnnModularProduct_1 (t, ml+ml, s, ml, s, ml, m, ml, mu);
+ s = t+ml; t += 2*ml;
+ }
+ nibble = (ed&mask)>>eoffset;
+ if (nibble)
+ {
+ /* Multiply */
+ BnnModularProduct_1 (t, ml+ml, s, ml, aCache[nibble], ml, m, ml, mu);
+ BnnAssign(sBUF, t+ml, ml);
+ }
+ else
+ BnnAssign(sBUF, s, ml);
+ mask >>= ln2pwr;
+ eoffset -= ln2pwr;
+ s = sBUF;
+ }
+ eoffset = BN_DIGIT_SIZE-ln2pwr;
+ mask = (pwr-1) << eoffset;
+ }
+ /* restore representation */
+
+ t = tBUF;
+ BnnSetToZero(t, 2*ml);
+ BnnModularProduct_1 (t, ml+ml, s, ml, one, ml, m, ml, mu);
+ BnnAssign(x, t+ml, ml);
+}
+
+#endif
--- /dev/null
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+/* This code was derived from Mark Shand's PRL Montgomery code. */
+
+#include <stdio.h>
+#include <time.h>
+#include <sys/types.h>
+#ifndef SYSV
+#include <sys/timeb.h>
+#endif
+
+#include "BigZ.h"
+#include "BigRSA.h"
+#include "bigrsacode.h"
+#include "bigkeygen.h"
+
+#ifdef mips
+#undef BnnSetToZero
+#endif
+
+#define KEY_LINE 64
+#define KEY_RADIX 16
+
+/*
+#define DEBUG_1
+*/
+
+/* Global storage indicating whether to print prime progress reports */
+
+int bigkeygenPrintStatistics = 0;
+
+#ifdef DEBUG
+#undef DEBUG
+#endif
+
+/*
+ * One-half the difference between the lengths of p and q, in bits
+ */
+#define PRIME_BIT_DIFF 3
+
+/*
+ * Local modular product routines
+ */
+
+/* put in-line RSA routines here */
+
+#include "RSAcrypto.h"
+
+static void BnnGCD_1();
+static void modpwr2_1();
+static BigNum muB_1();
+static int bigprime();
+
+/*
+ * newRSAKey generates a new RSA key instance.
+ *
+ * bitlen length of primes, in bits. Modulus will be
+ * approximately 2*bitlen
+ * keys RSAKeyStorage structure for new key
+ */
+
+int newRSAKey ( bitlen , keys )
+int bitlen ;
+RSAKeyStorage *keys ;
+{
+ BigNum p = keys->p, q = keys->q ;
+ unsigned lowbits = 1, confidence = 20, pl, ql;
+#ifdef DEBUG
+ clock_t mark, tenths;
+ struct timeb start_time , end_time ;
+#endif
+
+ if ((bitlen<128)||(bitlen>MaxPrimeBits)) return (0);
+
+ memset(keys,0,sizeof(RSAKeyStorage));
+ BnnInit();
+
+#ifdef DEBUG
+ mark = clock();
+ ftime (&start_time);
+#endif
+
+ bigprime(p, &pl, bitlen+PRIME_BIT_DIFF, lowbits, confidence, 0);
+ do {
+ bigprime(q, &ql, bitlen-PRIME_BIT_DIFF, lowbits, confidence, 0);
+ } while (BnnCompare(p, pl, q, ql) == 0);
+
+#ifdef DEBUG
+ mark = clock() - mark ;
+ ftime (&end_time);
+
+#ifdef ultrix
+#ifndef CLOCKS_PER_SEC
+#define CLOCKS_PER_SEC 1000000
+#endif
+ tenths = (100*(mark%CLOCKS_PER_SEC))/CLOCKS_PER_SEC ;
+ mark /= CLOCKS_PER_SEC ;
+#else
+ tenths = (100*(mark%CLK_TCK))/CLK_TCK ;
+ mark /= CLK_TCK ;
+#endif
+
+ printf ("\n/* Primes found in %d.%02d seconds of process time*/\n", mark, tenths );
+ mark = end_time.time - start_time.time ;
+ { long xt = (unsigned long) end_time.millitm - (unsigned long) start_time.millitm ;
+ if (xt<0) { mark--; xt = 1000 - xt;}
+ printf ("\n/* Primes found in %d.%03d elapsed seconds */\n",
+ end_time.time-start_time.time, xt );
+ }
+#endif
+
+ if (BnnCompare(p, pl, q, ql) == -1) {
+ unsigned tpl = pl;
+ BigNumDigit tp[DigitLim];
+ BnnSetToZero(tp,DigitLim);
+ BnnAssign(tp,p,pl);
+ BnnSetToZero(p,pl);
+ BnnAssign(p,q,ql);
+ BnnAssign(q,tp,pl);
+ pl = ql;
+ ql = tpl;
+ }
+
+ keys->pl = pl;
+ keys->ql = ql;
+
+ /*
+ * Set exponent to F16 and compute modulus.
+ */
+ BnnSetDigit(keys->e, (BigNumDigit) ((1<<16)+1));
+ keys->el = 1;
+
+ BnnMultiply(keys->n, pl+ql, p, pl, q, ql),
+ keys->nl = pl+ql;
+
+ if (FinishKey(keys)==0) return (0);
+
+ if (TestRSAKeys(keys)!=1) {
+#ifdef DEBUG
+printf("\nFailed.\n");
+#endif
+ return(0);
+ }
+
+ BnnClose();
+ return(1);
+}
+
+
+/*
+ * Prime-finding routines
+ */
+
+
+static BigNumDigit smallprime[]=
+{3,5,7,11,13,17,19,23,29,31,37,41,43,53,59,
+61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,
+163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,
+257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,
+359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,
+461,463,467,479,487,491,499 };
+
+
+/*
+ * Test for primality.
+ */
+
+static int IsPrime(n,nl,confidence)
+BigNum n;
+int nl;
+{
+ int i;
+ static BigNumDigit x[DigitLim],
+ y[2*DigitLim],
+ beta2n[2*DigitLim+1],
+ nINV [2*DigitLim] ;
+
+ for(i=0;i<=(sizeof(smallprime)/sizeof(BigNumDigit));i++)
+ if(BnnDivideDigit(y,n,nl+1,smallprime[i])==0) goto exit ;
+
+ muB_1(nINV, n, nl*BN_DIGIT_SIZE);
+ modpwr2_1(beta2n, 2, n, nl);
+ BnnSetToZero (x, nl);
+
+ for(i=0;i<=confidence;i++) {
+ x[0]+= smallprime[i] ;
+ BnnDyRaise_1(y, x, n, nl, n, beta2n, nINV, nl);
+ BnnDyCanon_1(y, n, nl);
+ if (BnnCompare(y, nl, x, nl)) goto exit;
+ }
+ return(1);
+
+exit:
+ return(0);
+}
+
+/*
+ * Generate a big prime.
+ */
+static bigprime (n,nlen,bitlen,lowbits,confidence,stats)
+BigNum n;
+unsigned *nlen;
+int bitlen;
+BigNumDigit lowbits;
+int confidence;
+unsigned *stats;
+{
+ char * z ;
+ static char sieve [1000];
+ int i,j;
+ BigNumDigit r, s, q[DigitLim] ;
+ unsigned nl =(bitlen+(BN_DIGIT_SIZE-1))/BN_DIGIT_SIZE ;
+ unsigned ntop = nl;
+
+ if((((bitlen-1)%BN_DIGIT_SIZE)+1)>=(BN_DIGIT_SIZE-1)) nl++;
+ *nlen = nl;
+ BnnSetToZero(n,nl+1);
+ while(1) {
+ random_BigNum(n,ntop);
+ n[nl-1]&=(1<<((BN_DIGIT_SIZE)-(nl*(BN_DIGIT_SIZE)-bitlen))) -1 ;
+ n[(bitlen-1)/BN_DIGIT_SIZE] |= 1<<((bitlen-1)%BN_DIGIT_SIZE);
+ n[(bitlen-2)/BN_DIGIT_SIZE] |= 1<<((bitlen-2)%BN_DIGIT_SIZE);
+ n[0]&=~1;
+
+ if(bigkeygenPrintStatistics)
+ printf("\nCandidate Random Number: %s\n",BzToString(BzFromBigNum(n,nl),16));
+
+ z = &sieve[0] ;
+ for (i=0;i<1000;i=i+2){*z++=1;*z++=0;};
+ r = BnnDivideDigit(q,n,nl+1,(BigNumDigit)3);
+ if (r==0) r = (BigNumDigit) 3;
+ r--;
+ z = &sieve[3-r] ;
+ for (j=3-r;j<1000;j+=3) {*z=1;z+=3;}
+
+ for (s=3;s<10000;s+=2) {
+ for (j=0; j<5; j++)if ((s>smallprime[j])&&(0==(s%smallprime[j]))) goto nexts;
+ r = BnnDivideDigit(q,n,nl+1,s);
+ if (r==0) r = s;
+ z = &sieve[s-r] ;
+ for (j=s-r;j<1000;j+=s) {*z=1;z+=s;}
+ nexts: ;
+ }
+ for(i=0;i<1000;i++) {
+ if (!sieve[i]) {
+
+ if(bigkeygenPrintStatistics) printf("|"),fflush(stdout);
+
+ if (IsPrime(n,nl,5)) goto exit;
+ }
+ BnnAddCarry(n,nl,1); /* try next one */
+ }
+ }
+exit:
+
+if(bigkeygenPrintStatistics) printf(""), fflush(stdout);
+
+}
+
+
+/*
+ * This routine expects modulus n and exponent e to be initialized
+ * in the RSAKeyStorage structure supplied. It computes the rest of
+ * the key components based on what is provided. If p and q are there
+ * it also makes sure a complete private key is initialized.
+ */
+int FinishKey (keys)
+RSAKeyStorage *keys;
+{
+ static BigNumDigit g[4*DigitLim], wgcd[12*DigitLim],
+ r[4*DigitLim], pq[4*DigitLim], d[4*DigitLim], z[4*DigitLim];
+
+ BigNum n = keys->n, dp = keys->dp, dq = keys->dq, cr = keys->cr,
+ e = keys->e, p = keys->p, q = keys->q ;
+
+ unsigned nl=keys->nl, pl=keys->pl, ql=keys->ql, tmp,
+ dpl = keys->dpl, dql = keys->dql ;
+
+ /*
+ * If primes are supplied, generate dp, dq, and cr if needed.
+ * Assume cr there if dp and dq are.
+ */
+
+ if (pl && ql && ((dpl == 0)||(dql ==0)) ) {
+ BnnAssign(pq, n, nl);
+ BnnSubtract(pq, nl, p, pl, 1);
+ BnnSubtract(pq, nl, q, ql, 1);
+ BnnAddCarry(pq, nl, 1);
+ BnnGCD_1(g, d, r, e, pq, wgcd, nl);
+ if (BnnCompare(g,nl,one,nl)!=0) {
+#ifdef DEBUG
+printf("GCD failed to generate private key exponent.\n");
+#endif
+ return(0);
+ }
+ BnnAssign(z, d, nl);
+ z[nl] = 0;
+ BnnAssign(pq, p, pl);
+ BnnSubtractBorrow(pq, pl, 0);
+ BnnDivide(z, nl+1, pq, tmp=BnnNumDigits(pq, pl));
+ BnnSetToZero(z+tmp, nl+1-tmp);
+ BnnAssign(dp, z, (keys->dpl)=BnnNumDigits(z,nl));
+
+ BnnAssign(z, d, nl);
+ z[nl] = 0;
+ BnnAssign(pq, q, ql);
+ BnnSubtractBorrow(pq, ql, 0);
+ BnnDivide(z, nl+1, pq, tmp=BnnNumDigits(pq, ql));
+ BnnSetToZero(z+tmp, nl+1-tmp);
+ BnnAssign(dq, z, (keys->dql)=BnnNumDigits(z,nl));
+
+ BnnGCD_1(g,r,cr,p,q,wgcd,pl);
+ if ((BnnGetDigit(cr+(pl-1))&TopBitInWord)!=0) BnnAdd(cr,pl,p,pl,0);
+ }
+
+ modpwr2_1(z, 2, n, nl);
+ BnnAssign(keys->beta2n, z, nl);
+ muB_1(keys->nINV, n, nl*BN_DIGIT_SIZE);
+
+ if (pl&&ql) {
+ modpwr2_1(z, 3, p, pl);
+ BnnAssign(keys->beta3p, z, pl);
+ modpwr2_1(z, 2, p, pl);
+ BnnAssign(keys->beta2p, z, pl);
+ modpwr2_1(z, 3, q, ql);
+ BnnAssign(keys->beta3q, z, ql);
+ muB_1(keys->pINV, p, pl*BN_DIGIT_SIZE);
+ muB_1(keys->qINV, q, ql*BN_DIGIT_SIZE);
+ }
+
+#ifdef DEBUG_1
+ printf("\n");
+ printf("p = %s\n", BzToString(BzFromBigNum(p, pl), 16));
+ printf("q = %s\n", BzToString(BzFromBigNum(q, ql), 16));
+ printf("n = %s\n", BzToString(BzFromBigNum(n, nl), 16));
+ printf("e = %s\n", BzToString(BzFromBigNum(e, nl), 16));
+ printf("d = %s\n", BzToString(BzFromBigNum(d, nl), 16));
+ printf("dp = %s\n", BzToString(BzFromBigNum(dp, dpl), 16));
+ printf("dq = %s\n", BzToString(BzFromBigNum(dq, dql), 16));
+ printf("cr = %s\n", BzToString(BzFromBigNum(cr, pl), 16));
+ fflush(stdout);
+#endif
+
+
+ return(1);
+}
+
+
+static BigNum muB_1(res, zz, bits)
+BigNum res, zz;
+int bits;
+{
+ /* Compute -z^-1 mod 2^bits */
+#define muBLIM 40
+ BigNumDigit n[muBLIM];
+ BigNumDigit msk[muBLIM], z[muBLIM];
+ unsigned nl = (bits+BN_DIGIT_SIZE-1)/BN_DIGIT_SIZE;
+ int i;
+
+ if (nl > muBLIM)
+ {
+ fprintf(stderr, "Limit check in %s:muB_1 line %d\n", __FILE__, __LINE__);
+ abort();
+ }
+
+ BnnSetToZero(n, nl);
+ BnnComplement(n,nl);
+ BnnSetToZero(res, nl);
+ BnnSetToZero(msk, nl);
+ BnnSetDigit(msk, 1);
+ BnnAssign(z, zz, nl);
+ BnnShiftRight(z,nl,1);
+ while (bits--)
+ {
+ if (BnnIsDigitOdd(*n))
+ {
+ for (i = 0; i < nl; i++)
+ BnnOrDigits(res+i, msk[i]);
+ BnnShiftRight(n,nl,1);
+ BnnSubtract(n, nl, z, nl, 1);
+ }
+ else
+ BnnShiftRight(n,nl,1);
+ BnnShiftLeft(msk,nl,1);
+ }
+ return res;
+}
+
+static void modpwr2_1(result, pwr, m, ml)
+BigNum result, m;
+unsigned pwr, ml;
+{ unsigned tmp;
+ BnnSetToZero(result, pwr*ml);
+ BnnSetDigit(result+pwr*ml, (BigNumDigit) 1);
+ BnnDivide(result, pwr*ml+1, m, tmp=BnnNumDigits(m, ml));
+ BnnSetToZero(result+tmp, pwr*ml+1-tmp);
+}
+
+
+static void BnnGCD_1(gcd, A, B, U, V, work, len)
+BigNum gcd, A, B, U, V, work;
+int len;
+{
+ /* Extended binary GCD
+ code based on Knuth Vol.2 Second Edition
+ section 4.5.2 Answers to Exercises page 599
+ */
+ /* Note: len must be large enough to hold 2*U or 2*V */
+ /* "work" is a BigNum of length 3*len */
+ BigNumDigit k;
+ BigNum u1,u2,u3, v1,v2,v3;
+ BigNum t1,t2,t3;
+ u1 = A; u2 = B; u3 = gcd;
+ v1 = work; v2 = work + len; v3 = work + 2*len;
+
+ k = 0;
+ while (!BnnIsDigitOdd(*U) && !BnnIsDigitOdd(*V))
+ {
+ BnnShiftRight(U, len, 1);
+ BnnShiftRight(V, len, 1);
+ k++;
+ }
+ BnnSetToZero(u1, len); BnnSetDigit(u1, (BigNumDigit) 1);
+ BnnSetToZero(u2, len);
+ BnnAssign(u3, U, len);
+ if (BnnIsDigitOdd(*U))
+ {
+ t1 = v1; t2 = v2; t3 = v3;
+ BnnSetToZero(v1, len);
+ BnnSetToZero(v2, len); BnnComplement(v2, len);
+ BnnSetToZero(v3, len); BnnSubtract(v3, len, V, len, 1);
+ }
+ else
+ {
+ t1 = u1; t2 = u2; t3 = u3;
+ BnnAssign(v1, V, len);
+ BnnSetToZero(v2, len); BnnSetDigit(v2, (BigNumDigit) 1);
+ BnnSubtract(v2, len, U, len, 1);
+ BnnAssign(v3, V, len);
+ }
+#ifdef PRINT_LEVEL2
+ printf("#[%d %d %d ] [ %d %d %d ]\n", *u1,*u2,*u3, *v1,*v2,*v3);
+#endif
+ while (!BnnIsZero(t3, len))
+ {
+ while (!BnnIsDigitOdd(*t3))
+ {
+ BigNumDigit sign;
+ if (!BnnIsDigitOdd(*t1) && !BnnIsDigitOdd(*t2))
+ {
+ sign = BnnGetDigit(t1+(len-1)) & TopBitInWord;
+ BnnShiftRight(t1, len, 1);
+ BnnOrDigits(t1+(len-1), sign);
+ sign = BnnGetDigit(t2+(len-1)) & TopBitInWord;
+ BnnShiftRight(t2, len, 1);
+ BnnOrDigits(t2+(len-1), sign);
+ }
+ else
+ {
+ BnnAdd(t1, len, V, len, 0);
+ sign = BnnGetDigit(t1+(len-1)) & TopBitInWord;
+ BnnShiftRight(t1, len, 1);
+ BnnOrDigits(t1+(len-1), sign);
+ BnnSubtract(t2, len, U, len, 1);
+ sign = BnnGetDigit(t2+(len-1)) & TopBitInWord;
+ BnnShiftRight(t2, len, 1);
+ BnnOrDigits(t2+(len-1), sign);
+ }
+ sign = BnnGetDigit(t3+(len-1)) & TopBitInWord;
+ BnnShiftRight(t3, len, 1);
+ BnnOrDigits(t3+(len-1), sign);
+ }
+ if (t1 == v1) /* a cheap way to recall what state we are in */
+ {
+ BnnComplement(v1, len);
+ BnnAdd(v1, len, V, len, 1);
+ BnnComplement(v2, len);
+ BnnAddCarry(v2, len, 1);
+ BnnSubtract(v2, len, U, len, 1);
+ BnnComplement(v3, len);
+ BnnAddCarry(v3, len, 1);
+ }
+ if (BnnCompare(u3, len, v3, len) > 0)
+ {
+ BnnSubtract(u1, len, v1, len, 1);
+ BnnSubtract(u2, len, v2, len, 1);
+ BnnSubtract(u3, len, v3, len, 1);
+ t1 = u1; t2 = u2; t3 = u3;
+ }
+ else
+ {
+ BnnComplement(v1, len);
+ BnnAdd(v1, len, u1, len, 1);
+ BnnComplement(v2, len);
+ BnnAdd(v2, len, u2, len, 1);
+ BnnComplement(v3, len);
+ BnnAdd(v3, len, u3, len, 1);
+ t1 = v1; t2 = v2; t3 = v3;
+ }
+
+ if (BnnGetDigit(t1+(len-1)) & TopBitInWord)
+ {
+ BnnAdd(t1, len, V, len, 0);
+ BnnSubtract(t2, len, U, len, 1);
+ }
+#ifdef PRINT_LEVEL2
+ printf(">[%d %d %d ] [ %d %d %d ]\n", *u1,*u2,*u3, *v1,*v2,*v3);
+#endif
+ }
+ while (k-- > 0)
+ BnnShiftLeft(u3, len, 1);
+}
+
+
+/**********************************************************************/
+
+static char *TestData = "Now is the time for all good men to come to the aid of their" ;
+static BigNumDigit test_in [2*DigitLim], test1 [2*DigitLim], test2 [2*DigitLim] ;
+
+int TestRSAKeys(key)
+RSAKeyStorage *key ;
+{
+ int nl=key->nl;
+ int ll = BnnNumDigits(key->n,nl);
+
+ memset(test_in,0,sizeof(test_in));
+ memset(test1,0,sizeof(test1));
+ memset(test2,0,sizeof(test2));
+ strcpy((char *)test_in,TestData);
+ BnnSetToZero(test_in+ll-2,(nl-ll)+3);
+#ifdef DEBUG
+printf("\nPrivate Key Encrypt/Decrypt Test.");
+printf("\nInput(hex): %s", BzToString(BzFromBigNum(test_in, nl), 16));
+printf("\nInput(string): %s", test_in);
+#endif
+ rsaencrypt_1(test_in,test1,key);
+#ifdef DEBUG
+printf("\nEncrypted: %s", BzToString(BzFromBigNum(test1, nl), 16));
+#endif
+ rsadecrypt_1(test1,test2,key);
+#ifdef DEBUG
+printf("\nDecrypted: %s", BzToString(BzFromBigNum(test2, nl), 16));
+printf("\n");
+#endif
+ if (BnnCompare(test_in,nl,test2,nl) != 0) {
+#ifdef DEBUG
+printf("\nKey Test Failed.\n");
+#endif
+ return(0);
+ }
+#ifdef DEBUG
+printf("\nKey Test Passed.\n");
+#endif
+ return(1);
+}
+
+static int Test2RSAPrivate_1(key)
+RSAKeyStorage *key ;
+{
+ int nl=key->nl;
+ int ll = BnnNumDigits(key->n,nl);
+
+ memset(test_in,0,sizeof(test_in));
+ memset(test1,0,sizeof(test1));
+ memset(test2,0,sizeof(test2));
+ strcpy((char *)test_in,TestData);
+ BnnSetToZero(test_in+ll-2,(nl-ll)+3);
+#ifdef DEBUG
+ printf("\nPrivate Key Decrypt/Encrypt Test.");
+ printf("\nInput(hex): %s", BzToString(BzFromBigNum(test_in, nl), 16));
+ printf("\nInput(string): %s", test_in);
+#endif
+ rsadecrypt_1(test_in,test1,key);
+#ifdef DEBUG
+printf("\nSigned: %s", BzToString(BzFromBigNum(test1, nl), 16));
+#endif
+ rsaencrypt_1(test1,test2,key);
+#ifdef DEBUG
+printf("\nVerified: %s", BzToString(BzFromBigNum(test2, nl), 16));
+printf("\n");
+#endif
+ if (BnnCompare(test_in,nl,test2,nl) != 0) {
+#ifdef DEBUG
+printf("\nKey Test Failed.\n");
+#endif
+ return(0);
+ }
+ return(1);
+}
+
+
+PrintBigNum(n,nl,radix)
+BigNum n;
+int radix, nl;
+{
+ static char oneline [KEY_LINE+1];
+ char *p = BzToString(BzFromBigNum(n,nl), radix);
+
+ oneline[KEY_LINE]='\0';
+ while(*p != '\0'){
+ strncpy(oneline,p,KEY_LINE);
+ printf("\n %s",oneline);
+ p+=((strlen(p)>KEY_LINE)?KEY_LINE:strlen(p));
+ }
+}
+
+int PrintTestKey (Keys)
+RSAKeyStorage *Keys;
+{
+ int i;
+
+ printf("\ne: (%d BigNumDigit", Keys->el);
+ if(Keys->el > 1) printf("s) "); else printf(")");
+ PrintBigNum(Keys->e,Keys->el,KEY_RADIX);
+ printf("\nn: (%d BigNumDigits) ", Keys->nl);
+ PrintBigNum(Keys->n,Keys->nl,KEY_RADIX);
+
+ if (Keys->pl) { printf("\np: (%d BigNumDigits) ", Keys->pl);
+ PrintBigNum(Keys->p,Keys->pl,KEY_RADIX);
+ printf("\nq: (%d BigNumDigits) ", Keys->ql);
+ PrintBigNum(Keys->q,Keys->ql,KEY_RADIX);
+ printf("\ndp: (%d BigNumDigits) ", Keys->dpl);
+ PrintBigNum(Keys->dp, Keys->dpl,KEY_RADIX);
+ printf("\ndq: (%d BigNumDigits) ", Keys->dql);
+ PrintBigNum(Keys->dq, Keys->dql,KEY_RADIX);
+ printf("\ncr: ");
+ PrintBigNum(Keys->cr, Keys->pl,KEY_RADIX);
+ }
+
+ i=BnnNumDigits(Keys->nINV,sizeof(*Keys->nINV)*sizeof(int));
+ printf("\nnINV: (%d BigNumDigits) ", i);
+ PrintBigNum(Keys->nINV, i, KEY_RADIX);
+
+ i=BnnNumDigits(Keys->beta2n,sizeof(*Keys->beta2n)*sizeof(int));
+ printf("\nbeta2n: (%d BigNumDigits) ", i);
+ PrintBigNum(Keys->beta2n, i,KEY_RADIX);
+
+ if(Keys->pl) {
+ i=BnnNumDigits(Keys->pINV,sizeof(*Keys->pINV)*sizeof(int));
+ printf("\npINV: (%d BigNumDigits) ", i);
+ PrintBigNum(Keys->pINV, i,KEY_RADIX);
+
+ i=BnnNumDigits(Keys->qINV,sizeof(*Keys->qINV)*sizeof(int));
+ printf("\nqINV: (%d BigNumDigits) ", i);
+ PrintBigNum(Keys->qINV, i,KEY_RADIX);
+
+
+ i=BnnNumDigits(Keys->beta2p,sizeof(*Keys->beta2p)*sizeof(int));
+ printf("\nbeta2p: (%d BigNumDigits) ", i);
+ PrintBigNum(Keys->beta2p, i,KEY_RADIX);
+
+ i=BnnNumDigits(Keys->beta3p,sizeof(*Keys->beta3p)*sizeof(int));
+ printf("\nbeta3p: (%d BigNumDigits) ", i);
+ PrintBigNum(Keys->beta3p, i,KEY_RADIX);
+
+ i=BnnNumDigits(Keys->beta3q,sizeof(*Keys->beta3q)*sizeof(int));
+ printf("\nbeta3q: (%d BigNumDigits) ", i);
+ PrintBigNum(Keys->beta3q, i,KEY_RADIX);
+ }
+
+ printf("\n");
+ fflush(stdout);
+}
+
+
+int PrintPubKey (Keys)
+RSAKeyStorage *Keys;
+{
+ int i=BnnNumDigits(Keys->n,Keys->nl);
+ i = i*BN_DIGIT_SIZE - BnnNumLeadingZeroBitsInDigit(Keys->n[i-1]);
+
+ printf("\ne: (%d BigNumDigit", Keys->el);
+ if(Keys->el > 1) printf("s) "); else printf(")");
+ PrintBigNum(Keys->e,Keys->el,KEY_RADIX);
+ printf("\nn: (%d BigNumDigits, %d bits) ", Keys->nl, i);
+ PrintBigNum(Keys->n,Keys->nl,KEY_RADIX);
+
+ printf("\n");
+ fflush(stdout);
+}
+
+int PrintPrivKey (Keys)
+RSAKeyStorage *Keys;
+{
+ int i=BnnNumDigits(Keys->n,Keys->nl);
+ i = i*BN_DIGIT_SIZE - BnnNumLeadingZeroBitsInDigit(Keys->n[i-1]);
+
+ printf("\ne: (%d BigNumDigit", Keys->el);
+ if(Keys->el > 1) printf("s) "); else printf(")");
+ PrintBigNum(Keys->e,Keys->el,KEY_RADIX);
+ printf("\nn: (%d BigNumDigits, %d bits) ", Keys->nl, i);
+ PrintBigNum(Keys->n,Keys->nl,KEY_RADIX);
+
+ if (Keys->pl) { printf("\np: (%d BigNumDigits) ", Keys->pl);
+ PrintBigNum(Keys->p,Keys->pl,KEY_RADIX);
+ printf("\nq: (%d BigNumDigits) ", Keys->ql);
+ PrintBigNum(Keys->q,Keys->ql,KEY_RADIX);
+ printf("\ndp: (%d BigNumDigits) ", Keys->dpl);
+ PrintBigNum(Keys->dp, Keys->dpl,KEY_RADIX);
+ printf("\ndq: (%d BigNumDigits) ", Keys->dql);
+ PrintBigNum(Keys->dq, Keys->dql,KEY_RADIX);
+ printf("\ncr: ");
+ PrintBigNum(Keys->cr, Keys->pl,KEY_RADIX);
+ }
+ else printf("\n no private key parameters.");
+
+ printf("\n");
+ fflush(stdout);
+ }
+
+
+/*********************************************************************/
+
+/* In-line DES routines here. */
+
+#include "DEScrypto.h"
+
+static KEYschedule local_key_schedule;
+static RSAKeyStorage tempkey;
+
+/*
+ * Decrypts an RSA private key.
+ */
+int recover_private(deskey, encrypted_key, encrypted_key_len, key)
+DESblock *deskey; /* derived from password */
+char *encrypted_key; /* input to be decrypted */
+unsigned encrypted_key_len; /* must be multiple of 8 bytes */
+RSAKeyStorage *key; /* output with new key in it */
+{
+ unsigned char *outbuf;
+ int rt=0;
+
+ if((outbuf=(unsigned char *)calloc(encrypted_key_len,1))==0)return(0);
+
+ DES_load_key_local( deskey, &local_key_schedule);
+ if (DES_CBC_decrypt_local(0, encrypted_key, encrypted_key_len,
+ outbuf, &local_key_schedule)==0)
+ goto clean;
+ memset(&tempkey,0,sizeof(tempkey));
+ if (key->nl) tempkey.nl=key->nl, BnnAssign(tempkey.n,key->n,key->nl);
+#ifdef DEBUG
+printf("\nDecrypted private key:\n");
+dumphex(outbuf,encrypted_key_len-sizeof(long));
+#endif
+ if (DecodePrivate(outbuf, &tempkey) != NULL) {
+#ifdef DEBUG
+printf("\nRecovered Key:\n");
+PrintTestKey(&tempkey);
+#endif
+ if (rt=TestRSAKeys(&tempkey)) memcpy(key,&tempkey,sizeof(RSAKeyStorage));
+ }
+#ifdef DEBUG
+ else printf("\nDecode Failed.\n");
+#endif
+
+ memset(outbuf,0,encrypted_key_len);
+ memset(&tempkey,0,sizeof(tempkey));
+clean:
+ free(outbuf);
+ return(rt);
+}
+
+/*
+ * Decrypts an RSA private key.
+ */
+int recover_privateP(deskey, encrypted_key, encrypted_key_len, key)
+DESblock *deskey; /* derived from password */
+char *encrypted_key; /* input to be decrypted */
+unsigned encrypted_key_len; /* must be multiple of 8 bytes */
+RSAKeyStorage *key; /* output with new key in it */
+{
+ unsigned char *outbuf;
+ int rt=0;
+
+ if((outbuf=(unsigned char *)calloc(encrypted_key_len,1))==0)return(0);
+
+ DES_load_key_local( deskey, &local_key_schedule);
+ if (DES_CBC_decrypt_local(0, encrypted_key, encrypted_key_len,
+ outbuf, &local_key_schedule)==0)
+ goto clean;
+ memset(&tempkey,0,sizeof(tempkey));
+ if (key->nl) tempkey.nl=key->nl, BnnAssign(tempkey.n,key->n,key->nl);
+#ifdef DEBUG
+printf("\nDecrypted private key:\n");
+dumphex(outbuf,encrypted_key_len-sizeof(long));
+#endif
+ /* make sure that we decode the private key with only the prime p */
+ if (DecodePrivateP(outbuf, &tempkey) != NULL) {
+#ifdef DEBUG
+printf("\nRecovered Key:\n");
+PrintTestKey(&tempkey);
+#endif
+ if (rt=TestRSAKeys(&tempkey)) memcpy(key,&tempkey,sizeof(RSAKeyStorage));
+ }
+#ifdef DEBUG
+ else printf("\nDecode Failed.\n");
+#endif
+
+ memset(outbuf,0,encrypted_key_len);
+ memset(&tempkey,0,sizeof(tempkey));
+clean:
+ free(outbuf);
+ return(rt);
+}
+
+/*
+ * Encrypts an RSA private key.
+ *
+ * NOTE: Contains components to foil use as a general encrypt/decrypt
+ * facility.
+ *
+ */
+int hide_private(deskey, encrypted_key, encrypted_key_len, key)
+DESblock *deskey; /* derived from password */
+char **encrypted_key; /* storage will be allocated */
+unsigned *encrypted_key_len; /* will be written */
+RSAKeyStorage *key; /* input must be a valid private key */
+{
+ unsigned char *outbuf, *encoded_key;
+ int len, klen;
+
+ if (TestRSAKeys(key)!=1) return(0);
+ if ((encoded_key=EncodePrivate(key))==0) return(0) ;
+ len = (((klen=DecodeTotalLength(encoded_key))+7)/8)*8; /* pad */
+ if ((outbuf = (unsigned char *)calloc(len,1)) ==0)
+ {FreePrivate(encoded_key); return(0);};
+ memcpy(outbuf,encoded_key,klen);
+ FreePrivate(encoded_key);
+ DES_load_key_local(deskey, &local_key_schedule);
+ DES_CBC_encrypt_local (0, outbuf, len, outbuf, &local_key_schedule);
+ *encrypted_key = (char *)outbuf;
+ *encrypted_key_len = len;
+ return(1);
+}
+
+
+/*
+ * Same as above, but only encrypts prime P
+ */
+int hide_privateP(deskey, encrypted_key, encrypted_key_len, key)
+DESblock *deskey; /* derived from password */
+char **encrypted_key; /* storage will be allocated */
+unsigned *encrypted_key_len; /* will be written */
+RSAKeyStorage *key; /* input must be a valid private key */
+{
+ unsigned char *outbuf, *encoded_key;
+ int len, klen;
+
+ if (TestRSAKeys(key)!=1) return(0);
+ if ((encoded_key=EncodePrivateP(key))==0) return(0) ;
+ len = (((klen=DecodeTotalLength(encoded_key))+7)/8)*8;
+ if ((outbuf = (unsigned char *)calloc(len,1)) ==0)
+ {FreePrivate(encoded_key); return(0);};
+ memcpy(outbuf,encoded_key,klen);
+ FreePrivate(encoded_key);
+ DES_load_key_local(deskey, &local_key_schedule);
+ DES_CBC_encrypt_local (0, outbuf, len, outbuf, &local_key_schedule);
+ *encrypted_key = (char *)outbuf;
+ *encrypted_key_len = len;
+ return(1);
+}
--- /dev/null
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include "BigNum.h"
+#include "BigRSA.h"
+
+#ifdef DEBUG
+#undef DEBUG
+#endif
+
+/*
+ * These routines convert ASN.1 to RSAKeyStorage and vice-versa.
+ */
+
+#define INTEGER_TAG 2
+#define BITSTRING_TAG 3
+#define SEQUENCE_TAG 48
+#define CONTEXT_0_TAG 160
+#define CONTEXT_1_TAG 161
+#define CONTEXT_2_TAG 162
+#define CONTEXT_3_TAG 163
+#define CONTEXT_4_TAG 164
+#define CONTEXT_5_TAG 165
+
+/*
+ * Routines for encoding keys.
+ */
+
+/*
+ * Compute total size of length field assuming minimal (X.509) encoding.
+ */
+
+int NumEncodeLengthOctets (size)
+int size;
+{
+ int i = 2;
+ if (size<128) i=1; else if (size>256) i=3 ;
+ return(i);
+}
+
+/*
+ * Write out length, advance pointer to next thing to be written.
+ */
+unsigned char *EncodeLength (input, size)
+unsigned char *input;
+int size;
+{
+ int i = NumEncodeLengthOctets(size);
+
+ if (i==1) (*input++)=(unsigned char)size ;
+ else { i--;
+ (*input++)= i+0x80;
+ for (i--;i>=0;i--) (*input++)=(size>>(i*8));
+ }
+ return(input);
+}
+
+/*
+ * Compute the value of the INTEGER encoded length field for a BigNum
+ * of length nl.
+ */
+int NumEncodeValueOctets(n,nl)
+int nl;
+BigNum n;
+{
+ int i,j;
+
+ if (n==0) return (0);
+
+ i = BnnNumDigits(n,nl);
+ j = BnnNumLeadingZeroBitsInDigit(BnnGetDigit(n+i-1));
+
+ i=i*sizeof(int)-j/8;
+ if ((j%8)==0)i++;
+ return(i);
+}
+
+/*
+ * Write out BigNum as encoded INTEGER, most to least significant octet, and
+ * return pointer to next octet in stream. Expects to be supplied with
+ * a sufficiently large buffer. Always expects the BigNum to be positive.
+ */
+unsigned char *EncodeBigIntegerValue (stream, input, size)
+unsigned char *stream;
+BigNum input;
+unsigned size;
+{
+ int nl = BnnNumDigits(input, size);
+ BigNumDigit d = BnnGetDigit(input+nl-1);
+ int i = BnnNumLeadingZeroBitsInDigit(d);
+
+ if ((i%8)==0) *stream++ = 0; /* want positive number, after all */
+ for(i=sizeof(int)-(i/8)-1;i>=0;i--) *stream++ = (unsigned char) (d>>(i*8))&0xff;
+ for(nl--;nl>0;nl--){
+ d = BnnGetDigit(input+nl-1);
+ for(i=sizeof(int)-1;i>=0;i--) *stream++ = (d>>(i*8))&0xff;
+ }
+ return(stream);
+}
+
+/*
+ * Make an encoded public key from RSAKeyStorage. This includes allocating
+ * the stream storage.
+ *
+ * A public key is defined as SEQUENCE { INTEGER, INTEGER }
+ */
+unsigned char *EncodePublic(keys)
+RSAKeyStorage *keys;
+{
+ int mod_len,exp_len,sequence_len,public_key_len ;
+ unsigned char *buffer, *start;
+
+ if ((keys->nl)==0) return(0);
+
+ mod_len = NumEncodeValueOctets(keys->n,keys->nl);
+ exp_len = NumEncodeValueOctets(keys->e,keys->el);
+ sequence_len = exp_len + mod_len + NumEncodeLengthOctets(exp_len)+
+ NumEncodeLengthOctets(mod_len)+2;
+ public_key_len = NumEncodeLengthOctets(sequence_len)+sequence_len+1;
+
+ if (start = buffer = (unsigned char *) calloc(public_key_len,1)) {
+ *buffer++ = SEQUENCE_TAG;
+ buffer = EncodeLength (buffer,sequence_len);
+ *buffer++= INTEGER_TAG;
+ buffer=EncodeLength (buffer,mod_len);
+ buffer=EncodeBigIntegerValue(buffer,keys->n,keys->nl);
+ *buffer++= INTEGER_TAG;
+ buffer=EncodeLength (buffer,exp_len);
+ buffer=EncodeBigIntegerValue (buffer,keys->e,keys->el);
+ }
+ return(start);
+}
+
+void FreePublic(buffer)
+{ free(buffer);
+}
+
+/*
+ * Make an encoded private key from RSAKeyStorage. This includes allocating
+ * the stream storage.
+ *
+ * A private key is defined as
+ * SEQUENCE {
+ * primep INTEGER, -- always there
+ * primeq [0] INTEGER OPTIONAL,
+ * mod [1] INTEGER OPTIONAL, -- never there
+ * exp [2] INTEGER OPTIONAL,
+ * dp [3] INTEGER OPTIONAL,
+ * dq [4] INTEGER OPTIONAL,
+ * cr [5] INTEGER OPTIONAL }
+ */
+unsigned char *EncodePrivate(keys)
+RSAKeyStorage *keys;
+{
+ int p_len, q_len, exp_len, dp_len, dq_len, cr_len, sequence_len ;
+ unsigned char *buffer, *start;
+
+ /* must have two primes to be a private key */
+ if ((keys->pl ==0)||(keys->ql ==0)) return(0);
+
+ sequence_len = 6 +
+ (p_len = NumEncodeValueOctets(keys->p,keys->pl)) +
+ NumEncodeLengthOctets(p_len) +
+ (q_len = NumEncodeValueOctets(keys->q,keys->ql)) +
+ NumEncodeLengthOctets(q_len) +
+ (exp_len = NumEncodeValueOctets(keys->e,keys->el)) +
+ NumEncodeLengthOctets(exp_len) +
+ (dp_len = NumEncodeValueOctets(keys->dp,keys->dpl)) +
+ NumEncodeLengthOctets(dp_len) +
+ (dq_len = NumEncodeValueOctets(keys->dq,keys->dql)) +
+ NumEncodeLengthOctets(dq_len) +
+ (cr_len = NumEncodeValueOctets(keys->cr,keys->pl)) +
+ NumEncodeLengthOctets(cr_len);
+
+ if (start=buffer=
+ (unsigned char *)calloc(1+NumEncodeLengthOctets(sequence_len)+sequence_len,1)) {
+ *buffer++ = SEQUENCE_TAG;
+ buffer=EncodeLength (buffer,sequence_len);
+ *buffer++= INTEGER_TAG;
+ buffer=EncodeLength (buffer,p_len);
+ buffer=EncodeBigIntegerValue (buffer,keys->p,keys->pl);
+ *buffer++= CONTEXT_0_TAG;
+ buffer=EncodeLength (buffer,q_len);
+ buffer=EncodeBigIntegerValue (buffer,keys->q,keys->ql);
+ /*
+ * No optional modulus.
+ */
+ *buffer++= CONTEXT_2_TAG;
+ buffer=EncodeLength (buffer,exp_len);
+ buffer=EncodeBigIntegerValue (buffer,keys->e,keys->el);
+ *buffer++= CONTEXT_3_TAG;
+ buffer=EncodeLength (buffer,dp_len);
+ buffer=EncodeBigIntegerValue (buffer,keys->dp,keys->dpl);
+ *buffer++= CONTEXT_4_TAG;
+ buffer=EncodeLength (buffer,dq_len);
+ buffer=EncodeBigIntegerValue (buffer,keys->dq,keys->dql);
+ *buffer++= CONTEXT_5_TAG;
+ buffer=EncodeLength (buffer,cr_len);
+ buffer=EncodeBigIntegerValue (buffer,keys->cr,keys->pl);
+ }
+ return(start);
+}
+
+/*
+ * The following routine is similar to the above but just puts prime p in
+ * the encoded private key.
+ */
+unsigned char *EncodePrivateP(keys)
+RSAKeyStorage *keys;
+{
+ int p_len = NumEncodeValueOctets(keys->p,keys->pl);
+ int sequence_len = p_len + 1 + NumEncodeLengthOctets(p_len) ;
+ unsigned char *start, *buffer ;
+
+ if (start=buffer= (unsigned char *)
+ calloc(1+NumEncodeLengthOctets(sequence_len)+sequence_len, 1)) {
+ *buffer++ = SEQUENCE_TAG;
+ buffer=EncodeLength (buffer,sequence_len);
+ *buffer++= INTEGER_TAG;
+ buffer=EncodeLength (buffer,p_len);
+ buffer=EncodeBigIntegerValue (buffer,keys->p,keys->pl);
+ }
+ return(start);
+}
+
+void FreePrivate(buffer)
+{ free(buffer);
+}
+
+
+/*
+ * Decoding routines.
+ */
+
+/*
+ * Input is an encoded value field, tells how many octets in the value.
+ * Does not handle indefinite length forms.
+ */
+int DecodeValueLength (input) /* handles non-minimal size case */
+unsigned char *input ;
+{
+ int len , i ;
+
+ if ((*input&0x80)==0) return(*input);
+ if (*input==0x80) return(0);
+ for (i=(*input++ & 0x7f),len=0;i>0;i--) len=(len << 8)+(unsigned int)*input++;
+
+ return(len);
+}
+
+/*
+ * Input is undecoded string. Returns offset to start of value field.
+ */
+int DecodeHeaderLength (input)
+unsigned char *input ;
+{
+ int tlen = DecodeTypeLength(input);
+ input+=tlen;
+ tlen++;
+ if (*input&0x80) tlen += (*input&0x7f);
+ return(tlen);
+}
+
+/*
+ * Compute number of type bytes.
+ */
+int DecodeTypeLength (input)
+unsigned char *input;
+{ int temp=1;
+ if ((*input&31)==31) do {input++;temp++;} while (*input&0x80) ;
+ return(temp);
+}
+
+/*
+ * Compute offset to next element to decode.
+ * Assumes definite length encoding.
+ */
+int DecodeTotalLength (input)
+unsigned char *input ;
+{
+ return (DecodeHeaderLength(input)+DecodeValueLength(input+DecodeTypeLength(input)));
+}
+
+/*
+ * DecodeBigInteger Returns pointer to one byte beyond end of encoded value.
+ * Reads in least to most significant.
+ */
+unsigned char *DecodeBigInteger (stream, value, size)
+unsigned char *stream;
+BigNum value ;
+int size;
+{
+ int nl = (size+sizeof(int)-1)/sizeof(int);
+ BigNumDigit d;
+ int i,j,k=size-1;
+
+ for(i=0;i<(nl-1);i++){
+ d = 0;
+ for(j=0;j<sizeof(int);j++)
+ d |= (BigNumDigit)(stream[k-j]&0xff)<<(j*8);
+ BnnSetDigit(value+i,d);
+ k-=sizeof(int);
+ }
+/* assert: i = nl-1 */
+ d=0;
+ BnnSetToZero(value+i,1);
+ nl=(size+sizeof(int)-1)%sizeof(int);
+ for(j=0;j<=nl;j++)
+ d |= (BigNumDigit)(stream[k-j]&0xff)<<(j*8);
+ BnnSetDigit(value+i,d);
+
+ return(stream+size);
+}
+
+/*
+ * DecodePublic. Initializes RSAKeyStorage.
+ * Returns pointer to next element if no syntax problems, else zero.
+ */
+unsigned char *DecodePublic (input, keys)
+unsigned char *input;
+RSAKeyStorage *keys;
+{
+ register len;
+ unsigned char *next=input;
+
+ memset(keys,0,sizeof(RSAKeyStorage));
+
+ if ((*input != SEQUENCE_TAG)|| /* must be definite form */
+ (DecodeValueLength(input+1)<=0)) goto syntax_error;
+ input += DecodeHeaderLength(input);
+
+ if (*input != INTEGER_TAG) goto syntax_error;
+ len = DecodeValueLength(input+1);
+ if ((len<=0)||(len >= sizeof(int)*2*DigitLim)) goto syntax_error;
+ input+= DecodeHeaderLength(input);
+ input = DecodeBigInteger (input, keys->n, len);
+ keys->nl = 1 + BnnNumDigits(keys->n, (len+sizeof(int)-1)/sizeof(int));
+
+ if (*input != INTEGER_TAG) goto syntax_error;
+ len = DecodeValueLength(input+1);
+ if ((len<=0)||(len >= sizeof(int)*2*DigitLim)) goto syntax_error;
+ input+= DecodeHeaderLength(input);
+ input = DecodeBigInteger (input, keys->e, len);
+ keys->el = BnnNumDigits(keys->e, (len+sizeof(int)-1)/sizeof(int));
+
+ /*
+ * should be at the end of the encoded substring
+ */
+ if (input != next+DecodeTotalLength(next)) goto syntax_error ;
+
+ FinishKey(keys);
+
+ return(input);
+
+syntax_error:
+#ifdef DEBUG
+printf("\nDecodePublic: Syntax Error.\n");
+#endif
+ return(0);
+}
+
+/*
+ * DecodePrivate. Returns pointer to next element if good, else zero.
+ *
+ * Fills in RSAKeyStorage with key parameters if succesful,
+ * assuming there is enough to go on. The modulus can be supplied in the structure
+ * already, but other values are assumed cleared as necessary. The idea
+ * in this case is to call with the same structure as the public key is in to
+ * make it into a private key structure based on decoding the prime p.
+ */
+unsigned char *DecodePrivate (input, keys)
+unsigned char *input;
+RSAKeyStorage *keys;
+{
+ int len, crl ;
+ unsigned char *next=input;
+ BigNum x;
+
+ if ((*input != SEQUENCE_TAG)|| /* must be definite form */
+ (DecodeValueLength(input+1)<=0)) goto syntax_error;
+ input += DecodeHeaderLength(input);
+
+ if (*input == INTEGER_TAG) { /* must have a p */
+ len = DecodeValueLength(input+1);
+ if ((len<=0)||(len >= sizeof(BigNumDigit)*PrimeSize)) goto syntax_error;
+ input+= DecodeHeaderLength(input);
+ input = DecodeBigInteger (input, keys->p, len);
+ len = keys->pl = BnnNumDigits(x=keys->p, (len+sizeof(int)-1)/sizeof(int));
+ if ((x[len-1]&(3<<BN_DIGIT_SIZE-2))!=0)
+ if (len<PrimeSize) keys->pl = len+1;
+ else goto syntax_error ;
+ } else goto syntax_error ;
+
+ if (*input == CONTEXT_0_TAG) { /* may have a q */
+ len = DecodeValueLength(input+1);
+ if ((len<=0)||(len >= sizeof(BigNumDigit)*PrimeSize)) goto syntax_error;
+ input+= DecodeHeaderLength(input);
+ input = DecodeBigInteger (input, keys->q, len);
+ len= keys->ql = BnnNumDigits(x=keys->q, (len+sizeof(int)-1)/sizeof(int));
+ if ((x[len-1]&(3<<BN_DIGIT_SIZE-2))!=0)
+ if (len<PrimeSize) keys->ql = len+1;
+ else goto syntax_error ;
+ }
+ else keys->ql=0;
+
+ if (*input == CONTEXT_1_TAG) { /* may have a modulus */
+ memset(keys->n,0,sizeof(*keys->n));
+ len = DecodeValueLength(input+1);
+ if ((len<=0)||(len >= sizeof(int)*2*DigitLim)) goto syntax_error;
+ input+= DecodeHeaderLength(input);
+ input = DecodeBigInteger (input, keys->n, len);
+ keys->nl = 1 + BnnNumDigits(keys->n, (len+sizeof(int)-1)/sizeof(int));
+ }
+
+ memset(keys->e,0,sizeof(*keys->e));
+ if (*input == CONTEXT_2_TAG) { /* may have an exponent */
+ len = DecodeValueLength(input+1);
+ if ((len<=0)||(len >= sizeof(int)*2*DigitLim)) goto syntax_error;
+ input+= DecodeHeaderLength(input);
+ input = DecodeBigInteger (input, keys->e, len);
+ }
+ else /* use default exponent */
+ BnnSetDigit(keys->e, (BigNumDigit) ((1<<16)+1) ); /* 32 bits */
+ keys->el = BnnNumDigits(keys->e, (len+sizeof(int)-1)/sizeof(int));
+
+ memset(keys->dp,0,sizeof(*keys->dp));
+ if (*input == CONTEXT_3_TAG) { /* may have a dp */
+ len = DecodeValueLength(input+1);
+ if ((len<=0)||(len >= sizeof(int)*2*DigitLim)) goto syntax_error;
+ input+= DecodeHeaderLength(input);
+ input = DecodeBigInteger (input, keys->dp, len);
+ keys->dpl = BnnNumDigits(keys->dp, (len+sizeof(int)-1)/sizeof(int));
+ }
+ else keys->dpl=0;
+
+ memset(keys->dq,0,sizeof(*keys->dq));
+ if (*input == CONTEXT_4_TAG) { /* may have a dq */
+ len = DecodeValueLength(input+1);
+ if ((len<=0)||(len >= sizeof(int)*2*DigitLim)) goto syntax_error;
+ input+= DecodeHeaderLength(input);
+ input = DecodeBigInteger (input, keys->dq, len);
+ keys->dql = BnnNumDigits(keys->dq, (len+sizeof(int)-1)/sizeof(int));
+ }
+ else keys->dql=0;
+
+ memset(keys->cr,0,sizeof(*keys->cr));
+ if (*input == CONTEXT_5_TAG) { /* may have a cr */
+ len = DecodeValueLength(input+1);
+ if ((len<=0)||(len >= sizeof(int)*2*DigitLim)) goto syntax_error;
+ input+= DecodeHeaderLength(input);
+ input = DecodeBigInteger (input, keys->cr, len);
+ crl = 1;
+ }
+ else crl=0;
+
+ /*
+ * should be at the end of the encoded substring
+ */
+ if (input != next+DecodeTotalLength(next)) goto syntax_error ;
+
+ if (keys->ql == 0) /* need to regenerate q */
+ if (keys->nl == 0) goto syntax_error; /* must know n */
+ else {
+ BigNumDigit xx[4*DigitLim];
+ int ql, pl, nl, i;
+
+ memset(xx,0,sizeof(xx));
+ BnnAssign(xx,keys->n,nl=keys->nl);
+ BnnDivide(xx,nl,keys->p,pl=keys->pl);
+ /* check that p evenly divided n */
+ for(i=0;i<pl;i++) if(xx[i]) goto syntax_error;
+ ql = keys->ql = BnnNumDigits(xx,nl) - pl;
+ BnnAssign(keys->q,xx+pl,ql);
+ if ((x[ql-1]&(3<<BN_DIGIT_SIZE-2))!=0)
+ if (ql<PrimeSize) keys->ql = ql+1;
+ else goto syntax_error ;
+ }
+
+ if (keys->nl == 0){ /* need to regenerate n */
+ int nl = keys->pl + keys->ql;
+ memset(keys->n,0,sizeof(*keys->n));
+ BnnMultiply(keys->n,nl,keys->p,keys->pl,keys->q,keys->ql);
+ keys->nl=nl;
+ }
+
+ if(FinishKey(keys) == 0) goto syntax_error ;
+
+ return(input);
+syntax_error:
+#ifdef DEBUG
+printf("\nDecodePrivate: Syntax Error.\n");
+#endif
+#ifndef DEBUG
+ memset(keys->p,0,sizeof(*keys->p));
+ memset(keys->q,0,sizeof(*keys->q));
+ memset(keys->dp,0,sizeof(*keys->dp));
+ memset(keys->dq,0,sizeof(*keys->dq));
+ memset(keys->cr,0,sizeof(*keys->cr));
+ keys->pl=keys->ql=keys->dpl=keys->dql=0;
+#endif
+ return(0);
+}
+
+/*
+ * DecodePrivateP. Returns pointer to next element if good, else zero.
+ *
+ * Fills in RSAKeyStorage with key parameters if succesful,
+ * assuming there is enough to go on. The modulus can be supplied in the structure
+ * already, but other values are assumed cleared as necessary. The idea
+ * in this case is to call with the same structure as the public key is in to
+ * make it into a private key structure based on decoding the prime p.
+ * Only the prime p must be passed in.
+ */
+unsigned char *DecodePrivateP (input, keys)
+unsigned char *input;
+RSAKeyStorage *keys;
+{
+ int len, crl ;
+ unsigned char *next=input;
+ BigNum x;
+
+ if ((*input != SEQUENCE_TAG)|| /* must be definite form */
+ (DecodeValueLength(input+1)<=0)) goto syntax_error;
+ input += DecodeHeaderLength(input);
+
+ if (*input == INTEGER_TAG) { /* must have a p */
+ len = DecodeValueLength(input+1);
+ if ((len<=0)||(len >= sizeof(BigNumDigit)*PrimeSize)) goto syntax_error;
+ input+= DecodeHeaderLength(input);
+ input = DecodeBigInteger (input, keys->p, len);
+ len = keys->pl = BnnNumDigits(x=keys->p, (len+sizeof(int)-1)/sizeof(int));
+ if ((x[len-1]&(3<<BN_DIGIT_SIZE-2))!=0)
+ if (len<PrimeSize) keys->pl = len+1;
+ else goto syntax_error ;
+ } else goto syntax_error ;
+
+ if (*input == CONTEXT_0_TAG) goto syntax_error ;
+ else keys->ql=0;
+
+ if (*input == CONTEXT_1_TAG) goto syntax_error ;
+
+ memset(keys->e,0,sizeof(*keys->e));
+ if (*input == CONTEXT_2_TAG) goto syntax_error ;
+ else /* use default exponent */
+ BnnSetDigit(keys->e, (BigNumDigit) ((1<<16)+1) ); /* 32 bits */
+ keys->el = BnnNumDigits(keys->e, (len+sizeof(int)-1)/sizeof(int));
+
+ memset(keys->dp,0,sizeof(*keys->dp));
+ if (*input == CONTEXT_3_TAG) goto syntax_error ;
+ else keys->dpl=0;
+
+ memset(keys->dq,0,sizeof(*keys->dq));
+ if (*input == CONTEXT_4_TAG) goto syntax_error ;
+ else keys->dql=0;
+
+ memset(keys->cr,0,sizeof(*keys->cr));
+ if (*input == CONTEXT_5_TAG) goto syntax_error ;
+ else crl=0;
+
+ /*
+ * should be at the end of the encoded substring
+ */
+ if (input != next+DecodeTotalLength(next)) goto syntax_error ;
+
+ if (keys->ql == 0) /* need to regenerate q */
+ if (keys->nl == 0) goto syntax_error; /* must know n */
+ else {
+ BigNumDigit xx[4*DigitLim];
+ int ql, pl, nl, i;
+
+ memset(xx,0,sizeof(xx));
+ BnnAssign(xx,keys->n,nl=keys->nl);
+ BnnDivide(xx,nl,keys->p,pl=keys->pl);
+ /* check that p evenly divided n */
+ for(i=0;i<pl;i++) if(xx[i]) goto syntax_error;
+ ql = keys->ql = BnnNumDigits(xx,nl) - pl;
+ BnnAssign(keys->q,xx+pl,ql);
+ if ((x[ql-1]&(3<<BN_DIGIT_SIZE-2))!=0)
+ if (ql<PrimeSize) keys->ql = ql+1;
+ else goto syntax_error ;
+ }
+
+ if (keys->nl == 0){ /* need to regenerate n */
+ int nl = keys->pl + keys->ql;
+ memset(keys->n,0,sizeof(*keys->n));
+ BnnMultiply(keys->n,nl,keys->p,keys->pl,keys->q,keys->ql);
+ keys->nl=nl;
+ }
+
+ if(FinishKey(keys) == 0) goto syntax_error ;
+
+ return(input);
+syntax_error:
+#ifdef DEBUG
+printf("\nDecodePrivateP: Syntax Error.\n");
+#endif
+#ifndef DEBUG
+ memset(keys->p,0,sizeof(*keys->p));
+ memset(keys->q,0,sizeof(*keys->q));
+ memset(keys->dp,0,sizeof(*keys->dp));
+ memset(keys->dq,0,sizeof(*keys->dq));
+ memset(keys->cr,0,sizeof(*keys->cr));
+ keys->pl=keys->ql=keys->dpl=keys->dql=0;
+#endif
+ return(0);
+}
--- /dev/null
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <time.h>
+#include <syslog.h>
+#include "bigsignverify.h"
+
+#ifdef DEBUG
+#undef DEBUG
+#endif
+
+/* in-line crypto routines here */
+
+#include "RSAcrypto.h"
+#include "DEScrypto.h"
+
+#define CLOCK_SKEW 5*60
+
+#ifdef mips
+#undef BnnSetToZero
+#endif
+
+/*
+ * Global
+ */
+
+static BigNumDigit buffer1[2*DigitLim], buffer2[2*DigitLim];
+
+/*
+ * RSASign takes a key in local format and a counted character string and
+ * writes a signature in "BER INTEGER" encoded format into the supplied buffer.
+ * The length in bytes is also written.
+ *
+ */
+
+int RSASign (toBeSigned, datalen, key, signature, siglen)
+RSAKeyStorage *key;
+unsigned char *toBeSigned;
+unsigned char *signature; /* output assumed large enough to hold modulus */
+int datalen, *siglen; /* in bytes */
+{
+ char *temp = (char *)buffer2;
+ int i, nl=key->nl, pl=key->pl, ql=key->ql;
+ BigNum signed_digest = buffer1, p = key->p, q = key->q;
+
+ if ((pl==0)||(ql==0)) return(0); /* not a private key */
+ RSA_MD2(toBeSigned, datalen, temp); /* hash to temp */
+ BnnSetToZero(signed_digest,nl);
+ for (i=0;i<16;i++) /* copy in right order */
+ signed_digest[i/sizeof(BigNumDigit)]|=
+ ((0x0ff&temp[15-i])<<((i%sizeof(BigNumDigit))*8));
+ signed_digest[4] |= 0x00000410;
+ rsadecrypt_1(signed_digest, signed_digest, key);
+ *siglen = NumEncodeValueOctets(signed_digest, nl);
+ if(EncodeBigIntegerValue(signature, signed_digest, nl)) return(TRUE);
+ else return(FALSE);
+}
+
+/*
+ * RSAVerify takes an encoded signature, allegedly signed data and key
+ * and yields a boolean (TRUE/FALSE).
+ */
+
+int RSAVerify (allegedSigned, datalen, key, signature, siglen)
+RSAKeyStorage *key;
+char *allegedSigned, *signature;
+int datalen, siglen;
+{
+ char *temp=(char *)buffer2;
+ BigNum md = buffer1, buffer = buffer2, n = key->n;
+ int i, bl, nl=key->nl;
+
+ if ((bl=(siglen+sizeof(BigNumDigit)-1)/sizeof(BigNumDigit)) > nl) {
+#ifdef DEBUG
+printf("\nRSAVerify: signature has more BigNumDigits than the modulus\n");
+#endif
+ return(FALSE);
+ }
+
+ BnnSetToZero(md,nl);
+ RSA_MD2(allegedSigned, datalen, temp);
+ for (i=0;i<16;i++) /* copy in right order */
+ md[i/sizeof(BigNumDigit)]|=((0x0ff&temp[15-i])<<((i%sizeof(BigNumDigit))*8));
+
+ BnnSetToZero(buffer,nl);
+ DecodeBigInteger(signature, buffer, siglen);
+ if (BnnCompare(n, nl, buffer, bl)!=1) {
+#ifdef DEBUG
+printf("\nRSAVerify: signature is larger BigNum value than modulus\n");
+#endif
+ return(FALSE);
+ }
+
+ rsaencrypt_1(buffer, buffer, key);
+#ifdef DEBUG
+printf("RSAVerify: computed md:\n");
+dumphex(md,nl*8);
+printf("RSAVerify: recovered md:\n");
+dumphex(buffer,nl*8);
+#endif
+ buffer[4] &= 0xffff0000;
+ if (BnnCompare(md,nl,buffer,nl)==0) return (TRUE);
+#ifdef DEBUG
+printf("\nRSAVerify: signature verification failed.\n");
+#endif
+ return(FALSE);
+
+}
+
+\f
+/*
+ * The initialization routine generates a DES key and encrypts it under
+ * the public key of the intended verifier principal.
+ *
+ * A word about byte ordering. The "least significant byte" of a BigNum
+ * is the byte that has the least significant bit in it. The "most
+ * significant byte" has the most significant bit in it.
+ *
+ */
+#include "endian.h"
+#define RandomOffset (sizeof(DESblock)+2*sizeof(time_t))
+#define BYTE_IN_BIGNUM(x) (SPHINX_ENDIAN?(sizeof(BigNumDigit)-(x%sizeof(BigNumDigit)-1)):x)
+
+int InitAuthenticationKey (verifier, delegation, new_key, encrypted_key,
+ encrypted_key_len, when_expires)
+RSAKeyStorage *verifier, *delegation;
+DESblock *new_key;
+unsigned char *encrypted_key;
+int *encrypted_key_len;
+time_t when_expires;
+{
+ time_t when_signed;
+ BigNum vn=verifier->n, p = buffer1, temp = buffer1;
+ int i, leading_zero_bytes, vnl=verifier->nl, tl;
+ RNGState rng;
+
+ /*
+ * This is all we need the delegation key for.
+ */
+ read_rng_state(&rng);
+ if(((rng.count)==0)&&delegation) initialize_rng_state(delegation->p,16);
+
+ /*
+ * Fill temporary storage with a random number.
+ */
+ BnnSetToZero(temp,vnl+1);
+ tl = BnnNumDigits(vn,vnl);
+ random_BigNum(temp,tl);
+
+ /*
+ * There must always be one more significant byte in the modulus than
+ * the one that has the "64" in the encrypted key.
+ */
+#ifdef DEBUG
+printf("\nleading zero bits: %d, vn[tl-1]=%08x\n",
+ BnnNumLeadingZeroBitsInDigit(vn[tl-1]), vn[tl-1]);
+#endif
+ leading_zero_bytes=BnnNumLeadingZeroBitsInDigit(BnnGetDigit(vn+tl-1))/8;
+ if (leading_zero_bytes == (sizeof(BigNumDigit)-1)) {
+ /*
+ * There is only one significant byte in the most significant BigNumDigit,
+ * so zero out top digit and put "64" into the most significant byte of
+ * the next-to-top digit
+ */
+ temp[tl-1] = 0;
+ temp[tl-2] &= ~(0x00ff << 8*leading_zero_bytes);
+ temp[tl-2] |= 64 << 8*leading_zero_bytes ;
+ }
+ else {
+ /*
+ * Zero out bytes with significant stuff in them, and put "64"
+ * in the next-most-significant byte.
+ */
+ for(i=0;i<=leading_zero_bytes+1;i++)
+ temp[tl-1] &= ~(0x00ff << (8*(sizeof(BigNumDigit)-1-i)));
+ temp[tl-1] |= 64<<((sizeof(BigNumDigit)-2-leading_zero_bytes)*8);
+ }
+#ifdef DEBUG
+printf("\nleading_zero_bytes=%d\n",leading_zero_bytes);
+printf("\ntl=%d, vnl=%d, temp[tl-1]=%08x, temp[tl-2]=%08x\n", tl, vnl, temp[tl-1], temp[tl-2]);
+#endif
+
+ BnnSetToZero(temp, (RandomOffset+4)/sizeof(BigNumDigit));
+ /*
+ * Generate 8 bytes of DES key, copy into buffer in right order
+ */
+ random_bytes(temp, sizeof(DESblock));
+ for (i=0;i<sizeof(DESblock);i++) new_key->bytes[sizeof(DESblock)-i-1] =
+ (temp[i/sizeof(BigNumDigit)]>>((i%sizeof(BigNumDigit)*8)));
+
+ /*
+ * Assume sizeof(time_t) == sizeof(BigNumDigit).
+ * Everyone has to swap these bytes, I guess.
+ */
+ time(&when_signed);
+ p = &temp[sizeof(DESblock)/sizeof(BigNumDigit)];
+ p[0]=when_signed;
+ p[1]=when_expires;
+/*
+ for(i=0;i<sizeof(time_t);i++) {
+ p[0] |= ((when_signed>>(i*8))&(BigNumDigit)0xff)<<((sizeof(time_t)-1-i)*8);
+ p[1] |= ((when_expires>>(i*8))&(BigNumDigit)0xff)<<((sizeof(time_t)-1-i)*8);
+ }
+*/
+#ifdef DEBUG
+printf("\nBlock to encrypt: (low to high order bytes) \n");
+dumphex(temp,tl*sizeof(BigNumDigit));
+printf("\nModulus:\n");
+dumphex(vn,vnl*sizeof(BigNumDigit));
+#endif
+ rsaencrypt_1(temp,temp,verifier);
+ *encrypted_key_len = NumEncodeValueOctets(temp,tl);
+ if (EncodeBigIntegerValue(encrypted_key,temp,tl)) return(TRUE);
+ else return(FALSE);
+}
+
+/*
+ * The accept routine takes in encoded elements and yields the transferred
+ * DES key along with an expiration date.
+ *
+ */
+int AcceptAuthenticationKey (verifier, new_key, encrypted_key,
+ encrypted_key_len, when_expires)
+RSAKeyStorage *verifier;
+DESblock *new_key;
+unsigned char *encrypted_key;
+int encrypted_key_len;
+time_t *when_expires;
+{
+ time_t now, when_signed, when_expires_temp ;
+ int i, tl, vnl=verifier->nl, leading_zero_bytes;
+ BigNum vn=verifier->n, p = buffer1, temp = buffer1;
+ char *ptr;
+
+ BnnSetToZero(temp,vnl+1);
+ if ((tl=(encrypted_key_len+sizeof(BigNumDigit)-1)/sizeof(BigNumDigit)) > vnl) {
+#ifdef DEBUG
+printf("\nAcceptAuthenticationKey: Signature has more BigNumDigits than modulus.\n");
+#endif
+syslog(LOG_INFO, "AAK : Signature has more BigNumDigits than modulus");
+ goto error;
+ }
+
+ DecodeBigInteger(encrypted_key,temp,encrypted_key_len);
+ if (BnnCompare(vn,vnl,temp,tl) != 1) {
+#ifdef DEBUG
+printf("\nAcceptAuthenticationKey: Signature is larger than modulus.\n");
+#endif
+syslog(LOG_INFO, "AAK : Signature is larger than modulus");
+ goto error;
+ }
+
+ rsadecrypt_1(temp,temp,verifier);
+#ifdef DEBUG
+printf("\nAcceptAuthenticationKey: Decrypted key:\n");
+dumphex(temp,(vnl+1)*sizeof(BigNumDigit));
+fflush(stdout);
+#endif
+ /*
+ * Check for a "64" in the right place.
+ */
+ tl = BnnNumDigits(vn,vnl);
+ leading_zero_bytes=BnnNumLeadingZeroBitsInDigit(BnnGetDigit(vn+tl-1))/8;
+ if (leading_zero_bytes == sizeof(BigNumDigit)-1) {
+ if ((temp[tl-1] != 0) ||
+ (((temp[tl-2]>>(8*leading_zero_bytes))&0x0ff) != 64)) {
+#ifdef DEBUG
+printf("\nTop digit not zero, or 64 byte test failed.\n");
+#endif
+syslog(LOG_INFO, "AAK : Top digit not zero, or 64 byte test failed");
+ goto error ;
+ }
+ }
+ else { for(i=0;i<leading_zero_bytes;i++)
+ if(((temp[tl-1]>>((sizeof(BigNumDigit)-leading_zero_bytes-1+i)*8))&0x0ff)
+ != 0) {
+#ifdef DEBUG
+printf("\nTop byte zero test failed.\n");
+#endif
+syslog(LOG_INFO, "AAK : Top byte zero test failed");
+ goto error ;
+ }
+ if (((temp[tl-1]>>((sizeof(BigNumDigit)-2-leading_zero_bytes)*8))&0xff)
+ != 64){
+#ifdef DEBUG
+printf("\nTop byte 64 test failed.\n");
+#endif
+syslog(LOG_INFO, "AAK : Top byte 64 test failed");
+ goto error ;
+ }
+ }
+
+ ptr = (char *) &temp[RandomOffset/sizeof(BigNumDigit)];
+ for (i=0;i<4;i++) if (*ptr++ !=0) {
+#ifdef DEBUG
+printf("\nAcceptAuthenticationKey: Zero mid-buffer error.\n");
+#endif
+syslog(LOG_INFO, "AAK : Zero mid-buffer error");
+ goto error;
+ }
+
+ when_signed=when_expires_temp=0;
+
+ p = &temp[sizeof(DESblock)/sizeof(BigNumDigit)];
+ when_signed = p[0];
+ when_expires_temp = p[1];
+/*
+ for(i=0;i<sizeof(time_t);i++) {
+ when_signed |= ((p[0]>>(i*8))&(BigNumDigit)0x0ff)<<((sizeof(time_t)-1-i)*8);
+ when_expires_temp |= ((p[1]>>(i*8))&(BigNumDigit)0x0ff)<<((sizeof(time_t)-1-i)*8);
+ }
+*/
+ time(&now);
+#ifdef DEBUG
+printf("\n Signed: %s", ctime(&when_signed));
+printf("\n Expires: %s\n", ctime(&when_expires_temp));
+#endif
+
+ if((when_signed > now + CLOCK_SKEW) || (when_expires_temp < now - CLOCK_SKEW)) {
+#ifdef DEBUG
+printf("\nAcceptAuthenticationKey: Key Has Expired.\n");
+#endif
+syslog(LOG_INFO, "AAK : signed on (%d) %s", when_signed, ctime(&when_signed));
+syslog(LOG_INFO, "AAK : expire on (%d) %s", when_expires_temp, ctime(&when_expires_temp));
+syslog(LOG_INFO, "AAK : key has expired - now is %d", now);
+ goto error;
+ }
+ *when_expires = when_expires_temp;
+
+ for (i=0;i<sizeof(DESblock);i++) new_key->bytes[sizeof(DESblock)-i-1] =
+ (temp[i/sizeof(BigNumDigit)]>>((i%sizeof(BigNumDigit)*8)));
+ return(TRUE);
+
+error:
+ return(FALSE);
+
+}
+
--- /dev/null
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+#ifndef SPHINX_ITAR
+#define SPHINX_ITAR
+static char copyright[] = "\n Copyright, 1989, 1990, Digital Equipment Corporation \n";
+static char warning[]= "\n This software is subject to export restrictions under \
+\n the U.S. Department of State's International Traffic in Arms \
+\n Regulations (ITAR). This software must not be transmitted \
+\n in source form outside the United States or to a foreign \
+\n national in the United States without a valid U.S. State \
+\n Department export license. ";
+#endif
+
+/*
+ * Generate the permutation tables for a software implementation of DES.
+ */
+#include <stdio.h>
+
+#define FILENAME "tables.h"
+#define EFILE "endian.h"
+
+typedef unsigned long INT32; /* generic type for 32-bit integer */
+
+/*
+ * The following tables are based on those in the Data Encryption
+ * Standard document (FIPS PUB 46).
+ */
+
+/*
+ * Initial permutation IP
+ */
+static char ip[] = { 2, 4, 6, 8, 1, 3, 5, 7 };
+
+/*
+ * Final permutation IP^-1
+ */
+static char fp[] = { 8, 7, 6, 5, 4, 3, 2, 1 };
+
+/*
+ * The (in)famous S-boxes
+ */
+static char si[8][64] = {
+ /*
+ * S1
+ */
+ 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
+ 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
+ 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
+ 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,
+
+ /*
+ * S2
+ */
+ 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
+ 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
+ 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
+ 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9,
+
+ /*
+ * S3
+ */
+ 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
+ 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
+ 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
+ 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,
+
+ /*
+ * S4
+ */
+ 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
+ 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
+ 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
+ 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14,
+
+ /*
+ * S5
+ */
+ 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
+ 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
+ 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
+ 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3,
+
+ /*
+ * S6
+ */
+ 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
+ 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
+ 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
+ 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13,
+
+ /*
+ * S7
+ */
+ 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
+ 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
+ 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
+ 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12,
+
+ /*
+ * S8
+ */
+ 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
+ 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
+ 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
+ 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
+};
+
+/*
+ * 32-bit permutation function P used on the output of the S-boxes
+ */
+static char p32i[] = {
+ 16, 7, 20, 21,
+ 29, 12, 28, 17,
+ 1, 15, 23, 26,
+ 5, 18, 31, 10,
+ 2, 8, 24, 14,
+ 32, 27, 3, 9,
+ 19, 13, 30, 6,
+ 22, 11, 4, 25
+};
+
+static char ei[] = {
+ 32, 1, 2, 3, 4, 5,
+ 4, 5, 6, 7, 8, 9,
+ 8, 9, 10, 11, 12, 13,
+ 12, 13, 14, 15, 16, 17,
+ 16, 17, 18, 19, 20, 21,
+ 20, 21, 22, 23, 24, 25,
+ 24, 25, 26, 27, 28, 29,
+ 28, 29, 30, 31, 32, 1
+};
+
+/*
+ * Permuted choice table (key)
+ */
+static char pc1[] = {
+ 57, 49, 41, 33, 25, 17, 9,
+ 1, 58, 50, 42, 34, 26, 18,
+ 10, 2, 59, 51, 43, 35, 27,
+ 19, 11, 3, 60, 52, 44, 36,
+
+ 63, 55, 47, 39, 31, 23, 15,
+ 7, 62, 54, 46, 38, 30, 22,
+ 14, 6, 61, 53, 45, 37, 29,
+ 21, 13, 5, 28, 20, 12, 4
+};
+
+/*
+ * Permuted choice key (table)
+ */
+static char pc2[] = {
+ 14, 17, 11, 24, 1, 5,
+ 3, 28, 15, 6, 21, 10,
+ 23, 19, 12, 4, 26, 8,
+ 16, 7, 27, 20, 13, 2,
+ 41, 52, 31, 37, 47, 55,
+ 30, 40, 51, 45, 33, 48,
+ 44, 49, 39, 56, 34, 53,
+ 46, 42, 50, 36, 29, 32
+};
+
+/*
+ * Note that the Standard is written in Big Endian terms so bit 1 is the
+ * high bit of the byte.
+ */
+static int bytebit[] = {
+ 0200, 0100, 040, 020, 010, 04, 02, 01
+};
+
+/*
+ * Generated tables
+ */
+static INT32 iperma[256],ipermb[256];
+static INT32 fperma[256],fpermb[256];
+static INT32 sp[8][64];
+static char pc1bit[56],pc1byte[56];
+
+static FILE *tables;
+static FILE *endian;
+
+/*
+ * Initialize a permutation array.
+ */
+static perminit( perma,permb,p )
+INT32 perma[256],permb[256];
+char p[8];
+{
+ register int i,j;
+
+ /*
+ * Clear out the permutation array.
+ */
+ memset(perma, 0, sizeof(perma));
+ memset(permb, 0, sizeof(permb));
+
+ /*
+ * Now produce the table.
+ */
+ for (i = 0; i < 4; i++)
+ for (j = 0; j < 256; j++)
+ {
+ if ((j & bytebit[p[i] - 1]) != 0)
+ perma[j] |= 1L << (8 * (3 - i));
+ if ((j & bytebit[p[i+4] - 1]) != 0)
+ permb[j] |= 1L << (8 * (3 - i));
+ }
+}
+
+outperm( perma,permb,name,comment )
+INT32 perma[256],permb[256];
+char *name,*comment;
+{
+ register int i, j;
+
+ fprintf(tables, "/*\n * %s\n */\n", comment);
+ fprintf(tables, "static INT32 %sa[256] = {", name);
+ for (i = 0; i < 64; i++)
+ {
+ fprintf(tables, "\n ");
+ for (j = 0; j < 4; j++)
+ fprintf(tables, "0x%lx, ", (long)perma[(i * 4) + j]);
+ }
+
+ fprintf(tables, "\n};\n\nstatic INT32 %sb[256] = {", name);
+ for (i = 0; i < 64; i++)
+ {
+ fprintf(tables, "\n ");
+ for (j = 0; j < 4; j++)
+ fprintf(tables, "0x%lx, ", (long)permb[(i * 4) + j]);
+ }
+ fprintf(tables, "\n};\n\n");
+}
+
+/*
+ * Intialize the combined S and P boxes
+ */
+static spinit()
+{
+ register int i,j,k,l;
+ INT32 perm;
+ unsigned char inv[32];
+
+ /*
+ * Invert the pbox array.
+ */
+ for (i = 0; i < 32; i++)
+ inv[p32i[i] - 1] = i;
+
+ /*
+ * Now build a combination of the p and s boxes.
+ */
+ for (i = 0; i < 8; i++)
+ for (j = 0; j < 64; j++)
+ {
+ perm = 0;
+
+ /*
+ * Compute the index into the sbox table. The row number is
+ * formed from bits 0 and 5 (VAX terminology) and the column
+ * number from the middle 4 bits.
+ */
+ l = (j & 0x20) | ((j & 1) ? 0x10 : 0) | ((j >> 1) & 0xF);
+
+ /*
+ * Each sbox entry gives us 4 bits which must be merged into
+ * the final table.
+ */
+ for (k = 0; k < 4; k++)
+ {
+ if ((si[i][l] & (8 >> k)) != 0)
+ perm |= 1L << (31 - inv[(i * 4) + k]);
+ }
+ sp[i][j] = perm;
+ }
+}
+
+outsp()
+{
+ register int i,j,k;
+
+ fprintf(tables, "/*\n * Combined s and p boxes\n */\n");
+ fprintf(tables, "static INT32 sp[8][64] = {");
+
+ for (i = 0; i < 8; i++)
+ {
+ fprintf(tables, "\n /*\n * Permuted S box %d\n */", i);
+ for (j = 0; j < 16; j++)
+ {
+ fprintf(tables, "\n ");
+ for (k = 0; k < 4; k++)
+ fprintf(tables, "0x%lx, ", (long)(sp[i][(j * 4) + k]));
+ }
+ }
+ fprintf(tables, "\n};\n\n");
+}
+
+choiceinit( pc,bit,byte )
+char pc[],bit[],byte[];
+{
+ register int i;
+
+ /*
+ * Convert a permuted choice table from bit addressing to 2 tables
+ * giving the byte and bit within the byte address.
+ */
+ for (i = 0; i < 56; i++)
+ {
+ bit[i] = bytebit[(pc[i] - 1) & 07];
+ byte[i] = (pc[i] - 1) >> 3;
+ }
+}
+
+outchoice( bit,byte,name,comment )
+char bit[],byte[],*name,*comment;
+{
+ register int i,j;
+
+ fprintf(tables, "/*\n * %s\n */\n", comment);
+ fprintf(tables, "static unsigned char %sbit[56] = {", name);
+ for (i = 0; i < 7; i++)
+ {
+ fprintf(tables, "\n ");
+ for (j = 0; j < 8; j++)
+ fprintf(tables, "0x%x, ", bit[(i * 8) + j] & 0xFF);
+ }
+ fprintf(tables, "\n};\n\n");
+
+ fprintf(tables, "static unsigned char %sbyte[56] = {", name);
+ for (i = 0; i < 7; i++)
+ {
+ fprintf(tables, "\n ");
+ for (j = 0; j < 8; j++)
+ fprintf(tables, "%2d, ", byte[(i * 8) + j]);
+ }
+ fprintf(tables, "\n};\n\n");
+
+}
+
+INT32 swap( x )
+INT32 x;
+{
+ register char *cp,temp;
+
+ cp = (char *)&x;
+ temp = cp[3];
+ cp[3] = cp[0];
+ cp[0] = temp;
+
+ temp = cp[2];
+ cp[2] = cp[1];
+ cp[1] = temp;
+
+ return (x);
+}
+
+main( argc,argv )
+int argc;
+char *argv[];
+{
+ register int i;
+ union { char bytes [ sizeof(long) ];
+ long longs; } testword ;
+ long now;
+
+ time(&now);
+
+ testword.longs = 1;
+
+ if ((endian = fopen(EFILE, "w")) == NULL)
+ {
+ perror("endian");
+ exit(2);
+ }
+
+ fprintf(endian, "/* endian.h */\n");
+ fprintf(endian, "/*\n * Machine generated on %s */\n", ctime(&now));
+ fprintf(endian, "\n#ifndef SPHINX_ENDIAN\n\n");
+ fprintf(endian, "/*\n");
+ fprintf(endian, " * Little endian machines are DEC/Intel like\n");
+ fprintf(endian, " * Big endian machines are IBM/SPARC/Motorola like\n *\n");
+ fprintf(endian, " * This machine is ");
+ if (testword.bytes[0]) fprintf (endian,"little "); else fprintf(endian,"big ");
+ fprintf(endian, "endian since the value of SPHINX_ENDIAN is %u\n", testword.bytes[0]);
+ fprintf(endian, " *\n */\n\n");
+ fprintf(endian, "\n#define SPHINX_ENDIAN %u\n\n", testword.bytes[0]);
+ fprintf(endian, "\n#endif\n\n\n");
+
+ if ((tables = fopen(FILENAME, "w")) == NULL)
+ {
+ perror("gentables");
+ exit(2);
+ }
+
+ fprintf(tables, "/*\n * Machine generated tables for DES encryption %s */\n\n",
+ ctime(&now));
+ if (testword.bytes[0])
+ fprintf(tables, "/*\n * Little Endian (DEC/Intel like)\n */\n\n");
+ else fprintf(tables, "/*\n * Big Endian (IBM/SPARC/Motorola like)\n */\n\n");
+
+ perminit(iperma, ipermb, ip);
+ perminit(fperma, fpermb, fp);
+
+ if (testword.bytes[0]) /* little endian */
+ /*
+ * Perform a byte swap on the final permutation table.
+ */
+ for (i = 0; i < 256; i++)
+ {
+ fperma[i] = swap(fperma[i]);
+ fpermb[i] = swap(fpermb[i]);
+ }
+
+ outperm(iperma, ipermb, "iperm", "Initial permutation");
+ outperm(fperma, fpermb, "fperm", "Final permutation");
+ spinit();
+ outsp();
+ choiceinit(pc1, pc1bit, pc1byte);
+ outchoice(pc1bit, pc1byte, "pc1", "Permuted choice 1 table");
+ exit(0);
+}
--- /dev/null
+/* hashes.h */
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+
+/*
+ * Externally Callable Routines. All arguments are character pointers
+ * or integer lengths.
+ */
+
+#ifndef SPHINX_HASHES
+#define SPHINX_HASHES
+
+void RSA_MD2(); /* RSA_MD2(input_buffer, length, hash_result) */
+void RSA_MD4(); /* RSA_MD4(input_buffer, length, hash_result) */
+void RSA_MAC(); /* RSA_MAC(input_buffer, length, mac, output_length) */
+void RSA_MD(); /* RSA_MD(input_buffer, length, hash_result) */
+
+int H1(); /* H1(username, password, hash_result) */
+int H2(); /* H2(username, password, hash_result) */
+
+/*
+ * Common data structures
+ */
+#define MAC_BLOCK_SIZE 8
+#define MD_BLOCK_SIZE 16
+
+
+#endif
+
--- /dev/null
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+/*
+ * NOTES:
+ *
+ * 1. This file is BSD 4.2, and possibly Ultrix specific
+ * 2. This file includes in-line DES code
+ *
+ * CONTENTS:
+ * 1. Random number generator components
+ * 2. DES MAC routine.
+ */
+
+#include <stdio.h>
+#ifndef ultrix
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#include <sys/types.h>
+#include <sys/resource.h>
+#ifdef POSIX
+#include <sys/utsname.h>
+#endif
+#ifdef SOLARIS
+#include <sys/times.h>
+#endif
+
+#include "DEScrypto.h"
+
+static RNGState rng ; /* this needs to be saved and restored as needed */
+static KEYschedule random_key_schedule;
+static unsigned char scramble_key[8] = {0x01, 0x23, 0x45, 0x67,
+ 0x89, 0xab, 0xcd, 0xef};
+static void DES_MAC();
+
+/*
+ * Routines to checkpoint and restore random number generator state.
+ */
+
+void read_rng_state ( state )
+RNGState *state ;
+{
+ memcpy (state, &rng, sizeof(RNGState));
+}
+
+void restore_rng_state ( state )
+RNGState *state ;
+{
+ memcpy (&rng, state, sizeof(RNGState));
+ DES_load_key_local( &rng.key, &random_key_schedule );
+}
+
+
+/*
+ *
+ * Initialize random number generator based on nl characters supplied by caller.
+ * Introduce some other uncertanity based on current time and resource usage.
+ *
+ */
+void initialize_rng_state (seed,nl)
+unsigned char * seed;
+int nl;
+{
+ struct timezone tz;
+ struct timeval tv;
+ struct rusage *rs;
+ int i;
+
+ /* start with hash of input string */
+ DES_load_key_local(scramble_key, &random_key_schedule) ;
+ DES_MAC (0, seed, nl, &rng.key, &random_key_schedule) ;
+
+ /* get whatever resource usage there is */
+#ifdef SOLARIS
+ rs = (struct rusage *)malloc (sizeof(struct tms));
+ (void) times((struct tms *)rs);
+ DES_MAC (0, rs, sizeof(struct tms), &rng.seed, &random_key_schedule) ;
+#else
+ rs = (struct rusage *) malloc(sizeof(struct rusage));
+ getrusage(0,rs);
+ rs->ru_stime.tv_sec += (long) rs ;
+ DES_MAC (0, rs, sizeof(struct rusage), &rng.seed, &random_key_schedule) ;
+#endif
+ free(rs);
+
+ /* get the current wall clock time, mix in process id */
+ gettimeofday(&tv,&tz);
+ rng.seed.longwords[0] = tv.tv_sec + getpid() + (long) &tz ;
+ rng.seed.longwords[1] = tv.tv_usec + clock();
+#ifdef POSIX
+ {
+ struct utsname name;
+ int i, sum = 0;
+
+ (void) uname(&name);
+ for (i = 0; name.nodename[i]; i++)
+ sum = (sum<<1) + name.nodename[i];
+ rng.seed.longwords[1] += sum;
+ }
+#else
+ rng.seed.longwords[1] += gethostid();
+#endif
+
+ DES_load_key_local( &rng.key, &random_key_schedule);
+ DESencrypt_local(&rng.seed, &rng.key, &random_key_schedule);
+ DES_load_key_local( &rng.key, &random_key_schedule);
+ rng.count=0;
+}
+
+
+/*
+ * random_bytes
+ *
+ * Pseudo-random number sequence generator based on NBS algorithm.
+ * Writes nl pseudo-random bytes to buffer n.
+ *
+ */
+void random_bytes (n,nl)
+char *n;
+int nl;
+{
+for(;nl>0;nl--){
+ if ((rng.count&7)==0) /* refresh */
+ {
+ struct timeval tv ;
+ struct timezone tz ;
+
+ gettimeofday(&tv, &tz);
+ rng.current.longwords[0]= tv.tv_sec + rng.count ;
+ rng.current.longwords[1]= tv.tv_usec + clock();
+ DESencrypt_local(&rng.current,&rng.current,&random_key_schedule);
+ rng.current.longwords[0] ^= rng.seed.longwords [0] ;
+ rng.current.longwords[1] ^= rng.seed.longwords [1] ;
+ DESencrypt_local(&rng.current,&rng.seed,&random_key_schedule);
+ DESdecrypt_local(&rng.current,&rng.current,&random_key_schedule);
+ }
+ rng.count++ ;
+ *n++ = rng.current.bytes [rng.count&7];
+}
+}
+
+
+static void DES_MAC (iv, inbuf, isize, mac, key_schedule)
+KEYschedule *key_schedule;
+char *iv, *inbuf, *mac;
+int isize;
+{
+ int i;
+ DESblock temp;
+
+ if(iv) memcpy(temp.bytes,iv,8) ;
+ else temp.longwords[0]=temp.longwords[1]=0;
+
+ for (;isize>=8;isize-=8) {
+ for(i=0;i<8;i++) temp.bytes[i] ^= *inbuf++ ;
+ DESencrypt_local(&temp,&temp,key_schedule);
+ }
+
+ if(isize) {
+ for(i=0;i<isize;i++) temp.bytes[i] ^= *inbuf++;
+ DESencrypt_local(&temp,&temp,key_schedule);
+ }
+
+ memcpy(mac, &temp, 8);
+}
+
+\f
+/*
+ *
+ * D E S _ X 9 _M A C
+ *
+ * Compute a DES based message authentication code (MAC) over the input
+ * buffer. This uses the definition in ANSI X9.9
+ *
+ * Inputs:
+ * key - input DES key
+ * inbuf - Pointer to the input buffer
+ * isize - Size of the input buffer
+ * mac - Pointer to a buffer to receive the MAC
+ *
+ * Outputs:
+ * mac - Resultant MAC
+ *
+ * Return Value:
+ *
+ */
+void DES_X9_MAC (key, inbuf, isize, mac)
+DESblock *key;
+char *inbuf , *mac ;
+int isize;
+{
+ KEYschedule key_schedule;
+
+ DES_load_key_local(key,&key_schedule);
+ DES_MAC(0,inbuf,isize,mac,&key_schedule);
+ memset(&key_schedule, 0, sizeof(KEYschedule));
+}
+
+
--- /dev/null
+/* random.h */
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+#ifndef SPHINX_RANDOM
+#define SPHINX_RANDOM
+
+typedef unsigned long INT32; /* 32-bit unsigned integer */
+
+typedef union
+{ /* data type for the DES blocks */
+ unsigned char bytes[8]; /* for access as bytes */
+ INT32 longwords[2]; /* for access as longwords */
+} DESblock;
+
+#define DES_BLOCK_SIZE sizeof(DESblock)
+
+typedef struct {
+ int count ;
+ DESblock seed , key , current;
+ } RNGState ;
+
+#define RNG_STATE_SIZE sizeof(RNGState)
+
+void read_rng_state ();
+void restore_rng_state ();
+void initialize_rng_state ();
+void random_bytes ();
+void DES_X9_MAC(); /* DES_X9_MAC(key,input_buffer, length, hash_result) */
+
+#endif
+
--- /dev/null
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+#include <stdio.h>
+#include <time.h>
+#include <sys/types.h>
+#include "random.h"
+#include "BigNum.h"
+#include "BigRSA.h"
+#include "bigkeygen.h"
+
+/*
+ * random_BigNum
+ *
+ * Pseudo-random number generator based on NBS algorithm.
+ *
+ * Writes nl pseudo-random BigNumDigits to buffer n.
+ * Called by prime finding routines
+ *
+ */
+random_BigNum (n,nl)
+BigNum n;
+unsigned nl;
+{
+ for(;nl>0;nl--) random_bytes(n++,sizeof(BigNumDigit)) ;
+}
--- /dev/null
+/* $Header$ */
+
+OBJECT = o/KerN.o o/bnInit.o o/bnMult.o o/bnDivide.o o/bnCmp.o o/bzf.o o/bz.o
+DEFINES = -DDIGITon32BIT -I./h
+KERNH = h/BigNum.h
+
+
+all:: $(OBJECT)
+
+clean::
+ $(RM) $(OBJECT)
+
+
+o/KerN.o: c/KerN.c
+ $(CC) $(CFLAGS) -c c/KerN.c
+ mv KerN.o o
+
+# Level N
+o/bnInit.o: c/bn/bnInit.c $(KERNH)
+ $(CC) $(CFLAGS) -c c/bn/bnInit.c
+ mv bnInit.o o
+
+o/bnMult.o: c/bn/bnMult.c $(KERNH)
+ $(CC) $(CFLAGS) -c c/bn/bnMult.c
+ mv bnMult.o o
+
+o/bnDivide.o: c/bn/bnDivide.c $(KERNH)
+ $(CC) $(CFLAGS) -c c/bn/bnDivide.c
+ mv bnDivide.o o
+
+o/bnCmp.o: c/bn/bnCmp.c $(KERNH)
+ $(CC) $(CFLAGS) -c c/bn/bnCmp.c
+ mv bnCmp.o o
+
+# Level Z
+o/bz.o: c/bz.c h/BigZ.h $(KERNH)
+ $(CC) $(CFLAGS) -c c/bz.c
+ mv bz.o o
+
+# Some functions build with BigZ
+o/bzf.o: c/bzf.c h/BigZ.h $(KERNH)
+ $(CC) $(CFLAGS) -c c/bzf.c
+ mv bzf.o o
+
--- /dev/null
+/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */
+/* Last modified_on Fri Mar 2 16:49:23 GMT+1:00 1990 by herve */
+/* modified_on Mon Feb 19 20:22:20 GMT+1:00 1990 by shand */
+
+
+/* KerN.c: the kernel written in C */
+
+/*
+ * Description of types and constants.
+ *
+ * Several conventions are used in the commentary:
+ * A "BigNum" is the name for an infinite-precision number.
+ * Capital letters (e.g., "N") are used to refer to the value of BigNums.
+ * The word "digit" refers to a single BigNum digit.
+ * The notation "Size(N)" refers to the number of digits in N,
+ * which is typically passed to the subroutine as "nl".
+ * The notation "Length(N)" refers to the number of digits in N,
+ * not including any leading zeros.
+ * The word "Base" is used for the number 2 ** BN_DIGIT_SIZE, where
+ * BN_DIGIT_SIZE is the number of bits in a single BigNum digit.
+ * The expression "BBase(N)" is used for Base ** NumDigits(N).
+ * The term "leading zeros" refers to any zeros before the most
+ * significant digit of a number.
+ *
+ *
+ * In the code, we have:
+ *
+ * "nn" is a pointer to a big number,
+ * "nl" is the number of digits from nn,
+ * "d" is a digit.
+ *
+ */
+
+
+/*\f*/
+
+
+#define BNNMACROS_OFF
+#include "BigNum.h"
+
+
+ /*** copyright ***/
+
+static char copyright[]="@(#)KerN.c: copyright Digital Equipment Corporation & INRIA 1988, 1989\n";
+
+
+ /******* non arithmetic access to digits ********/
+
+
+void BnnSetToZero (nn, nl)
+
+register BigNum nn;
+register int nl;
+
+/*
+ * Sets all the specified digits of the BigNum to 0
+ */
+
+{
+#ifdef NOMEM
+ while (--nl >= 0)
+ *(nn++) = 0;
+#else
+ memset (nn, 0, nl*BN_DIGIT_SIZE/BN_BYTE_SIZE);
+#endif
+}
+
+ /***************************************/
+
+
+void BnnAssign (mm, nn, nl)
+
+register BigNum mm, nn;
+register int nl;
+
+/*
+ * Copies N => M
+ */
+
+{
+ if (mm < nn || mm > nn+nl)
+#ifdef NOMEM
+ while (--nl >= 0)
+ *mm++ = *nn++;
+#else
+ /* be care: bcopy (SRC, DEST, L): SRC-->DEST !!! */
+#ifdef SOLARIS
+ memmove (mm, nn, nl*BN_DIGIT_SIZE/BN_BYTE_SIZE);
+#else
+ bcopy (nn, mm, nl*BN_DIGIT_SIZE/BN_BYTE_SIZE);
+#endif
+#endif
+ else
+ if (mm > nn)
+ {
+ nn += nl;
+ mm += nl;
+ while (--nl >= 0)
+ *--mm = *--nn;
+ }
+}
+
+ /***************************************/
+/*\f*/
+
+
+void BnnSetDigit (nn, d)
+
+BigNum nn;
+int d;
+
+/*
+ * Sets a single digit of N to the passed value
+ */
+
+{
+ *nn = d;
+}
+
+ /***************************************/
+
+
+BigNumDigit BnnGetDigit (nn)
+
+BigNum nn;
+
+/*
+ * Returns the single digit pointed by N
+ */
+
+{
+ return (*nn);
+}
+
+ /***************************************/
+/*\f*/
+
+
+BigNumLength BnnNumDigits (nn, nl)
+
+register BigNum nn;
+register int nl;
+
+/*
+ * Returns the number of digits of N, not counting leading zeros
+ */
+
+{
+ nn += nl;
+
+ while (nl != 0 && *--nn == 0)
+ nl--;
+
+ return (nl == 0 ? 1 : nl);
+}
+
+ /***************************************/
+
+
+BigNumDigit BnnNumLeadingZeroBitsInDigit (d)
+
+BigNumDigit d;
+
+/*
+ * Returns the number of leading zero bits in a digit
+ */
+
+{
+ register BigNumDigit mask = 1 << (BN_DIGIT_SIZE - 1);
+ register int p = 0;
+
+
+ if (d == 0)
+ return (BN_DIGIT_SIZE);
+
+ while ((d & mask) == 0)
+ {
+ p++;
+ mask >>= 1;
+ }
+
+ return (p);
+}
+
+ /***************************************/
+/*\f*/
+
+ /************** Predicates on one digit ***************/
+
+
+Boolean BnnDoesDigitFitInWord (d)
+
+BigNumDigit d;
+
+/*
+ * Returns TRUE iff the digit can be represented in just BN_WORD_SIZE bits
+ */
+{
+ /* The C compiler must evaluate the predicate at compile time */
+ if (BN_DIGIT_SIZE > BN_WORD_SIZE)
+ return (d >= 1 << BN_WORD_SIZE ? FALSE : TRUE);
+ else
+ return (TRUE);
+}
+
+ /***************************************/
+
+
+Boolean BnnIsDigitZero (d)
+
+BigNumDigit d;
+
+/* Returns TRUE iff digit = 0 */
+
+{
+ return (d == 0);
+}
+
+ /***************************************/
+
+
+Boolean BnnIsDigitNormalized (d)
+
+BigNumDigit d;
+
+/*
+ * Returns TRUE iff Base/2 <= digit < Base
+ * i.e., if digit's leading bit is 1
+ */
+
+{
+ return (d & (1 << (BN_DIGIT_SIZE - 1)) ? TRUE : FALSE);
+}
+
+ /***************************************/
+
+
+Boolean BnnIsDigitOdd (d)
+
+BigNumDigit d;
+
+/*
+ * Returns TRUE iff digit is odd
+ */
+
+{
+ return (d & 1 ? TRUE : FALSE);
+}
+
+ /***************************************/
+
+
+BigNumCmp BnnCompareDigits (d1, d2)
+
+BigNumDigit d1, d2;
+
+/*
+ * Returns BN_GREATER if digit1 > digit2
+ * BN_EQUAL if digit1 = digit2
+ * BN_LESS if digit1 < digit2
+ */
+
+{
+ return (d1 > d2 ? BN_GT : (d1 == d2 ? BN_EQ : BN_LT));
+}
+
+ /***************** Logical operations ********************/
+
+
+void BnnComplement (nn, nl)
+
+register BigNum nn;
+register int nl;
+
+/*
+ * Performs the computation BBase(N) - N - 1 => N
+ */
+
+{
+ while (--nl >= 0)
+ *(nn++) ^= -1;
+}
+
+ /***************************************/
+/*\f*/
+
+
+void BnnAndDigits (n, d)
+
+BigNum n;
+BigNumDigit d;
+
+/*
+ * Returns the logical computation n[0] AND d in n[0]
+ */
+
+{
+ *n &= d;
+}
+
+ /***************************************/
+
+
+void BnnOrDigits (n, d)
+
+BigNum n;
+BigNumDigit d;
+
+/*
+ * Returns the logical computation n[0] OR d2 in n[0].
+ */
+
+{
+ *n |= d;
+}
+
+ /***************************************/
+
+
+void BnnXorDigits (n, d)
+
+BigNum n;
+BigNumDigit d;
+
+/*
+ * Returns the logical computation n[0] XOR d in n[0].
+ */
+
+{
+ *n ^= d;
+}
+
+ /***************************************/
+/*\f*/
+
+ /****************** Shift operations *******************/
+
+
+BigNumDigit BnnShiftLeft (mm, ml, nbits)
+
+register BigNum mm;
+register int ml;
+ int nbits;
+
+/*
+ * Shifts M left by "nbits", filling with 0s.
+ * Returns the leftmost "nbits" of M in a digit.
+ * Assumes 0 <= nbits < BN_DIGIT_SIZE.
+ */
+
+{
+ register BigNumDigit res = 0, save;
+ int rnbits;
+
+
+ if (nbits != 0)
+ {
+ rnbits = BN_DIGIT_SIZE - nbits;
+
+ while (--ml >= 0)
+ {
+ save = *mm;
+ *mm++ = (save << nbits) | res;
+ res = save >> rnbits;
+ }
+ }
+
+ return (res);
+}
+
+ /***************************************/
+/*\f*/
+
+
+BigNumDigit BnnShiftRight (mm, ml, nbits)
+
+register BigNum mm;
+register int ml;
+ int nbits;
+
+/*
+ * Shifts M right by "nbits", filling with 0s.
+ * Returns the rightmost "nbits" of M in a digit.
+ * Assumes 0 <= nbits < BN_DIGIT_SIZE.
+ */
+
+{
+ register BigNumDigit res = 0, save;
+ int lnbits;
+
+
+ if (nbits != 0)
+ {
+ mm += ml;
+ lnbits = BN_DIGIT_SIZE - nbits;
+
+ while (--ml >= 0)
+ {
+ save = *(--mm);
+ *mm = (save >> nbits) | res;
+ res = save << lnbits;
+ }
+ }
+
+ return (res);
+}
+
+ /***************************************/
+/*\f*/
+
+
+ /******************* Additions **************************/
+
+
+BigNumCarry BnnAddCarry (nn, nl, carryin)
+
+register BigNum nn;
+register int nl;
+ BigNumCarry carryin;
+
+/*
+ * Performs the sum N + CarryIn => N.
+ * Returns the CarryOut.
+ */
+
+{
+ if (carryin == 0)
+ return (0);
+
+ if (nl == 0)
+ return (1);
+
+ while (--nl >= 0 && !(++(*nn++)))
+ ;
+
+ return (nl >= 0 ? 0 : 1);
+}
+
+ /***************************************/
+/*\f*/
+
+
+BigNumCarry BnnAdd (mm, ml, nn, nl, carryin)
+
+register BigNum mm, nn;
+ int ml;
+register int nl;
+ BigNumCarry carryin;
+
+/*
+ * Performs the sum M + N + CarryIn => M.
+ * Returns the CarryOut.
+ * Assumes Size(M) >= Size(N).
+ */
+
+{
+ register BigNumProduct c = carryin;
+
+
+ ml -= nl;
+ /* test computed at compile time */
+ if (sizeof (BigNumProduct) > sizeof (BigNumDigit))
+ {
+ while (--nl >= 0)
+ {
+ c += *mm + *(nn++);
+ *(mm++) = c;
+ c >>= BN_DIGIT_SIZE;
+ }
+ }
+ else
+ {
+ register BigNumProduct save;
+
+ while (--nl >= 0)
+ {
+ save = *mm;
+ c += save;
+ if (c < save)
+ {
+ *(mm++) = *(nn++);
+ c = 1;
+ }
+ else
+ {
+ save = *(nn++);
+ c += save;
+ *(mm++) = c;
+ c = (c < save) ? 1 : 0;
+ }
+ }
+ }
+
+ return (BnnAddCarry (mm, ml, (BigNumCarry) c));
+}
+
+ /***************************************/
+/*\f*/
+
+ /****************** Subtraction *************************/
+
+
+
+BigNumCarry BnnSubtractBorrow (nn, nl, carryin)
+
+register BigNum nn;
+register int nl;
+ BigNumCarry carryin;
+
+/*
+ * Performs the difference N + CarryIn - 1 => N.
+ * Returns the CarryOut.
+ */
+
+{
+ if (carryin == 1)
+ return (1);
+ if (nl == 0)
+ return (0);
+
+#ifdef ibm032
+ while (--nl >= 0 && !(*nn)--) nn++;
+#else
+ while (--nl >= 0 && !((*nn++)--))
+#endif
+ ;
+
+ return (nl >= 0 ? 1 : 0);
+}
+
+ /***************************************/
+/*\f*/
+
+
+BigNumCarry BnnSubtract (mm, ml, nn, nl, carryin)
+
+register BigNum mm, nn;
+ int ml;
+register int nl;
+ BigNumCarry carryin;
+
+/*
+ * Performs the difference M - N + CarryIn - 1 => M.
+ * Returns the CarryOut.
+ * Assumes Size(M) >= Size(N).
+ */
+
+{
+ register BigNumProduct c = carryin;
+ register BigNumDigit invn;
+
+
+ ml -= nl;
+ /* test computed at compile time */
+ if (sizeof (BigNumProduct) > sizeof (BigNumDigit))
+ {
+ while (--nl >= 0)
+ {
+ invn = *(nn++) ^ -1;
+ c += *mm + invn;
+ *(mm++) = c;
+ c >>= BN_DIGIT_SIZE;
+ }
+ }
+ else
+ {
+ register BigNumProduct save;
+
+ while (--nl >= 0)
+ {
+ save = *mm;
+ invn = *(nn++) ^ -1;
+ c += save;
+
+ if (c < save)
+ {
+ *(mm++) = invn;
+ c = 1;
+ }
+ else
+ {
+ c += invn;
+ *(mm++) = c;
+ c = (c < invn) ? 1 : 0;
+ }
+ }
+ }
+
+ return (BnnSubtractBorrow (mm, ml, (BigNumCarry) c)); }
+
+
+ /***************************************/
+/*\f */
+
+ /***************** Multiplication ************************/
+
+
+BigNumCarry BnnMultiplyDigit (pp, pl, mm, ml, d)
+
+register BigNum pp, mm;
+ int pl, ml;
+ BigNumDigit d;
+
+/*
+ * Performs the product:
+ * Q = P + M * d
+ * BB = BBase(P)
+ * Q mod BB => P
+ * Q div BB => CarryOut
+ * Returns the CarryOut.
+ * Assumes Size(P) >= Size(M) + 1.
+ */
+
+{
+ register BigNumProduct c = 0;
+
+
+ if (d == 0)
+ return (0);
+
+ if (d == 1)
+ return (BnnAdd (pp, pl, mm, ml, (BigNumCarry) 0));
+
+ pl -= ml;
+ /* test computed at compile time */
+ if (sizeof (BigNumProduct) > sizeof (BigNumDigit))
+ {
+ while (ml != 0)
+ {
+ ml--;
+ c += *pp + (d * (*(mm++)));
+ *(pp++) = c;
+ c >>= BN_DIGIT_SIZE;
+ }
+
+ while (pl != 0) {
+ pl--;
+ c += *pp;
+ *(pp++) = c;
+ c >>= BN_DIGIT_SIZE;
+ }
+
+ return (c);
+ }
+ else
+ {
+/* help for stupid compilers--may actually be counter
+ productive on pipelined machines with decent register allocation!! */
+#define m_digit X0
+#define X3 Lm
+#define X1 Hm
+ register BigNumDigit Lm, Hm, Ld, Hd, X0, X2 /*, X1, X3 */;
+
+ Ld = d & ((1 << (BN_DIGIT_SIZE / 2)) -1);
+ Hd = d >> (BN_DIGIT_SIZE / 2);
+ while (ml != 0)
+ {
+ ml--;
+ m_digit = *mm++;
+ Lm = m_digit & ((1 << (BN_DIGIT_SIZE / 2)) -1);
+ Hm = m_digit >> (BN_DIGIT_SIZE / 2);
+ X0 = Ld * Lm;
+ X2 = Hd * Lm;
+ X3 = Hd * Hm;
+ X1 = Ld * Hm;
+
+ if ((c += X0) < X0) X3++;
+ if ((X1 += X2) < X2) X3 += (1<<(BN_DIGIT_SIZE / 2));
+ X3 += (X1 >> (BN_DIGIT_SIZE / 2));
+ X1 <<= (BN_DIGIT_SIZE / 2);
+ if ((c += X1) < X1) X3++;
+ if ((*pp += c) < c) X3++;
+ pp++;
+
+ c = X3;
+#undef m_digit
+#undef X1
+#undef X3
+ }
+
+ X0 = *pp;
+ c += X0;
+ *(pp++) = c;
+
+ if (c >= X0)
+ return (0);
+
+ pl--;
+ while (pl != 0 && !(++(*pp++)))
+ pl--;
+
+ return (pl != 0 ? 0 : 1);
+ }
+}
+
+#ifdef mips
+BigNumCarry BnnMultiply2Digit (pp, pl, mm, ml, d0, d1)
+
+register BigNum pp, mm;
+register int pl, ml;
+ BigNumDigit d0, d1;
+
+/*
+ * Provided for compatibility with mips assembler implementation.
+ * Performs the product:
+ * Q = P + M * d0_d1
+ * BB = BBase(P)
+ * Q mod BB => P
+ * Q div BB => CarryOut
+ * Returns the CarryOut.
+ * Assumes Size(P) >= Size(M) + 1.
+ */
+
+{
+ return
+ BnnMultiplyDigit (pp, pl, mm, ml, d0)
+ + BnnMultiplyDigit (pp+1, pl-1, mm, ml, d1);
+}
+#endif /* mips */
+
+ /***************************************/
+/*\f*/
+
+ /********************** Division *************************/
+
+
+ /* xh:xl -= yh:yl */
+#define SUB(xh,xl,yh,yl) if (yl > xl) {xl -= yl; xh -= yh + 1;}\
+ else {xl -= yl; xh -= yh;}
+
+#define LOW(x) (x & ((1 << (BN_DIGIT_SIZE / 2)) -1))
+#define HIGH(x) (x >> (BN_DIGIT_SIZE / 2))
+#define L2H(x) (x << (BN_DIGIT_SIZE / 2))
+
+
+BigNumDigit BnnDivideDigit (qq, nn, nl, d)
+
+register BigNum qq, nn;
+register int nl;
+ BigNumDigit d;
+
+/* Performs the quotient: N div d => Q
+ * Returns R = N mod d
+ * Assumes leading digit of N < d, and d > 0.
+ */
+
+{
+ /* test computed at compile time */
+ if (sizeof (BigNumProduct) > sizeof (BigNumDigit))
+ {
+ register BigNumProduct quad;
+
+
+ nn += nl;
+ nl--;
+ qq += nl;
+ quad = *(--nn);
+
+ while (nl != 0)
+ {
+ nl--;
+ quad = (quad << BN_DIGIT_SIZE) | *(--nn);
+ *(--qq) = quad / d;
+ quad = quad % d;
+ }
+
+ return (quad);
+ }
+ else
+ {
+ int k;
+ int orig_nl;
+ BigNumDigit rh; /* Two halves of current remainder */
+ BigNumDigit rl; /* Correspond to quad above */
+ register BigNumDigit qa; /* Current appr. to quotient */
+ register BigNumDigit ph, pl; /* product of c and qa */
+ BigNumDigit ch, cl, prev_qq;
+
+
+ /* Normalize divisor */
+ k = BnnNumLeadingZeroBitsInDigit (d);
+ if (k != 0)
+ {
+ prev_qq = qq[-1];
+ orig_nl = nl;
+ d <<= k;
+ BnnShiftLeft (nn, nl, k);
+ }
+
+ nn += nl;
+ nl--;
+ qq += nl;
+
+ ch = HIGH (d);
+ cl = LOW (d);
+
+ rl = *(--nn);
+
+ while (nl != 0)
+ {
+ nl--;
+ rh = rl;
+ rl = *(--nn);
+ qa = rh / ch; /* appr. quotient */
+
+ /* Compute ph, pl */
+ pl = cl * qa;
+ ph = ch * qa;
+ ph += HIGH (pl);
+ pl = L2H (pl);
+
+ /* While ph:pl > rh:rl, decrement qa, adjust qh:ql */
+ while (ph > rh || ph == rh && pl > rl)
+ {
+ qa--;
+ SUB (ph, pl, ch, L2H (cl));
+ }
+
+ SUB (rh, rl, ph, pl);
+
+ /* Top half of quotient is correct; save it */
+ *(--qq) = L2H (qa);
+ qa = (L2H (rh) | HIGH (rl)) / ch;
+
+ /* Approx low half of q */
+ /* Compute ph, pl, again */
+ pl = cl * qa;
+ ph = ch * qa;
+ ph += HIGH (pl);
+ pl = LOW (pl) | L2H (LOW (ph));
+ ph = HIGH (ph);
+
+ /* While ph:pl > rh:rl, decrement qa, adjust qh:ql */
+ while (ph > rh || ph == rh && pl > rl)
+ {
+ qa--;
+ SUB (ph, pl, 0, d);
+ }
+
+ /* Subtract ph:pl from rh:rl; we know rh will be 0 */
+ rl -= pl;
+ *qq |= qa;
+ }
+
+ /* Denormalize dividend */
+ if (k != 0) {
+ if((qq > nn) && (qq < &nn[orig_nl])) {
+ /* Overlap between qq and nn. Care of *qq! */
+ orig_nl = (qq - nn);
+ BnnShiftRight (nn, orig_nl, k);
+ nn[orig_nl - 1] = prev_qq;
+ } else if(qq == nn) {
+ BnnShiftRight(&nn[orig_nl - 1], 1, k);
+ } else {
+ BnnShiftRight (nn, orig_nl, k);
+ } }
+ return (rl >> k);
+ }
+}
+
+ /***************************************/
+
+
--- /dev/null
+/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */
+/* Last modified_on Fri Aug 10 17:21:47 GMT+2:00 1990 by shand */
+/* modified_on Fri Apr 28 18:36:28 GMT+2:00 1989 by herve */
+
+
+/* bnCmp.c: a piece of the bignum kernel written in C */
+
+
+ /***************************************/
+
+#define BNNMACROS_OFF
+#include "BigNum.h"
+
+ /*** copyright ***/
+
+static char copyright[]="@(#)bnCmp.c: copyright Digital Equipment Corporation & INRIA 1988, 1989, 1990\n";
+
+
+Boolean BnnIsZero (nn, nl)
+
+BigNum nn;
+BigNumLength nl;
+
+/*
+ * Returns TRUE iff N = 0
+ */
+
+{
+ return (BnnNumDigits (nn, nl) == 1 && (nl == 0 || BnnIsDigitZero (*nn)));
+}
+
+ /***************************************/
+/*\f*/
+
+
+BigNumCmp BnnCompare (mm, ml, nn, nl)
+
+ BigNum mm, nn;
+register BigNumLength ml, nl;
+
+/*
+ * return
+ * BN_GT iff M > N
+ * BN_EQ iff N = N
+ * BN_LT iff N < N
+*/
+
+{
+ register BigNumCmp result = BN_EQ;
+
+
+ ml = BnnNumDigits (mm, ml);
+ nl = BnnNumDigits (nn, nl);
+
+ if (ml != nl)
+ return (ml > nl ? BN_GT : BN_LT);
+
+ while (result == BN_EQ && ml-- > 0)
+ result = BnnCompareDigits (*(mm+ml), *(nn+ml));
+
+ return (result);
+
+/**** USE memcmp() instead: extern int memcmp ();
+
+ if (ml == nl)
+ {
+ lex = memcmp (mm, nn, nl*BN_DIGIT_SIZE/BN_BYTE_SIZE);
+ return (lex > 0 ? BN_GT: (lex == 0 ? BN_EQ: BN_LT));
+ }
+ else
+ return (ml > nl ? BN_GT : BN_LT);
+******/
+}
--- /dev/null
+/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */
+/* Last modified_on Fri Mar 30 3:29:17 GMT+2:00 1990 by shand */
+/* modified_on Fri Apr 28 18:36:28 GMT+2:00 1989 by herve */
+
+
+/* bnDivide.c: a piece of the bignum kernel written in C */
+
+
+ /***************************************/
+
+#define BNNMACROS_OFF
+#include "BigNum.h"
+
+ /*** copyright ***/
+
+static char copyright[]="@(#)bnDivide.c: copyright Digital Equipment Corporation & INRIA 1988, 1989, 1990\n";
+
+
+static divide (nn, nl, dd, dl)
+
+ BigNum nn, dd;
+register BigNumLength nl, dl;
+
+/*
+ * In-place division.
+ *
+ * Input (N has been EXTENDED by 1 PLACE; D is normalized):
+ * +-----------------------------------------------+----+
+ * | N EXT|
+ * +-----------------------------------------------+----+
+ *
+ * +-------------------------------+
+ * | D 1|
+ * +-------------------------------+
+ *
+ * Output (in place of N):
+ * +-------------------------------+---------------+----+
+ * | R | Q |
+ * +-------------------------------+---------------+----+
+ *
+ * Assumes:
+ * N > D
+ * Size(N) > Size(D)
+ * last digit of N < last digit of D
+ * D is normalized (Base/2 <= last digit of D < Base)
+ */
+
+{
+ register int ni;
+ BigNumDigit DDigit, BaseMinus1, QApp, RApp;
+
+
+ /* Initialize constants */
+ BnnSetDigit (&BaseMinus1, 0);
+ BnnComplement(&BaseMinus1, 1);
+
+ /* Save the most significant digit of D */
+ BnnAssign (&DDigit, dd+dl-1, 1);
+
+ /* Replace D by Base - D */
+ BnnComplement (dd, dl);
+ BnnAddCarry (dd, dl, 1);
+
+ /* For each digit of the divisor, from most significant to least: */
+ nl += 1;
+ ni = nl-dl;
+ while (--ni >= 0)
+ {
+ /* Compute the approximate quotient */
+ nl--;
+
+ /* If first digits of numerator and denominator are the same, */
+ if (BnnCompareDigits (*(nn+nl), DDigit) == BN_EQ)
+ /* Use "Base - 1" for the approximate quotient */
+ BnnAssign (&QApp, &BaseMinus1, 1);
+ else
+ /* Divide the first 2 digits of N by the first digit of D */
+ RApp = BnnDivideDigit (&QApp, nn+nl-1, 2, DDigit);
+
+ /* Compute the remainder */
+ BnnMultiplyDigit (nn+ni, dl+1, dd, dl, QApp);
+
+ /* Correct the approximate quotient, in case it was too large */
+ while (BnnCompareDigits (*(nn+nl), QApp) != BN_EQ)
+ {
+ BnnSubtract (nn+ni, dl+1, dd, dl, 1); /* Subtract D from N */
+ BnnSubtractBorrow (&QApp, 1, 0); /* Q -= 1 */
+ }
+ }
+
+ /* Restore original D */
+ BnnComplement (dd, dl);
+ BnnAddCarry (dd, dl, 1);
+}
+
+
+ /***************************************/
+/*\f*/
+
+
+void BnnDivide (nn, nl, dd, dl)
+
+ BigNum nn, dd;
+register BigNumLength nl, dl;
+
+/*
+ * Performs the quotient:
+ * N div D => high-order bits of N, starting at N[dl]
+ * N mod D => low-order dl bits of N
+ *
+ * Assumes
+ * Size(N) > Size(D),
+ * last digit of N < last digit of D (if N > D).
+ */
+
+{
+ BigNumDigit nshift;
+
+
+ /* Take care of easy cases first */
+ switch (BnnCompare (nn, nl, dd, dl))
+ {
+ case BN_LT: /* n < d */
+ ; /* N => R */
+ BnnSetToZero (nn+dl, nl-dl); /* 0 => Q */
+ return;
+ case BN_EQ: /* n == d */
+ BnnSetToZero (nn, nl); /* 0 => R */
+ BnnSetDigit (nn+nl-1, 1); /* 1 => Q */
+ return;
+ }
+
+ /* here: n > d */
+
+ /* If divisor is just 1 digit, use a special divide */
+ if (dl == 1)
+ *nn = BnnDivideDigit (nn+1, nn, nl, *dd); /* note: nn+1 = nn+dl */
+ /* Otherwise, divide one digit at a time */
+ else
+ {
+ /* Normalize */
+ nshift = BnnNumLeadingZeroBitsInDigit (*(dd+dl-1));
+ BnnShiftLeft (dd, dl, nshift);
+ BnnShiftLeft (nn, nl, nshift);
+
+ /* Divide */
+ divide (nn, nl-1, dd, dl);
+
+ /* Unnormalize */
+ BnnShiftRight (dd, dl, nshift);
+ BnnShiftRight (nn, dl, nshift);
+ /* note: unnormalize N <=> unnormalize R (with R < D) */
+ }
+}
--- /dev/null
+/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */
+/* Last modified_on Fri Mar 30 3:28:56 GMT+2:00 1990 by shand */
+/* modified_on Wed Feb 14 16:06:50 GMT+1:00 1990 by herve */
+
+
+/* bnInit.c: a piece of the bignum kernel written in C */
+
+
+ /***************************************/
+
+#define BNNMACROS_OFF
+#include "BigNum.h"
+
+static int Initialized = FALSE;
+
+ /*** copyright ***/
+
+static char copyright[]="@(#)bnInit.c: copyright Digital Equipment Corporation & INRIA 1988, 1989, 1990\n";
+
+
+ /***************************************/
+
+void BnnInit ()
+{
+ if (!Initialized)
+ {
+
+
+ Initialized = TRUE;
+ }
+}
+
+ /***************************************/
+
+void BnnClose ()
+{
+ if (Initialized)
+ {
+
+
+ Initialized = FALSE;
+ }
+}
+
+ /***************************************/
+
+ /* some U*x standard functions do not exist on VMS */
+
+#ifdef VMS
+
+/* Copies LENGTH bytes from string SRC to string DST */
+void bcopy(src, dst, length)
+char *src, *dst;
+register int length;
+{
+ for (; length > 0; length--)
+ *dst++ = *src++;
+}
+
+/* Places LENGTH 0 bytes in the string B */
+void bzero(buffer, length)
+char *buffer;
+register int length;
+{
+ for (; length>0; length--)
+ *buffer++ = 0;
+}
+
+#endif
+
+
+ /***************************************/
--- /dev/null
+/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */
+/* Last modified_on Fri Mar 30 4:13:47 GMT+2:00 1990 by shand */
+/* modified_on Mon Mar 26 18:09:25 GMT+2:00 1990 by herve */
+
+
+/* bnMult.c: a piece of the bignum kernel written in C */
+
+
+ /***************************************/
+
+#define BNNMACROS_OFF
+#include "BigNum.h"
+
+ /*** copyright ***/
+
+static char copyright[]="@(#)bnMult.c: copyright Digital Equipment Corporation & INRIA 1988, 1989, 1990\n";
+
+BigNumCarry BnnMultiply (pp, pl, mm, ml, nn, nl)
+
+register BigNum pp, nn;
+ BigNum mm;
+register BigNumLength pl, nl;
+ BigNumLength ml;
+
+/*
+ * Performs the product:
+ * Q = P + M * N
+ * BB = BBase(P)
+ * Q mod BB => P
+ * Q div BB => CarryOut
+ *
+ * Returns the CarryOut.
+ *
+ * Assumes:
+ * Size(P) >= Size(M) + Size(N),
+ * Size(M) >= Size(N).
+ */
+
+{
+ BigNumCarry c;
+
+ /* Multiply one digit at a time */
+
+ /* the following code give higher performance squaring.
+ ** Unfortunately for small nl, procedure call overheads kills it
+ */
+#ifndef mips
+ /* Squaring code provoke a mips optimizer bug in V1.31 */
+ if (mm == nn && ml == nl && nl > 6)
+ {
+ register n_prev = 0;
+ /* special case of squaring */
+ for (c = 0; nl > 0; )
+ {
+ register BigNumDigit n = *nn;
+ c += BnnMultiplyDigit(pp, pl, nn, 1, n);
+ if (n_prev)
+ c += BnnAdd(pp, pl, nn, 1, 0);
+ nl--, nn++;
+ pp += 2, pl -= 2;
+ c += BnnMultiplyDigit(pp-1, pl+1, nn, nl, n+n+n_prev);
+ n_prev = ((long) n) < 0;
+ }
+ }
+ else
+#endif /* mips */
+ for (c = 0; nl-- > 0; pp++, nn++, pl--)
+ c += BnnMultiplyDigit (pp, pl, mm, ml, *nn);
+
+ return c;
+}
--- /dev/null
+/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */
+/* Last modified_on Tue Mar 27 15:35:41 GMT+2:00 1990 by herve */
+/* modified_on Thu Mar 22 20:45:38 GMT+1:00 1990 by shand */
+
+
+/* bz.c: provides an implementation of "unlimited-precision"
+ * arithmetic for signed integers.
+ *
+ * Several conventions are used in the commentary:
+ * A "BigZ" is the name for an arbitrary-precision signed integer.
+ * Capital letters (e.g., "Z") are used to refer to the value of BigZs.
+ */
+
+
+#include "BigZ.h"
+
+
+ /***************************************/
+/*
+#include <stdio.h>
+#include <macros.h>
+#include <math.h>
+#include <malloc.h>
+#include <values.h>
+*/
+
+#define NULL 0
+#define max(a,b) (a<b ? b : a)
+#define abs(x) (x>=0 ? x : -(x))
+#define M_LN2 0.69314718055994530942
+#define M_LN10 2.30258509299404568402
+#define BITSPERBYTE 8
+#define BITS(type) (BITSPERBYTE * (int)sizeof(type))
+#define HIBITI (1 << BITS(int) - 1)
+#define MAXINT (~HIBITI)
+
+ /***************************************/
+
+#define BzToBn(z) ((z)->Digits)
+#define CTOI(c) (c >= '0' && c <= '9' ? c - '0' :\
+ c >= 'a' && c <= 'f' ? c - 'a' + 10:\
+ c >= 'A' && c <= 'F' ? c - 'A' + 10:\
+ 0)
+
+extern char *malloc();
+
+ /*** copyright ***/
+
+static char copyright[]="@(#)bz.c: copyright Digital Equipment Corporation & INRIA 1988, 1989\n";
+
+
+ /***************************************/
+
+static int Initialized = FALSE;
+
+/* constants used by BzToString() and BzFromString() */
+static double BzLog [] =
+{
+ 0,
+ 0, /* log (1) */
+ M_LN2, /* log (2) */
+ 1.098612, /* log (3) */
+ 1.386294, /* log (4) */
+ 1.609438, /* log (5) */
+ 1.791759, /* log (6) */
+ 1.945910, /* log (7) */
+ 2.079442, /* log (8) */
+ 2.197225, /* log (9) */
+ M_LN10, /* log (10) */
+ 2.397895, /* log (11) */
+ 2.484907, /* log (12) */
+ 2.564949, /* log (13) */
+ 2.639057, /* log (14) */
+ 2.708050, /* log (15) */
+ 2.772588, /* log (16) */
+};
+
+/*\f*/
+
+
+void BzInit ()
+{
+ if (!Initialized)
+ {
+ BnnInit ();
+ Initialized = TRUE;
+ }
+}
+
+ /***************************************/
+
+
+BigZ BzCreate (Size)
+
+int Size;
+
+/*
+ * Allocates a BigZ of the desired size.
+ * Sets it to 0.
+ */
+
+{
+ BigZ z;
+
+
+ if ((z = (BigZ) (malloc (sizeof (struct BigZHeader) + Size * sizeof (BigNumDigit)))) != NULL)
+ {
+ /* reset digits */
+ BnnSetToZero (BzToBn (z), Size);
+
+ /* init header */
+ BzSetSize (z, Size);
+ BzSetSign (z, BZ_ZERO);
+ }
+
+ return (z);
+}
+
+
+
+void BzFree (z)
+
+BigZ z;
+
+/*
+ * Frees an existing BigZ.
+ */
+
+{
+ free (z);
+}
+
+ /***************************************/
+ /***************************************/
+
+
+void BzFreeString (s)
+
+char *s;
+
+/*
+ * Frees an existing BigZ allocated string.
+ */
+
+{
+ free (s);
+}
+
+ /***************************************/
+/*\f*/
+
+unsigned BzNumDigits (z)
+
+BigZ z;
+
+/*
+ * Returns the number of digits used by z.
+ */
+
+{
+ return (BnnNumDigits (BzToBn (z), BzGetSize (z)));
+}
+
+
+ /***************************************/
+
+
+BigZ BzCopy (z)
+
+BigZ z;
+
+/*
+ * Creates a copy of the passed BigZ.
+ */
+
+{
+ BigZ y;
+ int zl;
+
+
+ zl = BzNumDigits (z);
+ if ((y = BzCreate (zl)) != NULL)
+ {
+ /* copy the digits */
+ BnnAssign (BzToBn (y), BzToBn (z), zl);
+
+ /* copy the header WITHOUT the size !! */
+ BzSetSign (y, BzGetSign (z));
+ }
+
+ return (y);
+}
+
+ /***************************************/
+/*\f*/
+
+
+BigZ BzNegate (z)
+
+BigZ z;
+
+/*
+ * Negates the passed BigZ.
+ */
+
+{
+ BigZ y;
+
+ y = BzCopy (z);
+ BzSetSign (y, BzGetOppositeSign (z));
+
+ return (y);
+}
+
+ /***************************************/
+
+
+BigZ BzAbs (z)
+
+BigZ z;
+
+/*
+ * Takes the absolute value of the passed BigZ.
+ */
+
+{
+ BigZ y;
+
+ y = BzCopy (z);
+ BzSetSign (y, abs (BzGetSign (z)));
+
+ return (y);
+}
+
+ /***************************************/
+
+
+BzCmp BzCompare (y, z)
+
+BigZ y, z;
+
+/*
+ * Returns BZ_GT if Y > Z,
+ * BZ_LT if Y < Z,
+ * BZ_EQ otherwise.
+ */
+
+{
+ return (BzGetSign (y) > BzGetSign (z) ? BZ_GT :
+ BzGetSign (y) < BzGetSign (z) ? BZ_LT :
+ BzGetSign (y) > 0 ? BnnCompare (BzToBn (y), BzGetSize (y),
+ BzToBn (z), BzGetSize (z)) :
+ BzGetSign (y) < 0 ? BnnCompare (BzToBn (z), BzGetSize (z),
+ BzToBn (y), BzGetSize (y)) :
+ BZ_EQ);
+}
+
+ /***************************************/
+/*\f*/
+
+
+BigZ BzAdd (y, z)
+
+BigZ y, z;
+
+/*
+ * Returns Y + Z.
+ */
+
+{
+ BigZ n;
+ int yl;
+ int zl;
+
+
+ yl = BzNumDigits (y);
+ zl = BzNumDigits (z);
+
+ if (BzGetSign (y) == BzGetSign (z))
+ {
+ /* Add magnitudes if signs are the same */
+ switch (BnnCompare (BzToBn (y), yl, BzToBn (z), zl))
+ {
+ case BZ_EQ:
+ case BZ_GT: /* |Y| >= |Z| */
+
+ if ((n = BzCreate (yl+1)) != NULL)
+ {
+ BnnAssign (BzToBn (n), BzToBn (y), yl);
+ BnnAdd (BzToBn (n), yl+1, BzToBn (z), zl, 0);
+ BzSetSign (n, BzGetSign (y));
+ }
+ break;
+
+ default: /* BZ_LT: |Y| < |Z| */
+
+ if ((n = BzCreate (zl+1)) != NULL)
+ {
+ BnnAssign (BzToBn (n), BzToBn (z), zl);
+ BnnAdd (BzToBn (n), zl+1, BzToBn (y), yl, 0);
+ BzSetSign (n, BzGetSign (z));
+ }
+ break;
+ }
+ }
+/*\f*/
+
+
+ else
+ {
+ /* Subtract magnitudes if signs are different */
+ switch (BnnCompare (BzToBn (y), yl, BzToBn (z), zl))
+ {
+ case BZ_EQ: /* Y = -Z */
+
+ n = BzCreate (1);
+ break;
+
+ case BZ_GT: /* |Y| > |Z| */
+
+ if ((n = BzCreate (yl)) != NULL)
+ {
+ BnnAssign (BzToBn (n), BzToBn (y), yl);
+ BnnSubtract (BzToBn (n), yl, BzToBn (z), zl, 1);
+ BzSetSign (n, BzGetSign (y));
+ }
+ break;
+
+ default: /* BZ_LT: |Y| < |Z| */
+
+ if ((n = BzCreate (zl)) != NULL)
+ {
+ BnnAssign (BzToBn (n), BzToBn (z), zl);
+ BnnSubtract (BzToBn (n), zl, BzToBn (y), yl, 1);
+ BzSetSign (n, BzGetSign (z));
+ }
+ break;
+ }
+ }
+
+ return (n);
+}
+
+ /***************************************/
+/*\f*/
+
+
+BigZ BzSubtract (y, z)
+
+BigZ y, z;
+
+/*
+ * Returns Y - Z.
+ */
+
+{
+ BigZ diff;
+
+
+ BzSetSign (z, BzGetOppositeSign (z));
+ diff = BzAdd (y, z);
+ BzSetSign (z, BzGetOppositeSign (z));
+
+ return diff;
+}
+
+ /***************************************/
+/*\f*/
+
+
+BigZ BzMultiply (y, z)
+
+BigZ y, z;
+
+/*
+ * Returns Y * Z.
+ */
+
+{
+ BigZ n;
+ int yl, zl;
+
+
+ yl = BzNumDigits (y);
+ zl = BzNumDigits (z);
+
+ if ((n = BzCreate (yl+zl)) != NULL)
+ {
+ BnnMultiply (BzToBn (n), yl+zl, BzToBn (y), yl, BzToBn (z), zl);
+ BzSetSign (n, BzGetSign (y) * BzGetSign (z));
+ }
+
+ return (n);
+}
+
+ /***************************************/
+/*\f*/
+
+
+BigZ BzDivide (y, z, r)
+
+BigZ y, z, *r;
+
+/*
+ * Sets Y mod Z => R,
+ * Returns Y div Z => Q
+ *
+ * such that Y = ZQ + R
+ * and 0 <= R < |Z|.
+ */
+
+{
+ BigZ q;
+ int yl, zl, ql, rl;
+ Boolean rnotnul;
+
+
+ if (BzGetSign (z) == BZ_ZERO)
+ return (NULL);
+
+ yl = BzNumDigits (y);
+ zl = BzNumDigits (z);
+
+ /* max +1 since BnnAddCarry can overflow */
+ ql = max (yl-zl+1, 1) +1;
+ rl = max (zl,yl) + 1;
+
+ /* Set up quotient, remainder */
+ q = BzCreate (ql);
+ *r = BzCreate (rl);
+
+ if (!*r || !q)
+ return (NULL);
+
+ BnnAssign (BzToBn (*r), BzToBn (y), yl);
+
+ /* Do the division */
+ BnnDivide (BzToBn (*r), rl, BzToBn (z), zl);
+ BnnAssign (BzToBn (q), BzToBn (*r) + zl, rl-zl);
+ BnnSetToZero (BzToBn (*r) + zl, rl-zl);
+ rl = zl;
+
+ /* Correct the signs, adjusting the quotient and remainder */
+ rnotnul = !BnnIsZero (BzToBn (*r), rl);
+ if (BzGetSign (y) == BZ_MINUS && rnotnul)
+ {
+ /* Y < 0, R > 0: (Q+1)=>Q, Z-R=>R */
+ BnnAddCarry (BzToBn (q), ql, (BigNumCarry) 1);
+
+ BzSetSign (q, BzGetOppositeSign (z));
+ BnnComplement (BzToBn (*r), rl);
+ BnnAdd (BzToBn (*r), rl, BzToBn (z), zl, (BigNumCarry) 1);
+ }
+ else
+ BzSetSign (q, BzGetSign (y) * BzGetSign (z));
+
+ /* Correct the sign of the remainder */
+ if (rnotnul)
+ BzSetSign (*r, BZ_PLUS);
+
+ return (q);
+}
+
+ /***************************************/
+/*\f*/
+
+
+BigZ BzDiv (y, z)
+
+BigZ y, z;
+
+/*
+ * Returns Y div Z.
+ */
+
+{
+ BigZ q, r;
+
+
+ q = BzDivide (y, z, &r);
+ BzFree (r);
+
+ return (q);
+}
+
+ /***************************************/
+
+
+BigZ BzMod (y, z)
+
+BigZ y, z;
+
+/*
+ * Returns Y mod Z.
+ */
+
+{
+ BigZ r;
+
+
+ BzFree (BzDivide (y, z, &r));
+
+ return (r);
+}
+
+ /***************************************/
+/*\f*/
+
+
+char * BzToString (z, base)
+
+BigZ z;
+BigNumDigit base;
+
+/*
+ * Returns a pointer to a string that represents Z in the specified base.
+ * Assumes 2 <= base <= 16.
+ */
+
+{
+ char * string;
+ BigZ y, q, t;
+ BigNumDigit r;
+
+ static char Digit[] = "0123456789ABCDEF";
+ char * s;
+ int sd, zl, sl;
+
+
+ if (base < 2 || base > 16)
+ return (NULL);
+
+ /* Allocate BigNums and set up string */
+ zl = BzNumDigits (z) + 1;
+ sl = BzLog[2] * BN_DIGIT_SIZE * zl / BzLog[base] + 3;
+
+ y = BzCreate (zl);
+ q = BzCreate (zl);
+
+ string = malloc (sl * sizeof (char));
+
+ if (!y || !q || !string)
+ return (NULL);
+
+ BnnAssign (BzToBn (y), BzToBn (z), zl-1);
+ s = string + sl;
+
+ /* Divide Z by base repeatedly; successive digits given by remainders */
+ *--s = '\0';
+ if (BzGetSign (z) == BZ_ZERO)
+ *--s = '0';
+ else
+ do
+ {
+ r = BnnDivideDigit (BzToBn (q), BzToBn (y), zl, base);
+ *--s = Digit[r];
+
+ /* exchange y and q (to avoid BzMove (y, q) */
+ t = q, q = y, y = t;
+ } while (!BnnIsZero (BzToBn (y), zl));
+
+ /* Set sign if negative */
+ if (BzGetSign (z) < 0)
+ *--s = '-';
+
+ /* and move string into position */
+ if ((sd = s-string) > 0)
+ while (s < string + sl)
+ {
+ *(s-sd) = *s;
+ s++;
+ }
+
+ /* Free temporary BigNums and return the string */
+ BzFree(y);
+ BzFree(q);
+
+ return string;
+}
+
+ /***************************************/
+/*\f*/
+
+
+BigZ BzFromString (s, base)
+
+char *s;
+BigNumDigit base;
+
+/*
+ * Creates a BigZ whose value is represented by "string" in the
+ * specified base. The "string" may contain leading spaces,
+ * followed by an optional sign, followed by a series of digits.
+ * Assumes 2 <= base <= 16.
+ * When called from C, only the first 2 arguments are passed.
+ */
+
+{
+ BigZ z, p, t;
+ BzSign sign;
+ int zl;
+
+
+ /* Throw away any initial space */
+ while (*s == ' ')
+ s++;
+
+ /* Allocate BigNums */
+ zl = strlen (s) * BzLog[base] / (BzLog[2] * BN_DIGIT_SIZE) + 1;
+
+ z = BzCreate (zl);
+ p = BzCreate (zl);
+
+ if (!z || !p)
+ return (NULL);
+
+ /* Set up sign, base, initialize result */
+ sign = (*s == '-' ? (s++, BZ_MINUS) : *s == '+' ? (s++, BZ_PLUS) : BZ_PLUS);
+
+ /* Multiply in the digits of the string, one at a time */
+ for (; *s != '\0'; s++)
+ {
+ BnnSetToZero (BzToBn (p), zl);
+ BnnSetDigit (BzToBn (p), CTOI (*s));
+ BnnMultiplyDigit (BzToBn (p), zl, BzToBn (z), zl, base);
+
+ /* exchange z and p (to avoid BzMove (z, p) */
+ t = p, p = z, z = t;
+ }
+
+ /* Set sign of result */
+ BzSetSign (z, BnnIsZero (BzToBn (z), zl) ? BZ_ZERO : sign);
+
+ /* Free temporary BigNums */
+ BzFree (p);
+
+ return (z);
+}
+
+ /***************************************/
+
+BigZ BzFromInteger (i)
+
+int i;
+
+{
+ BigZ z;
+
+
+ z = BzCreate (1);
+
+ z->Digits[0] = abs (i);
+
+ if (i > 0)
+ BzSetSign (z, BZ_PLUS);
+ else
+ if (i < 0)
+ BzSetSign (z, BZ_MINUS);
+ else
+ BzSetSign (z, BZ_ZERO);
+
+ return z;
+}
+
+ /***************************************/
+
+
+int BzToInteger (z)
+
+BigZ z;
+
+{
+ if (BzNumDigits (z) > 1)
+ return (MAXINT);
+
+ if (BzGetSign (z) == BZ_MINUS)
+ return (- z->Digits[0]);
+ else
+ return (z->Digits[0]);
+}
+
+ /***************************************/
+
+
+BigZ BzFromBigNum (n, nl)
+
+BigNum n;
+BigNumLength nl;
+
+{
+ BigZ z;
+ int i;
+
+
+ z = BzCreate (nl);
+
+ /* set the sign of z such that the pointer n is unchanged yet */
+ if (BnnIsZero (n, nl))
+ BzSetSign (z, BZ_ZERO);
+ else
+ BzSetSign (z, BZ_PLUS);
+
+ for (i = 0; i < nl; i++, n++)
+ z->Digits[i] = *n;
+
+ return z;
+}
+
+ /***************************************/
+
+BigNum BzToBigNum (z, nl)
+
+BigZ z;
+BigNumLength *nl;
+
+{
+ BigNum n, m;
+ int i;
+
+
+ if (BzGetSign (z) == BZ_MINUS)
+ return NULL;
+
+ *nl = BzNumDigits (z);
+
+ if ((n = (BigNum) (malloc (((*nl+1) * sizeof (BigNumDigit))))) != NULL)
+ {
+ *n = *nl; /* set size */
+
+ for (i = 0, m = ++n; i < *nl; i++, m++)
+ *m = z->Digits[i];
+ }
+
+ return n;
+}
+
+ /***************************************/
+
+
+void BzClose ()
+{
+ if (Initialized)
+ {
+ BnnClose ();
+ Initialized = FALSE;
+ }
+}
+
+ /***************************************/
--- /dev/null
+/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */
+/* Last modified_on Mon Jan 23 16:05:27 GMT+1:00 1989 by herve */
+
+/*
+ * bzf.c: Miscellaneous functions built on top of BigZ.
+ *
+ */
+
+
+#include "BigZ.h"
+
+ /***************************************/
+
+#define BzToBn(z) ((z)->Digits)
+
+ /***************************************/
+
+
+BigZ BzFactorial (z)
+
+BigZ z;
+
+/*
+ * Returns Z!
+ * Assumes Z < Base.
+ */
+
+{
+ BigZ f;
+ BigNumDigit zval;
+ int fl = 1;
+
+
+ zval = BnnGetDigit (BzToBn (z));
+ f = BzCreate (zval+1);
+ BnnSetDigit (BzToBn (f), 1);
+ BzSetSign (f, BzGetSign (z));
+
+ while (zval-- > 1)
+ {
+ BnnMultiplyDigit (BzToBn (f), fl+1, BzToBn (f), fl, zval);
+ fl = BnnNumDigits (BzToBn (f), fl+1);
+ }
+
+ return (f);
+}
+
--- /dev/null
+/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */
+/* Last modified_on Tue Mar 27 15:29:04 GMT+2:00 1990 by herve */
+/* modified_on Tue Feb 13 17:55:06 GMT+1:00 1990 by shand */
+
+#include <stdio.h>
+#include "BigZ.h"
+
+#define S(A,B) strcmp(A,B)
+#define NEWLINE fprintf(stderr,"\n")
+#define P(A) fprintf(stderr,"%d...",A)
+#define E(A,B,C) fprintf(stderr,"\nError in test #%d:\nComputed: %s\nCorrect: %s\n",A,C,B)
+#define T(A,B,C) S(B,C)?E(A,B,C):P(A)
+#define To(A) BzToString(A,10)
+#define From(A) BzFromString(A,10)
+#define Abs(A) BzAbs(A)
+#define Neg(A) BzNegate(A)
+#define Add(A,B) BzAdd(A,B)
+#define Sub(A,B) BzSubtract(A,B)
+#define Mul(A,B) BzMultiply(A,B)
+#define Div(A,B) BzDiv(A,B)
+#define Mod(A,B) BzMod(A,B)
+#define Fac(A) BzFactorial(A)
+#define FromI(I) BzFromInteger(I)
+
+#define one FromI(1)
+#define two FromI(2)
+#define minusone FromI(-1)
+#define two31m1 FromI(0x7FFFFFFF)
+
+main()
+{
+ BigZ a,b;
+
+
+ T(1,"12", To(From("12"))) ;
+ T(2,"12345678910", To(From("12345678910"))) ;
+ T(3,"123", To(From("00000123"))) ;
+ T(4,"-123", To(From("-123"))) ;
+ T(5,"-32768", To(From("-32768"))) ;
+ T(6,"-32768", To(Neg(From("32768")))) ;
+ T(7,"-32768", To(Add(From("-16384"),From("-16384")))) ;
+ T(8,"-32768", To(Add(From("-16383"),From("-16385")))) ;
+ T(9,"-32768", To(Mul(From("2"),From("-16384")))) ;
+ T(10,"-16384", To(Div(From("-32768"),From("2")))) ;
+ NEWLINE;
+ T(11,"100000", To(Add(From("1"),From("99999")))) ;
+ T(12,"12343994",To(Add(From("-1684"),From("12345678"))));
+ T(13,"-12329294",To(Sub(From("16384"),From("12345678"))));
+ T(14,"135801",To(Add(From("12345"),From("123456"))));
+ T(15,"123456135801",To(Add(From("12345"),From("123456123456"))));
+ T(16,"135801",To(Add(From("123456"),From("12345"))));
+ T(17,"123456135801",To(Add(From("123456123456"),From("12345"))));
+ T(18,"135801",To(Sub(From("12345"),From("-123456"))));
+ T(19,"123456135801",To(Sub(From("12345"),From("-123456123456"))));
+ T(20,"135801",To(Sub(From("123456"),From("-12345"))));
+ NEWLINE;
+ T(21,"123456135801",To(Sub(From("123456123456"),From("-12345"))));
+ T(22,"-111111",To(Sub(From("12345"),From("123456"))));
+ T(23,"111111",To(Sub(From("123456"),From("12345"))));
+ T(24,"-123456111111",To(Sub(From("12345"),From("123456123456"))));
+ T(25,"123456111111",To(Sub(From("123456123456"),From("12345"))));
+ T(26,"-111111",To(Add(From("12345"),From("-123456"))));
+ T(27,"111111",To(Add(From("123456"),From("-12345"))));
+ T(28,"-123456111111",To(Add(From("12345"),From("-123456123456"))));
+ T(29,"123456111111",To(Add(From("123456123456"),From("-12345"))));
+ T(30,"2", To(Div(From("264195"),From("97200")))) ;
+ NEWLINE;
+ T(31,"27405", To(Mod(From("97200"),From("69795")))) ;
+ T(32,"4294967295", To(Div(From("22685491128062564230891640495451214097"),From("5281877500950955845296219748")))) ;
+ T(33,"99997",To(Add(From("-3"),From("100000"))));
+ T(34,"-100003",To(Add(From("-3"),From("-100000"))));
+ T(35,"999999",To(Sub(From("1000000"),From("1"))));
+ T(36,"999999999",To(Mul(From("12345679"),From("81"))));
+ a = From("1234567");
+ b = From("123456");
+ T(37,"1234567",To(Add(Mul(Div(a,b),b),Mod(a,b))));
+ T(38,"-1234567",To(Add(Mul(Div(Neg(a),Neg(b)),Neg(b)),Mod(Neg(a),Neg(b)))));
+ T(39,"1234567",To(Add(Mul(Div(a,Neg(b)),Neg(b)),Mod(a,Neg(b)))));
+ T(40,"10000000000000000000000",To(Mul(From("-100000000000"),From("-100000000000"))));
+ NEWLINE;
+ T(41,"-10000000000000000000000",To(Mul(From("-100000000000"),From("100000000000"))));
+ T(42,"-10000000000000000000000",To(Mul(From("100000000000"),From("-100000000000"))));
+ T(43,"10000000000000000000000",To(Mul(From("100000000000"),From("100000000000"))));
+ a = Sub(From("10000000000000"),From("10000000000000"));
+ T(44,"0",To(Mod(a,From("1000000000000"))));
+ T(45,"0",To(Div(a,From("1000000000000"))));
+ T(46,"0",To(Mod(Neg(a),From("10000000000000"))));
+ T(47,"0",To(Div(Neg(a),From("10000000000000"))));
+ T(48,"2",To(Div(From("3000"),Sub(From("1234567891234"),From("1234567890000")))));
+ T(49,"532",To(Mod(From("3000"),Sub(From("1234567891234"),From("1234567890000")))));
+ T(50,"9",To(Mod(From("-1234567890"),From("1234567899"))));
+ NEWLINE;
+ T(51,"2",To(Mod(Sub(From("12345678900000"),From("12345678926887")),From("3"))));
+ T(52,"40830949904677684825316369628906250000000000000",To(Mul(From("48270948888581289062500000000"),From("845870049062500000"))));
+ T(53,"22666179639240748063923391983020279316955515",To(Mul(From("6956883693"),From("3258093801689886619170103176686855"))));
+ T(54,"1405006117752879898543142606244511569936384000000000",To(Fac(From("42"))));
+ T(55,"0",To(Mod(Fac(From("13")),Fac(From("9")))));
+ T(56,"0",To(Mod(Fac(From("34")),Fac(From("13")))));
+ T(57,"0",To(Mod(Fac(From("57")),Fac(From("21")))));
+ T(58,"0",To(Mod(Fac(From("40")),Fac(From("39")))));
+ T(59,"59",To(Div(Fac(From("59")),Fac(From("58")))));
+ T(60,"2",To(Div(From("5"),From("2"))));
+ NEWLINE;
+ T(61,"1",To(Mod(From("5"),From("2"))));
+ T(62,"-3",To(Div(From("-5"),From("2"))));
+ T(63,"1",To(Mod(From("-5"),From("2"))));
+ T(64,"3",To(Div(From("-5"),From("-2"))));
+ T(65,"1",To(Mod(From("-5"),From("-2"))));
+ T(66,"-2",To(Div(From("5"),From("-2"))));
+ T(67,"1",To(Mod(From("5"),From("-2"))));
+ T(68,"3",To(Div(From("6"),From("2"))));
+ T(69,"0",To(Mod(From("6"),From("2"))));
+ T(70,"-3",To(Div(From("-6"),From("2"))));
+ NEWLINE;
+ T(71,"0",To(Mod(From("-6"),From("2"))));
+ T(72,"3",To(Div(From("-6"),From("-2"))));
+ T(73,"0",To(Mod(From("-6"),From("-2"))));
+ T(74,"-3",To(Div(From("6"),From("-2"))));
+ T(75,"0",To(Mod(From("6"),From("-2"))));
+ T(76,"0",To(Abs(From("0"))));
+ T(77,"1234567890",To(Abs(From("1234567890"))));
+ T(78,"1234567890",To(Abs(From("-1234567890"))));
+ T(79,"1",BzCompare(From("-1234567890"),From("12345"))<0?"1":"0");
+ T(80,"1",BzGetSign(From("-1234567890"))<0?"1":"0");
+ NEWLINE;
+ T(81,"0", To(Add(From("-1"),Mul(From("-1"),From("-1")))));
+ T(82,"-1",To(Add(From("-1"),Mul(From("0"), From("-1")))));
+ T(83,"-3",To(Add(From("-1"),Mul(From("-2"),From("1" )))));
+ T(84,"1", To(Add(From("-1"),Mul(From("-2"),From("-1")))));
+ T(85,"-1",To(Add(From("1"), Mul(From("-2"),From("1" )))));
+ T(86,"18446744065119617025",To(Mul(From("4294967295"),From("4294967295"))));
+ /* (-2^64 + 2^32 - 1) / 2^32 */
+ T(87,"-4294967296",To(Div(
+ Sub(Mul(Mul(Add(Mul(two31m1,two),one),Mul(Add(two31m1,one), two)),minusone),one),
+ Mul(Add (two31m1,one),two))));
+ NEWLINE;
+}
--- /dev/null
+/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */
+/* testKerN.c: tests des primitives de KerN */
+/* Last modified_on Mon Mar 26 20:37:00 GMT+2:00 1990 by shand */
+/* modified_on Wed Feb 14 16:14:04 GMT+1:00 1990 by herve */
+/* modified_on 17-OCT-1989 20:35:55.91 by Jim Lawton */
+
+/* You can comment the line below if you want to test the C macro Package
+ instead of C or Assembly functions. */
+
+#define BNNMACROS_OFF 1
+
+
+#include "BigNum.h"
+#include "BntoBnn.h"
+
+
+ /* structure d'un test */
+
+struct testenv {
+ char *name; /* Le nom de la fonction teste'e. */
+ int flag; /* Pour savoir si l'on continue le Test. */
+ char hist[2048]; /* L'expression qui provoque l'erreur. */
+ char *depend; /* De quoi depend le Test. */
+};
+
+
+ /* Les nombres pre'de'finies. */
+
+static BigNum NumbVect[5][2];
+static BigNum NumbProto, Ntmp2, NtmpBig;
+
+#define RN(n) NumbVect[n][0]
+#define SN(n) NumbVect[n][1]
+
+ /* Taille des nombres utilise's. */
+ /* de la forme 4(n + 1) */
+#define TESTLENGTH 16
+#define DTL TESTLENGTH/2
+#define QTL TESTLENGTH/4
+
+/* Nombre de test. */
+int TestCount;
+
+ResetTest(n) int n; {
+ /* Remet le nieme nombre a` la valeur prototype. */
+ BnAssign(RN(n), 0, NumbProto, 0, TESTLENGTH);
+ BnAssign(SN(n), 0, NumbProto, 0, TESTLENGTH);
+}
+
+Check(n) int n; {
+ int i;
+ /* Verifie que les n nombres calcules correspondent aux simule's. */
+ for(i = 0; i < n; i++)
+ if(CheckSubRange(i, 0, TESTLENGTH)) return(1);
+ return(FALSE);
+}
+
+CheckSubRange(x, nd, nl) int x, nd, nl; {
+ /* Verifie l'e'galite' des sous-nombres
+ (RN(x), nd, nl) et (SN(x), nd, nl) */
+ while(nl) {
+ nl--;
+ if(BnCompareDigits(RN(x), nd, SN(x), nd)) return(nd + 1);
+ nd++;
+ }
+ return(FALSE);
+}
+
+ShowDiff0(e, r1, r2) struct testenv *e; int r1,r2; {
+ ErrorPrint(e);
+ if(r1 != r2)
+ printf("---- Result is %d and should be %d----\n", r1, r2);
+ return(e->flag);
+}
+
+ShowDiff1(e, r1, r2, n, nd, nl)
+ struct testenv *e; char *n; int r1, r2, nd, nl; {
+ ErrorPrint(e);
+ if(r1 != r2)
+ printf("---- Result is %d and should be %d----\n", r1, r2);
+ ShowOutRange(0, n, nd, nl);
+ ShowSubNumber(0, n, nd, nl);
+ return(e->flag);
+}
+
+ShowDiff2(e, r1, r2, n, nd, nl, m, md, ml)
+ struct testenv *e; char *n, *m; int r1, r2, nd, nl, md, ml; {
+ ErrorPrint(e);
+ if(r1 != r2)
+ printf("---- Result is %d and should be %d----\n", r1, r2);
+ ShowOutRange(0, n, nd, nl);
+ ShowOutRange(1, m, md, ml);
+ ShowSubNumber(0, n, nd, nl);
+ ShowSubNumber(1, m, md, ml);
+ return(e->flag);
+}
+
+ShowDiff3(e, r1, r2, n, nd, nl, m, md, ml, o, od, ol)
+ struct testenv *e; char *n, *m, *o;
+ int r1, r2, nd, nl, md, ml, od, ol; {
+ ErrorPrint(e);
+ if(r1 != r2)
+ printf("---- Result is %d and should be %d----\n", r1, r2);
+ ShowOutRange(0, n, nd, nl);
+ ShowOutRange(1, m, md, ml);
+ ShowOutRange(2, o, od, ol);
+ ShowSubNumber(0, n, nd, nl);
+ ShowSubNumber(1, m, md, ml);
+ ShowSubNumber(2, o, od, ol);
+ return(e->flag);
+}
+
+ShowDiff4(e, r1, r2, n, nd, nl, m, md, ml, o, od, ol, p, pd, pl)
+ struct testenv *e; char *n, *m, *o, *p;
+ int r1, r2, nd, nl, md, ml, od, ol, pd, pl; {
+ ErrorPrint(e);
+ if(r1 != r2)
+ printf("---- Result is %d and should be %d----\n", r1, r2);
+ ShowOutRange(0, n, nd, nl);
+ ShowOutRange(1, m, md, ml);
+ ShowOutRange(2, o, od, ol);
+ ShowOutRange(3, p, pd, pl);
+ ShowSubNumber(0, n, nd, nl);
+ ShowSubNumber(1, m, md, ml);
+ ShowSubNumber(2, o, od, ol);
+ ShowSubNumber(3, p, pd, pl);
+ return(e->flag);
+}
+
+ShowSubNumber(x, n, nd, nl) char *n; int x, nd, nl; {
+ printf("[%s, %d, %d] = ", n, nd, nl);
+ RangeNumberPrint("", RN(x), nd, nl);
+ if(CheckSubRange(x, nd, nl)) {
+ RangeNumberPrint(" Before: ", NumbProto, nd, nl);
+ RangeNumberPrint(" Simulated: ", SN(x), nd, nl);
+} }
+
+RangeNumberPrint(s, n, nd, nl) char *s; BigNum n; int nd, nl; {
+ int first = 1;
+
+ /* Ne marche que si BnGetDigit est garanti!!! */
+ printf("%s {", s);
+ while(nl) {
+ nl--;
+ if(!first) printf(", "); else first = 0;
+ if(BN_DIGIT_SIZE <= 16)
+ printf("%.4X", BnGetDigit(n, nd + nl));
+ else printf("%.8X", BnGetDigit(n, nd + nl));
+ }
+ printf("}\n");
+}
+
+char *msg = "---- Modification Out of Range of number ";
+ShowOutRange(x, n, nd, nl) char *n; int x, nd, nl; {
+ int i = 0, bol = 0;
+
+ while(i = CheckSubRange(x, i, TESTLENGTH - i)) {
+ if((i <= nd) || (i > nd + nl)) {
+ if(!bol) {
+ bol = 1;
+ printf("%s %s at index: (%d", msg, n, i - 1);
+ } else {
+ printf(" %d", i - 1);
+ } } }
+ if(bol) printf(").\n");
+}
+
+ErrorPrint(e) struct testenv *e; {
+ printf("*** Error in compute : %s\n", e->hist);
+ printf(" Depends on %s\n", e->depend);
+}
+
+/*
+ * Tests des fonctions non redefinisables
+ */
+
+int genlengthvec[] = {9, 8, 1, 0, 2000, 32000,};
+BigNumType gentypevec[] = {0, 1, 2, 3, 4, 5,};
+
+Generique(e) struct testenv *e; {
+ int i;
+ int length, length2;
+ BigNumType type, type2;
+ int fix;
+ BigNum n;
+
+
+ for(i=0; i < 6; i++) {
+ type = gentypevec[i];
+ length = genlengthvec[i];
+ n = BnCreate(type, length);
+ if((type2 = BnGetType(n)) != type) {
+ sprintf(e->hist,"BnGetType(BnCreate(%d, %d));", type, length);
+ if(ShowDiff0(e, type, type2)) return(TRUE);
+ }
+ if((length2 = BnGetSize(n)) != length) {
+ sprintf(e->hist,"BnGetSize(BnCreate(%d, %d));", type, length);
+ if(ShowDiff0(e, length, length2)) return(TRUE);
+ }
+ if(BnFree(n) == 0) {
+ sprintf(e->hist, "BnFree(BnCreate(%d, %d));", type, length);
+ if(ShowDiff0(e, 1, 0)) return(TRUE);
+ }
+ BnSetType((n = BnAlloc(length)), type);
+ if((type2 = BnGetType(n)) != type) {
+ sprintf(e->hist,"BnGetType(BnAlloc(%d, %d));", type, length);
+ if(ShowDiff0(e, type, type2)) return(TRUE);
+ }
+ if((length2 = BnGetSize(n)) != length) {
+ sprintf(e->hist,"BnGetSize(BnAlloc(%d, %d));", type, length);
+ if(ShowDiff0(e, length, length2)) return(TRUE);
+ }
+ if(BnFree(n) == 0) {
+ sprintf(e->hist, "BnFree(BnAlloc(%d, %d));", type, length);
+ if(ShowDiff0(e, 1, 0)) return(TRUE);
+ }
+ }
+ return(FALSE);
+}
+
+/*
+ * BnSetToZero
+ */
+___BnSetToZero___(n, nd, nl) register BigNum n; register int nd, nl; {
+ register int i;
+ for(i=0; i<nl; i++)
+ BnSetDigit(n, nd + i, 0);
+}
+
+TestBnSetToZero(e) struct testenv *e; {
+ int nd, nl;
+
+ e->depend = "()";
+ for(nd = 0; nd <= TESTLENGTH; nd++)
+ for(nl = 0; nl <= TESTLENGTH - nd; nl++) {
+ TestCount++;
+ ResetTest(0);
+ BnSetToZero (RN(0), nd, nl);
+ ___BnSetToZero___(SN(0), nd, nl);
+ if(Check(1)) {
+ sprintf(e->hist, "%s(n, %d, %d)", e->name, nd, nl);
+ if(ShowDiff1(e, 0, 0, "n", nd, nl)) return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnAssign
+ */
+___BnAssign___(m, md, n, nd, nl) BigNum m, n; int md, nd, nl; {
+ BnSetToZero(NtmpBig, 0, nl);
+ BnAdd(NtmpBig, 0, nl, n, nd, nl, 0);
+ BnSetToZero(m, md, nl);
+ BnAdd(m, md, nl, NtmpBig, 0, nl, 0);
+}
+
+TestBnAssign(e) struct testenv *e; {
+ int md, nd, nl;
+
+ e->depend = "(BnSetToZero, BnAdd)";
+ for(md = 0; md <= TESTLENGTH; md++)
+ for(nd = 0; nd <= TESTLENGTH; nd++)
+ for(nl=0; ((nl<=TESTLENGTH-nd) && (nl<=TESTLENGTH-md)); nl++) {
+ TestCount++;
+ ResetTest(0);
+ BnAssign (RN(0), md, RN(0), nd, nl);
+ ___BnAssign___(SN(0), md, SN(0), nd, nl);
+ if(Check(1)) {
+ sprintf(e->hist, "%s(n, %d, n, %d, %d)", e->name,
+ md, nd, nl);
+ if(ShowDiff1(e, 0, 0, "n", md, nl)) return(1);
+ } }
+ return(FALSE);
+}
+
+
+/*
+ * BnNumDigits
+ */
+___BnNumDigits___(n, nd, nl) register BigNum n; register int nd, nl; {
+
+ while(nl != 0) {
+ nl--;
+ if(!BnIsDigitZero(n, nd + nl)) break;
+ }
+ return(nl + 1);
+}
+
+TestBnNumDigits(e) struct testenv *e; {
+ int nd0, nl0, nd, nl, l1, l2;
+
+ e->depend = "(BnIsDigitZero)";
+ for(nd0 = 0; nd0 <= TESTLENGTH; nd0++)
+ for(nl0 = 0; nl0 <= TESTLENGTH - nd0; nl0++)
+ for(nd = 0; nd <= TESTLENGTH; nd++)
+ for(nl = 0; nl <= TESTLENGTH - nd; nl++) {
+ TestCount++;
+ ResetTest(0);
+ BnSetToZero(RN(0), nd0, nl0);
+ BnSetToZero(SN(0), nd0, nl0);
+ l1 = BnNumDigits (RN(0), nd, nl);
+ l2 = ___BnNumDigits___(SN(0), nd, nl);
+ if(Check(1) || l1 != l2) {
+ sprintf(e->hist, "%s(n, %d, %d)", e->name, nd, nl);
+ if(ShowDiff1(e, l1, l2, "n", nd, nl)) return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnNumLeadingZeroBitsInDigit
+ */
+__BnNumLeadingZeroBitsInDigit__(n, nd) BigNum n; int nd; {
+ int p = 0;
+
+ if(BnIsDigitZero(n, nd)) return(BN_DIGIT_SIZE);
+ BnAssign(Ntmp2, 0, n, nd, 1);
+ BnShiftLeft(Ntmp2, 0, 1, Ntmp2, 1, 1);
+ while(BnIsDigitZero(Ntmp2, 1)) {
+ BnShiftLeft(Ntmp2, 0, 1, Ntmp2, 1, 1);
+ p++;
+ }
+ return(p);
+}
+
+TestBnNumLeadingZeroBitsInDigit(e) struct testenv *e; {
+ int nd; int l1, l2;
+
+
+ e->depend = "(BnShiftLeft, BnIsDigitZero)";
+ ResetTest(0);
+ for(nd = 0; nd < TESTLENGTH; nd++) {
+ TestCount++;
+ l1 = BnNumLeadingZeroBitsInDigit (RN(0), nd);
+ l2 = __BnNumLeadingZeroBitsInDigit__(SN(0), nd);
+ if(Check(1) || l1 != l2) {
+ sprintf(e->hist, "%s(n, %d)", e->name, nd);
+ if(ShowDiff1(e, l1, l2, "n", nd, 1)) return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnIsDigitZero
+ */
+___BnIsDigitZero___(n, nd) BigNum n; int nd; {
+ if(BnGetDigit(n, nd) == 0) return(1);
+ return(0);
+}
+
+TestBnIsDigitZero(e) struct testenv *e; {
+ int nd; int l1, l2;
+
+ e->depend = "()";
+ ResetTest(0);
+ for(nd = 0; nd < TESTLENGTH; nd++) {
+ TestCount++;
+ l1 = BnIsDigitZero (RN(0), nd);
+ l2 = ___BnIsDigitZero___(SN(0), nd);
+ if(Check(1) || ((l1 == 0) && (l2 != 0)) ||
+ ((l1 != 0) && (l2 == 0))) {
+ sprintf(e->hist, "%s(n, %d)", e->name, nd);
+ if(ShowDiff1(e, l1, l2, "n", nd, 1)) return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnIsDigitNormalized
+ */
+___BnIsDigitNormalized___(n, nd) BigNum n; int nd; {
+ BnAssign(Ntmp2, 0, n, nd, 1);
+ BnShiftLeft(Ntmp2, 0, 1, Ntmp2, 1, 1);
+ if(BnIsDigitZero(Ntmp2, 1)) return(0);
+ return(1);
+}
+
+TestBnIsDigitNormalized(e) struct testenv *e; {
+ int nd; int l1, l2;
+
+ e->depend = "(BnShiftLeft, BnIsDigitZero)";
+ ResetTest(0);
+ for(nd = 0; nd < TESTLENGTH; nd++) {
+ TestCount++;
+ l1 = BnIsDigitNormalized (RN(0), nd);
+ l2 = ___BnIsDigitNormalized___(SN(0), nd);
+ if(Check(1) || ((l1 == 0) && (l2 != 0)) ||
+ ((l1 != 0) && (l2 == 0))) {
+ sprintf(e->hist, "%s(n, %d)", e->name, nd);
+ if(ShowDiff1(e, l1, l2, "n", nd, 1)) return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnIsDigitOdd
+ */
+___BnIsDigitOdd___(n, nd) BigNum n; int nd; {
+ BnAssign(Ntmp2, 0, n, nd, 1);
+ BnShiftRight(Ntmp2, 0, 1, Ntmp2, 1, 1);
+ if(BnIsDigitZero(Ntmp2, 1)) return(0);
+ return(1);
+}
+
+TestBnIsDigitOdd(e) struct testenv *e; {
+ int nd; int l1, l2;
+
+ e->depend = "(BnShiftRight, BnIsDigitZero)";
+ ResetTest(0);
+ for(nd = 0; nd < TESTLENGTH; nd++) {
+ TestCount++;
+ l1 = BnIsDigitOdd (RN(0), nd);
+ l2 = ___BnIsDigitOdd___(SN(0), nd);
+ if(Check(1) || ((l1 == 0) && (l2 != 0)) ||
+ ((l1 != 0) && (l2 == 0))) {
+ sprintf(e->hist, "%s(n, %d)", e->name, nd);
+ if(ShowDiff1(e, l1, l2, "n", nd, 1)) return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnCompareDigits
+ */
+___BnCompareDigits___(n, nd, m, md) BigNum n, m; int nd, md; {
+ BnAssign(Ntmp2, 0, n, nd, 1);
+ BnComplement(Ntmp2, 0, 1);
+ if(BnAdd(Ntmp2, 0, 1, m, md, 1, 0)) return(-1);
+ BnComplement(Ntmp2, 0, 1);
+ if(BnIsDigitZero(Ntmp2, 0)) return(0);
+ return(1);
+}
+
+TestBnCompareDigits(e) struct testenv *e; {
+ int nd, md; int l1, l2;
+
+ e->depend = "(BnComplement, BnAdd, BnIsDigitZero)";
+ ResetTest(0);
+ ResetTest(1);
+ for(nd = 0; nd < TESTLENGTH; nd++)
+ for(md = 0; md < TESTLENGTH; md++) {
+ TestCount++;
+ l1 = BnCompareDigits (RN(0), nd, RN(1), md);
+ l2 = ___BnCompareDigits___(SN(0), nd, SN(1), md);
+ if(Check(2) || l1 != l2) {
+ sprintf(e->hist, "%s(n, %d, m, %d)", e->name, nd, md);
+ if(ShowDiff2(e, l1, l2, "n", nd, 1, "m", md, 1))
+ return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnComplement
+ */
+___BnComplement___(n, nd, nl) BigNum n; int nd, nl; {
+ int i;
+
+ BnSetDigit(Ntmp2, 0, 0);
+ BnSubtractBorrow(Ntmp2, 0, 1, 0);
+ for(i = 0; i < nl; i++)
+ BnXorDigits(n, nd + i, Ntmp2, 0);
+}
+
+TestBnComplement(e) struct testenv *e; {
+ int nd, nl;
+
+ e->depend = "(BnSubtractBorrow, BnXorDigits)";
+ for(nd = 0; nd <= TESTLENGTH; nd++)
+ for(nl = 0; nl <= TESTLENGTH - nd; nl++) {
+ TestCount++;
+ ResetTest(0);
+ BnComplement (RN(0), nd, nl);
+ ___BnComplement___(SN(0), nd, nl);
+ if(Check(1)) {
+ sprintf(e->hist, "%s(n, %d, %d)", e->name, nd, nl);
+ if(ShowDiff1(e, 0, 0, "n", nd, nl)) return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnAndDigits
+ */
+___BnAndDigits___(n, nd, m, md) BigNum n, m; int nd, md; {
+ BnAssign(Ntmp2, 0, n, nd, 1);
+ BnOrDigits(Ntmp2, 0, m, md);
+ BnXorDigits(Ntmp2, 0, m, md);
+ BnXorDigits(n, nd, Ntmp2, 0);
+}
+
+TestBnAndDigits(e) struct testenv *e; {
+ int nd, md;
+
+ e->depend = "(BnOrDigits, BnXorDigits)";
+ ResetTest(1);
+ for(nd = 0; nd < TESTLENGTH; nd++)
+ for(md = 0; md < TESTLENGTH; md++) {
+ TestCount++;
+ ResetTest(0);
+ BnAndDigits (RN(0), nd, RN(1), md);
+ ___BnAndDigits___(SN(0), nd, SN(1), md);
+ if(Check(2)) {
+ sprintf(e->hist, "%s(n, %d, m, %d)", e->name, nd, md);
+ if(ShowDiff2(e, 0, 0, "n", nd, 1, "m", md, 1))
+ return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnOrDigits
+ */
+___BnOrDigits___(n, nd, m, md) BigNum n, m; int nd, md; {
+ BnAssign(Ntmp2, 0, n, nd, 1);
+ BnAndDigits(Ntmp2, 0, m, md);
+ BnXorDigits(Ntmp2, 0, m, md);
+ BnXorDigits(n, nd, Ntmp2, 0);
+}
+
+TestBnOrDigits(e) struct testenv *e; {
+ int nd, md;
+
+ e->depend = "(BnAndDigits, BnXorDigits)";
+ ResetTest(1);
+ for(nd = 0; nd < TESTLENGTH; nd++)
+ for(md = 0; md < TESTLENGTH; md++) {
+ TestCount++;
+ ResetTest(0);
+ BnOrDigits (RN(0), nd, RN(1), md);
+ ___BnOrDigits___(SN(0), nd, SN(1), md);
+ if(Check(2)) {
+ sprintf(e->hist, "%s(n, %d, m, %d)", e->name, nd, md);
+ if(ShowDiff2(e, 0, 0, "n", nd, 1, "m", md, 1))
+ return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnXorDigits
+ */
+___BnXorDigits___(n, nd, m, md) BigNum n, m; int nd, md; {
+ BnAssign(Ntmp2, 0, n, nd, 1);
+ BnAndDigits(Ntmp2, 0, m, md);
+ BnComplement(Ntmp2, 0, 1);
+ BnOrDigits(n, nd, m, md);
+ BnAndDigits(n, nd, Ntmp2, 0);
+}
+
+TestBnXorDigits(e) struct testenv *e; {
+ int nd, md;
+
+ e->depend = "(BnAndDigits, BnComplement, BnOrDigits)";
+ ResetTest(1);
+ for(nd = 0; nd < TESTLENGTH; nd++)
+ for(md = 0; md < TESTLENGTH; md++) {
+ TestCount++;
+ ResetTest(0);
+ BnXorDigits (RN(0), nd, RN(1), md);
+ ___BnXorDigits___(SN(0), nd, SN(1), md);
+ if(Check(2)) {
+ sprintf(e->hist, "%s(n, %d, m, %d)", e->name, nd, md);
+ if(ShowDiff2(e, 0, 0, "n", nd, 1, "m", md, 1))
+ return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnShiftLeft
+ */
+___BnShiftLeft___(n, nd, nl, m, md, s) BigNum n, m; int nd, nl, md; int s; {
+ BnSetDigit(m, md, 2);
+ BnSetDigit(Ntmp2, 0, 1);
+ while(s--) {
+ BnSetToZero(NtmpBig, 0, 2);
+ BnMultiplyDigit(NtmpBig, 0, 2, Ntmp2, 0, 1, m, md);
+ BnAssign(Ntmp2, 0, NtmpBig, 0, 1);
+ }
+ BnSetToZero(NtmpBig, 0, nl + 1);
+ BnMultiplyDigit(NtmpBig, 0, nl + 1, n, nd, nl, Ntmp2, 0);
+ BnAssign(n, nd, NtmpBig, 0, nl);
+ BnAssign(m, md, NtmpBig, nl, 1);
+}
+
+TestBnShiftLeft(e) struct testenv *e; {
+ int nd, nl, md; int s;
+
+ e->depend = "(BnSetToZero, BnMultiplyDigit)";
+ ResetTest(1);
+ for(nd = 0; nd <= TESTLENGTH; nd++)
+ for(nl = 0; nl <= TESTLENGTH - nd; nl++)
+ for(md = 0; md < 2; md++)
+ for(s = 0; s < BN_DIGIT_SIZE; s++) {
+ TestCount++;
+ ResetTest(0);
+ BnShiftLeft (RN(0), nd, nl, RN(1), md, s);
+ ___BnShiftLeft___(SN(0), nd, nl, SN(1), md, s);
+ if(Check(2)) {
+ sprintf(e->hist, "%s(n, %d, %d, m, %d, %d)",
+ e->name, nd, nl, md, s);
+ if(ShowDiff2(e, 0, 0, "n", nd, nl, "m", md, 1))
+ return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnShiftRight
+ */
+___BnShiftRight___(n, nd, nl, m, md, s) BigNum n, m; int nd, nl, md; int s; {
+ if((nl == 0) || (s == 0)) {
+ BnSetDigit(m, md, 0);
+ return;
+ }
+ BnAssign(NtmpBig, 0, n, nd, nl);
+ BnShiftLeft(NtmpBig, 0, nl, NtmpBig, nl, BN_DIGIT_SIZE - s);
+ BnAssign(n, nd, NtmpBig, 1, nl);
+ BnAssign(m, md, NtmpBig, 0, 1);
+}
+
+TestBnShiftRight(e) struct testenv *e; {
+ int nd, nl, md; int s;
+
+ e->depend = "(BnShiftLeft)";
+ ResetTest(1);
+ for(nd = 0; nd <= TESTLENGTH; nd++)
+ for(nl = 0; nl <= TESTLENGTH - nd; nl++)
+ for(md = 0; md < 2; md++)
+ for(s = 0; s < BN_DIGIT_SIZE; s++) {
+ TestCount++;
+ ResetTest(0);
+ BnShiftRight (RN(0), nd, nl, RN(1), md, s);
+ ___BnShiftRight___(SN(0), nd, nl, SN(1), md, s);
+ if(Check(2)) {
+ sprintf(e->hist, "%s(n, %d, %d, m, %d, %d)",
+ e->name, nd, nl, md, s);
+ if(ShowDiff2(e, 0, 0, "n", nd, nl, "m", md, 1))
+ return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnAddCarry
+ */
+___BnAddCarry___(n, nd, nl, r) BigNum n; int nd, nl; int r;{
+ if(r == 0) return(0);
+ BnComplement(n, nd, nl);
+ r = BnSubtractBorrow(n, nd, nl, 0);
+ BnComplement(n, nd, nl);
+ if(r == 0) return(1);
+ return(0);
+}
+
+TestBnAddCarry(e) struct testenv *e; {
+ int nd, nl; int r, l1, l2;
+
+ e->depend = "(BnComplement, BnSubtractBorrow)";
+ for(nd = 0; nd <= TESTLENGTH; nd++)
+ for(nl = 0; nl <= TESTLENGTH - nd; nl++)
+ for(r = 0; r < 2; r++) {
+ TestCount++;
+ ResetTest(0);
+ l1 = BnAddCarry (RN(0), nd, nl, r);
+ l2 = ___BnAddCarry___(SN(0), nd, nl, r);
+ if(Check(1) || l1 != l2) {
+ sprintf(e->hist, "%s(n, %d, %d, %d)",
+ e->name, nd, nl, r);
+ if(ShowDiff1(e, l1, l2, "n", nd, nl)) return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnAdd
+ */
+___BnAdd___(n, nd, nl, m, md, ml, r) BigNum n, m; int nd, nl, md, ml; int r;{
+ BnComplement(m, md, ml);
+ r = BnSubtract(n, nd, ml, m, md, ml, r);
+ BnComplement(m, md, ml);
+ return(BnAddCarry(n, nd + ml, nl - ml, r));
+}
+
+TestBnAdd(e) struct testenv *e; {
+ int nd, nl, md, ml; int r, l1, l2;
+
+ e->depend = "(BnComplement, BnSubtract, BnAddCarry)";
+ ResetTest(1);
+ for(nd = 0; nd <= TESTLENGTH; nd++)
+ for(nl = 0; nl <= TESTLENGTH - nd; nl++)
+ for(md = 0; md <= TESTLENGTH - nl; md++)
+ for(ml = 0; ml <= nl ; ml++)
+ for(r = 0; r < 2; r++) {
+ TestCount++;
+ ResetTest(0);
+ l1 = BnAdd (RN(0), nd, nl, RN(1), md, ml, r);
+ l2 = ___BnAdd___(SN(0), nd, nl, SN(1), md, ml, r);
+ if(Check(2) || l1 != l2) {
+ sprintf(e->hist, "%s(n, %d, %d, m, %d, %d, %d)",
+ e->name, nd, nl, md, ml, r);
+ if(ShowDiff2(e, l1, l2, "n", nd, nl, "m", md, ml))
+ return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnSubtractBorrow
+ */
+___BnSubtractBorrow___(n, nd, nl, r) BigNum n; int nd, nl; int r;{
+ if(r == 1) return(1);
+ BnComplement(n, nd, nl);
+ r = BnAddCarry(n, nd, nl, 1);
+ BnComplement(n, nd, nl);
+ if(r == 0) return(1);
+ return(0);
+}
+
+TestBnSubtractBorrow(e) struct testenv *e; {
+ int nd, nl; int r, l1, l2;
+
+ e->depend = "(BnComplement, BnAddCarry)";
+ for(nd = 0; nd <= TESTLENGTH; nd++)
+ for(nl = 0; nl <= TESTLENGTH - nd; nl++)
+ for(r = 0; r < 2; r++) {
+ TestCount++;
+ ResetTest(0);
+ l1 = BnSubtractBorrow (RN(0), nd, nl, r);
+ l2 = ___BnSubtractBorrow___(SN(0), nd, nl, r);
+ if(Check(1) || l1 != l2) {
+ sprintf(e->hist, "%s(n, %d, %d, %d)",
+ e->name, nd, nl, r);
+ if(ShowDiff1(e, l1, l2, "n", nd, nl)) return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnSubtract
+ */
+___BnSubtract___(n, nd, nl, m, md, ml, r) BigNum n, m; int nd, nl, md, ml; int r;{
+ BnComplement(m, md, ml);
+ r = BnAdd(n, nd, ml, m, md, ml, r);
+ BnComplement(m, md, ml);
+ return(BnSubtractBorrow(n, nd + ml, nl - ml, r));
+}
+
+TestBnSubtract(e) struct testenv *e; {
+ int nd, nl, md, ml; int r, l1, l2;
+
+ e->depend = "(BnComplement, BnAdd, BnSubtractBorrow)";
+ ResetTest(1);
+ for(nd = 0; nd <= TESTLENGTH; nd++)
+ for(nl = 0; nl <= TESTLENGTH - nd; nl++)
+ for(md = 0; md <= TESTLENGTH - nl; md++)
+ for(ml = 0; ml <= nl ; ml++)
+ for(r = 0; r < 2; r++) {
+ TestCount++;
+ ResetTest(0);
+ l1 = BnSubtract (RN(0), nd, nl, RN(1), md, ml, r);
+ l2 = ___BnSubtract___(SN(0), nd, nl, SN(1), md, ml, r);
+ if(Check(2) || l1 != l2) {
+ sprintf(e->hist, "%s(n, %d, %d, m, %d, %d, %d)",
+ e->name, nd, nl, md, ml, r);
+ if(ShowDiff2(e, l1, l2, "n", nd, nl, "m", md, ml))
+ return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnMultiplyDigit
+ */
+___BnMultiplyDigit___(p, pd, pl, n, nd, nl, m, md) BigNum p, n, m; int pd, pl, nd, nl, md; {
+ int r = 0, ret = 0;
+
+ BnAssign(Ntmp2, 0, m, md, 1);
+ BnAssign(NtmpBig, 0, n, nd, nl);
+ BnSetToZero(NtmpBig, nl, 1);
+ while(!BnIsDigitZero(Ntmp2, 0)) {
+ if(BnIsDigitOdd(Ntmp2, 0)) {
+ r = BnAdd(p, pd, pl, NtmpBig, 0, nl + 1, 0);
+ if((ret == 0) && (r == 1)) ret = 1;
+ else if((ret == 1) && (r == 1)) ret = 2;
+ }
+ BnShiftRight(Ntmp2, 0, 1, Ntmp2, 1, 1);
+ BnShiftLeft(NtmpBig, 0, nl + 1, Ntmp2, 1, 1);
+ if(!BnIsDigitZero(Ntmp2, 1)) ret = 3;
+ }
+ return(ret);
+}
+
+TestBnMultiplyDigit(e) struct testenv *e; {
+ int pd, pl, nd, nl, md; int l1, l2;
+
+ e->depend = "(BnSetToZero, BnIsDigitZero, BnIsDigitOdd, BnAdd, BnShiftRight, BnShiftLeft)";
+ ResetTest(1);
+ ResetTest(2);
+ for(pd = 0; pd <= TESTLENGTH; pd++)
+ for(pl = 0; pl <= TESTLENGTH - pd; pl++)
+ for(nd = 0; nd <= TESTLENGTH - pl; nd++)
+ for(nl = 0; nl < pl ; nl++)
+ for(md = 0; md < TESTLENGTH; md++) {
+ TestCount++;
+ ResetTest(0);
+ l1 = BnMultiplyDigit (RN(0),pd,pl,RN(1),nd,nl,RN(2),md);
+ l2 = ___BnMultiplyDigit___(SN(0),pd,pl,SN(1),nd,nl,SN(2),md);
+ if(Check(3) || l1 != l2) {
+ sprintf(e->hist,
+ "BnMultiplyDigit(p, %d, %d, n, %d, %d, m, %d)",
+ pd, pl, nd, nl, md);
+ if(ShowDiff3(e,l1,l2,"p",pd,pl,"n",nd,nl,"m",md,1))
+ return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnDivideDigit
+ */
+TestBnDivideDigit(e) struct testenv *e; {
+ int nd, nl, md, qd, rd, l2;
+
+ e->depend = "(BnSetToZero, BnMultiplyDigit, BnCompareDigits)";
+ ResetTest(2);
+ ResetTest(3);
+ for(nd = 0; nd <= TESTLENGTH - 2; nd++)
+ for(nl = 2; nl <= TESTLENGTH - nd; nl++)
+ for(md = 0; md < TESTLENGTH; md++)
+ for(qd = 0; qd < TESTLENGTH - nl + 1 ; qd++)
+ for(rd = 0; rd < 2; rd++)
+ if((!BnIsDigitZero(RN(3), md)) &&
+ (BnCompareDigits(RN(2), nd+nl-1, RN(3), md) == -1)) {
+ TestCount++;
+ ResetTest(0);
+ ResetTest(1);
+ BnDivideDigit(RN(0), qd, RN(1), rd, RN(2), nd, nl, RN(3), md);
+ BnAssign(SN(0), qd, RN(0), qd, nl - 1);
+ BnAssign(SN(1), rd, RN(1), rd, 1);
+ BnSetToZero(SN(2), nd, nl);
+ BnAssign(SN(2), nd, SN(1), rd, 1);
+ l2 = BnMultiplyDigit(SN(2),nd,nl, SN(0),qd,nl - 1, SN(3), md);
+ if(Check(4) || l2 != 0) {
+ sprintf(e->hist,
+ "BnDivideDigit(q, %d, r, %d, n, %d, %d, m, %d)",
+ qd, rd, nd, nl, md);
+ if(ShowDiff4(e, 0, l2, "q", qd, nl - 1, "r", rd, 1,
+ "n", nd, nl, "m", md, 1))
+ return(TRUE);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnMultiply
+ */
+___BnMultiply___(p, pd, pl, m, md, ml, n, nd, nl) BigNum p, m, n; int pd, pl, md, ml, nd, nl; {
+ int ret;
+
+ for (ret = 0; nl-- > 0; pd++, nd++, pl--)
+ ret += BnMultiplyDigit (p, pd, pl, m, md, ml, n, nd);
+ return(ret);
+}
+
+TestBnMultiply(e) struct testenv *e; {
+ int pd, pl, nd, nl, md, ml; int l1, l2;
+
+ e->depend = "(BnSetToZero, BnMultiplyDigit)";
+ ResetTest(1);
+ ResetTest(2);
+ for(pd = 0; pd <= TESTLENGTH; pd++)
+ for(pl = 0; pl <= TESTLENGTH - pd && pl <= TESTLENGTH/2; pl++)
+ for(nd = 0; nd <= TESTLENGTH - pl; nd++)
+ for(nl = 0; nl < pl && nl <= TESTLENGTH/3; nl++)
+ {
+ if (nl <= pl-nl)
+ {
+ /* Test squaring */
+ TestCount++;
+ ResetTest(0);
+ l1 = BnMultiply (RN(0),pd,pl,RN(1),nd,nl,RN(1),nd,nl);
+ l2 = ___BnMultiply___(SN(0),pd,pl,SN(1),nd,nl,SN(1),nd,nl);
+ if(Check(3) || l1 != l2) {
+ sprintf(e->hist,
+ "BnMultiply(p, %d, %d, n, %d, %d, n, %d, %d)",
+ pd, pl, nd, nl, nd, nl);
+ if(ShowDiff3(e,l1,l2,"p",pd,pl,"n",nd,nl,"n",nd,nl))
+ return(1);
+ }
+
+ }
+ for(md = 0; md <= TESTLENGTH; md++)
+ for (ml = 0; ml <= pl-nl && ml <= TESTLENGTH/3 && md+ml <= TESTLENGTH; ml++) {
+ TestCount++;
+ ResetTest(0);
+ l1 = BnMultiply (RN(0),pd,pl,RN(1),nd,nl,RN(2),md,ml);
+ l2 = ___BnMultiply___(SN(0),pd,pl,SN(1),nd,nl,SN(2),md,ml);
+ if(Check(3) || l1 != l2) {
+ sprintf(e->hist,
+ "BnMultiply(p, %d, %d, n, %d, %d, m, %d, %d)",
+ pd, pl, nd, nl, md, ml);
+ if(ShowDiff3(e,l1,l2,"p",pd,pl,"n",nd,nl,"m",md,ml))
+ return(1);
+ } } }
+ return(FALSE);
+}
+
+/*
+ * Main
+ */
+typedef struct {
+ int (*TestFnt)();
+ char *NameFnt;
+} TESTONE;
+TESTONE AllTest[] = {
+ Generique, "Generic Functions",
+ TestBnSetToZero, "BnSetToZero",
+ TestBnAssign, "BnAssign",
+ TestBnNumDigits, "BnNumDigits",
+ TestBnNumLeadingZeroBitsInDigit, "BnNumLeadingZeroBitsInDigit",
+ TestBnIsDigitZero, "BnIsDigitZero",
+ TestBnIsDigitNormalized, "BnIsDigitNormalized",
+ TestBnIsDigitOdd, "BnIsDigitOdd",
+ TestBnCompareDigits, "BnCompareDigits",
+ TestBnComplement, "BnComplement",
+ TestBnAndDigits, "BnAndDigits",
+ TestBnOrDigits, "BnOrDigits",
+ TestBnXorDigits, "BnXorDigits",
+ TestBnShiftLeft, "BnShiftLeft",
+ TestBnShiftRight, "BnShiftRight",
+ TestBnAddCarry, "BnAddCarry",
+ TestBnAdd, "BnAdd",
+ TestBnSubtractBorrow, "BnSubtractBorrow",
+ TestBnSubtract, "BnSubtract",
+ TestBnMultiplyDigit, "BnMultiplyDigit",
+ TestBnDivideDigit, "BnDivideDigit",
+ TestBnMultiply, "BnMultiply",
+};
+
+main(n, s) int n; char **s; {
+ struct testenv realenv, *e = &realenv;
+ int i, j, nbtest, SizeAllTest;
+
+ /* Initialisations de l'environnement de test. */
+ e->flag = 1;
+ e->depend = "()";
+ /* Allocation des 2 nombres globaux. */
+ Ntmp2 = BnAlloc(2);
+ NtmpBig = BnAlloc(2 * TESTLENGTH);
+ NumbProto = BnAlloc(TESTLENGTH);
+ /* Creation du nombre prototype. */
+ BnSetDigit(NumbProto, 0, 0); /* Les 2 premiers a` ze'ro. */
+ BnSetDigit(NumbProto, 1, 0);
+ for(i=0; i < TESTLENGTH/4 - 1; i++) /* Le premier quart est la */
+ BnSetDigit(NumbProto, i + 2, i + 1); /* suite 1, 2, 3, ... */
+ /* Le 2nd quart est le 1er shifte de BN_DIGIT_SIZE - 2. 0x4000 0x8000 ...*/
+ BnAssign(NumbProto, QTL + 1, NumbProto, 2, QTL - 1);
+ BnShiftLeft(NumbProto, QTL + 1, QTL - 1, NumbProto, 0, BN_DIGIT_SIZE - 2);
+ /* La 2nd moitie est l'inverse logique de la 1ere */
+ BnAssign(NumbProto, DTL, NumbProto, 0, DTL);
+ BnComplement(NumbProto, DTL, DTL);
+ /* Allocation des nombres utilise's */
+ for(i=0; i < 5; i++) {
+ RN(i) = BnAlloc(TESTLENGTH);
+ SN(i) = BnAlloc(TESTLENGTH);
+ }
+ if(n == 1) {
+ printf("%s [v|a|TestNum]\n", s[0]);
+ }
+ /* On y va */
+ SizeAllTest = (sizeof(AllTest)/sizeof(AllTest[0]));
+ for(i = 1; i < n; i++) {
+ if(s[i][0] == 'm') {
+ /* 0 = No skip; 1 = skip to next; else STOP */
+ e->flag = atoi(&s[i][1]);
+ } else if(s[i][0] == 'a') {
+ for(i = 0; i < SizeAllTest; i++)
+ dotest(e, i);
+ } else if(s[i][0] == 'v') {
+ for(j = 0; j < SizeAllTest; j++)
+ seetest(j);
+ } else {
+ nbtest = atoi(s[i]);
+ if((nbtest < 0) || (nbtest >= SizeAllTest))
+ printf("Test %d is invalid\n", nbtest);
+ else dotest(e, nbtest);
+} } }
+
+dotest(e, n) struct testenv *e; int n; {
+ seetest(n);
+ TestCount = 0;
+ e->name = AllTest[n].NameFnt;
+ if(((*(AllTest[n].TestFnt)) (e)) && e->flag > 1) exit(0);
+ printf("%d tests were performed\n", TestCount);
+}
+
+seetest(n) int n; {
+ printf("%d. Testing %s\n", n, AllTest[n].NameFnt);
+}
+
--- /dev/null
+/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */
+/* Last modified_on Fri Aug 17 17:19:01 GMT+2:00 1990 by shand */
+/* modified_on Wed Jul 5 10:19:33 GMT+2:00 1989 by bertin */
+/* modified_on Fri Apr 28 20:03:23 GMT+2:00 1989 by herve */
+
+
+/* BigN.h - Types and structures for clients of BigNum */
+
+
+
+ /******** representation of a bignum ******/
+/*
+** <--------------------------- nl ---------------------------->
+** | Least Most |
+** |Significant| | | |Significant|
+** |BigNumDigit| | | |BigNumDigit|
+** |___________|___________|___________|___________|___________|
+** ^ (sometimes
+** | is zero)
+** nn
+*/
+
+/* signals BigNum.h already included */
+#define BIGNUM
+
+ /*************** sizes ********************/
+
+#define BN_BYTE_SIZE 8
+#define BN_WORD_SIZE (sizeof (int) * BN_BYTE_SIZE)
+#define BN_DIGIT_SIZE (sizeof (BigNumDigit) * BN_BYTE_SIZE)
+
+/* notes: */
+/* BN_BYTE_SIZE: number of bits in a byte */
+/* BN_WORD_SIZE: number of bits in an "int" in the target language */
+/* BN_DIGIT_SIZE: number of bits in a digit of a BigNum */
+
+
+ /****** results of compare functions ******/
+
+ /* Note: we don't use "enum" to interface with Modula2+, Lisp, ... */
+#define BN_LT -1
+#define BN_EQ 0
+#define BN_GT 1
+
+ /*************** boolean ******************/
+
+#define TRUE 1
+#define FALSE 0
+
+
+ /* if DIGITon16BITS is defined, a single digit is on 16 bits */
+ /* otherwise (by default) a single digit is on 32 bits *****/
+ /* Note: on 32 bit machine it makes little sense to mix */
+ /* longs and short, so we define Boolean & BigNumCmp to be */
+ /* int usually */
+
+#ifdef DIGITon16BITS
+typedef unsigned short BigNumDigit;
+typedef short Boolean;
+#else
+typedef unsigned int BigNumDigit;
+typedef int Boolean;
+#endif
+
+
+ /* bignum types: digits, big numbers, carries ... */
+
+typedef BigNumDigit * BigNum; /* A big number is a digit pointer */
+typedef BigNumDigit BigNumCarry; /* Either 0 or 1 */
+typedef unsigned long BigNumProduct; /* The product of two digits */
+typedef unsigned long BigNumLength; /* The length of a bignum */
+#ifdef DIGITon16BITS
+typedef short BigNumCmp; /* result of comparison */
+#else
+typedef int BigNumCmp; /* result of comparison */
+#endif
+
+
+/*\f*/
+
+
+ /************ functions of bn.c ***********/
+
+extern void BnnInit ();
+extern void BnnClose ();
+
+extern Boolean BnnIsZero ();
+extern BigNumCarry BnnMultiply ();
+extern void BnnDivide ();
+extern BigNumCmp BnnCompare ();
+
+
+ /*********** functions of KerN.c **********/
+
+extern void BnnSetToZero ();
+extern void BnnAssign ();
+extern void BnnSetDigit ();
+extern BigNumDigit BnnGetDigit ();
+extern BigNumLength BnnNumDigits ();
+extern BigNumDigit BnnNumLeadingZeroBitsInDigit ();
+extern Boolean BnnDoesDigitFitInWord ();
+extern Boolean BnnIsDigitZero ();
+extern Boolean BnnIsDigitNormalized ();
+extern Boolean BnnIsDigitOdd ();
+extern BigNumCmp BnnCompareDigits ();
+extern void BnnComplement ();
+extern void BnnAndDigits ();
+extern void BnnOrDigits ();
+extern void BnnXorDigits ();
+extern BigNumDigit BnnShiftLeft ();
+extern BigNumDigit BnnShiftRight ();
+extern BigNumCarry BnnAddCarry ();
+extern BigNumCarry BnnAdd ();
+extern BigNumCarry BnnSubtractBorrow ();
+extern BigNumCarry BnnSubtract ();
+extern BigNumCarry BnnMultiplyDigit ();
+extern BigNumDigit BnnDivideDigit ();
+
+/*\f*/
+
+ /* some functions can be written with macro-procedures */
+
+
+#ifndef BNNMACROS_OFF
+/* the functions BnnIsZero and BnnCompareDigits are not macro procedures
+since they use parameters twice, and that can produce some bugs if
+you pass a parameter like x++, the increment will be executed twice ! */
+#define BnnSetDigit(nn,d) (*(nn) = (d))
+#define BnnGetDigit(nn) ((unsigned)(*(nn)))
+#define BnnDoesDigitFitInWord(d) (BN_DIGIT_SIZE > BN_WORD_SIZE ? ((d) >= 1 << BN_WORD_SIZE ? FALSE : TRUE) : TRUE)
+#define BnnIsDigitZero(d) ((d) == 0)
+#define BnnIsDigitNormalized(d) ((d) & (1 << (BN_DIGIT_SIZE - 1)) ? TRUE : FALSE)
+#define BnnIsDigitOdd(d) ((d) & 1 ? TRUE : FALSE)
+#define BnnAndDigits(nn, d) (*(nn) &= (d))
+#define BnnOrDigits(nn, d) (*(nn) |= (d))
+#define BnnXorDigits(nn, d) (*(nn) ^= (d))
+
+#endif
+
+
--- /dev/null
+/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */
+/* Last modified_on Thu Mar 22 21:29:09 GMT+1:00 1990 by shand */
+/* modified_on Mon Jan 23 18:38:46 GMT+1:00 1989 by herve */
+
+/* BigZ.h: Types and structures for clients of BigZ */
+
+
+ /* BigZ sign */
+
+
+#define BZ_PLUS 1
+#define BZ_ZERO 0
+#define BZ_MINUS -1
+#define BzSign BigNumCmp
+
+
+ /* BigZ compare result */
+
+
+#define BZ_LT BN_LT
+#define BZ_EQ BN_EQ
+#define BZ_GT BN_GT
+#define BzCmp BigNumCmp
+
+
+ /* BigZ number */
+
+#ifndef BIGNUM
+#include "BigNum.h"
+#endif
+
+struct BigZHeader
+{
+ unsigned long Size;
+ BzSign Sign;
+};
+
+
+struct BigZStruct
+{
+ struct BigZHeader Header;
+ BigNumDigit Digits [16];
+};
+
+
+typedef struct BigZStruct * BigZ;
+
+/*\f*/
+
+
+ /*********** macros of bz.c **********/
+
+
+#define BzGetSize(z) ((z)->Header.Size)
+#define BzGetSign(z) ((z)->Header.Sign)
+
+#define BzSetSize(z,s) (z)->Header.Size = s
+#define BzSetSign(z,s) (z)->Header.Sign = s
+
+#define BzGetOppositeSign(z) (-(z)->Header.Sign)
+
+
+ /*********** functions of bz.c **********/
+
+extern void BzInit ();
+extern void BzClose ();
+
+extern BigZ BzCreate ();
+extern void BzFree ();
+extern void BzFreeString ();
+
+extern unsigned BzNumDigits ();
+
+extern BigZ BzCopy ();
+extern BigZ BzNegate ();
+extern BigZ BzAbs ();
+extern BzCmp BzCompare ();
+
+extern BigZ BzAdd ();
+extern BigZ BzSubtract ();
+extern BigZ BzMultiply ();
+extern BigZ BzDivide ();
+extern BigZ BzDiv ();
+extern BigZ BzMod ();
+
+extern BigZ BzFromString ();
+extern char * BzToString ();
+
+extern BigZ BzFromInteger ();
+extern int BzToInteger ();
+
+extern BigZ BzFromBigNum ();
+extern BigNum BzToBigNum ();
+
+ /*********** functions of bzf.c **********/
+
+extern BigZ BzFactorial ();
--- /dev/null
+/* Copyright Digital Equipment Corporation & INRIA 1988 */
+/* Last modified_on Wed Feb 14 16:20:34 GMT+1:00 1990 by herve */
+/* modified_on 17-OCT-1989 20:23:23.17 by Jim Lawton SDE/Galway */
+
+/* BntoBnn.h: allowing to use the new interfaces of KerN */
+
+
+#ifndef VMS
+extern char *malloc();
+#endif
+
+
+ /* old types of Bn */
+
+typedef unsigned int BigNumType; /* A BigNum's type */
+
+struct BigNumHeader /* The header of a BigNum */
+{
+ BigNumType type;
+ int length;
+};
+
+
+ /* macros of old types of Bn */
+
+#define BN_TYPE(n) (((struct BigNumHeader *) n) - 1)->type
+#define BN_LENGTH(n) (((struct BigNumHeader *) n) - 1)->length
+
+
+ /* macros of functions of Bn to functions Bnn */
+
+#define BnIsZero(n, nd, nl) BnnIsZero ((n+nd), nl)
+#define BnMultiply(p, pd, pl, m, md, ml, n, nd, nl) BnnMultiply ((p+pd), pl, (m+md), ml, (n+nd), nl)
+#define BnDivide(n, nd, nl, d, dd, dl) BnnDivide ((n+nd), nl, (d+dd), dl)
+#define BnCompare(m, md, ml, n, nd, nl) BnnCompare ((m+md), ml, (n+nd), nl)
+#define BnSetToZero(n, nd, nl) BnnSetToZero ((n+nd), nl)
+#define BnAssign(m, md, n, nd, nl) BnnAssign ((m+md), (n+nd), nl)
+#define BnSetDigit(n, nd, d) BnnSetDigit ((n+nd), d)
+#define BnGetDigit(n, nd) BnnGetDigit ((n+nd))
+#define BnNumDigits(n, nd, nl) BnnNumDigits ((n+nd), nl)
+#define BnNumLeadingZeroBitsInDigit(n, nd) BnnNumLeadingZeroBitsInDigit (*(n+nd))
+#define BnDoesDigitFitInWord(n, nd) BnnDoesDigitFitInWord (*(n+nd))
+#define BnIsDigitZero(n, nd) BnnIsDigitZero (*(n+nd))
+#define BnIsDigitNormalized(n, nd) BnnIsDigitNormalized (*(n+nd))
+#define BnIsDigitOdd(n, nd) BnnIsDigitOdd (*(n+nd))
+#define BnCompareDigits(m, md, n, nd) BnnCompareDigits (*(m+md), *(n+nd))
+#define BnComplement(n, nd, nl) BnnComplement ((n+nd), nl)
+#define BnAndDigits(m, md, n, nd) BnnAndDigits ((m+md), *(n+nd))
+#define BnOrDigits(m, md, n, nd) BnnOrDigits ((m+md), *(n+nd))
+#define BnXorDigits(m, md, n, nd) BnnXorDigits ((m+md), *(n+nd))
+#define BnShiftLeft(m, md, ml, n, nd, nbits) *(n+nd) = BnnShiftLeft ((m+md), ml, nbits)
+#define BnShiftRight(m, md, ml, n, nd, nbits) *(n+nd) = BnnShiftRight ((m+md), ml, nbits)
+#define BnAddCarry(n, nd, nl, carryin) BnnAddCarry ((n+nd), nl, carryin)
+#define BnAdd(m, md, ml, n, nd, nl, carryin) BnnAdd ((m+md), ml, (n+nd), nl, carryin)
+#define BnSubtractBorrow(n, nd, nl, carryin) BnnSubtractBorrow ((n+nd), nl, carryin)
+#define BnSubtract(m, md, ml, n, nd, nl, carryin) BnnSubtract ((m+md), ml, (n+nd), nl, carryin)
+#define BnMultiplyDigit(p, pd, pl, m, md, ml, n, nd) BnnMultiplyDigit ((p+pd), pl, (m+md), ml, *(n+nd))
+#define BnDivideDigit(q, qd, r, rd, n, nd, nl, d, dd) *(r+rd) = BnnDivideDigit ((q+qd), (n+nd), nl, *(d+dd))
+
+
+ /* old functions of Bn */
+
+/*
+ * Creation and access to type and length fields.
+ */
+extern char *malloc();
+/* Allocates a BigNum structure and returns a pointer to it */
+BigNum BnAlloc(size) int size; {
+ register BigNum n;
+
+ n = (BigNum) (malloc(sizeof(struct BigNumHeader) +
+ size * sizeof(BigNumDigit))
+ + sizeof(struct BigNumHeader));
+ BN_LENGTH(n) = size;
+ return(n);
+}
+
+/* Allocates a BigNum, inserts its Type, and returns a pointer to it */
+BigNum BnCreate(type, size) BigNumType type; int size; {
+ register BigNum n;
+
+ n = BnAlloc(size);
+ BN_TYPE(n) = type;
+ BnSetToZero(n, 0, size);
+ return(n);
+}
+
+/* Frees a BigNum structure */
+BnFree(n) BigNum n; {
+ free(((struct BigNumHeader *) n) - 1);
+ return 1;
+}
+
+/* Returns the BigNum's Type */
+BigNumType BnGetType(n) BigNum n; {
+ return(BN_TYPE(n));
+}
+
+/* Sets the BigNum's Type */
+BnSetType(n, type) BigNum n; BigNumType type; {
+ BN_TYPE(n) = type;
+}
+
+/* Returns the number of digits allocated for the BigNum */
+BnGetSize(n) BigNum n; {
+ return(BN_LENGTH(n));
+}
+
--- /dev/null
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+#include <stdio.h>
+#ifndef ultrix
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#include <sys/types.h>
+#include "random.h"
+#include "BigNum.h"
+#include "BigRSA.h"
+#include "bigkeygen.h"
+
+/*
+ * InitDelegationKey. Generate a new rsa key of desired bit length.
+ * If random number generator is not yet seeded,
+ * initialize with uncertainty from the principal
+ * prime.
+ */
+int InitDelegationKey(principal, delegation, bitlen)
+RSAKeyStorage *principal, *delegation;
+int bitlen;
+{
+ RNGState rng;
+ read_rng_state (&rng);
+ if ((rng.count)==0) initialize_rng_state (principal->p,32);
+ return(newRSAKey (delegation, bitlen));
+}
+
+/*
+ * Private2Public. Remove private key stuff in a key storage block.
+ */
+int Private2Public (key)
+RSAKeyStorage *key;
+{
+ memset(key->p,0,PRIVATE_KEY_SIZE-PUBLIC_KEY_SIZE);
+ key->pl=key->ql=key->dpl=key->dql=0;
+}
+
+
+/*
+ * initrandom - interactive random number initializer
+ *
+ * The following routine attempts to initialize the random number generator
+ * with a reasonable amount of uncertainty. This is provided mostly by
+ * the user, with some additional time inputs from the system.
+ */
+int initrandom()
+{
+unsigned char bar[16];
+int seed ;
+char buffer[256], sphinx_ans[80];
+char *ptr=buffer, *env=NULL;
+int i;
+long tick = clock();
+struct timeval tv ;
+struct timezone tz ;
+int thischar , lastchar ;
+
+ memset(ptr,0,256);
+
+ gettimeofday(&tv, &tz);
+ memcpy(ptr,&tv,sizeof(struct timeval));
+ ptr += sizeof(struct timeval);
+/*
+ printf("\nRiddle of the Sphinx :\n\n");
+ printf("What creature is it, that in the morning goes on four feet,\n");
+ printf("at noon on two, and at night on three?\n\n");
+ fflush(stdout);
+ scanf("%s", sphinx_ans); gets(ptr);
+ if ((strcasecmp(sphinx_ans, "man") == 0) || (strcasecmp(sphinx_ans, "woman") == 0)) {
+ printf("\nCorrect!\n\n");
+ } else {
+ printf("\nWrong! Please brush up on your Egyptian mythology.\n\n");
+ }
+*/
+ tick = clock();
+ memcpy(ptr,&tick,sizeof(long));
+ ptr += sizeof(long);
+ memcpy(ptr,&ptr,sizeof(char *));
+ ptr+=sizeof(char *);
+ gettimeofday(&tv, &tz);
+ memcpy(ptr,&tv,sizeof(struct timeval));
+ ptr += sizeof(struct timeval);
+
+ seed = sizeof(buffer) - (ptr - buffer) - sizeof(struct timeval);
+
+ printf("\nSome 'uncertainty' is needed to initialize the random");
+ printf("\nnumber generator to generate your long term key. Please");
+ printf("\nenter up to %d characters of text. The quality of your key", seed);
+ printf("\ndepends upon how 'uncertain' this input is. When you");
+ printf("\nthink you have entered enough text, enter two successive");
+ printf("\ncarriage returns.");
+ printf("\n\n");
+ fflush(stdout);
+
+ for( i = thischar = lastchar = 0;
+ (thischar=getchar())!= EOF,((thischar != '\n')||(lastchar != '\n')); i++) {
+ lastchar = thischar;
+ ptr[ i % seed ] += (unsigned char) thischar ;
+ }
+
+ printf("\nThank you very much.\n");
+
+ gettimeofday(&tv, &tz);
+ memcpy(ptr,&tv,sizeof(struct timeval));
+
+ initialize_rng_state (buffer, sizeof(buffer));
+
+}
+
--- /dev/null
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+/* dumphex.c */
+#include <stdio.h>
+#include <ctype.h>
+
+#define CHARS_PER_LINE 16
+
+/*
+ * write out half-ASCII hex characters to a file
+ */
+
+int fdumphex (x,l,fp)
+int l;
+unsigned char * x;
+FILE *fp ;
+{
+ int i;
+ for(i=0;i<l;i++){
+ if ((i%CHARS_PER_LINE)==0)fprintf(fp,"\n");
+ fprintf(fp," %02x",*x++);
+ }
+ fprintf(fp,"\n");
+}
+
+/*
+ * read in half-ASCII text, skipping whites, until EOF or non-hex encoded byte
+ * found, returning number of bytes read.
+ */
+int freadhex (x,l,fp)
+int l;
+unsigned char * x;
+FILE *fp ;
+{
+ int i,j;
+ for(i=0;fscanf(fp," %02x",&j);i++) *x++=j;
+ return (i);
+}
+
+
+int dumphex (x,l)
+int l;
+unsigned char * x;
+{
+ fdumphex(x,l,stdout);
+}
--- /dev/null
+/* endian.h */
+/*
+ * Machine generated on Mon Jan 21 11:21:03 1991
+ */
+
+#ifndef SPHINX_ENDIAN
+
+/*
+ * Little endian machines are DEC/Intel like
+ * Big endian machines are IBM/SPARC/Motorola like
+ *
+ * This machine is little endian since the value of SPHINX_ENDIAN is 1
+ *
+ */
+
+
+#define SPHINX_ENDIAN 1
+
+
+#endif
+
+
--- /dev/null
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+/*
+ * CONTENTS:
+ *
+ * This file contains RSA hash routines.
+ */
+
+#include <stdio.h>
+#include "endian.h"
+#include "hashes.h"
+
+
+/*
+ * This conditionally includes the BSAFE MD and MAC routines. These
+ * are not used by Sphinx so usually this definition is commented out.
+ */
+
+/*
+#define INCLUDE_RSA_BSAFE_STUFF 1
+*/
+
+#define TEMP_BUFSIZ 256
+
+/*
+ * Externally Callable Routines. All arguments are character pointers
+ * or integer lengths.
+ */
+
+void RSA_MD2(); /* RSA_MD2(input_buffer, length, hash_result) */
+void RSA_MD4(); /* RSA_MD4(input_buffer, length, hash_result) */
+#ifdef INCLUDE_RSA_BSAFE_STUFF
+void RSA_MAC(); /* RSA_MAC(input_buffer, length, mac, output_length) */
+void RSA_MD(); /* RSA_MD(input_buffer, length, hash_result) */
+#endif
+
+\f
+/*
+** **************************************************************************
+** md4.h -- Header file for implementation of MD4 Message Digest Algorithm **
+** Updated: 2/13/90 by Ronald L. Rivest **
+** (C) 1990 RSA Data Security, Inc. **
+** **************************************************************************
+*/
+
+/* MDstruct is the data structure for a message digest computation.
+*/
+typedef struct {
+ unsigned int buffer[4]; /* Holds 4-word result of MD computation */
+ unsigned char count[8]; /* Number of bits processed so far */
+ unsigned int done; /* Nonzero means MD computation finished */
+} MDstruct, *MDptr;
+
+/*
+** **************************************************************************
+** md4.c -- Implementation of MD4 Message Digest Algorithm **
+** Updated: 2/16/90 by Ronald L. Rivest **
+** (C) 1990 RSA Data Security, Inc. **
+** **************************************************************************
+*/
+
+/*
+** To use MD4:
+** -- Include md4.h in your program
+** -- Declare an MDstruct MD to hold the state of the digest computation.
+** -- Initialize MD using MDbegin(&MD)
+** -- For each full block (64 bytes) X you wish to process, call
+** MDupdate(&MD,X,512)
+** (512 is the number of bits in a full block.)
+** -- For the last block (less than 64 bytes) you wish to process,
+** MDupdate(&MD,X,n)
+** where n is the number of bits in the partial block. A partial
+** block terminates the computation, so every MD computation should
+** terminate by processing a partial block, even if it has n = 0.
+** -- The message digest is available in MD.buffer[0] ... MD.buffer[3].
+** (Least-significant byte of each word should be output first.)
+** -- You can print out the digest using MDprint(&MD)
+*/
+
+/* Implementation notes:
+** This implementation assumes that ints are 32-bit quantities.
+** If the machine stores the least-significant byte of an int in the
+** least-addressed byte (eg., VAX and 8086), then LOWBYTEFIRST should be
+** set to TRUE. Otherwise (eg., SUNS), LOWBYTEFIRST should be set to
+** FALSE. Note that on machines with LOWBYTEFIRST FALSE the routine
+** MDupdate modifies has a side-effect on its input array (the order of bytes
+** in each word are reversed). If this is undesired a call to MDreverse(X) can
+** reverse the bytes of X back into order after each call to MDupdate.
+*/
+#ifdef TRUE
+#undef TRUE
+#endif
+
+#define TRUE 1
+
+#ifdef FALSE
+#undef FALSE
+#endif
+
+#define FALSE 0
+
+#define LOWBYTEFIRST SPHINX_ENDIAN
+
+/* Compile-time declarations of MD4 ``magic constants''.
+*/
+#define I0 0x67452301 /* Initial values for MD buffer */
+#define I1 0xefcdab89
+#define I2 0x98badcfe
+#define I3 0x10325476
+#define C2 013240474631 /* round 2 constant = sqrt(2) in octal */
+#define C3 015666365641 /* round 3 constant = sqrt(3) in octal */
+/* C2 and C3 are from Knuth, The Art of Programming, Volume 2
+** (Seminumerical Algorithms), Second Edition (1981), Addison-Wesley.
+** Table 2, page 660.
+*/
+#define fs1 3 /* round 1 shift amounts */
+#define fs2 7
+#define fs3 11
+#define fs4 19
+#define gs1 3 /* round 2 shift amounts */
+#define gs2 5
+#define gs3 9
+#define gs4 13
+#define hs1 3 /* round 3 shift amounts */
+#define hs2 9
+#define hs3 11
+#define hs4 15
+
+
+/* Compile-time macro declarations for MD4.
+** Note: The ``rot'' operator uses the variable ``tmp''.
+** It assumes tmp is declared as unsigned int, so that the >>
+** operator will shift in zeros rather than extending the sign bit.
+*/
+#define f(X,Y,Z) ((X&Y) | ((~X)&Z))
+#define g(X,Y,Z) ((X&Y) | (X&Z) | (Y&Z))
+#define h(X,Y,Z) (X^Y^Z)
+#define rot(X,S) (tmp=X,(tmp<<S) | (tmp>>(32-S)))
+#define ff(A,B,C,D,i,s) A = rot((A + f(B,C,D) + X[i]),s)
+#define gg(A,B,C,D,i,s) A = rot((A + g(B,C,D) + X[i] + C2),s)
+#define hh(A,B,C,D,i,s) A = rot((A + h(B,C,D) + X[i] + C3),s)
+
+\f
+/* MDprint(MDp)
+** Print message digest buffer MDp as 32 hexadecimal digits.
+** Order is from low-order byte of buffer[0] to high-order byte of buffer[3].
+** Each byte is printed with high-order hexadecimal digit first.
+** This is a user-callable routine.
+*/
+static void MDprint(MDp)
+MDptr MDp;
+{ int i,j;
+ for (i=0;i<4;i++)
+ for (j=0;j<32;j=j+8)
+ printf("%02x",(MDp->buffer[i]>>j) & 0xFF);
+}
+
+/* MDbegin(MDp)
+** Initialize message digest buffer MDp.
+** This is a user-callable routine.
+*/
+static void MDbegin(MDp)
+MDptr MDp;
+{ int i;
+ MDp->buffer[0] = I0;
+ MDp->buffer[1] = I1;
+ MDp->buffer[2] = I2;
+ MDp->buffer[3] = I3;
+ for (i=0;i<8;i++) MDp->count[i] = 0;
+ MDp->done = 0;
+}
+
+/* MDreverse(X)
+** Reverse the byte-ordering of every int in X.
+** Assumes X is an array of 16 ints.
+** The macro revx reverses the byte-ordering of the next word of X.
+*/
+#define revx { t = (*X << 16) | (*X >> 16); \
+ *X++ = ((t & 0xFF00FF00) >> 8) | ((t & 0x00FF00FF) << 8); }
+static void MDreverse(X)
+unsigned int *X;
+{ register unsigned int t;
+ revx; revx; revx; revx; revx; revx; revx; revx;
+ revx; revx; revx; revx; revx; revx; revx; revx;
+}
+\f
+/* MDblock(MDp,X)
+** Update message digest buffer MDp->buffer using 16-word data block X.
+** Assumes all 16 words of X are full of data.
+** Does not update MDp->count.
+** This routine is not user-callable.
+*/
+static void MDblock(MDp,X)
+MDptr MDp;
+unsigned int *X;
+{
+ register unsigned int tmp, A, B, C, D;
+#if LOWBYTEFIRST == FALSE
+ MDreverse(X);
+#endif
+ A = MDp->buffer[0];
+ B = MDp->buffer[1];
+ C = MDp->buffer[2];
+ D = MDp->buffer[3];
+ /* Update the message digest buffer */
+ ff(A , B , C , D , 0 , fs1); /* Round 1 */
+ ff(D , A , B , C , 1 , fs2);
+ ff(C , D , A , B , 2 , fs3);
+ ff(B , C , D , A , 3 , fs4);
+ ff(A , B , C , D , 4 , fs1);
+ ff(D , A , B , C , 5 , fs2);
+ ff(C , D , A , B , 6 , fs3);
+ ff(B , C , D , A , 7 , fs4);
+ ff(A , B , C , D , 8 , fs1);
+ ff(D , A , B , C , 9 , fs2);
+ ff(C , D , A , B , 10 , fs3);
+ ff(B , C , D , A , 11 , fs4);
+ ff(A , B , C , D , 12 , fs1);
+ ff(D , A , B , C , 13 , fs2);
+ ff(C , D , A , B , 14 , fs3);
+ ff(B , C , D , A , 15 , fs4);
+ gg(A , B , C , D , 0 , gs1); /* Round 2 */
+ gg(D , A , B , C , 4 , gs2);
+ gg(C , D , A , B , 8 , gs3);
+ gg(B , C , D , A , 12 , gs4);
+ gg(A , B , C , D , 1 , gs1);
+ gg(D , A , B , C , 5 , gs2);
+ gg(C , D , A , B , 9 , gs3);
+ gg(B , C , D , A , 13 , gs4);
+ gg(A , B , C , D , 2 , gs1);
+ gg(D , A , B , C , 6 , gs2);
+ gg(C , D , A , B , 10 , gs3);
+ gg(B , C , D , A , 14 , gs4);
+ gg(A , B , C , D , 3 , gs1);
+ gg(D , A , B , C , 7 , gs2);
+ gg(C , D , A , B , 11 , gs3);
+ gg(B , C , D , A , 15 , gs4);
+ hh(A , B , C , D , 0 , hs1); /* Round 3 */
+ hh(D , A , B , C , 8 , hs2);
+ hh(C , D , A , B , 4 , hs3);
+ hh(B , C , D , A , 12 , hs4);
+ hh(A , B , C , D , 2 , hs1);
+ hh(D , A , B , C , 10 , hs2);
+ hh(C , D , A , B , 6 , hs3);
+ hh(B , C , D , A , 14 , hs4);
+ hh(A , B , C , D , 1 , hs1);
+ hh(D , A , B , C , 9 , hs2);
+ hh(C , D , A , B , 5 , hs3);
+ hh(B , C , D , A , 13 , hs4);
+ hh(A , B , C , D , 3 , hs1);
+ hh(D , A , B , C , 11 , hs2);
+ hh(C , D , A , B , 7 , hs3);
+ hh(B , C , D , A , 15 , hs4);
+ MDp->buffer[0] += A;
+ MDp->buffer[1] += B;
+ MDp->buffer[2] += C;
+ MDp->buffer[3] += D;
+}
+
+\f
+/* MDupdate(MDp,X,count)
+** Input: MDp -- an MDptr
+** X -- a pointer to an array of unsigned characters.
+** count -- the number of bits of X to use.
+** (if not a multiple of 8, uses high bits of last byte.)
+** Update MDp using the number of bits of X given by count.
+** This is the basic input routine for an MD4 user.
+** The routine completes the MD computation when count < 512, so
+** every MD computation should end with one call to MDupdate with a
+** count less than 512. A call with count 0 will be ignored if the
+** MD has already been terminated (done != 0), so an extra call with count
+** 0 can be given as a ``courtesy close'' to force termination if desired.
+*/
+static int MDupdate(MDp,X,count)
+MDptr MDp;
+unsigned char *X;
+unsigned int count;
+{ unsigned int i, tmp, bit, byte, mask;
+ unsigned char XX[64];
+ unsigned char *p;
+ /* return with no error if this is a courtesy close with count
+ ** zero and MDp->done is true.
+ */
+ if (count == 0 && MDp->done) return(1);
+ /* check to see if MD is already done and report error */
+ if (MDp->done) {
+#ifdef DEBUG
+ printf("\nError: MDupdate MD already done.");
+#endif
+ return(0); }
+ /* Add count to MDp->count */
+ tmp = count;
+ p = MDp->count;
+ while (tmp)
+ { tmp += *p;
+ *p++ = tmp;
+ tmp = tmp >> 8;
+ }
+ /* Process data */
+ if (count == 512)
+ { /* Full block of data to handle */
+ MDblock(MDp,(unsigned int *)X);
+ }
+ else if (count > 512) /* Check for count too large */
+ {
+#ifdef DEBUG
+printf("\nError: MDupdate called with illegal count value %d.",count);
+#endif
+ return(0);
+ }
+ else /* partial block -- must be last block so finish up */
+ { /* Find out how many bytes and residual bits there are */
+ byte = count >> 3;
+ bit = count & 7;
+ /* Copy X into XX since we need to modify it */
+ for (i=0;i<=byte;i++) XX[i] = X[i];
+ for (i=byte+1;i<64;i++) XX[i] = 0;
+ /* Add padding '1' bit and low-order zeros in last byte */
+ mask = 1 << (7 - bit);
+ XX[byte] = (XX[byte] | mask) & ~( mask - 1);
+ /* If room for bit count, finish up with this block */
+ if (byte <= 55)
+ { for (i=0;i<8;i++) XX[56+i] = MDp->count[i];
+ MDblock(MDp,(unsigned int *)XX);
+ }
+ else /* need to do two blocks to finish up */
+ { MDblock(MDp,(unsigned int *)XX);
+ for (i=0;i<56;i++) XX[i] = 0;
+ for (i=0;i<8;i++) XX[56+i] = MDp->count[i];
+ MDblock(MDp,(unsigned int *)XX);
+ }
+ /* Set flag saying we're done with MD computation */
+ MDp->done = 1;
+ }
+ return(1);
+}
+
+/*
+** End of md4.c
+*/
+
+
+\f
+/*
+ * MD4
+ */
+void RSA_MD4 (inbuf, isize, digest)
+char * inbuf, * digest ;
+int isize;
+{ unsigned int i;
+ MDstruct MD;
+ MDbegin(&MD);
+ for (i=0;i+64<=isize;i=i+64) MDupdate(&MD,inbuf+i,512);
+ MDupdate(&MD,inbuf+i,(isize-i)*8);
+ memcpy(digest,MD.buffer,16);
+}
+
+
+\f
+#ifdef INCLUDE_RSA_BSAFE_STUFF
+/* SUBSTITUTION TABLE BASED ON DIGITS OF PI -- SEE PISUBST.DOC */
+/* obtained from RSA, Inc. */
+static unsigned char _pisubst[256] = {
+ 189, 86,234,242,162,241,172, 42,176,147,209,156, 27, 51,253,208,
+ 48, 4,182,220,125,223, 50, 75,247,203, 69,155, 49,187, 33, 90,
+ 65,159,225,217, 74, 77,158,218,160,104, 44,195, 39, 95,128, 54,
+ 62,238,251,149, 26,254,206,168, 52,169, 19,240,166, 63,216, 12,
+ 120, 36,175, 35, 82,193,103, 23,245,102,144,231,232, 7,184, 96,
+ 72,230, 30, 83,243,146,164,114,140, 8, 21,110,134, 0,132,250,
+ 244,127,138, 66, 25,246,219,205, 20,141, 80, 18,186, 60, 6, 78,
+ 236,179, 53, 17,161,136,142, 43,148,153,183,113,116,211,228,191,
+ 58,222,150, 14,188, 10,237,119,252, 55,107, 3,121,137, 98,198,
+ 215,192,210,124,106,139, 34,163, 91, 5, 93, 2,117,213, 97,227,
+ 24,143, 85, 81,173, 31, 11, 94,133,229,194, 87, 99,202, 61,108,
+ 180,197,204,112,178,145, 89, 13, 71, 32,200, 79, 88,224, 1,226,
+ 22, 56,196,111, 59, 15,101, 70,190,126, 45,123,130,249, 64,181,
+ 29,115,248,235, 38,199,135,151, 37, 84,177, 40,170,152,157,165,
+ 100,109,122,212, 16,129, 68,239, 73,214,174, 46,221,118, 92, 47,
+ 167, 28,201, 9,105,154,131,207, 41, 57,185,233, 76,255, 67,171
+ };
+
+/* The table PS given below is a permutation of 0...255 constructed */
+/* from the digits of pi. It is a ``random'' nonlinear byte */
+/* substitution operation. */
+static unsigned char PS[256] = {
+ 41, 46, 67,201,162,216,124, 1, 61, 54, 84,161,236,240, 6, 19,
+ 98,167, 5,243,192,199,115,140,152,147, 43,217,188, 76,130,202,
+ 30,155, 87, 60,253,212,224, 22,103, 66,111, 24,138, 23,229, 18,
+ 190, 78,196,214,218,158,222, 73,160,251,245,142,187, 47,238,122,
+ 169,104,121,145, 21,178, 7, 63,148,194, 16,137, 11, 34, 95, 33,
+ 128,127, 93,154, 90,144, 50, 39, 53, 62,204,231,191,247,151, 3,
+ 255, 25, 48,179, 72,165,181,209,215, 94,146, 42,172, 86,170,198,
+ 79,184, 56,210,150,164,125,182,118,252,107,226,156,116, 4,241,
+ 69,157,112, 89,100,113,135, 32,134, 91,207,101,230, 45,168, 2,
+ 27, 96, 37,173,174,176,185,246, 28, 70, 97,105, 52, 64,126, 15,
+ 85, 71,163, 35,221, 81,175, 58,195, 92,249,206,186,197,234, 38,
+ 44, 83, 13,110,133, 40,132, 9,211,223,205,244, 65,129, 77, 82,
+ 106,220, 55,200,108,193,171,250, 36,225,123, 8, 12,189,177, 74,
+ 120,136,149,139,227, 99,232,109,233,203,213,254, 59, 0, 29, 57,
+ 242,239,183, 14,102, 88,208,228,166,119,114,248,235,117, 75, 10,
+ 49, 68, 80,180,143,237, 31, 26,219,153,141, 51,159, 17,131, 20,
+};
+
+\f
+/*
+ * R S A _ m a c
+ *
+ * Compute a message authentication code (MAC) over the specified
+ * buffer. This uses the RSADSI MAC algorithm.
+ *
+ * Inputs:
+ * inbuf - Pointer to the input buffer
+ * isize - Size of the input buffer
+ * macsize - Number of bytes desired in MAC
+ *
+ * Outputs:
+ * mac - Pointer to the resultant message authentication code buffer
+ *
+ * Return Value:
+ */
+void RSA_MAC(inbuf, isize, mac, macsize)
+unsigned char * inbuf, * mac ;
+int isize, macsize ;
+{
+ int i;
+ unsigned char temp;
+ memset(mac, 0, macsize); /* initialize the mac buffer */
+ macsize--; /* change to index */
+ /*
+ * Run over the input buffer merging each byte into the MAC.
+ */
+ for (i = 0; i < isize; i++)
+ {
+ temp = _pisubst[mac[0] ^ mac[1]];
+ /*
+ * Shift down the MAC one place and merge the new value into
+ * the last place.
+ */
+#ifdef VAX
+ memcpy(&mac[0],&mac[1], macsize);
+#else
+ memmove(&mac[0],&mac[1], macsize);
+#endif
+ mac[macsize] = temp ^ *inbuf++;
+ }
+}
+
+
+\f
+/*
+ * R S A _ M D
+ *
+ * Compute a message digest over the specified buffer using the
+ * RSA, Inc., message digest "MD" algorithm.
+ *
+ * Inputs:
+ * inbuf - Pointer to the input buffer
+ * isize - Size of the input buffer
+ *
+ * Outputs:
+ * digest - Pointer to the resultant digest buffer. Assumed to be
+ * 16 bytes.
+ *
+ */
+
+void RSA_MD (inbuf, isize, digest )
+char * inbuf, * digest ;
+int isize;
+{
+ register int i,
+ j,
+ k,
+ l;
+ static int padlen;
+ static unsigned char lastmac ,
+ x,
+ t,
+ buf[48],
+ mac[16];
+
+
+ memset(digest, 0, MD_BLOCK_SIZE); /* initialize return digest */
+ memset(buf, 0, sizeof(buf)); /* initialize temporaries */
+ memset(mac, 0, sizeof(mac));
+
+ for (i = 0, k = 0 , lastmac = 0 ; i < isize ; i++)
+ {
+ /*
+ * Merge the new character into the buffer and
+ * update the MAC.
+ */
+ buf[k + 16] = *inbuf;
+ buf[k + 32] = *inbuf ^ buf[k];
+ lastmac = (mac[k] ^= PS[(*inbuf++ ^ lastmac) & 0xFF]);
+
+ k = (k + 1) & 15;
+ /*
+ * Encrypt at the end of each block.
+ */
+ if (k==0){
+ t = 0;
+ for (l = 0; l < 18; l++)
+ for (j = 48; j > 0; j--)
+ t = (buf[48 - j] ^= PS[(t + j) & 0xFF]);
+ }
+ }
+
+ padlen = MD_BLOCK_SIZE - k;
+ x = (unsigned char) padlen ;
+
+ for (i = 0; i < padlen ; i++)
+ {
+ buf[k + 16] = x ;
+ buf[k + 32] = x ^ buf[k];
+ lastmac = (mac[k] ^= PS[(x ^ lastmac) & 0xFF]);
+
+ k = (k + 1) & 15;
+ /*
+ * Encrypt
+ */
+ if (k==0){
+ t = 0;
+ for (l = 0; l < 18; l++)
+ for (j = 48; j > 0; j--)
+ t = (buf[48 - j] ^= PS[(t + j) & 0xFF]);
+ }
+ }
+
+ /*
+ * Now merge the MAC computed above into the message digest value.
+ */
+ for (i = 0; i < 16; i++)
+ {
+ buf[i + 16] = mac[i];
+ buf[i + 32] = mac[i] ^ buf[i];
+ }
+ t = 0;
+ for (i = 0; i < 18; i++)
+ {
+ for (j = 48; j > 0; j--)
+ {
+ t = (buf[48 - j] ^= PS[(t + j) & 0xFF]);
+ }
+ }
+
+ /*
+ * Now copy the final digest value to the output.
+ */
+ memcpy(digest, buf, MD_BLOCK_SIZE);
+
+}
+
+#endif /* INCLUDE_RSA_BSAFE_STUFF */
+
+
+
+
+/* RSA-MD2 Message Digest algorithm in C */
+/* by Ronald L. Rivest 10/1/88 */
+
+/**********************************************************************/
+/* Message digest routines: */
+/* To form the message digest for a message M */
+/* (1) Initialize a context buffer md using MDINIT */
+/* (2) Call MDUPDATE on md and each character of M in turn */
+/* (3) Call MDFINAL on md */
+/* The message digest is now in md->D[0...15] */
+/**********************************************************************/
+/* An MDCTX structure is a context buffer for a message digest */
+/* computation; it holds the current "state" of a message digest */
+/* computation */
+struct MDCTX
+{
+ unsigned char D[48]; /* buffer for forming digest in */
+ /* At the end, D[0...15] form the message */
+ /* digest */
+ unsigned char C[16]; /* checksum register */
+ unsigned char i; /* number of bytes handled, modulo 16 */
+ unsigned char L; /* last checksum char saved */
+};
+/* The table S given below is a permutation of 0...255 constructed */
+/* from the digits of pi. It is a ``random'' nonlinear byte */
+/* substitution operation. */
+int S[256] = {
+ 41, 46, 67,201,162,216,124, 1, 61, 54, 84,161,236,240, 6, 19,
+ 98,167, 5,243,192,199,115,140,152,147, 43,217,188, 76,130,202,
+ 30,155, 87, 60,253,212,224, 22,103, 66,111, 24,138, 23,229, 18,
+ 190, 78,196,214,218,158,222, 73,160,251,245,142,187, 47,238,122,
+ 169,104,121,145, 21,178, 7, 63,148,194, 16,137, 11, 34, 95, 33,
+ 128,127, 93,154, 90,144, 50, 39, 53, 62,204,231,191,247,151, 3,
+ 255, 25, 48,179, 72,165,181,209,215, 94,146, 42,172, 86,170,198,
+ 79,184, 56,210,150,164,125,182,118,252,107,226,156,116, 4,241,
+ 69,157,112, 89,100,113,135, 32,134, 91,207,101,230, 45,168, 2,
+ 27, 96, 37,173,174,176,185,246, 28, 70, 97,105, 52, 64,126, 15,
+ 85, 71,163, 35,221, 81,175, 58,195, 92,249,206,186,197,234, 38,
+ 44, 83, 13,110,133, 40,132, 9,211,223,205,244, 65,129, 77, 82,
+ 106,220, 55,200,108,193,171,250, 36,225,123, 8, 12,189,177, 74,
+ 120,136,149,139,227, 99,232,109,233,203,213,254, 59, 0, 29, 57,
+ 242,239,183, 14,102, 88,208,228,166,119,114,248,235,117, 75, 10,
+ 49, 68, 80,180,143,237, 31, 26,219,153,141, 51,159, 17,131, 20,
+};
+/*The routine MDINIT initializes the message digest context buffer md.*/
+/* All fields are set to zero. */
+void MDINIT(md)
+ struct MDCTX *md;
+ { int i;
+ for (i=0;i<16;i++) md->D[i] = md->C[i] = 0;
+ md->i = 0;
+ md->L = 0;
+ }
+/* The routine MDUPDATE updates the message digest context buffer to */
+/* account for the presence of the character c in the message whose */
+/* digest is being computed. This routine will be called for each */
+/* message byte in turn. */
+void MDUPDATE(md,c)
+ struct MDCTX *md;
+ unsigned char c;
+ { register unsigned char i,j,t,*p;
+ /**** Put i in a local register for efficiency ****/
+ i = md->i;
+ /**** Add new character to buffer ****/
+ md->D[16+i] = c;
+ md->D[32+i] = c ^ md->D[i];
+ /**** Update checksum register C and value L ****/
+ md->L = (md->C[i] ^= S[0xFF & (c ^ md->L)]);
+ /**** Increment md->i by one modulo 16 ****/
+ i = md->i = (i + 1) & 15;
+ /**** Transform D if i=0 ****/
+ if (i == 0)
+ { t = 0;
+ for (j=0;j<18;j++)
+ {/*The following is a more efficient version of the loop:*/
+ /* for (i=0;i<48;i++) t = md->D[i] = md->D[i] ^ S[t]; */
+ p = md->D;
+ for (i=0;i<8;i++)
+ { t = (*p++ ^= S[t]);
+ t = (*p++ ^= S[t]);
+ t = (*p++ ^= S[t]);
+ t = (*p++ ^= S[t]);
+ t = (*p++ ^= S[t]);
+ t = (*p++ ^= S[t]);
+ }
+ /* End of more efficient loop implementation */
+ t = t + j;
+ }
+ }
+ }
+/* The routine MDFINAL terminates the message digest computation and */
+/* ends with the desired message digest being in md->D[0...15]. */
+void MDFINAL(md)
+ struct MDCTX *md;
+ { int i,padlen;
+ /* pad out to multiple of 16 */
+ padlen = 16 - (md->i);
+ for (i=0;i<padlen;i++) MDUPDATE(md,(unsigned char)padlen);
+ /* extend with checksum */
+ /* Note that although md->C is modified by MDUPDATE, character */
+ /* md->C[i] is modified after it has been passed to MDUPDATE, so */
+ /* the net effect is the same as if md->C were not being modified.*/
+ for (i=0;i<16;i++) MDUPDATE(md,md->C[i]);
+ }
+
+/**********************************************************************/
+/* End of message digest implementation */
+/**********************************************************************/
+
+void RSA_MD2 (inbuf, isize, digest )
+char * inbuf, * digest ;
+int isize;
+{
+ struct MDCTX temp ;
+ int i;
+
+ MDINIT(&temp);
+ for(i=0;i<isize;i++) MDUPDATE(&temp,*inbuf++);
+ MDFINAL(&temp);
+ memcpy(digest,temp.D,16);
+}
--- /dev/null
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+#include "hashes.h"
+#include <stdio.h>
+
+int MIN_PASSWORD_LENGTH = 6 ;
+
+
+#define TEMP_BUFSIZ 256
+
+static unsigned char scramble_key [8] = { 0x01, 0x23, 0x45, 0x67,
+ 0x89, 0xab, 0xcd, 0xef };
+
+char *getpassword();
+
+\f
+/*
+ * Password hashing routine number 1. This is stored with the encrypted
+ * private key in the LEAF database. Result is an 8 byte quantity.
+ */
+
+int H1(username, pw, hash)
+char *username, *pw, *hash ;
+{
+ char temp[TEMP_BUFSIZ];
+ char md2_hash [16];
+
+ temp[0] = '\0';
+
+ if (2 + (username?strlen(username):0) + strlen(pw) > sizeof(temp)) return(0);
+
+ if (username) strcat(temp,username);
+ strcat(temp,pw);
+
+ RSA_MD2 (temp, strlen(temp), md2_hash);
+ memcpy(hash, md2_hash, 8);
+
+ memset(temp,0,sizeof(temp));
+ memset(md2_hash,0,sizeof(md2_hash));
+
+ return(1);
+}
+
+
+\f
+/*
+ * Password hashing routine number 2. This is the key used to encrypt
+ * the private key.
+ */
+
+int H2(username, pw, hash)
+char *username, *pw, *hash ;
+{
+ char temp[TEMP_BUFSIZ];
+
+ if (2 + (username?strlen(username):0) + strlen(pw) > sizeof(temp)) return(0);
+
+ temp[0] = '\0';
+ if (username) strcat(temp,username);
+ strcat(temp,pw);
+
+ DES_X9_MAC (scramble_key, temp, strlen(temp), hash);
+
+ memset(temp,0,sizeof(temp));
+
+ return(1);
+}
+
+\f
+/*
+ * Read password. Returns a DES key.
+ */
+
+int DES_read_password(k,prompt,verify)
+char *prompt, *k;
+int verify; /* non-zero means prompt twice for password */
+{
+ char *pw = getpassword(prompt);
+ char *env = NULL;
+ int ret = 0;
+
+ if ((verify) && (strlen(pw) < MIN_PASSWORD_LENGTH)) {
+ printf("Length error, (must be at least %d char) please re-enter: ", MIN_PASSWORD_LENGTH);
+ fflush(stdout);
+ pw = getpassword("");
+ if (strlen(pw) < MIN_PASSWORD_LENGTH) {
+ printf("Password length error. \n");
+ goto cleanup;
+ }
+ }
+
+ if (verify) {
+ char pwcpy[80];
+ strcpy(pwcpy,pw);
+ printf("Verifying, please re-enter: ");
+ fflush(stdout);
+ pw = getpassword("");
+ if (verify = strcmp(pwcpy,pw)) {
+ printf("\nVerification Error\n");
+ memset(pwcpy,0,strlen(pwcpy));
+ goto cleanup;
+ }
+ memset(pwcpy,0,strlen(pwcpy));
+ }
+
+done:
+ ret = H2(0,pw,k);
+
+cleanup:
+ memset(pw,0,strlen(pw));
+ return(ret);
+}
+
+
+int DES_read_password_hash(H2hash,H1hash,username,prompt,verify)
+char *prompt, *H2hash, *username, *H1hash;
+int verify; /* non-zero means prompt twice for password */
+{
+
+ char *pw = getpassword(prompt);
+ char *env = NULL;
+ int ret = 0;
+
+ if ((verify) && (strlen(pw) < MIN_PASSWORD_LENGTH)) {
+ printf("Length error, (must be at least %d char) please re-enter: ", MIN_PASSWORD_LENGTH);
+ fflush(stdout);
+ pw = getpassword("");
+ if (strlen(pw) < MIN_PASSWORD_LENGTH) {
+ printf("Password length error. \n");
+ goto cleanup;
+ }
+ }
+
+ if (verify) {
+ char pwcpy[80];
+ strcpy(pwcpy,pw);
+ printf("Verifying, please re-enter: ");
+ fflush(stdout);
+ pw = getpassword("");
+ if (verify = strcmp(pwcpy,pw)) {
+ printf("\nVerification Error\n");
+ memset(pwcpy,0,strlen(pwcpy));
+ goto cleanup;
+ }
+ memset(pwcpy,0,strlen(pwcpy));
+ }
+
+done:
+ H1(username,pw,H1hash);
+ H2(0,pw,H2hash);
+ ret = 1;
+
+cleanup:
+ memset(pw,0,strlen(pw));
+ return(ret);
+}
+
--- /dev/null
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include "BigNum.h"
+#include "BigRSA.h"
+#include "random.h"
+#include "hashes.h"
+#include "read_password.h"
+
+#define MAX_NAME 80
+#define MAX_UID 80
+#define MAX_KEY 2048
+#define MAX_HASH 8
+
+#ifdef DEBUG
+#undef DEBUG
+#endif
+
+int read_privkey_messages =0;
+RSAKeyStorage RSAKeys ;
+
+int read_privkey_verbose(filename,name,uid,uid_len,hashkey,key)
+char *filename, *name, *hashkey;
+unsigned char *uid;
+int *uid_len;
+RSAKeyStorage *key;
+{
+int save = read_privkey_messages ,x;
+ read_privkey_messages = 1;
+ x=read_privkey (filename,name,uid,uid_len,hashkey,key);
+ read_privkey_messages = save;
+ return(x);
+}
+
+int read_privkey(filename,name,uid,uid_len,hashkey,key)
+char *filename, *name, *hashkey;
+unsigned char *uid;
+int *uid_len;
+RSAKeyStorage *key;
+{
+ static unsigned char buffer [MAX_KEY];
+ DESblock pwkey ;
+ char *ptr;
+ unsigned char *uptr;
+ int i,j,c;
+ FILE *fp;
+ char tempname[80], prompt[80];
+
+ strcpy(tempname,filename);
+ strcat(tempname,"_privkey");
+
+ if((fp=fopen(tempname,"r"))==NULL) {
+ if (read_privkey_messages)
+ printf("\n%s: Can't open file %s.\n", __FILE__,tempname);
+ return(0);
+ }
+
+ ptr=name;
+ for(i=0,j=0;i<MAX_NAME;i++) {
+ if((c=getc(fp))==EOF) {
+ if (read_privkey_messages)
+ printf("\n%s: Unexpected end of file %s.\n",__FILE__,tempname);
+ return(0);
+ }
+ switch (*ptr++ = (char) c){
+ case '{': j++;
+ break;
+ case '}': j--;
+ if(j==0) goto next;
+ break;
+ case '\n': if(j==0) {ptr--; goto next;}
+ break;
+ }
+ }
+ next:
+ if(i>=MAX_NAME-1) {
+ if (read_privkey_messages)
+ printf("\n%s: Issuer name too long.\n", __FILE__);
+ return(0);
+ }
+ *ptr='\0';
+
+#ifdef DEBUG
+printf("\n%s: issuer name= %s",__FILE__,name);
+#endif
+
+ uptr=uid;
+ for(i=0;i<MAX_UID;i++)
+ if(fscanf(fp,"%2x",&j)==1) *uptr++ =j; else break;
+ if(i==MAX_UID)return(0);
+
+ *uid_len = i;
+
+#ifdef DEBUG
+printf("\n%s: uid is ",__FILE__);
+dumphex(uid,i);
+#endif
+
+ while(getc(fp)!=';');
+ for(i=0;i<MAX_HASH;i++)
+ if(fscanf(fp,"%2x",&j)==1) hashkey[i]=j ;
+ else break;
+#ifdef DEBUG
+printf("\n%s: Size of hash: %d\n", __FILE__,i);
+dumphex(hashkey,i);
+#endif
+
+ /* next non-white must be a ';' */
+ do {j=getc(fp);}while(isspace(j));
+ if(j != ';'){
+ if(read_privkey_messages) printf("\n%s: Hash Overflow.\n",__FILE__);
+ return(0);
+ }
+
+ for(i=0;i<MAX_KEY;i++)
+ if(fscanf(fp,"%2x",&j)==1) buffer[i]=j ;
+ else break;
+ if(i==MAX_KEY) return(0);
+#ifdef DEBUG
+printf("\n%s: Size of private key read: %d\n", __FILE__,i);
+dumphex(buffer,i);
+#endif
+ sprintf(prompt,"\nEnter %s's password: ", filename);
+ if (DES_read_password(&pwkey, prompt, 0) == 0) {
+ if (read_privkey_messages) printf("\n%s, Error entering password.\n",__FILE__);
+ return(0);
+ }
+
+ memset(key,0,sizeof(*key));
+ if (recover_private(&pwkey,buffer,i,key)==0) {
+ if (read_privkey_messages) printf("\nError recovering key.\n");
+ return(0);
+ }
+
+#ifdef DEBUG
+printf("\n%s: Recovered Key: \n",__FILE__);
+PrintTestKey(key);
+#endif
+
+return(1);
+}
+
+
--- /dev/null
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+#include <stdio.h>
+#include "BigNum.h"
+#include "BigRSA.h"
+
+#define MAX_NAME 80
+#define MAX_UID 80
+#define MAX_KEY 2048
+
+#ifdef DEBUG
+#undef DEBUG
+#endif
+
+int read_pubkey_messages = 0;
+
+int read_pubkey_verbose (user,name,uid,uid_len,key)
+RSAKeyStorage *key;
+char *name;
+unsigned char *uid;
+int *uid_len;
+{
+int save = read_pubkey_messages, x;
+ read_pubkey_messages = 1;
+ x = read_pubkey (user,name,uid,uid_len,key);
+ read_pubkey_messages = save;
+ return(x);
+}
+
+int read_pubkey (user,name,uid,uid_len,key)
+RSAKeyStorage *key;
+char *user, *name;
+unsigned char *uid;
+int *uid_len;
+{
+ char tempname[80];
+ static unsigned char buffer [MAX_KEY];
+ char *ptr = name;
+ unsigned char *uptr = uid;
+ int i,j,c;
+ FILE *fp;
+
+ strcpy(tempname,user);
+ strcat(tempname,"_pubkey");
+ if((fp = fopen(tempname,"r")) == NULL) {
+ if (read_pubkey_messages)
+ printf("\n%s: can't open file %s.\n", __FILE__, tempname);
+ return(0);
+ }
+
+ ptr=name;
+ for(i=0,j=0;i<MAX_NAME;i++) {
+ if((c=getc(fp))==EOF) {
+ if (read_pubkey_messages)
+ printf("\nUnexpected end of file %s.\n",tempname);
+ return(0);
+ }
+ switch (*ptr++ = (char)c){
+ case '{': j++;break;
+ case '}': j--; if (j==0) goto next; break;
+ case '\n': if(j==0){ptr--;goto next;} break;
+ }
+ }
+ next:
+ if(i>=MAX_NAME-1) {
+ if (read_pubkey_messages)
+ printf("\n%sIssuer name too long.\n", __FILE__);
+ return(0);
+ }
+ *ptr='\0';
+
+#ifdef DEBUG
+printf("\n%s: name is %s",__FILE__,name);
+#endif
+
+ uptr=uid;
+ for(i=0;i<MAX_UID;i++)
+ if(fscanf(fp,"%2x",&j)==1) *uptr++ =j; else break;
+ if(i==MAX_UID)return(0);
+
+ *uid_len = i;
+
+#ifdef DEBUG
+printf("\n%s: uid is ", __FILE__);
+dumphex(uid,i);
+#endif
+
+ while(getc(fp)!=';');
+ for(i=0;i<MAX_KEY;i++)
+ if(fscanf(fp,"%2x",&j)==1) buffer[i]=j ;
+ else break;
+ if(i==MAX_KEY) {
+ if (read_pubkey_messages)
+ printf("\n%s: Length error reading public key buffer.\n",__FILE__);
+ return(0);
+ }
+#ifdef DEBUG
+printf("\n%s: Size of public key read is %d\n", __FILE__,i);
+dumphex(buffer,i);
+#endif
+
+ if(i=DecodePublic(buffer,key)) {
+#ifdef DEBUG
+printf("\n%s: Recovered Key is\n",__FILE__);
+PrintTestKey(key);
+#endif
+ return(1);
+ }
+ else {
+ if (read_pubkey_messages) printf("\n%s: Key decode failed.\n",__FILE__);
+ return(0);
+ }
+}
+
+
--- /dev/null
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include "BigNum.h"
+#include "BigRSA.h"
+#include "random.h"
+#include "hashes.h"
+#include "read_password.h"
+#include "bigkeygen.h"
+#include "bigrsacode.h"
+
+#define MAX_NAME 80
+#define MAX_UID 80
+#define MAX_KEY 2048
+#define MAX_HASH 16
+
+#ifdef DEBUG
+#undef DEBUG
+#endif
+
+static RSAKeyStorage keys ;
+static RSAKeyStorage public_key ;
+static RSAKeyStorage private_key ;
+
+main(argc,argv)
+int argc;
+char **argv;
+{
+ unsigned char *encodedP ;
+ char usernameBuf [50], uidBuf [50], x500NameBuf[50], hashkey[50];
+ int uid_len;
+ FILE *publ, *priv;
+
+ if (argc < 2)
+ {
+badargs:
+ printf("usage: %s name \n", argv[0]);
+ exit(1);
+ }
+
+ strcpy(usernameBuf, argv[1]);
+
+ memset(&keys,0,sizeof(keys));
+
+ if (read_privkey (usernameBuf, x500NameBuf, uidBuf, &uid_len, hashkey, &private_key)) {
+ printf("\nPrivate key read.");
+ PrintTestKey(&private_key);
+ }
+ else {
+ printf("\nPrivate key read failed.\n");
+ exit(0);
+ }
+
+ if (read_pubkey (usernameBuf, x500NameBuf, uidBuf, &uid_len, &public_key)){
+ printf("\nPublic key read.");
+ PrintTestKey(&public_key);
+ }
+
+ if ((encodedP=EncodePrivateP(&private_key))==0) {
+ printf("\nEncode private key failed.\n");
+ exit(0);
+ }
+
+ printf("\nEncoded private key (prime P only):\n");
+ dumphex(encodedP,DecodeTotalLength(encodedP));
+
+ printf("\nDecoding...\n");
+
+ if ((DecodePrivate(encodedP, &public_key))==0) {
+ printf("\nDecode of private key failed.\n");
+ exit(0);
+ }
+ else {
+ printf("\nRecovered Private Key:\n");
+ PrintTestKey (&public_key);
+ }
+
+BnnClose();
+exit(0);
+}
+
+
+
+
+int read_privkey (filename,name,uid,uid_len,hashkey,key)
+char *filename, *name, *hashkey;
+unsigned char *uid;
+int *uid_len;
+RSAKeyStorage *key;
+{
+ static unsigned char buffer [MAX_KEY];
+ DESblock pwkey ;
+ char *ptr;
+ unsigned char *uptr;
+ int i,j,c;
+ FILE *fp;
+ char tempname[80];
+
+ strcpy(tempname,filename);
+ strcat(tempname,"_privkey");
+
+ if((fp=fopen(tempname,"r"))==NULL) {
+ printf("\nCan't open file %s.\n", tempname);
+ return(0);
+ }
+
+ ptr=name;
+ for(i=0,j=0;i<MAX_NAME;i++)
+ switch (*ptr++ =getc(fp)){
+ case '{': j++;break;
+ case '}': j--;if(j==0)goto next;break;
+ case EOF : {
+ printf("\nUnexpected end of file %s.\n",tempname);
+ return(0);
+ }
+ }
+ next:
+ if(i>=MAX_NAME-1) {
+ printf("\nIssuer name too long.\n");
+ return(0);
+ }
+ *ptr='\0';
+
+#ifdef DEBUG
+printf("\nissuer name= %s",name);
+#endif
+
+ uptr=uid;
+ for(i=0;i<MAX_UID;i++)
+ if(fscanf(fp,"%2x",&j)==1) *uptr++ =j; else break;
+ if(i==MAX_UID)return(0);
+
+ *uid_len = i;
+
+#ifdef DEBUG
+printf("\nuid=");
+dumphex(uid,i);
+#endif
+
+ while(getc(fp)!=';');
+ for(i=0;i<MAX_HASH;i++)
+ if(fscanf(fp,"%2x",&j)==1) hashkey[i]=j ;
+ else break;
+ if(i==MAX_HASH) return(0);
+#ifdef DEBUG
+printf("\nSize of hash: %d\n", i);
+dumphex(hashkey,i);
+#endif
+
+ while(getc(fp)!=';');
+ for(i=0;i<MAX_KEY;i++)
+ if(fscanf(fp,"%2x",&j)==1) buffer[i]=j ;
+ else break;
+ if(i==MAX_KEY) return(0);
+#ifdef DEBUG
+printf("\nSize of private key read: %d\n", i);
+dumphex(buffer,i);
+#endif
+
+ if (DES_read_password(&pwkey, "\nEnter Password: ", 0) == 0) {
+ printf("\nError entering password.\n");
+ return(0);
+ }
+
+ memset(key,0,sizeof(*key));
+ if (recover_private(&pwkey,buffer,i,key)==0) {
+ printf("\nError recovering key.\n");
+ return(0);
+ }
+
+#ifdef DEBUG
+printf("\nRecovered Key: \n");
+PrintTestKey(key);
+#endif
+
+
+return(1);
+}
+
+
--- /dev/null
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <time.h>
+
+#include "bigsignverify.h"
+
+#define MAX_NAME 80
+#define MAX_UID 80
+#define MAX_KEY 2048
+#define MAX_HASH 16
+
+#ifdef DEBUG
+#undef DEBUG
+#endif
+
+RSAKeyStorage keys ;
+RSAKeyStorage public_key ;
+RSAKeyStorage private_key ;
+unsigned char bigbuf [2*DigitLim*sizeof(BigNumDigit)];
+unsigned char testdata[]="Now is the time for all good men to come to the aid";
+
+main(argc,argv)
+int argc;
+char **argv;
+{
+ char usernameBuf [50], uidBuf [50], x500NameBuf[50], hashkey[50];
+ int uid_len;
+ FILE *publ, *priv;
+ DESblock newkey1, newkey2;
+ int bigbuflen;
+ time_t expires1, expires2;
+
+ if (argc < 2)
+ {
+badargs:
+ printf("usage: %s name \n", argv[0]);
+ exit(1);
+ }
+
+ strcpy(usernameBuf, argv[1]);
+
+ memset(&keys,0,sizeof(keys));
+
+ if (read_privkey (usernameBuf, x500NameBuf, uidBuf, &uid_len, hashkey, &private_key)) {
+ printf("\nPrivate key read.");
+ PrintTestKey(&private_key);
+ }
+ else {
+ printf("\nUnable to read private key for %s.\n", usernameBuf);
+ exit(0);
+ }
+
+ if (read_pubkey (usernameBuf, x500NameBuf, uidBuf, &uid_len, &public_key)){
+ printf("\nPublic key read.");
+ PrintTestKey(&public_key);
+ }
+ else {
+ printf("\nUnable to read public key for %s.\n", usernameBuf);
+ exit(0);
+ }
+
+ if(!RSASign(testdata, sizeof(testdata), &private_key, bigbuf, &bigbuflen)) {
+ printf("\nError signing test data.\n");
+ exit(0);
+ }
+
+ printf("\nSigned Data:\n");
+ dumphex(bigbuf, bigbuflen);
+
+ if(!RSAVerify(testdata, sizeof(testdata), &public_key, bigbuf, bigbuflen)) {
+ printf("\nError verifying signature.\n");
+ exit(0);
+ }
+ printf("\nSignature verifies.\n");
+
+ time(&expires1);
+ printf("\nCurrent time: %s", ctime(&expires1));
+ expires1 += (time_t) 60; /* one minute */
+
+ InitAuthenticationKey ( &private_key, &public_key, &newkey1, bigbuf,
+ &bigbuflen, expires1);
+
+ printf("\nNew generated key:\n");
+ dumphex(&newkey1, sizeof(DESblock));
+ printf("\nExpires %s", ctime(&expires1));
+ printf("\nEncrypted key (length %d):\n", bigbuflen);
+ dumphex(bigbuf, bigbuflen);
+
+ if (AcceptAuthenticationKey (&private_key, &newkey2, bigbuf, bigbuflen, &expires2)) {
+ printf("\nRecovered key:\n");
+ dumphex(&newkey1, sizeof(DESblock));
+ printf("\nExpires %s", ctime(&expires2));
+ }
+ else {
+ printf("\nRecovery of key failed.\n");
+ }
+
+exit(0);
+}
+
--- /dev/null
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "BigZ.h"
+#include "BigRSA.h"
+
+write_pubkey(keys,name,subject,uidBuf,uid_len)
+RSAKeyStorage *keys;
+int uid_len;
+char *uidBuf, *name, *subject;
+{
+ char publicBuf [80], *tempbuf;
+ FILE *publ;
+
+ strcpy(publicBuf,name);
+ strcat(publicBuf,"_pubkey");
+
+ if ((publ = fopen(publicBuf, "w")) == NULL)
+ {
+ printf("\n%s: could not open/create %s", __FILE__, publicBuf);
+ return(0);
+ }
+ fprintf(publ, "%s", subject);
+ fdumphex(uidBuf, uid_len, publ);
+ fprintf(publ," ;");
+ if ((tempbuf = (char *)EncodePublic(keys))==NULL) {
+ printf("\n%s: Allocation Error.\n", __FILE__);
+ return(0);
+ }
+ fdumphex(tempbuf, DecodeTotalLength(tempbuf), publ);
+ FreePublic(tempbuf);
+ fprintf(publ," ;");
+ fclose(publ);
+}
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ * $Header$
+ */
+/*
+ * GDSS The Generic Digital Signature Service
+ *
+ * gdss.c: Main interface routines
+ */
+
+#include <BigNum.h>
+#include <BigRSA.h>
+#include <krb.h>
+#include <gdss.h>
+#include <stdio.h>
+
+static RSAKeyStorage gdss_pubkey;
+static int gdss_have_key;
+static int pfetchkey();
+
+#ifdef notdef
+/* This function is obsolete */
+int GDSS_Sig_Info(Signature, aSigInfo)
+unsigned char *Signature;
+SigInfo *aSigInfo;
+{
+ int status;
+ static int pfetchkey();
+ unsigned char hash[16];
+ unsigned char *cp;
+
+ cp = aSigInfo->rawsig;
+ memset(aSigInfo, 0, sizeof(SigInfo));
+ aSigInfo->rawsig = cp;
+ aSigInfo->SigInfoVersion = 0;
+ do {
+ status = pfetchkey();
+ if (status) break;
+ status = gdss_rverify(Signature, hash, &(*aSigInfo).pname,
+ &(*aSigInfo).pinst, &(*aSigInfo).prealm,
+ &gdss_pubkey, &(*aSigInfo).timestamp,
+ aSigInfo->rawsig);
+ } while(0);
+ return (status);
+}
+#endif
+
+int GDSS_Verify(Data, DataLen, Signature, aSigInfo)
+unsigned char *Data;
+unsigned int DataLen;
+unsigned char *Signature;
+SigInfo *aSigInfo;
+{
+ unsigned char hash[16];
+ SigInfo bSigInfo, *iSigInfo;
+ int status;
+ unsigned char *cp;
+
+ if (aSigInfo == NULL) {
+ iSigInfo = &bSigInfo;
+ } else {
+ iSigInfo = aSigInfo;
+ }
+ status = pfetchkey();
+ if (status) return (status);
+
+ memset(&bSigInfo, 0, sizeof(bSigInfo));
+ cp = iSigInfo->rawsig;
+ memset(iSigInfo, 0, sizeof(bSigInfo));
+ iSigInfo->rawsig = cp;
+
+ RSA_MD2(Data, DataLen, hash);
+
+ status = gdss_rverify(Signature, hash, iSigInfo->pname,
+ iSigInfo->pinst, iSigInfo->prealm,
+ &gdss_pubkey, &iSigInfo->timestamp, iSigInfo->rawsig);
+
+ if (status) return (status);
+ return (GDSS_SUCCESS);
+}
+
+int GDSS_Sig_Size()
+{
+ int status;
+ int retval;
+ status = pfetchkey();
+ if (status) retval = 512; /* No provision for errors, so default value */
+ retval = sizeof(SigInfo) + (gdss_pubkey.nl)*4 + GDSS_PAD + 5;
+ return (retval);
+}
+
+static int pfetchkey()
+{
+ FILE *keyf;
+ unsigned char buffer[512];
+
+ if (gdss_have_key) return (0);
+ keyf = fopen("/etc/athena/gdss_public_key", "r");
+ if (keyf == NULL) {
+ keyf = fopen("/afs/net.mit.edu/system/config/gdss_public_key", "r");
+ if (keyf == NULL) return (GDSS_E_NOPUBKEY);
+ }
+ fread(buffer, 1, 512, keyf);
+ fclose(keyf);
+ DecodePublic(buffer, &gdss_pubkey);
+ gdss_have_key++;
+ return (GDSS_SUCCESS);
+}
+
+GDSS_Recompose(aSigInfo, signature)
+SigInfo *aSigInfo;
+unsigned char *signature;
+{
+ if (aSigInfo->rawsig == NULL) return (GDSS_E_BADINPUT);
+ return(gdss_recompose(aSigInfo, signature));
+}
+
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/time.h>
+#include <hesiod.h>
+
+static struct timeval timeout = { CLIENT_KRB_TIMEOUT, 0 };
+GDSS_Sign(Data, DataLen, Signature)
+unsigned char *Data;
+unsigned int DataLen;
+unsigned char *Signature;
+{
+ KTEXT_ST authent;
+ char lrealm[REALM_SZ];
+ char linst[INST_SZ];
+ char sinst[INST_SZ];
+ char *cp;
+ unsigned char hash[16];
+ unsigned char dhash[16]; /* Second level hash */
+ int s; /* Socket to do i/o on */
+ int status;
+ register int i;
+ unsigned int cksum;
+ unsigned char packet[2048];
+ int plen;
+ unsigned char ipacket[2048];
+ int iplen;
+ struct hostent *hp;
+ struct sockaddr_in sin, lsin;
+ fd_set readfds;
+ char **hostname;
+ int trys;
+ char *krb_get_phost();
+
+ memset(packet, 0, sizeof(packet)); /* Zeroize Memory */
+ memset(ipacket, 0, sizeof(ipacket));
+ krb_get_lrealm(lrealm, 1); /* Get our Kerberos realm */
+
+ RSA_MD2(Data, DataLen, hash);
+ RSA_MD2(hash, 16, dhash); /* For use of Kerberos */
+ memcpy(packet, hash, 16);
+
+ cksum = 0;
+ for (i = 0; i < 4; i++) /* High order 32 bits of dhash is the
+ Kerberos checksum, I wish we could do
+ better, but this is all kerberos allows
+ us */
+ cksum = (cksum << 8) + dhash[i];
+
+ /* Use Hesiod to find service location of GDSS Server Here */
+
+ hostname = hes_resolve("gdss", "sloc");
+ if (hostname == NULL) return(-1); /* No hesiod available */
+
+ cp = krb_get_phost(*hostname);
+ if (cp == NULL) return (-1); /* Should use a better error code */
+
+ strcpy(sinst, cp);
+
+ hp = gethostbyname(*hostname);
+
+ if(hp == NULL) return (-1); /* Could not find host, you lose */
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = hp->h_addrtype;
+ memcpy(&sin.sin_addr, hp->h_addr, sizeof(hp->h_addr));
+ sin.sin_port = htons(7201); /* Should get this from services or Hesiod */
+
+ strcpy(linst, "gdss"); /* Grrr... krb_mk_req bashes its input
+ So we better copy it first! */
+ status = krb_mk_req(&authent, linst, sinst, lrealm, cksum);
+ if (status != KSUCCESS) return (GDSS_E_KRBFAIL);
+ packet[0] = 0; /* Version 0 of protocol */
+ memcpy(&packet[1], hash, 16);
+ memcpy(&packet[17], &authent, sizeof(authent));
+ plen = sizeof(authent) + 16 + 1; /* KTEXT_ST plus the hash + version */
+
+ s = -1; /* "NULL" Value for socket */
+ do {
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s < 0) {
+ status = GDSS_E_NOSOCKET;
+ break;
+ }
+ if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+ status = GDSS_E_NOCONNECT;
+ break;
+ }
+ trys = 3;
+ status = GDSS_E_TIMEDOUT;
+ while (trys > 0) {
+ if(send(s, packet, plen, 0) < 0) break;
+ FD_ZERO(&readfds);
+ FD_SET(s, &readfds);
+ if ((select(s+1, &readfds, (fd_set *)0, (fd_set *)0, &timeout) < 1)
+ || !FD_ISSET(s, &readfds)) {
+ trys--;
+ continue;
+ }
+ if((iplen = recv(s, (char *)ipacket, 2048, 0)) < 0) break;
+ status = GDSS_SUCCESS;
+ break;
+ }
+ } while (0);
+ shutdown(s, 0);
+ close(s);
+ if (status != GDSS_SUCCESS) return (status);
+ memcpy(Signature, ipacket, iplen);
+ return (GDSS_SUCCESS);
+}
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ * $Header$
+ */
+/*
+ * GDSS The Generic Digital Signature Service
+ *
+ * rgdss.c: Raw signature signing and verification routines.
+ */
+
+#include <BigNum.h>
+#include <BigRSA.h>
+#include <krb.h>
+#include <gdss.h>
+#include <stdio.h>
+#include <time.h>
+
+int gdss_rsign(signature, hash, name, instance, realm, key)
+unsigned char *signature;
+unsigned char *hash;
+char *name;
+char *instance;
+char *realm;
+RSAKeyStorage *key;
+{
+ unsigned char *cp, *ip;
+ time_t the_time;
+ register int i;
+ register int status;
+ int loopcnt;
+ int siglen;
+
+ for (loopcnt = 0; loopcnt < 10; loopcnt++) {
+ cp = signature;
+ for (i = 0; i < 16; i++)
+ *cp++ = hash[i];
+ *cp++ = 0x44; /* Version Number */
+ ip = (unsigned char *) name;
+ while (*cp++ = *ip++);
+ ip = (unsigned char *) instance;
+ while (*cp++ = *ip++);
+ ip = (unsigned char *) realm;
+ while (*cp++ = *ip++);
+ time(&the_time);
+ *cp++ = ((the_time) >> 24) & 0xff;
+ *cp++ = ((the_time) >> 16) & 0xff;
+ *cp++ = ((the_time) >> 8) & 0xff;
+ *cp++ = the_time & 0xff;
+ if(!RSASign(signature, cp - signature, key, &signature[cp - signature],
+ &siglen)) return (-1);
+ status = gdss_rpadout(&signature[16], cp - signature + siglen - 16);
+ if ((status == GDSS_SUCCESS) || (status != GDSS_E_PADTOOMANY)) {
+ ip = &signature[16];
+ cp = signature;
+ while (*cp++ = *ip++); /* shuffle over hash */
+ return(GDSS_SUCCESS);
+ }
+ sleep(1); /* Allow time to change */
+ }
+ return (GDSS_E_PADTOOMANY);
+}
+
+/* gdss_rpadout: Remove null bytes from signature by replacing them with
+ the sequence GDSS_ESCAPE, GDSS_NULL. Keep track of how much bigger
+ the signature block is getting and abort if too many bytes (more than
+ GDSS_PAD) would be required.
+*/
+
+int gdss_rpadout(signature, siglen)
+unsigned char *signature;
+int siglen;
+{
+ register unsigned char *cp;
+ register unsigned char *bp;
+ unsigned char *buf;
+ register int i;
+ register int c;
+ buf = (unsigned char *)malloc(siglen + GDSS_PAD + 1); /* 1 for the null! */
+ if (buf == NULL) return (GDSS_E_ALLOC);
+ memset(buf, 0, siglen + GDSS_PAD + 1); /* Just to be safe */
+ bp = buf;
+ cp = signature;
+ c = 0;
+ for (i = 0; i < siglen; i++) {
+ if ((*cp != '\0') && (*cp != GDSS_ESCAPE)) {
+ *bp++ = *cp++;
+ continue;
+ }
+ if (c++ > GDSS_PAD) {
+ free(buf); /* Don't have to zeroize, nothing
+ confidential */
+ return (GDSS_E_PADTOOMANY);
+ }
+ *bp++ = GDSS_ESCAPE;
+ *bp++ = (*cp == '\0') ? GDSS_NULL : GDSS_ESCAPE;
+ cp++;
+ }
+ *bp++ = '\0'; /* Null Terminate */
+ memcpy(signature, buf, bp - buf);
+ free(buf);
+ return (GDSS_SUCCESS);
+}
+
+int gdss_rpadin(signature, outlen)
+unsigned char *signature;
+int *outlen;
+{
+ unsigned char *buf;
+ register unsigned char *cp;
+ register unsigned char *bp;
+ buf = (unsigned char *) malloc(strlen(signature));
+ if (buf == NULL) return (GDSS_E_ALLOC);
+ bp = buf;
+ cp = signature;
+ while (*cp) {
+ if (*cp != GDSS_ESCAPE) {
+ *bp++ = *cp++;
+ continue;
+ }
+ if (*(++cp) == GDSS_NULL) {
+ *bp++ = '\0';
+ } else *bp++ = GDSS_ESCAPE;
+ if(!*cp++) break;
+ }
+ *outlen = bp - buf;
+ memcpy(signature, buf, *outlen);
+ free (buf);
+ return (GDSS_SUCCESS);
+}
+
+int gdss_rverify(isignature, hash, name, instance,
+ realm, key, the_time, rawsig)
+unsigned char *isignature;
+unsigned char *hash;
+char *name;
+char *instance;
+char *realm;
+RSAKeyStorage *key;
+unsigned int *the_time;
+unsigned char *rawsig;
+{
+ unsigned char *cp, *ip;
+ register int i;
+ int status;
+ int siglen;
+ unsigned char *signature;
+
+ if (*isignature != 0x44) return (GDSS_E_BVERSION); /* Bad Version */
+
+ signature = (unsigned char *) malloc (strlen(isignature) + 17);
+ /* Length of input signature + null byte + 16 bytes of hash */
+ strcpy(&signature[16], isignature);
+
+ status = gdss_rpadin(&signature[16], &siglen);
+ if (status) return (status);
+
+ siglen += 16; /* Account for the hash */
+ cp = signature;
+ for (i = 0; i < 16; i++)
+ *cp++ = hash[i];
+ if (*cp++ != 0x44) return (GDSS_E_BVERSION); /* Bad Version */
+ ip = (unsigned char *) name;
+ while (*ip++ = *cp++);
+ ip = (unsigned char *) instance;
+ while (*ip++ = *cp++);
+ ip = (unsigned char *) realm;
+ while (*ip++ = *cp++);
+ *the_time = 0;
+ *the_time |= *cp++ << 24;
+ *the_time |= *cp++ << 16;
+ *the_time |= *cp++ << 8;
+ *the_time |= *cp++;
+ if(!RSAVerify(signature, cp - signature, key, &signature[cp - signature],
+ siglen - (cp - signature))) {
+ free (signature);
+ return (GDSS_E_BADSIG);
+ }
+ if (rawsig == NULL) {
+ free (signature);
+ return (GDSS_SUCCESS);
+ }
+ memcpy(rawsig, &signature[cp - signature], siglen - (cp - signature));
+ status = gdss_rpadout(rawsig, siglen - (cp - signature));
+ free (signature);
+ return (status);
+}
+
+gdss_recompose(aSigInfo, signature)
+SigInfo *aSigInfo;
+unsigned char *signature;
+{
+ register unsigned char *ip;
+ register unsigned char *cp;
+ unsigned char *isignature;
+ int siglen;
+ int status;
+
+ isignature = (unsigned char *) malloc(strlen(aSigInfo->rawsig) + 1);
+ if (isignature == NULL) return (GDSS_E_ALLOC);
+ strcpy(isignature, aSigInfo->rawsig);
+ status = gdss_rpadin(isignature, &siglen);
+ if (status) {
+ free(isignature);
+ return (status);
+ }
+
+ cp = signature;
+ *cp++ = 0x44; /* Version */
+ ip = (unsigned char *) aSigInfo->pname;
+ while (*cp++ = *ip++);
+ ip = (unsigned char *) aSigInfo->pinst;
+ while (*cp++ = *ip++);
+ ip = (unsigned char *) aSigInfo->prealm;
+ while (*cp++ = *ip++);
+ *cp++ = ((aSigInfo->timestamp) >> 24) & 0xff;
+ *cp++ = ((aSigInfo->timestamp) >> 16) & 0xff;
+ *cp++ = ((aSigInfo->timestamp) >> 8) & 0xff;
+ *cp++ = aSigInfo->timestamp & 0xff;
+ memcpy(cp, isignature, siglen);
+ free(isignature);
+ return(gdss_rpadout(signature, cp - signature + siglen));
+}