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