OLD | NEW |
| (Empty) |
1 // Copyright 2007-2009 Google Inc. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 // ======================================================================== | |
15 // | |
16 // Optimized for minimal code size. | |
17 | |
18 #include "sha.h" | |
19 | |
20 #include <stdio.h> | |
21 #include <string.h> | |
22 #include <inttypes.h> | |
23 | |
24 #define rol(bits, value) (((value) << (bits)) | ((value) >> (32 - (bits)))) | |
25 | |
26 static void SHA1_Transform(SHA_CTX* ctx) { | |
27 uint32_t W[80]; | |
28 uint32_t A, B, C, D, E; | |
29 uint8_t* p = ctx->buf; | |
30 int t; | |
31 | |
32 for(t = 0; t < 16; ++t) { | |
33 uint32_t tmp = *p++ << 24; | |
34 tmp |= *p++ << 16; | |
35 tmp |= *p++ << 8; | |
36 tmp |= *p++; | |
37 W[t] = tmp; | |
38 } | |
39 | |
40 for(; t < 80; t++) { | |
41 W[t] = rol(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); | |
42 } | |
43 | |
44 A = ctx->state[0]; | |
45 B = ctx->state[1]; | |
46 C = ctx->state[2]; | |
47 D = ctx->state[3]; | |
48 E = ctx->state[4]; | |
49 | |
50 for(t = 0; t < 80; t++) { | |
51 uint32_t tmp = rol(5,A) + E + W[t]; | |
52 | |
53 if (t < 20) | |
54 tmp += (D^(B&(C^D))) + 0x5A827999; | |
55 else if ( t < 40) | |
56 tmp += (B^C^D) + 0x6ED9EBA1; | |
57 else if ( t < 60) | |
58 tmp += ((B&C)|(D&(B|C))) + 0x8F1BBCDC; | |
59 else | |
60 tmp += (B^C^D) + 0xCA62C1D6; | |
61 | |
62 E = D; | |
63 D = C; | |
64 C = rol(30,B); | |
65 B = A; | |
66 A = tmp; | |
67 } | |
68 | |
69 ctx->state[0] += A; | |
70 ctx->state[1] += B; | |
71 ctx->state[2] += C; | |
72 ctx->state[3] += D; | |
73 ctx->state[4] += E; | |
74 } | |
75 | |
76 static const HASH_VTAB SHA_VTAB = { | |
77 SHA_init, | |
78 SHA_update, | |
79 SHA_final, | |
80 SHA, | |
81 SHA_DIGEST_SIZE | |
82 }; | |
83 | |
84 void SHA_init(SHA_CTX* ctx) { | |
85 ctx->f = &SHA_VTAB; | |
86 ctx->state[0] = 0x67452301; | |
87 ctx->state[1] = 0xEFCDAB89; | |
88 ctx->state[2] = 0x98BADCFE; | |
89 ctx->state[3] = 0x10325476; | |
90 ctx->state[4] = 0xC3D2E1F0; | |
91 ctx->count = 0; | |
92 } | |
93 | |
94 | |
95 void SHA_update(SHA_CTX* ctx, const void* data, int len) { | |
96 int i = ctx->count & 63; | |
97 const uint8_t* p = (const uint8_t*)data; | |
98 | |
99 ctx->count += len; | |
100 | |
101 while (len--) { | |
102 ctx->buf[i++] = *p++; | |
103 if (i == 64) { | |
104 SHA1_Transform(ctx); | |
105 i = 0; | |
106 } | |
107 } | |
108 } | |
109 | |
110 | |
111 const uint8_t* SHA_final(SHA_CTX* ctx) { | |
112 uint8_t *p = ctx->buf; | |
113 uint64_t cnt = ctx->count * 8; | |
114 int i; | |
115 | |
116 SHA_update(ctx, (uint8_t*)"\x80", 1); | |
117 while ((ctx->count & 63) != 56) { | |
118 SHA_update(ctx, (uint8_t*)"\0", 1); | |
119 } | |
120 for (i = 0; i < 8; ++i) { | |
121 uint8_t tmp = cnt >> ((7 - i) * 8); | |
122 SHA_update(ctx, &tmp, 1); | |
123 } | |
124 | |
125 for (i = 0; i < 5; i++) { | |
126 uint32_t tmp = ctx->state[i]; | |
127 *p++ = tmp >> 24; | |
128 *p++ = tmp >> 16; | |
129 *p++ = tmp >> 8; | |
130 *p++ = tmp >> 0; | |
131 } | |
132 | |
133 return ctx->buf; | |
134 } | |
135 | |
136 /* Convenience function */ | |
137 const uint8_t* SHA(const void* data, int len, uint8_t* digest) { | |
138 SHA_CTX ctx; | |
139 SHA_init(&ctx); | |
140 SHA_update(&ctx, data, len); | |
141 memcpy(digest, SHA_final(&ctx), SHA_DIGEST_SIZE); | |
142 return digest; | |
143 } | |
OLD | NEW |