finnur@chromium.org | fa6208c | 2011-02-14 18:25:30 +0900 | [diff] [blame] | 1 | // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
jhawkins@chromium.org | f64907f | 2009-11-05 04:29:58 +0900 | [diff] [blame] | 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 | |
hans@chromium.org | 273df68 | 2011-03-14 06:17:20 +0900 | [diff] [blame] | 7 | #include <string.h> |
| 8 | |
jhawkins@chromium.org | f64907f | 2009-11-05 04:29:58 +0900 | [diff] [blame] | 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 | |
jhawkins@chromium.org | f64907f | 2009-11-05 04:29:58 +0900 | [diff] [blame] | 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 |
wtc@chromium.org | d828db4 | 2010-06-24 06:41:40 +0900 | [diff] [blame] | 31 | // implementation using each platform's crypto library. See |
| 32 | // http://crbug.com/47218 |
jhawkins@chromium.org | f64907f | 2009-11-05 04:29:58 +0900 | [diff] [blame] | 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; |
wtc@chromium.org | 81c9f98 | 2014-07-14 23:46:09 +0900 | [diff] [blame] | 63 | uint64 l; |
jhawkins@chromium.org | f64907f | 2009-11-05 04:29:58 +0900 | [diff] [blame] | 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 | |
wtc@chromium.org | d828db4 | 2010-06-24 06:41:40 +0900 | [diff] [blame] | 94 | static inline void swapends(uint32* t) { |
wtc@chromium.org | 81c9f98 | 2014-07-14 23:46:09 +0900 | [diff] [blame] | 95 | *t = (*t >> 24) | ((*t >> 8) & 0xff00) | ((*t & 0xff00) << 8) | (*t << 24); |
jhawkins@chromium.org | f64907f | 2009-11-05 04:29:58 +0900 | [diff] [blame] | 96 | } |
| 97 | |
| 98 | const int SecureHashAlgorithm::kDigestSizeBytes = 20; |
| 99 | |
| 100 | void SecureHashAlgorithm::Init() { |
finnur@chromium.org | fa6208c | 2011-02-14 18:25:30 +0900 | [diff] [blame] | 101 | A = 0; |
| 102 | B = 0; |
| 103 | C = 0; |
| 104 | D = 0; |
| 105 | E = 0; |
jhawkins@chromium.org | f64907f | 2009-11-05 04:29:58 +0900 | [diff] [blame] | 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) |
wtc@chromium.org | d828db4 | 2010-06-24 06:41:40 +0900 | [diff] [blame] | 120 | swapends(&H[t]); |
jhawkins@chromium.org | f64907f | 2009-11-05 04:29:58 +0900 | [diff] [blame] | 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 | |
wtc@chromium.org | 81c9f98 | 2014-07-14 23:46:09 +0900 | [diff] [blame] | 144 | while (cursor < 64-8) |
jhawkins@chromium.org | f64907f | 2009-11-05 04:29:58 +0900 | [diff] [blame] | 145 | M[cursor++] = 0; |
| 146 | |
wtc@chromium.org | 81c9f98 | 2014-07-14 23:46:09 +0900 | [diff] [blame] | 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; |
jhawkins@chromium.org | f64907f | 2009-11-05 04:29:58 +0900 | [diff] [blame] | 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) |
wtc@chromium.org | d828db4 | 2010-06-24 06:41:40 +0900 | [diff] [blame] | 167 | swapends(&W[t]); |
jhawkins@chromium.org | f64907f | 2009-11-05 04:29:58 +0900 | [diff] [blame] | 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) { |
hans@chromium.org | 273df68 | 2011-03-14 06:17:20 +0900 | [diff] [blame] | 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) { |
jhawkins@chromium.org | f64907f | 2009-11-05 04:29:58 +0900 | [diff] [blame] | 209 | SecureHashAlgorithm sha; |
hans@chromium.org | 273df68 | 2011-03-14 06:17:20 +0900 | [diff] [blame] | 210 | sha.Update(data, len); |
jhawkins@chromium.org | f64907f | 2009-11-05 04:29:58 +0900 | [diff] [blame] | 211 | sha.Final(); |
hans@chromium.org | 273df68 | 2011-03-14 06:17:20 +0900 | [diff] [blame] | 212 | |
| 213 | memcpy(hash, sha.Digest(), SecureHashAlgorithm::kDigestSizeBytes); |
jhawkins@chromium.org | f64907f | 2009-11-05 04:29:58 +0900 | [diff] [blame] | 214 | } |
| 215 | |
| 216 | } // namespace base |