]>
Commit | Line | Data |
---|---|---|
0095f096 | 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 |