Upstream version 9.38.198.0
[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   uint64 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 >> 24) | ((*t >> 8) & 0xff00) | ((*t & 0xff00) << 8) | (*t << 24);
96 }
97
98 const int SecureHashAlgorithm::kDigestSizeBytes = 20;
99
100 void SecureHashAlgorithm::Init() {
101   A = 0;
102   B = 0;
103   C = 0;
104   D = 0;
105   E = 0;
106   cursor = 0;
107   l = 0;
108   H[0] = 0x67452301;
109   H[1] = 0xefcdab89;
110   H[2] = 0x98badcfe;
111   H[3] = 0x10325476;
112   H[4] = 0xc3d2e1f0;
113 }
114
115 void SecureHashAlgorithm::Final() {
116   Pad();
117   Process();
118
119   for (int t = 0; t < 5; ++t)
120     swapends(&H[t]);
121 }
122
123 void SecureHashAlgorithm::Update(const void* data, size_t nbytes) {
124   const uint8* d = reinterpret_cast<const uint8*>(data);
125   while (nbytes--) {
126     M[cursor++] = *d++;
127     if (cursor >= 64)
128       Process();
129     l += 8;
130   }
131 }
132
133 void SecureHashAlgorithm::Pad() {
134   M[cursor++] = 0x80;
135
136   if (cursor > 64-8) {
137     // pad out to next block
138     while (cursor < 64)
139       M[cursor++] = 0;
140
141     Process();
142   }
143
144   while (cursor < 64-8)
145     M[cursor++] = 0;
146
147   M[cursor++] = (l >> 56) & 0xff;
148   M[cursor++] = (l >> 48) & 0xff;
149   M[cursor++] = (l >> 40) & 0xff;
150   M[cursor++] = (l >> 32) & 0xff;
151   M[cursor++] = (l >> 24) & 0xff;
152   M[cursor++] = (l >> 16) & 0xff;
153   M[cursor++] = (l >> 8) & 0xff;
154   M[cursor++] = l & 0xff;
155 }
156
157 void SecureHashAlgorithm::Process() {
158   uint32 t;
159
160   // Each a...e corresponds to a section in the FIPS 180-3 algorithm.
161
162   // a.
163   //
164   // W and M are in a union, so no need to memcpy.
165   // memcpy(W, M, sizeof(M));
166   for (t = 0; t < 16; ++t)
167     swapends(&W[t]);
168
169   // b.
170   for (t = 16; t < 80; ++t)
171     W[t] = S(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]);
172
173   // c.
174   A = H[0];
175   B = H[1];
176   C = H[2];
177   D = H[3];
178   E = H[4];
179
180   // d.
181   for (t = 0; t < 80; ++t) {
182     uint32 TEMP = S(5, A) + f(t, B, C, D) + E + W[t] + K(t);
183     E = D;
184     D = C;
185     C = S(30, B);
186     B = A;
187     A = TEMP;
188   }
189
190   // e.
191   H[0] += A;
192   H[1] += B;
193   H[2] += C;
194   H[3] += D;
195   H[4] += E;
196
197   cursor = 0;
198 }
199
200 std::string SHA1HashString(const std::string& str) {
201   char hash[SecureHashAlgorithm::kDigestSizeBytes];
202   SHA1HashBytes(reinterpret_cast<const unsigned char*>(str.c_str()),
203                 str.length(), reinterpret_cast<unsigned char*>(hash));
204   return std::string(hash, SecureHashAlgorithm::kDigestSizeBytes);
205 }
206
207 void SHA1HashBytes(const unsigned char* data, size_t len,
208                    unsigned char* hash) {
209   SecureHashAlgorithm sha;
210   sha.Update(data, len);
211   sha.Final();
212
213   memcpy(hash, sha.Digest(), SecureHashAlgorithm::kDigestSizeBytes);
214 }
215
216 }  // namespace base