• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 The Chromium Authors
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/hash/sha1.h"
6 
7 #include <stddef.h>
8 #include <stdint.h>
9 #include <string.h>
10 
11 #include "base/sys_byteorder.h"
12 
13 namespace base {
14 // Implementation of SHA-1. Only handles data in byte-sized blocks,
15 // which simplifies the code a fair bit.
16 
17 // Identifier names follow notation in FIPS PUB 180-3, where you'll
18 // also find a description of the algorithm:
19 // http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf
20 
21 // Usage example:
22 //
23 // SecureHashAlgorithm sha;
24 // while(there is data to hash)
25 //   sha.Update(moredata, size of data);
26 // sha.Final();
27 // memcpy(somewhere, sha.Digest(), 20);
28 //
29 // to reuse the instance of sha, call sha.Init();
30 
f(uint32_t t,uint32_t B,uint32_t C,uint32_t D)31 static inline uint32_t f(uint32_t t, uint32_t B, uint32_t C, uint32_t D) {
32   if (t < 20)
33     return (B & C) | ((~B) & D);
34   if (t < 40)
35     return B ^ C ^ D;
36   if (t < 60)
37     return (B & C) | (B & D) | (C & D);
38   return B ^ C ^ D;
39 }
40 
S(uint32_t n,uint32_t X)41 static inline uint32_t S(uint32_t n, uint32_t X) {
42   return (X << n) | (X >> (32 - n));
43 }
44 
K(uint32_t t)45 static inline uint32_t K(uint32_t t) {
46   if (t < 20)
47     return 0x5a827999;
48   if (t < 40)
49     return 0x6ed9eba1;
50   if (t < 60)
51     return 0x8f1bbcdc;
52   return 0xca62c1d6;
53 }
54 
Init()55 void SHA1Context::Init() {
56   A = 0;
57   B = 0;
58   C = 0;
59   D = 0;
60   E = 0;
61   cursor = 0;
62   l = 0;
63   H[0] = 0x67452301;
64   H[1] = 0xefcdab89;
65   H[2] = 0x98badcfe;
66   H[3] = 0x10325476;
67   H[4] = 0xc3d2e1f0;
68 }
69 
Update(const void * data,size_t nbytes)70 void SHA1Context::Update(const void* data, size_t nbytes) {
71   const uint8_t* d = reinterpret_cast<const uint8_t*>(data);
72   while (nbytes--) {
73     M[cursor++] = *d++;
74     if (cursor >= 64) {
75       Process();
76     }
77     l += 8;
78   }
79 }
80 
Final()81 void SHA1Context::Final() {
82   Pad();
83   Process();
84 
85   for (auto& t : H) {
86     t = ByteSwap(t);
87   }
88 }
89 
GetDigest() const90 const unsigned char* SHA1Context::GetDigest() const {
91   return reinterpret_cast<const unsigned char*>(H);
92 }
93 
Pad()94 void SHA1Context::Pad() {
95   M[cursor++] = 0x80;
96 
97   if (cursor > 64 - 8) {
98     // pad out to next block
99     while (cursor < 64) {
100       M[cursor++] = 0;
101     }
102 
103     Process();
104   }
105 
106   while (cursor < 64 - 8) {
107     M[cursor++] = 0;
108   }
109 
110   M[cursor++] = (l >> 56) & 0xff;
111   M[cursor++] = (l >> 48) & 0xff;
112   M[cursor++] = (l >> 40) & 0xff;
113   M[cursor++] = (l >> 32) & 0xff;
114   M[cursor++] = (l >> 24) & 0xff;
115   M[cursor++] = (l >> 16) & 0xff;
116   M[cursor++] = (l >> 8) & 0xff;
117   M[cursor++] = l & 0xff;
118 }
119 
Process()120 void SHA1Context::Process() {
121   uint32_t t;
122 
123   // Each a...e corresponds to a section in the FIPS 180-3 algorithm.
124 
125   // a.
126   //
127   // W and M are in a union, so no need to memcpy.
128   // memcpy(W, M, sizeof(M));
129   for (t = 0; t < 16; ++t) {
130     W[t] = ByteSwap(W[t]);
131   }
132 
133   // b.
134   for (t = 16; t < 80; ++t) {
135     W[t] = S(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]);
136   }
137 
138   // c.
139   A = H[0];
140   B = H[1];
141   C = H[2];
142   D = H[3];
143   E = H[4];
144 
145   // d.
146   for (t = 0; t < 80; ++t) {
147     uint32_t TEMP = S(5, A) + f(t, B, C, D) + E + W[t] + K(t);
148     E = D;
149     D = C;
150     C = S(30, B);
151     B = A;
152     A = TEMP;
153   }
154 
155   // e.
156   H[0] += A;
157   H[1] += B;
158   H[2] += C;
159   H[3] += D;
160   H[4] += E;
161 
162   cursor = 0;
163 }
164 
165 // These functions allow streaming SHA-1 operations.
SHA1Init(SHA1Context & context)166 void SHA1Init(SHA1Context& context) {
167   context.Init();
168 }
169 
SHA1Update(const StringPiece data,SHA1Context & context)170 void SHA1Update(const StringPiece data, SHA1Context& context) {
171   context.Update(data.data(), data.size());
172 }
173 
SHA1Final(SHA1Context & context,SHA1Digest & digest)174 void SHA1Final(SHA1Context& context, SHA1Digest& digest) {
175   context.Final();
176   memcpy(digest.data(), context.GetDigest(), kSHA1Length);
177 }
178 
SHA1HashSpan(span<const uint8_t> data)179 SHA1Digest SHA1HashSpan(span<const uint8_t> data) {
180   SHA1Digest hash;
181   SHA1HashBytes(data.data(), data.size(), hash.data());
182   return hash;
183 }
184 
SHA1HashString(StringPiece str)185 std::string SHA1HashString(StringPiece str) {
186   char hash[kSHA1Length];
187   SHA1HashBytes(reinterpret_cast<const unsigned char*>(str.data()),
188                 str.length(), reinterpret_cast<unsigned char*>(hash));
189   return std::string(hash, kSHA1Length);
190 }
191 
SHA1HashBytes(const unsigned char * data,size_t len,unsigned char * hash)192 void SHA1HashBytes(const unsigned char* data, size_t len, unsigned char* hash) {
193   SHA1Context context;
194   context.Init();
195   context.Update(data, len);
196   context.Final();
197 
198   memcpy(hash, context.GetDigest(), kSHA1Length);
199 }
200 
201 }  // namespace base
202