1 | // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | #include "anglebase/sha1.h" |
6 | |
7 | #include <stddef.h> |
8 | #include <stdint.h> |
9 | #include <string.h> |
10 | |
11 | #include "anglebase/sys_byteorder.h" |
12 | |
13 | namespace angle |
14 | { |
15 | |
16 | namespace base |
17 | { |
18 | |
19 | // Implementation of SHA-1. Only handles data in byte-sized blocks, |
20 | // which simplifies the code a fair bit. |
21 | |
22 | // Identifier names follow notation in FIPS PUB 180-3, where you'll |
23 | // also find a description of the algorithm: |
24 | // http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf |
25 | |
26 | // Usage example: |
27 | // |
28 | // SecureHashAlgorithm sha; |
29 | // while(there is data to hash) |
30 | // sha.Update(moredata, size of data); |
31 | // sha.Final(); |
32 | // memcpy(somewhere, sha.Digest(), 20); |
33 | // |
34 | // to reuse the instance of sha, call sha.Init(); |
35 | |
36 | // TODO(jhawkins): Replace this implementation with a per-platform |
37 | // implementation using each platform's crypto library. See |
38 | // http://crbug.com/47218 |
39 | |
40 | class SecureHashAlgorithm |
41 | { |
42 | public: |
43 | SecureHashAlgorithm() { Init(); } |
44 | |
45 | static const int kDigestSizeBytes; |
46 | |
47 | void Init(); |
48 | void Update(const void *data, size_t nbytes); |
49 | void Final(); |
50 | |
51 | // 20 bytes of message digest. |
52 | const unsigned char *Digest() const { return reinterpret_cast<const unsigned char *>(H); } |
53 | |
54 | private: |
55 | void Pad(); |
56 | void Process(); |
57 | |
58 | uint32_t A, B, C, D, E; |
59 | |
60 | uint32_t H[5]; |
61 | |
62 | union { |
63 | uint32_t W[80]; |
64 | uint8_t M[64]; |
65 | }; |
66 | |
67 | uint32_t cursor; |
68 | uint64_t l; |
69 | }; |
70 | |
71 | static inline uint32_t f(uint32_t t, uint32_t B, uint32_t C, uint32_t D) |
72 | { |
73 | if (t < 20) |
74 | { |
75 | return (B & C) | ((~B) & D); |
76 | } |
77 | else if (t < 40) |
78 | { |
79 | return B ^ C ^ D; |
80 | } |
81 | else if (t < 60) |
82 | { |
83 | return (B & C) | (B & D) | (C & D); |
84 | } |
85 | else |
86 | { |
87 | return B ^ C ^ D; |
88 | } |
89 | } |
90 | |
91 | static inline uint32_t S(uint32_t n, uint32_t X) |
92 | { |
93 | return (X << n) | (X >> (32 - n)); |
94 | } |
95 | |
96 | static inline uint32_t K(uint32_t t) |
97 | { |
98 | if (t < 20) |
99 | { |
100 | return 0x5a827999; |
101 | } |
102 | else if (t < 40) |
103 | { |
104 | return 0x6ed9eba1; |
105 | } |
106 | else if (t < 60) |
107 | { |
108 | return 0x8f1bbcdc; |
109 | } |
110 | else |
111 | { |
112 | return 0xca62c1d6; |
113 | } |
114 | } |
115 | |
116 | const int SecureHashAlgorithm::kDigestSizeBytes = 20; |
117 | |
118 | void SecureHashAlgorithm::Init() |
119 | { |
120 | A = 0; |
121 | B = 0; |
122 | C = 0; |
123 | D = 0; |
124 | E = 0; |
125 | cursor = 0; |
126 | l = 0; |
127 | H[0] = 0x67452301; |
128 | H[1] = 0xefcdab89; |
129 | H[2] = 0x98badcfe; |
130 | H[3] = 0x10325476; |
131 | H[4] = 0xc3d2e1f0; |
132 | } |
133 | |
134 | void SecureHashAlgorithm::Final() |
135 | { |
136 | Pad(); |
137 | Process(); |
138 | |
139 | for (int t = 0; t < 5; ++t) |
140 | H[t] = ByteSwap(H[t]); |
141 | } |
142 | |
143 | void SecureHashAlgorithm::Update(const void *data, size_t nbytes) |
144 | { |
145 | const uint8_t *d = reinterpret_cast<const uint8_t *>(data); |
146 | while (nbytes--) |
147 | { |
148 | M[cursor++] = *d++; |
149 | if (cursor >= 64) |
150 | Process(); |
151 | l += 8; |
152 | } |
153 | } |
154 | |
155 | void SecureHashAlgorithm::Pad() |
156 | { |
157 | M[cursor++] = 0x80; |
158 | |
159 | if (cursor > 64 - 8) |
160 | { |
161 | // pad out to next block |
162 | while (cursor < 64) |
163 | M[cursor++] = 0; |
164 | |
165 | Process(); |
166 | } |
167 | |
168 | while (cursor < 64 - 8) |
169 | M[cursor++] = 0; |
170 | |
171 | M[cursor++] = (l >> 56) & 0xff; |
172 | M[cursor++] = (l >> 48) & 0xff; |
173 | M[cursor++] = (l >> 40) & 0xff; |
174 | M[cursor++] = (l >> 32) & 0xff; |
175 | M[cursor++] = (l >> 24) & 0xff; |
176 | M[cursor++] = (l >> 16) & 0xff; |
177 | M[cursor++] = (l >> 8) & 0xff; |
178 | M[cursor++] = l & 0xff; |
179 | } |
180 | |
181 | void SecureHashAlgorithm::Process() |
182 | { |
183 | uint32_t t; |
184 | |
185 | // Each a...e corresponds to a section in the FIPS 180-3 algorithm. |
186 | |
187 | // a. |
188 | // |
189 | // W and M are in a union, so no need to memcpy. |
190 | // memcpy(W, M, sizeof(M)); |
191 | for (t = 0; t < 16; ++t) |
192 | W[t] = ByteSwap(W[t]); |
193 | |
194 | // b. |
195 | for (t = 16; t < 80; ++t) |
196 | W[t] = S(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]); |
197 | |
198 | // c. |
199 | A = H[0]; |
200 | B = H[1]; |
201 | C = H[2]; |
202 | D = H[3]; |
203 | E = H[4]; |
204 | |
205 | // d. |
206 | for (t = 0; t < 80; ++t) |
207 | { |
208 | uint32_t TEMP = S(5, A) + f(t, B, C, D) + E + W[t] + K(t); |
209 | E = D; |
210 | D = C; |
211 | C = S(30, B); |
212 | B = A; |
213 | A = TEMP; |
214 | } |
215 | |
216 | // e. |
217 | H[0] += A; |
218 | H[1] += B; |
219 | H[2] += C; |
220 | H[3] += D; |
221 | H[4] += E; |
222 | |
223 | cursor = 0; |
224 | } |
225 | |
226 | std::string SHA1HashString(const std::string &str) |
227 | { |
228 | char hash[SecureHashAlgorithm::kDigestSizeBytes]; |
229 | SHA1HashBytes(reinterpret_cast<const unsigned char *>(str.c_str()), str.length(), |
230 | reinterpret_cast<unsigned char *>(hash)); |
231 | return std::string(hash, SecureHashAlgorithm::kDigestSizeBytes); |
232 | } |
233 | |
234 | void SHA1HashBytes(const unsigned char *data, size_t len, unsigned char *hash) |
235 | { |
236 | SecureHashAlgorithm sha; |
237 | sha.Update(data, len); |
238 | sha.Final(); |
239 | |
240 | memcpy(hash, sha.Digest(), SecureHashAlgorithm::kDigestSizeBytes); |
241 | } |
242 | |
243 | } // namespace base |
244 | |
245 | } // namespace angle |
246 | |