There are no available options for this view.

Parent Directory Parent Directory | Revision <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a> Revision <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a>

Revision 1.1.1.1 - (show annotations) (download) (as text) (vendor branch)
Mon Sep 30 00:25:04 2002 UTC (9 years, 7 months ago) by scottg
Branch: scottg, MAIN
CVS Tags: start, v0_1, HEAD
Changes since 1.1: +0 -0 lines
File MIME type: text/x-chdr
Initial import.

1 /*
2 * The contents of this file are subject to the AOLserver Public License
3 * Version 1.1 (the "License"); you may not use this file except in
4 * compliance with the License. You may obtain a copy of the License at
5 * http://aolserver.com/.
6 *
7 * Software distributed under the License is distributed on an "AS IS"
8 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
9 * the License for the specific language governing rights and limitations
10 * under the License.
11 *
12 * The Original Code is AOLserver Code and related documentation
13 * distributed by AOL.
14 *
15 * The Initial Developer of the Original Code is America Online,
16 * Inc. Portions created by AOL are Copyright (C) 1999 America Online,
17 * Inc. All Rights Reserved.
18 *
19 * Alternatively, the contents of this file may be used under the terms
20 * of the GNU General Public License (the "GPL"), in which case the
21 * provisions of GPL are applicable instead of those above. If you wish
22 * to allow use of your version of this file only under the terms of the
23 * GPL and not to allow others to use your version of this file under the
24 * License, indicate your decision by deleting the provisions above and
25 * replace them with the notice and other provisions required by the GPL.
26 * If you do not delete the provisions above, a recipient may use your
27 * version of this file under either the License or the GPL.
28 */
29
30 /*
31 * nssha1.c --
32 *
33 * A simple AOLserver module to perform SHA1 hashes. The SHA1 routines
34 * are borrowed from libmd, which contains the following header:
35 *
36 * * sha.c - NIST Secure Hash Algorithm, FIPS PUB 180 and 180.1.
37 * * The algorithm is by spook(s) unknown at the U.S. National Security Agency.
38 * *
39 * * Written 2 September 1992, Peter C. Gutmann.
40 * * This implementation placed in the public domain.
41 * *
42 * * Modified 1 June 1993, Colin Plumb.
43 * * Modified for the new SHS based on Peter Gutmann's work,
44 * * 18 July 1994, Colin Plumb.
45 * *
46 * * Renamed to SHA and comments updated a bit 1 November 1995, Colin Plumb.
47 * * These modifications placed in the public domain.
48 * *
49 * * Comments to pgut1@cs.aukuni.ac.nz
50 * *
51 * * Hacked for use in libmd by Martin Hinner <mhi@penguin.cz>
52 *
53 * This Tcl library was hacked by Jon Salz <jsalz@mit.edu>.
54 *
55 */
56
57 static const char *RCSID = "@(#) $Header: /cvsroot-fuse/aolserver/nssha1/nssha1.c,v 1.1.1.1 2002/09/30 00:25:04 scottg Exp $, compiled: " __DATE__ " " __TIME__;
58
59 #include "ns.h"
60
61 #include <string.h>
62 #include <sys/types.h>
63
64 /*
65 * The Ns_ModuleVersion variable is required.
66 */
67 int Ns_ModuleVersion = 1;
68
69 static char hexChars[] = "0123456789ABCDEF";
70
71 /*
72 * Private functions
73 */
74 int
75 Ns_ModuleInit(char *hServer, char *hModule);
76
77 static int
78 <a href="/cvs/aolserver/nssha1/nssha1.c#A_SHA1InterpInit">SHA1InterpInit</a>(Tcl_Interp *interp, void *context);
79
80 static int
81 <a href="/cvs/aolserver/nssha1/nssha1.c#A_SHA1Cmd">SHA1Cmd</a>(ClientData context, Tcl_Interp *interp, int argc, char **argv);
82
83
84
85 /*
86 *----------------------------------------------------------------------
87 *
88 * Ns_ModuleInit --
89 *
90 * This is the nssha1 module's entry point. AOLserver runs
91 * this function right after the module is loaded. It is used to
92 * read configuration data, initialize data structures, kick off
93 * the Tcl initialization function (if any), and do other things
94 * at startup.
95 *
96 * Results:
97 * NS_OK or NS_ERROR
98 *
99 * Side effects:
100 * Module loads and initializes itself.
101 *
102 *----------------------------------------------------------------------
103 */
104
105 int
106 Ns_ModuleInit(char *hServer, char *hModule)
107 {
108
109 return (<a href="/cvs/aolserver/aolserver/nsd/tclinit.c#A_Ns_TclInitInterps">Ns_TclInitInterps</a>(hServer, <a href="/cvs/aolserver/nssha1/nssha1.c#A_SHA1InterpInit">SHA1InterpInit</a>, NULL));
110
111 }
112
113
114
115 /*
116 *----------------------------------------------------------------------
117 *
118 * <a href="/cvs/aolserver/nssha1/nssha1.c#A_SHA1InterpInit">SHA1InterpInit</a> --
119 *
120 * Register new commands with the Tcl interpreter.
121 *
122 * Results:
123 * NS_OK or NS_ERROR
124 *
125 * Side effects:
126 * A C function is registered with the Tcl interpreter.
127 *
128 *----------------------------------------------------------------------
129 */
130
131 static int
132 <a href="/cvs/aolserver/nssha1/nssha1.c#A_SHA1InterpInit">SHA1InterpInit</a>(Tcl_Interp *interp, void *context)
133 {
134 Tcl_CreateCommand(interp, "ns_sha1", <a href="/cvs/aolserver/nssha1/nssha1.c#A_SHA1Cmd">SHA1Cmd</a>, NULL, NULL);
135
136 return NS_OK;
137 }
138
139 typedef unsigned int u_int32_t;
140 typedef unsigned char u_int8_t;
141
142 /*** FROM sha.h: ***/
143
144 /*
145 * Define to 1 for FIPS 180.1 version (with extra rotate in prescheduling),
146 * 0 for FIPS 180 version (with the mysterious "weakness" that the NSA
147 * isn't talking about).
148 */
149 #define SHA_VERSION 1
150
151 #define SHA_BLOCKBYTES 64
152 #define SHA_BLOCKWORDS 16
153
154 #define SHA_HASHBYTES 20
155 #define SHA_HASHWORDS 5
156
157 /* SHA context. */
158 typedef struct SHAContext {
159 unsigned int key[SHA_BLOCKWORDS];
160 u_int32_t iv[SHA_HASHWORDS];
161 #ifdef HAVE64
162 u_int64_t bytes;
163 #else
164 u_int32_t bytesHi, bytesLo;
165 #endif
166 } SHA_CTX;
167
168 /*** END sha.h ***/
169
170 /*** FROM sha.c: ***/
171
172 /*
173 Shuffle the bytes into big-endian order within words, as per the
174 SHA spec.
175 */
176 static void
177 <a href="/cvs/aolserver/nssha1/nssha1.c#A_shaByteSwap">shaByteSwap</a> (u_int32_t * dest, u_int8_t const *src, unsigned int words)
178 {
179 do
180 {
181 *dest++ = (u_int32_t) ((unsigned) src[0] << 8 | src[1]) << 16 |
182 ((unsigned) src[2] << 8 | src[3]);
183 src += 4;
184 }
185 while (--words);
186 }
187
188 /* Initialize the SHA values */
189 static void
190 <a href="/cvs/aolserver/nssha1/nssha1.c#A_SHAInit">SHAInit</a> (SHA_CTX * ctx)
191 {
192
193 /* Set the h-vars to their initial values */
194 ctx->iv[0] = 0x67452301;
195 ctx->iv[1] = 0xEFCDAB89;
196 ctx->iv[2] = 0x98BADCFE;
197 ctx->iv[3] = 0x10325476;
198 ctx->iv[4] = 0xC3D2E1F0;
199
200 /* Initialise bit count */
201 #ifdef HAVE64
202 ctx->bytes = 0;
203 #else
204 ctx->bytesHi = 0;
205 ctx->bytesLo = 0;
206 #endif
207 }
208
209 /*
210 The SHA f()-functions. The f1 and f3 functions can be optimized to
211 save one boolean operation each - thanks to Rich Schroeppel,
212 rcs@cs.arizona.edu for discovering this.
213 The f3 function can be modified to use an addition to combine the
214 two halves rather than OR, allowing more opportunity for using
215 associativity in optimization. (Colin Plumb)
216
217 Note that it may be necessary to add parentheses to these macros
218 if they are to be called with expressions as arguments.
219 */
220 #define f1(x,y,z) ( z ^ (x & (y ^ z) ) ) /* Rounds 0-19 */
221 #define f2(x,y,z) ( x ^ y ^ z ) /* Rounds 20-39 */
222 #define f3(x,y,z) ( (x & y) + (z & (x ^ y) ) ) /* Rounds 40-59 */
223 #define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */
224
225 /* The SHA Mysterious Constants. */
226 #define K2 0x5A827999L /* Rounds 0 -19 - floor(sqrt(2) * 2^30) */
227 #define K3 0x6ED9EBA1L /* Rounds 20-39 - floor(sqrt(3) * 2^30) */
228 #define K5 0x8F1BBCDCL /* Rounds 40-59 - floor(sqrt(5) * 2^30) */
229 #define K10 0xCA62C1D6L /* Rounds 60-79 - floor(sqrt(10) * 2^30) */
230
231 /* 32-bit rotate left - kludged with shifts */
232 #define ROTL(n,X) ( (X << n) | (X >> (32-n)) )
233
234 /*
235 The initial expanding function
236
237 The hash function is defined over an 80-word expanded input array W,
238 where the first 16 are copies of the input data, and the remaining 64
239 are defined by W[i] = W[i-16] ^ W[i-14] ^ W[i-8] ^ W[i-3]. This
240 implementation generates these values on the fly in a circular buffer.
241
242 The new "corrected" FIPS 180.1 added a 1-bit left rotate to this
243 computation of W[i].
244
245 The expandx() version doesn't write the result back, which can be
246 used for the last three rounds since those outputs are never used.
247 */
248 #if SHA_VERSION /* FIPS 180.1 */
249
250 #define expandx(W,i) (t = W[i&15] ^ W[(i-14)&15] ^ W[(i-8)&15] ^ W[(i-3)&15],\
251 ROTL(1, t))
252 #define expand(W,i) (W[i&15] = expandx(W,i))
253
254 #else /* Old FIPS 180 */
255
256 #define expandx(W,i) (W[i&15] ^ W[(i-14)&15] ^ W[(i-8)&15] ^ W[(i-3)&15])
257 #define expand(W,i) (W[i&15] ^= W[(i-14)&15] ^ W[(i-8)&15] ^ W[(i-3)&15])a
258
259 #endif /* SHA_VERSION */
260
261 /*
262 The prototype SHA sub-round
263
264 The fundamental sub-round is
265 a' = e + ROTL(5,a) + f(b, c, d) + k + data;
266 b' = a;
267 c' = ROTL(30,b);
268 d' = c;
269 e' = d;
270 ... but this is implemented by unrolling the loop 5 times and renaming
271 the variables (e,a,b,c,d) = (a',b',c',d',e') each iteration.
272 */
273 #define subRound(a, b, c, d, e, f, k, data) \
274 ( e += ROTL(5,a) + f(b, c, d) + k + data, b = ROTL(30, b) )
275 /*
276 The above code is replicated 20 times for each of the 4 functions,
277 using the next 20 values from the W[] array for "data" each time.
278 */
279
280 /*
281 Perform the SHA transformation. Note that this code, like MD5, seems to
282 break some optimizing compilers due to the complexity of the expressions
283 and the size of the basic block. It may be necessary to split it into
284 sections, e.g. based on the four subrounds
285
286 Note that this corrupts the sha->key area.
287 */
288 static void
289 <a href="/cvs/aolserver/nssha1/nssha1.c#A_SHATransform">SHATransform</a> (struct SHAContext *sha)
290 {
291 register u_int32_t A, B, C, D, E;
292 #if SHA_VERSION
293 register u_int32_t t;
294 #endif
295
296 /* Set up first buffer */
297 A = sha->iv[0];
298 B = sha->iv[1];
299 C = sha->iv[2];
300 D = sha->iv[3];
301 E = sha->iv[4];
302
303 /* Heavy mangling, in 4 sub-rounds of 20 interations each. */
304 subRound (A, B, C, D, E, f1, K2, sha->key[0]);
305 subRound (E, A, B, C, D, f1, K2, sha->key[1]);
306 subRound (D, E, A, B, C, f1, K2, sha->key[2]);
307 subRound (C, D, E, A, B, f1, K2, sha->key[3]);
308 subRound (B, C, D, E, A, f1, K2, sha->key[4]);
309 subRound (A, B, C, D, E, f1, K2, sha->key[5]);
310 subRound (E, A, B, C, D, f1, K2, sha->key[6]);
311 subRound (D, E, A, B, C, f1, K2, sha->key[7]);
312 subRound (C, D, E, A, B, f1, K2, sha->key[8]);
313 subRound (B, C, D, E, A, f1, K2, sha->key[9]);
314 subRound (A, B, C, D, E, f1, K2, sha->key[10]);
315 subRound (E, A, B, C, D, f1, K2, sha->key[11]);
316 subRound (D, E, A, B, C, f1, K2, sha->key[12]);
317 subRound (C, D, E, A, B, f1, K2, sha->key[13]);
318 subRound (B, C, D, E, A, f1, K2, sha->key[14]);
319 subRound (A, B, C, D, E, f1, K2, sha->key[15]);
320 subRound (E, A, B, C, D, f1, K2, expand (sha->key, 16));
321 subRound (D, E, A, B, C, f1, K2, expand (sha->key, 17));
322 subRound (C, D, E, A, B, f1, K2, expand (sha->key, 18));
323 subRound (B, C, D, E, A, f1, K2, expand (sha->key, 19));
324
325 subRound (A, B, C, D, E, f2, K3, expand (sha->key, 20));
326 subRound (E, A, B, C, D, f2, K3, expand (sha->key, 21));
327 subRound (D, E, A, B, C, f2, K3, expand (sha->key, 22));
328 subRound (C, D, E, A, B, f2, K3, expand (sha->key, 23));
329 subRound (B, C, D, E, A, f2, K3, expand (sha->key, 24));
330 subRound (A, B, C, D, E, f2, K3, expand (sha->key, 25));
331 subRound (E, A, B, C, D, f2, K3, expand (sha->key, 26));
332 subRound (D, E, A, B, C, f2, K3, expand (sha->key, 27));
333 subRound (C, D, E, A, B, f2, K3, expand (sha->key, 28));
334 subRound (B, C, D, E, A, f2, K3, expand (sha->key, 29));
335 subRound (A, B, C, D, E, f2, K3, expand (sha->key, 30));
336 subRound (E, A, B, C, D, f2, K3, expand (sha->key, 31));
337 subRound (D, E, A, B, C, f2, K3, expand (sha->key, 32));
338 subRound (C, D, E, A, B, f2, K3, expand (sha->key, 33));
339 subRound (B, C, D, E, A, f2, K3, expand (sha->key, 34));
340 subRound (A, B, C, D, E, f2, K3, expand (sha->key, 35));
341 subRound (E, A, B, C, D, f2, K3, expand (sha->key, 36));
342 subRound (D, E, A, B, C, f2, K3, expand (sha->key, 37));
343 subRound (C, D, E, A, B, f2, K3, expand (sha->key, 38));
344 subRound (B, C, D, E, A, f2, K3, expand (sha->key, 39));
345
346 subRound (A, B, C, D, E, f3, K5, expand (sha->key, 40));
347 subRound (E, A, B, C, D, f3, K5, expand (sha->key, 41));
348 subRound (D, E, A, B, C, f3, K5, expand (sha->key, 42));
349 subRound (C, D, E, A, B, f3, K5, expand (sha->key, 43));
350 subRound (B, C, D, E, A, f3, K5, expand (sha->key, 44));
351 subRound (A, B, C, D, E, f3, K5, expand (sha->key, 45));
352 subRound (E, A, B, C, D, f3, K5, expand (sha->key, 46));
353 subRound (D, E, A, B, C, f3, K5, expand (sha->key, 47));
354 subRound (C, D, E, A, B, f3, K5, expand (sha->key, 48));
355 subRound (B, C, D, E, A, f3, K5, expand (sha->key, 49));
356 subRound (A, B, C, D, E, f3, K5, expand (sha->key, 50));
357 subRound (E, A, B, C, D, f3, K5, expand (sha->key, 51));
358 subRound (D, E, A, B, C, f3, K5, expand (sha->key, 52));
359 subRound (C, D, E, A, B, f3, K5, expand (sha->key, 53));
360 subRound (B, C, D, E, A, f3, K5, expand (sha->key, 54));
361 subRound (A, B, C, D, E, f3, K5, expand (sha->key, 55));
362 subRound (E, A, B, C, D, f3, K5, expand (sha->key, 56));
363 subRound (D, E, A, B, C, f3, K5, expand (sha->key, 57));
364 subRound (C, D, E, A, B, f3, K5, expand (sha->key, 58));
365 subRound (B, C, D, E, A, f3, K5, expand (sha->key, 59));
366
367 subRound (A, B, C, D, E, f4, K10, expand (sha->key, 60));
368 subRound (E, A, B, C, D, f4, K10, expand (sha->key, 61));
369 subRound (D, E, A, B, C, f4, K10, expand (sha->key, 62));
370 subRound (C, D, E, A, B, f4, K10, expand (sha->key, 63));
371 subRound (B, C, D, E, A, f4, K10, expand (sha->key, 64));
372 subRound (A, B, C, D, E, f4, K10, expand (sha->key, 65));
373 subRound (E, A, B, C, D, f4, K10, expand (sha->key, 66));
374 subRound (D, E, A, B, C, f4, K10, expand (sha->key, 67));
375 subRound (C, D, E, A, B, f4, K10, expand (sha->key, 68));
376 subRound (B, C, D, E, A, f4, K10, expand (sha->key, 69));
377 subRound (A, B, C, D, E, f4, K10, expand (sha->key, 70));
378 subRound (E, A, B, C, D, f4, K10, expand (sha->key, 71));
379 subRound (D, E, A, B, C, f4, K10, expand (sha->key, 72));
380 subRound (C, D, E, A, B, f4, K10, expand (sha->key, 73));
381 subRound (B, C, D, E, A, f4, K10, expand (sha->key, 74));
382 subRound (A, B, C, D, E, f4, K10, expand (sha->key, 75));
383 subRound (E, A, B, C, D, f4, K10, expand (sha->key, 76));
384 subRound (D, E, A, B, C, f4, K10, expandx (sha->key, 77));
385 subRound (C, D, E, A, B, f4, K10, expandx (sha->key, 78));
386 subRound (B, C, D, E, A, f4, K10, expandx (sha->key, 79));
387
388 /* Build message digest */
389 sha->iv[0] += A;
390 sha->iv[1] += B;
391 sha->iv[2] += C;
392 sha->iv[3] += D;
393 sha->iv[4] += E;
394 }
395
396 /* Update SHA for a block of data. */
397 static void
398 <a href="/cvs/aolserver/nssha1/nssha1.c#A_SHAUpdate">SHAUpdate</a> (SHA_CTX * ctx, const unsigned char *buf, unsigned int len)
399 {
400 unsigned i;
401
402 /* Update bitcount */
403
404 #ifdef HAVE64
405 i = (unsigned) ctx->bytes % SHA_BLOCKBYTES;
406 ctx->bytes += len;
407 #else
408 u_int32_t t = ctx->bytesLo;
409 if ((ctx->bytesLo = t + len) < t)
410 ctx->bytesHi++; /* Carry from low to high */
411
412 i = (unsigned) t % SHA_BLOCKBYTES; /* Bytes already in ctx->key */
413 #endif
414
415 /* i is always less than SHA_BLOCKBYTES. */
416 if (SHA_BLOCKBYTES - i > len)
417 {
418 memcpy ((u_int8_t *) ctx->key + i, buf, len);
419 return;
420 }
421
422 if (i)
423 { /* First chunk is an odd size */
424 memcpy ((u_int8_t *) ctx->key + i, buf, SHA_BLOCKBYTES - i);
425 <a href="/cvs/aolserver/nssha1/nssha1.c#A_shaByteSwap">shaByteSwap</a> (ctx->key, (u_int8_t *) ctx->key, SHA_BLOCKWORDS);
426 <a href="/cvs/aolserver/nssha1/nssha1.c#A_SHATransform">SHATransform</a> (ctx);
427 buf += SHA_BLOCKBYTES - i;
428 len -= SHA_BLOCKBYTES - i;
429 }
430
431 /* Process data in 64-byte chunks */
432 while (len >= SHA_BLOCKBYTES)
433 {
434 <a href="/cvs/aolserver/nssha1/nssha1.c#A_shaByteSwap">shaByteSwap</a> (ctx->key, buf, SHA_BLOCKWORDS);
435 <a href="/cvs/aolserver/nssha1/nssha1.c#A_SHATransform">SHATransform</a> (ctx);
436 buf += SHA_BLOCKBYTES;
437 len -= SHA_BLOCKBYTES;
438 }
439
440 /* Handle any remaining bytes of data. */
441 if (len)
442 memcpy (ctx->key, buf, len);
443 }
444
445 /*
446 * Final wrapup - pad to 64-byte boundary with the bit pattern
447 * 1 0* (64-bit count of bits processed, MSB-first)
448 */
449
450 static void
451 <a href="/cvs/aolserver/nssha1/nssha1.c#A_SHAFinal">SHAFinal</a> (unsigned char digest[20], SHA_CTX * ctx)
452 {
453 #if HAVE64
454 unsigned i = (unsigned) ctx->bytes % SHA_BLOCKBYTES;
455 #else
456 unsigned i = (unsigned) ctx->bytesLo % SHA_BLOCKBYTES;
457 #endif
458 u_int8_t *p = (u_int8_t *) ctx->key + i; /* First unused byte */
459 u_int32_t t;
460
461 /* Set the first char of padding to 0x80. There is always room. */
462 *p++ = 0x80;
463
464 /* Bytes of padding needed to make 64 bytes (0..63) */
465 i = SHA_BLOCKBYTES - 1 - i;
466
467 if (i < 8)
468 { /* Padding forces an extra block */
469 memset (p, 0, i);
470 <a href="/cvs/aolserver/nssha1/nssha1.c#A_shaByteSwap">shaByteSwap</a> (ctx->key, (u_int8_t *) ctx->key, 16);
471 <a href="/cvs/aolserver/nssha1/nssha1.c#A_SHATransform">SHATransform</a> (ctx);
472 p = (u_int8_t *) ctx->key;
473 i = 64;
474 }
475 memset (p, 0, i - 8);
476 <a href="/cvs/aolserver/nssha1/nssha1.c#A_shaByteSwap">shaByteSwap</a> (ctx->key, (u_int8_t *) ctx->key, 14);
477
478 /* Append length in bits and transform */
479 #if HAVE64
480 ctx->key[14] = (u_int32_t) (ctx->bytes >> 29);
481 ctx->key[15] = (u_int32_t) ctx->bytes << 3;
482 #else
483 ctx->key[14] = ctx->bytesHi << 3 | ctx->bytesLo >> 29;
484 ctx->key[15] = ctx->bytesLo << 3;
485 #endif
486 <a href="/cvs/aolserver/nssha1/nssha1.c#A_SHATransform">SHATransform</a> (ctx);
487
488 memcpy (digest, ctx->iv, sizeof (digest));
489 for (i = 0; i < SHA_HASHWORDS; i++)
490 {
491 t = ctx->iv[i];
492 digest[i * 4 + 0] = (u_int8_t) (t >> 24);
493 digest[i * 4 + 1] = (u_int8_t) (t >> 16);
494 digest[i * 4 + 2] = (u_int8_t) (t >> 8);
495 digest[i * 4 + 3] = (u_int8_t) t;
496 }
497
498 memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
499 }
500
501 /*** END sha.c ***/
502
503
504
505 /*
506 *----------------------------------------------------------------------
507 *
508 * <a href="/cvs/aolserver/nssha1/nssha1.c#A_SHA1Cmd">SHA1Cmd</a> --
509 *
510 * Returns a 40-character, hex-encoded string containing the SHA1
511 * hash of the first argument.
512 *
513 * Results:
514 * NS_OK
515 *
516 * Side effects:
517 * Tcl result is set to a string value.
518 *
519 *----------------------------------------------------------------------
520 */
521
522 static int
523 <a href="/cvs/aolserver/nssha1/nssha1.c#A_SHA1Cmd">SHA1Cmd</a>(ClientData context, Tcl_Interp *interp, int argc, char **argv)
524 {
525 SHA_CTX ctx;
526 char digest[20];
527 char digestChars[41];
528 int i;
529
530 if (argc != 2) {
531 Tcl_AppendResult(interp, "wrong # of args: should be ", argv[0], " string", NULL);
532 return TCL_ERROR;
533 }
534
535 <a href="/cvs/aolserver/nssha1/nssha1.c#A_SHAInit">SHAInit</a>(&ctx);
536 <a href="/cvs/aolserver/nssha1/nssha1.c#A_SHAUpdate">SHAUpdate</a>(&ctx, argv[1], strlen(argv[1]));
537 <a href="/cvs/aolserver/nssha1/nssha1.c#A_SHAFinal">SHAFinal</a>(digest, &ctx);
538
539 for (i = 0; i < 20; ++i) {
540 digestChars[i * 2] = hexChars[(unsigned char)(digest[i]) >> 4];
541 digestChars[i * 2 + 1] = hexChars[(unsigned char)(digest[i]) & 0xF];
542 }
543 digestChars[40] = '\0';
544
545 Tcl_AppendResult(interp, digestChars, NULL);
546
547 return NS_OK;
548 }