aac3417afa507ee74ef08a6f07def85504e64259
[openafs.git] / src / afsweb / securehash.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * All Rights Reserved
12  * Licensed Materials - Property of Transarc
13  *
14  * For copyright information, see IPL which you accepted in order to
15  * download this software.
16  *
17  * COMPONENT_NAME: nsafs
18  *
19  * ORIGINS: Transarc Corp.
20  *
21  */
22
23 /*
24  * This module implements the Secure Hash Algorithm (SHA) as specified in
25  * the Secure Hash Standard (SHS, FIPS PUB 180.1).
26  */
27
28 #include <afsconfig.h>
29 #include "../afs/param.h"
30
31 RCSID("$Header$");
32
33 #include "../afs/sysincludes.h" /* Standard vendor system headers */
34 #include <net/if.h>
35 #include "../afs/afsincludes.h" /* Afs-based standard headers */
36 #include "../afs/afs_stats.h"
37 #include "../afs/auth.h"
38 #include "../afs/cellconfig.h"
39 #include "../afs/vice.h"
40 #include "../afs/nsafs.h"
41
42 static int big_endian;
43
44 static const sha_int hashinit[] = {
45     0x67452301, 0xEFCDAB89, 0x98BADCFE,
46     0x10325476, 0xC3D2E1F0
47 };
48
49 #define ROTL(n, x) (((x) << (n)) | ((x) >> (SHA_BITS_PER_INT - (n))))
50
51 #ifdef DISABLED_CODE_HERE
52 static sha_int f(int t, sha_int x, sha_int y, sha_int z)
53 {
54     if (t < 0 || t >= SHA_ROUNDS) return 0;
55     if (t < 20)
56         return (z ^ (x & (y ^ z)));
57     if (t < 40)
58         return (x ^ y ^ z);
59     if (t < 60)
60         return ((x & y) | (z & (x | y))); /* saves 1 boolean op */
61     return (x ^ y ^ z);         /* 60-79 same as 40-59 */
62 }
63 #endif
64
65 /* This is the "magic" function used for each round.         */
66 /* Were this a C function, the interface would be:           */
67 /* static sha_int f(int t, sha_int x, sha_int y, sha_int z) */
68 /* The function call version preserved above until stable    */
69
70 #define f_a(x, y, z) (z ^ (x & (y ^ z)))
71 #define f_b(x, y, z) (x ^ y ^ z)
72 #define f_c(x, y, z) (( (x & y) | (z & (x | y))))
73
74 #define f(t, x, y, z)                     \
75       ( (t < 0 || t >= SHA_ROUNDS) ? 0 :  \
76           ( (t < 20) ? f_a(x, y, z) :     \
77               ( (t < 40) ? f_b(x, y, z) : \
78                   ( (t < 60) ? f_c(x, y, z) : f_b(x, y, z)))))
79
80 /*
81  *static sha_int K(int t)
82  *{
83  *    if (t < 0 || t >= SHA_ROUNDS) return 0;
84  *   if (t < 20)
85  *      return 0x5A827999;
86  *   if (t < 40)
87  *      return 0x6ED9EBA1;
88  *   if (t < 60)
89  *      return 0x8F1BBCDC;
90  *   return 0xCA62C1D6;
91  * }
92  */
93
94 /* This macro/function supplies the "magic" constant for each round. */
95 /* The function call version preserved above until stable            */
96
97 static const sha_int k_vals[] = { 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6};
98
99 #define K(t) ( (t < 0 || t >= SHA_ROUNDS) ? 0 : k_vals[ t/20 ] )
100
101 /*
102  * Update the internal state based on the given chunk.
103  */
104 static void transform(shaState *shaStateP, sha_int *chunk)
105 {
106     sha_int A = shaStateP->digest[0];
107     sha_int B = shaStateP->digest[1];
108     sha_int C = shaStateP->digest[2];
109     sha_int D = shaStateP->digest[3];
110     sha_int E = shaStateP->digest[4];
111     sha_int TEMP = 0;
112
113     int t;
114     sha_int W[SHA_ROUNDS];
115
116     for (t = 0; t < SHA_CHUNK_INTS; t++)
117         W[t] = chunk[t];
118     for (; t < SHA_ROUNDS; t++) {
119         TEMP = W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16];
120         W[t] = ROTL(1, TEMP);
121     }
122
123     for (t = 0; t < SHA_ROUNDS; t++) {
124         TEMP = ROTL(5, A) + f(t, B, C, D) + E + W[t] + K(t);
125         E = D; D = C; C = ROTL(30, B); B = A; A = TEMP;
126     }
127
128     shaStateP->digest[0] += A;
129     shaStateP->digest[1] += B;
130     shaStateP->digest[2] += C;
131     shaStateP->digest[3] += D;
132     shaStateP->digest[4] += E;
133 }
134
135
136 /*
137  * This function takes an array of SHA_CHUNK_BYTES bytes
138  * as input and produces an output array of ints that is
139  * SHA_CHUNK_INTS long.
140  */
141 static void buildInts(const char *data, sha_int *chunk)
142 {
143     /*
144      * Need to copy the data because we can't be certain that
145      * the input buffer will be aligned correctly.
146      */
147     memcpy((void *)chunk, (void *)data, SHA_CHUNK_BYTES);
148
149     if (!big_endian) {
150         /* This loop does nothing but waste time on a big endian machine. */
151         int i;
152
153         for (i = 0; i < SHA_CHUNK_INTS; i++)
154             chunk[i] = ntohl(chunk[i]);
155     }
156 }
157
158 /*
159  * This function updates the internal state of the hash by using
160  * buildInts to break the input up into chunks and repeatedly passing
161  * these chunks to transform().
162  */
163 void sha_update(shaState *shaStateP, const char *buffer, int bufferLen)
164 {
165     int i;
166     sha_int chunk[SHA_CHUNK_INTS];
167     sha_int newLo;
168
169     if (buffer == NULL || bufferLen == 0)
170         return;
171
172     newLo = shaStateP->bitcountLo + (bufferLen << 3);
173     if (newLo < shaStateP->bitcountLo)
174         shaStateP->bitcountHi++;
175     shaStateP->bitcountLo = newLo;
176     shaStateP->bitcountHi += ((bufferLen >> (SHA_BITS_PER_INT - 3)) & 0x07);
177     
178     /*
179      * If we won't have enough for a full chunk, just tack this
180      * buffer onto the leftover piece and return.
181      */
182     if (shaStateP->leftoverLen + bufferLen < SHA_CHUNK_BYTES) {
183         memcpy((void *)&(shaStateP->leftover[shaStateP->leftoverLen]),
184                (void *)buffer, bufferLen);
185         shaStateP->leftoverLen += bufferLen;
186         return;
187     }
188
189     /* If we have a leftover chunk, process it first. */
190     if (shaStateP->leftoverLen > 0) {
191         i = (SHA_CHUNK_BYTES - shaStateP->leftoverLen);
192         memcpy((void *)&(shaStateP->leftover[shaStateP->leftoverLen]),
193                (void *)buffer, i);
194         buffer += i;
195         bufferLen -= i;
196         buildInts(shaStateP->leftover, chunk);
197         shaStateP->leftoverLen = 0;
198         transform(shaStateP, chunk);
199     }
200
201     while (bufferLen >= SHA_CHUNK_BYTES) {
202         buildInts(buffer, chunk);
203         transform(shaStateP, chunk);
204         buffer += SHA_CHUNK_BYTES;
205         bufferLen -= SHA_CHUNK_BYTES;
206     }
207     assert((bufferLen >= 0) && (bufferLen < SHA_CHUNK_BYTES));
208
209     if (bufferLen > 0) {
210         memcpy((void *)&shaStateP->leftover[0], (void *)buffer, bufferLen);
211         shaStateP->leftoverLen = bufferLen;
212     }
213 }
214
215
216 /*
217  * This method updates the internal state of the hash using
218  * any leftover data plus appropriate padding and incorporation
219  * of the hash bitcount to finish the hash.  The hash value
220  * is not valid until finish() has been called.
221  */
222 void sha_finish(shaState *shaStateP)
223 {
224     sha_int chunk[SHA_CHUNK_INTS];
225     int i;
226
227     if (shaStateP->leftoverLen > (SHA_CHUNK_BYTES - 9)) {
228         shaStateP->leftover[shaStateP->leftoverLen++] = 0x80;
229         memset(&(shaStateP->leftover[shaStateP->leftoverLen]), 0,
230                (SHA_CHUNK_BYTES - shaStateP->leftoverLen));
231         buildInts(shaStateP->leftover, chunk);
232         transform(shaStateP, chunk);
233         memset(chunk, 0, SHA_CHUNK_BYTES);
234     } else {
235         shaStateP->leftover[shaStateP->leftoverLen++] = 0x80;
236         memset(&(shaStateP->leftover[shaStateP->leftoverLen]), 0,
237                (SHA_CHUNK_BYTES - shaStateP->leftoverLen));
238         buildInts(shaStateP->leftover, chunk);
239     }
240     shaStateP->leftoverLen = 0;
241
242     chunk[SHA_CHUNK_INTS - 2] = shaStateP->bitcountHi;
243     chunk[SHA_CHUNK_INTS - 1] = shaStateP->bitcountLo;
244     transform(shaStateP, chunk);
245 }
246
247
248 /*
249  * Initialize the hash to its "magic" initial value specified by the
250  * SHS standard, and clear out the bitcount and leftover vars.
251  * This should be used to initialize an shaState.
252  */
253 void sha_clear(shaState *shaStateP)
254 {
255     big_endian = (0x01020304 == htonl(0x01020304));
256
257     memcpy((void *)&shaStateP->digest[0], (void *)&hashinit[0], SHA_HASH_BYTES);
258     shaStateP->bitcountLo = shaStateP->bitcountHi = 0;
259     shaStateP->leftoverLen = 0;
260 }
261
262
263 /*
264  * Hash the buffer and place the result in *shaStateP.
265  */
266 void sha_hash(shaState *shaStateP, const char *buffer, int bufferLen)
267 {
268     sha_clear(shaStateP);
269     sha_update(shaStateP, buffer, bufferLen);
270     sha_finish(shaStateP);
271 }
272
273
274 /*
275  * Returns the current state of the hash as an array of 20 bytes.
276  * This will be an interim result if finish() has not yet been called.
277  */
278 void sha_bytes(const shaState *shaStateP, char *bytes)
279 {
280     sha_int temp[SHA_HASH_INTS];
281     int  i;
282
283     for (i = 0; i < SHA_HASH_INTS; i++)
284         temp[i] = htonl(shaStateP->digest[i]);
285     memcpy(bytes, (void *)&temp[0], SHA_HASH_BYTES);
286 }