2 * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
5 * "Digital Equipment Corporation authorizes the reproduction,
6 * distribution and modification of this software subject to the following
9 * 1. Any partial or whole copy of this software, or any modification
10 * thereof, must include this copyright notice in its entirety.
12 * 2. This software is supplied "as is" with no warranty of any kind,
13 * expressed or implied, for any purpose, including any warranty of fitness
14 * or merchantibility. DIGITAL assumes no responsibility for the use or
15 * reliability of this software, nor promises to provide any form of
16 * support for it on any basis.
18 * 3. Distribution of this software is authorized only if no profit or
19 * remuneration of any kind is received in exchange for such distribution.
21 * 4. This software produces public key authentication certificates
22 * bearing an expiration date established by DIGITAL and RSA Data
23 * Security, Inc. It may cease to generate certificates after the expiration
24 * date. Any modification of this software that changes or defeats
25 * the expiration date or its effect is unauthorized.
27 * 5. Software that will renew or extend the expiration date of
28 * authentication certificates produced by this software may be obtained
29 * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
30 * 94065, (415)595-8782, or from DIGITAL"
35 #include <sys/types.h>
38 #include "bigsignverify.h"
44 /* in-line crypto routines here */
46 #include "RSAcrypto.h"
47 #include "DEScrypto.h"
49 #define CLOCK_SKEW 5*60
59 static BigNumDigit buffer1[2*DigitLim], buffer2[2*DigitLim];
62 * RSASign takes a key in local format and a counted character string and
63 * writes a signature in "BER INTEGER" encoded format into the supplied buffer.
64 * The length in bytes is also written.
68 int RSASign (toBeSigned, datalen, key, signature, siglen)
70 unsigned char *toBeSigned;
71 unsigned char *signature; /* output assumed large enough to hold modulus */
72 int datalen, *siglen; /* in bytes */
74 char *temp = (char *)buffer2;
75 int i, nl=key->nl, pl=key->pl, ql=key->ql;
76 BigNum signed_digest = buffer1, p = key->p, q = key->q;
78 if ((pl==0)||(ql==0)) return(0); /* not a private key */
79 RSA_MD2(toBeSigned, datalen, temp); /* hash to temp */
80 BnnSetToZero(signed_digest,nl);
81 for (i=0;i<16;i++) /* copy in right order */
82 signed_digest[i/sizeof(BigNumDigit)]|=
83 ((0x0ff&temp[15-i])<<((i%sizeof(BigNumDigit))*8));
84 signed_digest[4] |= 0x00000410;
85 rsadecrypt_1(signed_digest, signed_digest, key);
86 *siglen = NumEncodeValueOctets(signed_digest, nl);
87 if(EncodeBigIntegerValue(signature, signed_digest, nl)) return(TRUE);
92 * RSAVerify takes an encoded signature, allegedly signed data and key
93 * and yields a boolean (TRUE/FALSE).
96 int RSAVerify (allegedSigned, datalen, key, signature, siglen)
98 char *allegedSigned, *signature;
101 char *temp=(char *)buffer2;
102 BigNum md = buffer1, buffer = buffer2, n = key->n;
103 int i, bl, nl=key->nl;
105 if ((bl=(siglen+sizeof(BigNumDigit)-1)/sizeof(BigNumDigit)) > nl) {
107 printf("\nRSAVerify: signature has more BigNumDigits than the modulus\n");
113 RSA_MD2(allegedSigned, datalen, temp);
114 for (i=0;i<16;i++) /* copy in right order */
115 md[i/sizeof(BigNumDigit)]|=((0x0ff&temp[15-i])<<((i%sizeof(BigNumDigit))*8));
117 BnnSetToZero(buffer,nl);
118 DecodeBigInteger(signature, buffer, siglen);
119 if (BnnCompare(n, nl, buffer, bl)!=1) {
121 printf("\nRSAVerify: signature is larger BigNum value than modulus\n");
126 rsaencrypt_1(buffer, buffer, key);
128 printf("RSAVerify: computed md:\n");
130 printf("RSAVerify: recovered md:\n");
131 dumphex(buffer,nl*8);
133 buffer[4] &= 0xffff0000;
134 if (BnnCompare(md,nl,buffer,nl)==0) return (TRUE);
136 printf("\nRSAVerify: signature verification failed.\n");
144 * The initialization routine generates a DES key and encrypts it under
145 * the public key of the intended verifier principal.
147 * A word about byte ordering. The "least significant byte" of a BigNum
148 * is the byte that has the least significant bit in it. The "most
149 * significant byte" has the most significant bit in it.
153 #define RandomOffset (sizeof(DESblock)+2*sizeof(time_t))
154 #define BYTE_IN_BIGNUM(x) (SPHINX_ENDIAN?(sizeof(BigNumDigit)-(x%sizeof(BigNumDigit)-1)):x)
156 int InitAuthenticationKey (verifier, delegation, new_key, encrypted_key,
157 encrypted_key_len, when_expires)
158 RSAKeyStorage *verifier, *delegation;
160 unsigned char *encrypted_key;
161 int *encrypted_key_len;
165 BigNum vn=verifier->n, p = buffer1, temp = buffer1;
166 int i, leading_zero_bytes, vnl=verifier->nl, tl;
170 * This is all we need the delegation key for.
172 read_rng_state(&rng);
173 if(((rng.count)==0)&&delegation) initialize_rng_state(delegation->p,16);
176 * Fill temporary storage with a random number.
178 BnnSetToZero(temp,vnl+1);
179 tl = BnnNumDigits(vn,vnl);
180 random_BigNum(temp,tl);
183 * There must always be one more significant byte in the modulus than
184 * the one that has the "64" in the encrypted key.
187 printf("\nleading zero bits: %d, vn[tl-1]=%08x\n",
188 BnnNumLeadingZeroBitsInDigit(vn[tl-1]), vn[tl-1]);
190 leading_zero_bytes=BnnNumLeadingZeroBitsInDigit(BnnGetDigit(vn+tl-1))/8;
191 if (leading_zero_bytes == (sizeof(BigNumDigit)-1)) {
193 * There is only one significant byte in the most significant BigNumDigit,
194 * so zero out top digit and put "64" into the most significant byte of
195 * the next-to-top digit
198 temp[tl-2] &= ~(0x00ff << 8*leading_zero_bytes);
199 temp[tl-2] |= 64 << 8*leading_zero_bytes ;
203 * Zero out bytes with significant stuff in them, and put "64"
204 * in the next-most-significant byte.
206 for(i=0;i<=leading_zero_bytes+1;i++)
207 temp[tl-1] &= ~(0x00ff << (8*(sizeof(BigNumDigit)-1-i)));
208 temp[tl-1] |= 64<<((sizeof(BigNumDigit)-2-leading_zero_bytes)*8);
211 printf("\nleading_zero_bytes=%d\n",leading_zero_bytes);
212 printf("\ntl=%d, vnl=%d, temp[tl-1]=%08x, temp[tl-2]=%08x\n", tl, vnl, temp[tl-1], temp[tl-2]);
215 BnnSetToZero(temp, (RandomOffset+4)/sizeof(BigNumDigit));
217 * Generate 8 bytes of DES key, copy into buffer in right order
219 random_bytes(temp, sizeof(DESblock));
220 for (i=0;i<sizeof(DESblock);i++) new_key->bytes[sizeof(DESblock)-i-1] =
221 (temp[i/sizeof(BigNumDigit)]>>((i%sizeof(BigNumDigit)*8)));
224 * Assume sizeof(time_t) == sizeof(BigNumDigit).
225 * Everyone has to swap these bytes, I guess.
228 p = &temp[sizeof(DESblock)/sizeof(BigNumDigit)];
232 for(i=0;i<sizeof(time_t);i++) {
233 p[0] |= ((when_signed>>(i*8))&(BigNumDigit)0xff)<<((sizeof(time_t)-1-i)*8);
234 p[1] |= ((when_expires>>(i*8))&(BigNumDigit)0xff)<<((sizeof(time_t)-1-i)*8);
238 printf("\nBlock to encrypt: (low to high order bytes) \n");
239 dumphex(temp,tl*sizeof(BigNumDigit));
240 printf("\nModulus:\n");
241 dumphex(vn,vnl*sizeof(BigNumDigit));
243 rsaencrypt_1(temp,temp,verifier);
244 *encrypted_key_len = NumEncodeValueOctets(temp,tl);
245 if (EncodeBigIntegerValue(encrypted_key,temp,tl)) return(TRUE);
250 * The accept routine takes in encoded elements and yields the transferred
251 * DES key along with an expiration date.
254 int AcceptAuthenticationKey (verifier, new_key, encrypted_key,
255 encrypted_key_len, when_expires)
256 RSAKeyStorage *verifier;
258 unsigned char *encrypted_key;
259 int encrypted_key_len;
260 time_t *when_expires;
262 time_t now, when_signed, when_expires_temp ;
263 int i, tl, vnl=verifier->nl, leading_zero_bytes;
264 BigNum vn=verifier->n, p = buffer1, temp = buffer1;
267 BnnSetToZero(temp,vnl+1);
268 if ((tl=(encrypted_key_len+sizeof(BigNumDigit)-1)/sizeof(BigNumDigit)) > vnl) {
270 printf("\nAcceptAuthenticationKey: Signature has more BigNumDigits than modulus.\n");
272 syslog(LOG_INFO, "AAK : Signature has more BigNumDigits than modulus");
276 DecodeBigInteger(encrypted_key,temp,encrypted_key_len);
277 if (BnnCompare(vn,vnl,temp,tl) != 1) {
279 printf("\nAcceptAuthenticationKey: Signature is larger than modulus.\n");
281 syslog(LOG_INFO, "AAK : Signature is larger than modulus");
285 rsadecrypt_1(temp,temp,verifier);
287 printf("\nAcceptAuthenticationKey: Decrypted key:\n");
288 dumphex(temp,(vnl+1)*sizeof(BigNumDigit));
292 * Check for a "64" in the right place.
294 tl = BnnNumDigits(vn,vnl);
295 leading_zero_bytes=BnnNumLeadingZeroBitsInDigit(BnnGetDigit(vn+tl-1))/8;
296 if (leading_zero_bytes == sizeof(BigNumDigit)-1) {
297 if ((temp[tl-1] != 0) ||
298 (((temp[tl-2]>>(8*leading_zero_bytes))&0x0ff) != 64)) {
300 printf("\nTop digit not zero, or 64 byte test failed.\n");
302 syslog(LOG_INFO, "AAK : Top digit not zero, or 64 byte test failed");
306 else { for(i=0;i<leading_zero_bytes;i++)
307 if(((temp[tl-1]>>((sizeof(BigNumDigit)-leading_zero_bytes-1+i)*8))&0x0ff)
310 printf("\nTop byte zero test failed.\n");
312 syslog(LOG_INFO, "AAK : Top byte zero test failed");
315 if (((temp[tl-1]>>((sizeof(BigNumDigit)-2-leading_zero_bytes)*8))&0xff)
318 printf("\nTop byte 64 test failed.\n");
320 syslog(LOG_INFO, "AAK : Top byte 64 test failed");
325 ptr = (char *) &temp[RandomOffset/sizeof(BigNumDigit)];
326 for (i=0;i<4;i++) if (*ptr++ !=0) {
328 printf("\nAcceptAuthenticationKey: Zero mid-buffer error.\n");
330 syslog(LOG_INFO, "AAK : Zero mid-buffer error");
334 when_signed=when_expires_temp=0;
336 p = &temp[sizeof(DESblock)/sizeof(BigNumDigit)];
338 when_expires_temp = p[1];
340 for(i=0;i<sizeof(time_t);i++) {
341 when_signed |= ((p[0]>>(i*8))&(BigNumDigit)0x0ff)<<((sizeof(time_t)-1-i)*8);
342 when_expires_temp |= ((p[1]>>(i*8))&(BigNumDigit)0x0ff)<<((sizeof(time_t)-1-i)*8);
347 printf("\n Signed: %s", ctime(&when_signed));
348 printf("\n Expires: %s\n", ctime(&when_expires_temp));
351 if((when_signed > now + CLOCK_SKEW) || (when_expires_temp < now - CLOCK_SKEW)) {
353 printf("\nAcceptAuthenticationKey: Key Has Expired.\n");
355 syslog(LOG_INFO, "AAK : signed on (%d) %s", when_signed, ctime(&when_signed));
356 syslog(LOG_INFO, "AAK : expire on (%d) %s", when_expires_temp, ctime(&when_expires_temp));
357 syslog(LOG_INFO, "AAK : key has expired - now is %d", now);
360 *when_expires = when_expires_temp;
362 for (i=0;i<sizeof(DESblock);i++) new_key->bytes[sizeof(DESblock)-i-1] =
363 (temp[i/sizeof(BigNumDigit)]>>((i%sizeof(BigNumDigit)*8)));