|
1 /* |
|
2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. |
|
3 * All rights reserved. |
|
4 * |
|
5 * Copyright (c) 2005 Andrey Korotaev <unC0Rr@gmail.com> |
|
6 * |
|
7 * Redistribution and use in source and binary forms, with or without |
|
8 * modification, are permitted provided that the following conditions |
|
9 * are met: |
|
10 * 1. Redistributions of source code must retain the above copyright |
|
11 * notice, this list of conditions and the following disclaimer. |
|
12 * 2. Redistributions in binary form must reproduce the above copyright |
|
13 * notice, this list of conditions and the following disclaimer in the |
|
14 * documentation and/or other materials provided with the distribution. |
|
15 * 3. Neither the name of the project nor the names of its contributors |
|
16 * may be used to endorse or promote products derived from this software |
|
17 * without specific prior written permission. |
|
18 * |
|
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND |
|
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE |
|
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
|
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|
29 * SUCH DAMAGE. |
|
30 */ |
|
31 |
|
32 /* |
|
33 * FIPS pub 180-1: Secure Hash Algorithm (SHA-1) |
|
34 * based on: http://csrc.nist.gov/fips/fip180-1.txt |
|
35 * implemented by Jun-ichiro itojun Itoh <itojun@itojun.org> |
|
36 */ |
|
37 |
|
38 #include "sha1.h" |
|
39 |
|
40 /* constant table */ |
|
41 static quint32 _K[] = { 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 }; |
|
42 #define K(t) _K[(t) / 20] |
|
43 |
|
44 #define F0(b, c, d) (((b) & (c)) | ((~(b)) & (d))) |
|
45 #define F1(b, c, d) (((b) ^ (c)) ^ (d)) |
|
46 #define F2(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d))) |
|
47 #define F3(b, c, d) (((b) ^ (c)) ^ (d)) |
|
48 |
|
49 #define S(n, x) (((x) << (n)) | ((x) >> (32 - n))) |
|
50 |
|
51 #define H(n) (ctxt->h.b32[(n)]) |
|
52 #define COUNT (ctxt->count) |
|
53 #define BCOUNT (ctxt->c.b64[0] / 8) |
|
54 #define W(n) (ctxt->m.b32[(n)]) |
|
55 |
|
56 #define PUTBYTE(x) { \ |
|
57 ctxt->m.b8[(COUNT % 64)] = (x); \ |
|
58 COUNT++; \ |
|
59 COUNT %= 64; \ |
|
60 ctxt->c.b64[0] += 8; \ |
|
61 if (COUNT % 64 == 0) \ |
|
62 sha1_step(ctxt); \ |
|
63 } |
|
64 |
|
65 #define PUTPAD(x) { \ |
|
66 ctxt->m.b8[(COUNT % 64)] = (x); \ |
|
67 COUNT++; \ |
|
68 COUNT %= 64; \ |
|
69 if (COUNT % 64 == 0) \ |
|
70 sha1_step(ctxt); \ |
|
71 } |
|
72 |
|
73 static void sha1_step(struct sha1_ctxt *); |
|
74 |
|
75 static void |
|
76 sha1_step(struct sha1_ctxt *ctxt) |
|
77 { |
|
78 quint32 a, b, c, d, e; |
|
79 size_t t, s; |
|
80 quint32 tmp; |
|
81 |
|
82 a = H(0); b = H(1); c = H(2); d = H(3); e = H(4); |
|
83 |
|
84 for (t = 0; t < 20; t++) { |
|
85 s = t & 0x0f; |
|
86 if (t >= 16) { |
|
87 W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s)); |
|
88 } |
|
89 tmp = S(5, a) + F0(b, c, d) + e + W(s) + K(t); |
|
90 e = d; d = c; c = S(30, b); b = a; a = tmp; |
|
91 } |
|
92 for (t = 20; t < 40; t++) { |
|
93 s = t & 0x0f; |
|
94 W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s)); |
|
95 tmp = S(5, a) + F1(b, c, d) + e + W(s) + K(t); |
|
96 e = d; d = c; c = S(30, b); b = a; a = tmp; |
|
97 } |
|
98 for (t = 40; t < 60; t++) { |
|
99 s = t & 0x0f; |
|
100 W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s)); |
|
101 tmp = S(5, a) + F2(b, c, d) + e + W(s) + K(t); |
|
102 e = d; d = c; c = S(30, b); b = a; a = tmp; |
|
103 } |
|
104 for (t = 60; t < 80; t++) { |
|
105 s = t & 0x0f; |
|
106 W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s)); |
|
107 tmp = S(5, a) + F3(b, c, d) + e + W(s) + K(t); |
|
108 e = d; d = c; c = S(30, b); b = a; a = tmp; |
|
109 } |
|
110 |
|
111 H(0) = H(0) + a; |
|
112 H(1) = H(1) + b; |
|
113 H(2) = H(2) + c; |
|
114 H(3) = H(3) + d; |
|
115 H(4) = H(4) + e; |
|
116 |
|
117 qMemSet(&ctxt->m.b8[0], 0, 64); |
|
118 } |
|
119 |
|
120 /*------------------------------------------------------------*/ |
|
121 |
|
122 void sha1_init(struct sha1_ctxt *ctxt) |
|
123 { |
|
124 qMemSet(ctxt, 0, sizeof(struct sha1_ctxt)); |
|
125 H(0) = 0x67452301; |
|
126 H(1) = 0xefcdab89; |
|
127 H(2) = 0x98badcfe; |
|
128 H(3) = 0x10325476; |
|
129 H(4) = 0xc3d2e1f0; |
|
130 } |
|
131 |
|
132 void sha1_pad(struct sha1_ctxt *ctxt) |
|
133 { |
|
134 size_t padlen; /*pad length in bytes*/ |
|
135 size_t padstart; |
|
136 |
|
137 PUTPAD(0x80); |
|
138 |
|
139 padstart = COUNT % 64; |
|
140 padlen = 64 - padstart; |
|
141 if (padlen < 8) { |
|
142 qMemSet(&ctxt->m.b8[padstart], 0, padlen); |
|
143 COUNT += padlen; |
|
144 COUNT %= 64; |
|
145 sha1_step(ctxt); |
|
146 padstart = COUNT % 64; /* should be 0 */ |
|
147 padlen = 64 - padstart; /* should be 64 */ |
|
148 } |
|
149 qMemSet(&ctxt->m.b8[padstart], 0, padlen - 8); |
|
150 COUNT += (padlen - 8); |
|
151 COUNT %= 64; |
|
152 PUTPAD(ctxt->c.b8[0]); PUTPAD(ctxt->c.b8[1]); |
|
153 PUTPAD(ctxt->c.b8[2]); PUTPAD(ctxt->c.b8[3]); |
|
154 PUTPAD(ctxt->c.b8[4]); PUTPAD(ctxt->c.b8[5]); |
|
155 PUTPAD(ctxt->c.b8[6]); PUTPAD(ctxt->c.b8[7]); |
|
156 } |
|
157 |
|
158 void sha1_loop(struct sha1_ctxt *ctxt, const quint8 *input, size_t len) |
|
159 { |
|
160 size_t gaplen; |
|
161 size_t gapstart; |
|
162 size_t off; |
|
163 size_t copysiz; |
|
164 |
|
165 off = 0; |
|
166 |
|
167 while (off < len) { |
|
168 gapstart = COUNT % 64; |
|
169 gaplen = 64 - gapstart; |
|
170 |
|
171 copysiz = (gaplen < len - off) ? gaplen : len - off; |
|
172 qMemCopy(&ctxt->m.b8[gapstart], &input[off], copysiz); |
|
173 COUNT += copysiz; |
|
174 COUNT %= 64; |
|
175 ctxt->c.b64[0] += copysiz * 8; |
|
176 if (COUNT % 64 == 0) |
|
177 sha1_step(ctxt); |
|
178 off += copysiz; |
|
179 } |
|
180 } |
|
181 |
|
182 void sha1_result(struct sha1_ctxt *ctxt, caddr_t digest0) |
|
183 { |
|
184 quint8 *digest; |
|
185 |
|
186 digest = (quint8 *)digest0; |
|
187 sha1_pad(ctxt); |
|
188 qMemCopy(digest, &ctxt->h.b8[0], 20); |
|
189 } |