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