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