blob: 33d1cb3f14794ffe544871c7bdf707090975eb5c [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001/* sha.c
2**
3** Copyright 2008, The Android Open Source Project
4**
5** Redistribution and use in source and binary forms, with or without
6** modification, are permitted provided that the following conditions are met:
7** * Redistributions of source code must retain the above copyright
8** notice, this list of conditions and the following disclaimer.
9** * Redistributions in binary form must reproduce the above copyright
10** notice, this list of conditions and the following disclaimer in the
11** documentation and/or other materials provided with the distribution.
12** * Neither the name of Google Inc. nor the names of its contributors may
13** be used to endorse or promote products derived from this software
14** without specific prior written permission.
15**
Doug Zongkera6de77d2009-08-17 15:38:31 -070016** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080017** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
Doug Zongkera6de77d2009-08-17 15:38:31 -070018** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080019** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
Doug Zongkera6de77d2009-08-17 15:38:31 -070021** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080024** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/
27
Doug Zongkera6de77d2009-08-17 15:38:31 -070028#include <byteswap.h>
29#include <endian.h>
30#include <memory.h>
31
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080032#include "mincrypt/sha.h"
33
Doug Zongkera6de77d2009-08-17 15:38:31 -070034#if __BYTE_ORDER == __LITTLE_ENDIAN
35
36// This version is about 28% faster than the generic version below,
37// but assumes little-endianness.
38
39static inline uint32_t ror27(uint32_t val) {
40 return (val >> 27) | (val << 5);
41}
42static inline uint32_t ror2(uint32_t val) {
43 return (val >> 2) | (val << 30);
44}
45static inline uint32_t ror31(uint32_t val) {
46 return (val >> 31) | (val << 1);
47}
48
49static void SHA1_Transform(SHA_CTX* ctx) {
50 uint32_t W[80];
51 register uint32_t A, B, C, D, E;
52 int t;
53
54 A = ctx->state[0];
55 B = ctx->state[1];
56 C = ctx->state[2];
57 D = ctx->state[3];
58 E = ctx->state[4];
59
60#define SHA_F1(A,B,C,D,E,t) \
61 E += ror27(A) + \
62 (W[t] = bswap_32(ctx->buf.w[t])) + \
63 (D^(B&(C^D))) + 0x5A827999; \
64 B = ror2(B);
65
66 for (t = 0; t < 15; t += 5) {
67 SHA_F1(A,B,C,D,E,t + 0);
68 SHA_F1(E,A,B,C,D,t + 1);
69 SHA_F1(D,E,A,B,C,t + 2);
70 SHA_F1(C,D,E,A,B,t + 3);
71 SHA_F1(B,C,D,E,A,t + 4);
72 }
73 SHA_F1(A,B,C,D,E,t + 0); // 16th one, t == 15
74
75#undef SHA_F1
76
77#define SHA_F1(A,B,C,D,E,t) \
78 E += ror27(A) + \
79 (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \
80 (D^(B&(C^D))) + 0x5A827999; \
81 B = ror2(B);
82
83 SHA_F1(E,A,B,C,D,t + 1);
84 SHA_F1(D,E,A,B,C,t + 2);
85 SHA_F1(C,D,E,A,B,t + 3);
86 SHA_F1(B,C,D,E,A,t + 4);
87
88#undef SHA_F1
89
90#define SHA_F2(A,B,C,D,E,t) \
91 E += ror27(A) + \
92 (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \
93 (B^C^D) + 0x6ED9EBA1; \
94 B = ror2(B);
95
96 for (t = 20; t < 40; t += 5) {
97 SHA_F2(A,B,C,D,E,t + 0);
98 SHA_F2(E,A,B,C,D,t + 1);
99 SHA_F2(D,E,A,B,C,t + 2);
100 SHA_F2(C,D,E,A,B,t + 3);
101 SHA_F2(B,C,D,E,A,t + 4);
102 }
103
104#undef SHA_F2
105
106#define SHA_F3(A,B,C,D,E,t) \
107 E += ror27(A) + \
108 (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \
109 ((B&C)|(D&(B|C))) + 0x8F1BBCDC; \
110 B = ror2(B);
111
112 for (; t < 60; t += 5) {
113 SHA_F3(A,B,C,D,E,t + 0);
114 SHA_F3(E,A,B,C,D,t + 1);
115 SHA_F3(D,E,A,B,C,t + 2);
116 SHA_F3(C,D,E,A,B,t + 3);
117 SHA_F3(B,C,D,E,A,t + 4);
118 }
119
120#undef SHA_F3
121
122#define SHA_F4(A,B,C,D,E,t) \
123 E += ror27(A) + \
124 (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \
125 (B^C^D) + 0xCA62C1D6; \
126 B = ror2(B);
127
128 for (; t < 80; t += 5) {
129 SHA_F4(A,B,C,D,E,t + 0);
130 SHA_F4(E,A,B,C,D,t + 1);
131 SHA_F4(D,E,A,B,C,t + 2);
132 SHA_F4(C,D,E,A,B,t + 3);
133 SHA_F4(B,C,D,E,A,t + 4);
134 }
135
136#undef SHA_F4
137
138 ctx->state[0] += A;
139 ctx->state[1] += B;
140 ctx->state[2] += C;
141 ctx->state[3] += D;
142 ctx->state[4] += E;
143}
144
145void SHA_update(SHA_CTX* ctx, const void* data, int len) {
146 int i = ctx->count % sizeof(ctx->buf);
147 const uint8_t* p = (const uint8_t*)data;
148
149 ctx->count += len;
150
151 while (len > sizeof(ctx->buf) - i) {
152 memcpy(&ctx->buf.b[i], p, sizeof(ctx->buf) - i);
153 len -= sizeof(ctx->buf) - i;
154 p += sizeof(ctx->buf) - i;
155 SHA1_Transform(ctx);
156 i = 0;
157 }
158
159 while (len--) {
160 ctx->buf.b[i++] = *p++;
161 if (i == sizeof(ctx->buf)) {
162 SHA1_Transform(ctx);
163 i = 0;
164 }
165 }
166}
167
168
169const uint8_t* SHA_final(SHA_CTX* ctx) {
170 uint64_t cnt = ctx->count * 8;
171 int i;
172
173 SHA_update(ctx, (uint8_t*)"\x80", 1);
174 while ((ctx->count % sizeof(ctx->buf)) != (sizeof(ctx->buf) - 8)) {
175 SHA_update(ctx, (uint8_t*)"\0", 1);
176 }
177 for (i = 0; i < 8; ++i) {
178 uint8_t tmp = cnt >> ((7 - i) * 8);
179 SHA_update(ctx, &tmp, 1);
180 }
181
182 for (i = 0; i < 5; i++) {
183 ctx->buf.w[i] = bswap_32(ctx->state[i]);
184 }
185
186 return ctx->buf.b;
187}
188
189#else // __BYTE_ORDER == BIG_ENDIAN
190
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800191#define rol(bits, value) (((value) << (bits)) | ((value) >> (32 - (bits))))
192
193static void SHA1_transform(SHA_CTX *ctx) {
194 uint32_t W[80];
195 uint32_t A, B, C, D, E;
196 uint8_t *p = ctx->buf;
197 int t;
198
199 for(t = 0; t < 16; ++t) {
200 uint32_t tmp = *p++ << 24;
201 tmp |= *p++ << 16;
202 tmp |= *p++ << 8;
203 tmp |= *p++;
204 W[t] = tmp;
205 }
206
207 for(; t < 80; t++) {
208 W[t] = rol(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
209 }
210
211 A = ctx->state[0];
212 B = ctx->state[1];
213 C = ctx->state[2];
214 D = ctx->state[3];
215 E = ctx->state[4];
216
217 for(t = 0; t < 80; t++) {
218 uint32_t tmp = rol(5,A) + E + W[t];
219
220 if (t < 20)
221 tmp += (D^(B&(C^D))) + 0x5A827999;
222 else if ( t < 40)
223 tmp += (B^C^D) + 0x6ED9EBA1;
224 else if ( t < 60)
225 tmp += ((B&C)|(D&(B|C))) + 0x8F1BBCDC;
226 else
227 tmp += (B^C^D) + 0xCA62C1D6;
228
229 E = D;
230 D = C;
231 C = rol(30,B);
232 B = A;
233 A = tmp;
234 }
235
236 ctx->state[0] += A;
237 ctx->state[1] += B;
238 ctx->state[2] += C;
239 ctx->state[3] += D;
240 ctx->state[4] += E;
241}
242
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800243void SHA_update(SHA_CTX *ctx, const void *data, int len) {
244 int i = ctx->count % sizeof(ctx->buf);
245 const uint8_t* p = (const uint8_t*)data;
246
247 ctx->count += len;
248
249 while (len--) {
250 ctx->buf[i++] = *p++;
251 if (i == sizeof(ctx->buf)) {
252 SHA1_transform(ctx);
253 i = 0;
254 }
255 }
256}
257const uint8_t *SHA_final(SHA_CTX *ctx) {
258 uint8_t *p = ctx->buf;
259 uint64_t cnt = ctx->count * 8;
260 int i;
261
262 SHA_update(ctx, (uint8_t*)"\x80", 1);
263 while ((ctx->count % sizeof(ctx->buf)) != (sizeof(ctx->buf) - 8)) {
264 SHA_update(ctx, (uint8_t*)"\0", 1);
265 }
266 for (i = 0; i < 8; ++i) {
267 uint8_t tmp = cnt >> ((7 - i) * 8);
268 SHA_update(ctx, &tmp, 1);
269 }
270
271 for (i = 0; i < 5; i++) {
272 uint32_t tmp = ctx->state[i];
273 *p++ = tmp >> 24;
274 *p++ = tmp >> 16;
275 *p++ = tmp >> 8;
276 *p++ = tmp >> 0;
277 }
278
279 return ctx->buf;
280}
281
Doug Zongkera6de77d2009-08-17 15:38:31 -0700282#endif // endianness
283
284void SHA_init(SHA_CTX* ctx) {
285 ctx->state[0] = 0x67452301;
286 ctx->state[1] = 0xEFCDAB89;
287 ctx->state[2] = 0x98BADCFE;
288 ctx->state[3] = 0x10325476;
289 ctx->state[4] = 0xC3D2E1F0;
290 ctx->count = 0;
291}
292
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800293/* Convenience function */
294const uint8_t* SHA(const void *data, int len, uint8_t *digest) {
295 const uint8_t *p;
296 int i;
297 SHA_CTX ctx;
298 SHA_init(&ctx);
299 SHA_update(&ctx, data, len);
300 p = SHA_final(&ctx);
301 for (i = 0; i < SHA_DIGEST_SIZE; ++i) {
302 digest[i] = *p++;
303 }
304 return digest;
305}