2 * Copyright (c) 1997-1999 The Stanford SRP Authentication Project
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
18 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
20 * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
21 * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
22 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
23 * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
24 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26 * In addition, the following conditions apply:
28 * 1. Any software that incorporates the SRP authentication technology
29 * must display the following acknowlegment:
30 * "This product uses the 'Secure Remote Password' cryptographic
31 * authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
33 * 2. Any software that incorporates all or part of the SRP distribution
34 * itself must also display the following acknowledgment:
35 * "This product includes software developed by Tom Wu and Eugene
36 * Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
38 * 3. Redistributions in source or binary form must retain an intact copy
39 * of this copyright notice and list of conditions.
42 #include "t_defines.h"
46 #endif /* HAVE_UNISTD_H */
49 #include <sys/types.h>
59 static unsigned char randpool
[SHA_DIGESTSIZE
], randout
[SHA_DIGESTSIZE
];
60 static unsigned long randcnt
= 0;
61 static unsigned int outpos
= 0;
65 * t_envhash - Generate a 160-bit SHA hash of the environment
67 * This routine performs an SHA hash of all the "name=value" pairs
68 * in the environment concatenated together and dumps them in the
69 * output. While it is true that anyone on the system can see
70 * your environment, someone not on the system will have a very
71 * difficult time guessing it, especially since some systems play
72 * tricks with variable ordering and sometimes define quirky
73 * environment variables like $WINDOWID or $_.
75 extern char ** environ
;
86 for(ptr
= environ
; *ptr
; ++ptr
) {
87 strncpy(ebuf
, *ptr
, 255);
89 SHA1Update(&ctxt
, ebuf
, strlen(ebuf
));
91 SHA1Final(out
, &ctxt
);
95 * t_fshash - Generate a 160-bit SHA hash from the file system
97 * This routine climbs up the directory tree from the current
98 * directory, running stat() on each directory until it hits the
99 * root directory. This information is sensitive to the last
100 * access/modification times of all the directories above you,
101 * so someone who lists one of those directories injects some
102 * entropy into the system. Obviously, this hash is very sensitive
103 * to your current directory when the program is run.
105 * For good measure, it also performs an fstat on the standard input,
106 * usually your tty, throws that into the buffer, creates a file in
107 * /tmp (the inode is unpredictable on a busy system), and runs stat()
108 * on that before deleting it.
110 * The entire buffer is run once through SHA to obtain the final result.
123 if(stat(".", &st
) >= 0) {
124 SHA1Update(&ctxt
, (unsigned char *) &st
, sizeof(st
));
127 strcpy(dotpath
, "..");
128 for(i
= 0; i
< 40; ++i
) {
129 if(stat(dotpath
, &st
) < 0)
131 if(st
.st_ino
== pinode
&& st
.st_dev
== pdev
)
133 SHA1Update(&ctxt
, (unsigned char *) &st
, sizeof(st
));
136 strcat(dotpath
, "/..");
140 if(fstat(0, &st
) >= 0)
141 SHA1Update(&ctxt
, (unsigned char *) &st
, sizeof(st
));
143 sprintf(dotpath
, "/tmp/rnd.%d", getpid());
144 if(creat(dotpath
, 0600) >= 0 && stat(dotpath
, &st
) >= 0)
145 SHA1Update(&ctxt
, (unsigned char *) &st
, sizeof(st
));
148 SHA1Final(out
, &ctxt
);
152 * Generate a high-entropy seed for the strong random number generator.
153 * This uses a wide variety of quickly gathered and somewhat unpredictable
154 * system information. The 'preseed' structure is assembled from:
156 * The system time in seconds
157 * The system time in microseconds
158 * The current process ID
159 * The parent process ID
160 * A hash of the user's environment
161 * A hash gathered from the file system
162 * Input from a random device, if available
163 * Timings of system interrupts
165 * The entire structure (60 bytes on most systems) is fed to SHA to produce
166 * a 160-bit seed for the strong random number generator. It is believed
167 * that in the worst case (on a quiet system with no random device versus
168 * an attacker who has access to the system already), the seed contains at
169 * least about 80 bits of entropy. Versus an attacker who does not have
170 * access to the system, the entropy should be slightly over 128 bits.
172 static char initialized
= 0;
180 unsigned char envh
[SHA_DIGESTSIZE
];
181 unsigned char fsh
[SHA_DIGESTSIZE
];
182 unsigned char devrand
[20];
186 unsigned long raw_truerand();
204 i
= open("/dev/urandom", O_RDONLY
);
206 r
+= read(i
, preseed
.devrand
, sizeof(preseed
.devrand
));
210 /* Resort to truerand only if desperate for some Real entropy */
212 preseed
.trand1
= raw_truerand();
217 gettimeofday(&t
, NULL
);
221 preseed
.sec
= t
.time
;
222 preseed
.usec
= t
.millitm
;
224 preseed
.sec
= t
.tv_sec
;
225 preseed
.usec
= t
.tv_usec
;
227 preseed
.pid
= getpid();
228 preseed
.ppid
= getppid();
229 t_envhash(preseed
.envh
);
230 t_fshash(preseed
.fsh
);
233 preseed
.trand2
= raw_truerand();
236 SHA1Update(&ctxt
, (unsigned char *) &preseed
, sizeof(preseed
));
237 SHA1Final(randpool
, &ctxt
);
239 memset((unsigned char *) &preseed
, 0, sizeof(preseed
));
240 memset((unsigned char *) &ctxt
, 0, sizeof(ctxt
));
243 #define NUM_RANDOMS 12
246 * The strong random number generator. This uses a 160-bit seed
247 * and uses SHA-1 in a feedback configuration to generate successive
248 * outputs. If S[0] is set to the initial seed, then:
250 * S[i+1] = SHA-1(i || S[i])
253 * where the A[i] are the output blocks starting with i=0.
254 * Each cycle generates 20 bytes of new output.
258 unsigned char * data
;
264 if(size
<= 0) /* t_random(NULL, 0) forces seed initialization */
267 while(size
> outpos
) {
269 memcpy(data
, randout
+ (sizeof(randout
) - outpos
), outpos
);
276 SHA1Update(&randctxt
, randpool
, sizeof(randpool
));
277 SHA1Final(randout
, &randctxt
);
279 SHA1Update(&randctxt
, (unsigned char *) &randcnt
, sizeof(randcnt
));
280 SHA1Update(&randctxt
, randpool
, sizeof(randpool
));
281 SHA1Final(randpool
, &randctxt
);
283 outpos
= sizeof(randout
);
287 memcpy(data
, randout
+ (sizeof(randout
) - outpos
), size
);
293 * The interleaved session-key hash. This separates the even and the odd
294 * bytes of the input (ignoring the first byte if the input length is odd),
295 * hashes them separately, and re-interleaves the two outputs to form a
296 * single 320-bit value.
298 _TYPE( unsigned char * )
299 t_sessionkey(key
, sk
, sklen
)
305 unsigned char * hbuf
;
306 unsigned char hout
[SHA_DIGESTSIZE
];
309 while(sklen
> 0 && *sk
== 0) { /* Skip leading 0's */
315 if((hbuf
= malloc(klen
* sizeof(char))) == 0)
318 for(i
= 0; i
< klen
; ++i
)
319 hbuf
[i
] = sk
[sklen
- 2 * i
- 1];
321 SHA1Update(&ctxt
, hbuf
, klen
);
322 SHA1Final(hout
, &ctxt
);
323 for(i
= 0; i
< sizeof(hout
); ++i
)
324 key
[2 * i
] = hout
[i
];
326 for(i
= 0; i
< klen
; ++i
)
327 hbuf
[i
] = sk
[sklen
- 2 * i
- 2];
329 SHA1Update(&ctxt
, hbuf
, klen
);
330 SHA1Final(hout
, &ctxt
);
331 for(i
= 0; i
< sizeof(hout
); ++i
)
332 key
[2 * i
+ 1] = hout
[i
];
334 memset(hout
, 0, sizeof(hout
));
335 memset(hbuf
, 0, klen
);
This page took 0.075952 seconds and 5 git commands to generate.