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:
SecureHashAlgorithm()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.
Digest() const52 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
f(uint32_t t,uint32_t B,uint32_t C,uint32_t D)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
S(uint32_t n,uint32_t X)91 static inline uint32_t S(uint32_t n, uint32_t X)
92 {
93 return (X << n) | (X >> (32 - n));
94 }
95
K(uint32_t t)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
Init()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
Final()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
Update(const void * data,size_t nbytes)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
Pad()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
Process()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
SHA1HashString(const std::string & str)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
SHA1HashBytes(const unsigned char * data,size_t len,unsigned char * hash)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