]> andersk Git - moira.git/blob - util/gdss/lib/crypto/algorithm/bigsignverify.c
initial import of gdss from the Athena source tree
[moira.git] / util / gdss / lib / crypto / algorithm / bigsignverify.c
1 /*
2  * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
3  * ALL RIGHTS RESERVED
4  *
5  * "Digital Equipment Corporation authorizes the reproduction,
6  * distribution and modification of this software subject to the following
7  * restrictions:
8  * 
9  * 1.  Any partial or whole copy of this software, or any modification
10  * thereof, must include this copyright notice in its entirety.
11  *
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.
17  *
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.
20  * 
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.
26  * 
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"
31  *
32  */
33
34 #include <stdio.h>
35 #include <sys/types.h>
36 #include <time.h>
37 #include <syslog.h>
38 #include "bigsignverify.h"
39
40 #ifdef DEBUG
41 #undef DEBUG
42 #endif
43
44 /* in-line crypto routines here */
45
46 #include "RSAcrypto.h"
47 #include "DEScrypto.h"
48
49 #define CLOCK_SKEW  5*60
50
51 #ifdef mips
52 #undef BnnSetToZero
53 #endif
54
55 /*
56  * Global
57  */
58  
59 static BigNumDigit buffer1[2*DigitLim], buffer2[2*DigitLim];
60
61 /*
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.
65  *
66  */
67
68 int RSASign (toBeSigned, datalen, key, signature, siglen)
69 RSAKeyStorage *key;
70 unsigned char *toBeSigned;
71 unsigned char *signature;       /* output assumed large enough to hold modulus */
72 int datalen, *siglen;           /* in bytes */
73 {
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;
77
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);
88         else return(FALSE);
89 }
90
91 /*
92  * RSAVerify takes an encoded signature, allegedly signed data and key
93  * and yields a boolean (TRUE/FALSE).
94  */
95
96 int RSAVerify (allegedSigned, datalen, key, signature, siglen)
97 RSAKeyStorage *key;
98 char *allegedSigned, *signature;
99 int datalen, siglen;
100 {
101         char *temp=(char *)buffer2;
102         BigNum md = buffer1, buffer = buffer2, n = key->n;
103         int i, bl, nl=key->nl;
104
105         if ((bl=(siglen+sizeof(BigNumDigit)-1)/sizeof(BigNumDigit)) > nl) {
106 #ifdef DEBUG        
107 printf("\nRSAVerify: signature has more BigNumDigits than the modulus\n");
108 #endif
109                 return(FALSE);
110         }
111
112         BnnSetToZero(md,nl);
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));
116
117         BnnSetToZero(buffer,nl);
118         DecodeBigInteger(signature, buffer, siglen);
119         if (BnnCompare(n, nl, buffer, bl)!=1) {
120 #ifdef DEBUG
121 printf("\nRSAVerify: signature is larger BigNum value than modulus\n");
122 #endif
123                 return(FALSE);
124         }
125
126         rsaencrypt_1(buffer, buffer, key);
127 #ifdef DEBUG
128 printf("RSAVerify: computed md:\n");
129 dumphex(md,nl*8);
130 printf("RSAVerify: recovered md:\n");
131 dumphex(buffer,nl*8);
132 #endif
133         buffer[4] &= 0xffff0000;
134         if (BnnCompare(md,nl,buffer,nl)==0)  return (TRUE);
135 #ifdef DEBUG
136 printf("\nRSAVerify: signature verification failed.\n");
137 #endif
138         return(FALSE);
139
140 }
141
142 \f
143 /*
144  * The initialization routine generates a DES key and encrypts it under
145  * the public key of the intended verifier principal.
146  *
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.
150  *
151  */
152 #include "endian.h"
153 #define RandomOffset (sizeof(DESblock)+2*sizeof(time_t))
154 #define BYTE_IN_BIGNUM(x) (SPHINX_ENDIAN?(sizeof(BigNumDigit)-(x%sizeof(BigNumDigit)-1)):x)
155
156 int InitAuthenticationKey (verifier, delegation, new_key, encrypted_key, 
157                                 encrypted_key_len, when_expires)
158 RSAKeyStorage *verifier, *delegation;
159 DESblock *new_key;
160 unsigned char *encrypted_key;
161 int *encrypted_key_len;
162 time_t when_expires;
163 {
164         time_t when_signed;
165         BigNum vn=verifier->n, p = buffer1, temp = buffer1;
166         int i, leading_zero_bytes, vnl=verifier->nl, tl;
167         RNGState rng;
168         
169         /*
170          * This is all we need the delegation key for.
171          */
172         read_rng_state(&rng);
173         if(((rng.count)==0)&&delegation) initialize_rng_state(delegation->p,16);
174
175         /*
176          * Fill temporary storage with a random number.
177          */
178         BnnSetToZero(temp,vnl+1);
179         tl = BnnNumDigits(vn,vnl);
180         random_BigNum(temp,tl);
181
182         /* 
183          * There must always be one more significant byte in the modulus than 
184          * the one that has the "64" in the encrypted key.
185          */
186 #ifdef DEBUG
187 printf("\nleading zero bits: %d, vn[tl-1]=%08x\n",
188                 BnnNumLeadingZeroBitsInDigit(vn[tl-1]), vn[tl-1]);
189 #endif
190         leading_zero_bytes=BnnNumLeadingZeroBitsInDigit(BnnGetDigit(vn+tl-1))/8;
191         if (leading_zero_bytes == (sizeof(BigNumDigit)-1)) { 
192         /* 
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 
196          */
197                 temp[tl-1] = 0;
198                 temp[tl-2] &= ~(0x00ff << 8*leading_zero_bytes); 
199                 temp[tl-2] |= 64 << 8*leading_zero_bytes ;
200                 }
201         else { 
202         /* 
203          * Zero out bytes with significant stuff in them, and put "64"
204          * in the next-most-significant byte.
205          */
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);
209         }
210 #ifdef DEBUG
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]);
213 #endif
214
215         BnnSetToZero(temp, (RandomOffset+4)/sizeof(BigNumDigit));
216         /*
217          * Generate 8 bytes of DES key, copy into buffer in right order
218          */
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)));
222
223         /*
224          * Assume sizeof(time_t) == sizeof(BigNumDigit).
225          * Everyone has to swap these bytes, I guess.
226          */
227         time(&when_signed);
228         p = &temp[sizeof(DESblock)/sizeof(BigNumDigit)];
229         p[0]=when_signed;
230         p[1]=when_expires;
231 /*
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);
235              }
236 */
237 #ifdef DEBUG
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));
242 #endif
243         rsaencrypt_1(temp,temp,verifier);
244         *encrypted_key_len = NumEncodeValueOctets(temp,tl);
245         if (EncodeBigIntegerValue(encrypted_key,temp,tl)) return(TRUE);
246         else return(FALSE);
247 }
248
249 /*
250  * The accept routine takes in encoded elements and yields the transferred
251  * DES key along with an expiration date.
252  *
253  */
254 int AcceptAuthenticationKey (verifier, new_key, encrypted_key, 
255                                 encrypted_key_len, when_expires)
256 RSAKeyStorage *verifier;
257 DESblock *new_key;
258 unsigned char *encrypted_key;
259 int encrypted_key_len;
260 time_t *when_expires;
261 {
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;
265         char *ptr;
266
267         BnnSetToZero(temp,vnl+1);
268         if ((tl=(encrypted_key_len+sizeof(BigNumDigit)-1)/sizeof(BigNumDigit)) > vnl) {
269 #ifdef DEBUG
270 printf("\nAcceptAuthenticationKey: Signature has more BigNumDigits than modulus.\n");
271 #endif
272 syslog(LOG_INFO, "AAK : Signature has more BigNumDigits than modulus");
273                 goto error;
274         }
275         
276         DecodeBigInteger(encrypted_key,temp,encrypted_key_len);
277         if (BnnCompare(vn,vnl,temp,tl) != 1) {
278 #ifdef DEBUG
279 printf("\nAcceptAuthenticationKey: Signature is larger than modulus.\n");
280 #endif
281 syslog(LOG_INFO, "AAK : Signature is larger than modulus");
282                 goto error;
283         }
284        
285         rsadecrypt_1(temp,temp,verifier);
286 #ifdef DEBUG
287 printf("\nAcceptAuthenticationKey: Decrypted key:\n");
288 dumphex(temp,(vnl+1)*sizeof(BigNumDigit));
289 fflush(stdout);
290 #endif
291         /* 
292          * Check for a "64" in the right place.
293          */
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)) {
299 #ifdef DEBUG
300 printf("\nTop digit not zero, or 64 byte test failed.\n");
301 #endif
302 syslog(LOG_INFO, "AAK : Top digit not zero, or 64 byte test failed");
303                                 goto error ;
304                         }
305                 }
306         else {  for(i=0;i<leading_zero_bytes;i++)
307                  if(((temp[tl-1]>>((sizeof(BigNumDigit)-leading_zero_bytes-1+i)*8))&0x0ff)
308                                 != 0) {
309 #ifdef DEBUG
310 printf("\nTop byte zero test failed.\n");
311 #endif
312 syslog(LOG_INFO, "AAK : Top byte zero test failed");
313                                 goto error ;
314                 }
315                 if (((temp[tl-1]>>((sizeof(BigNumDigit)-2-leading_zero_bytes)*8))&0xff)
316                                 != 64){
317 #ifdef DEBUG
318 printf("\nTop byte 64 test failed.\n");
319 #endif
320 syslog(LOG_INFO, "AAK : Top byte 64 test failed");
321                                 goto error ;
322                 }
323         }
324
325         ptr = (char *) &temp[RandomOffset/sizeof(BigNumDigit)];
326         for (i=0;i<4;i++) if (*ptr++ !=0) {
327 #ifdef DEBUG
328 printf("\nAcceptAuthenticationKey: Zero mid-buffer error.\n");
329 #endif
330 syslog(LOG_INFO, "AAK : Zero mid-buffer error");
331                 goto error;
332         }
333
334         when_signed=when_expires_temp=0;
335
336         p = &temp[sizeof(DESblock)/sizeof(BigNumDigit)];
337         when_signed = p[0];
338         when_expires_temp = p[1];
339 /*
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);
343              }
344 */
345         time(&now);
346 #ifdef DEBUG
347 printf("\n Signed:  %s", ctime(&when_signed));
348 printf("\n Expires: %s\n", ctime(&when_expires_temp));
349 #endif
350
351         if((when_signed > now + CLOCK_SKEW) || (when_expires_temp < now - CLOCK_SKEW)) {
352 #ifdef DEBUG
353 printf("\nAcceptAuthenticationKey: Key Has Expired.\n");
354 #endif
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);
358                goto error;
359         }
360         *when_expires = when_expires_temp;
361
362         for (i=0;i<sizeof(DESblock);i++) new_key->bytes[sizeof(DESblock)-i-1] =
363            (temp[i/sizeof(BigNumDigit)]>>((i%sizeof(BigNumDigit)*8)));
364         return(TRUE);
365
366 error:
367         return(FALSE);
368         
369 }
370
This page took 0.071891 seconds and 5 git commands to generate.