blob: a710001ab70ec7a00ec2096370d2bbc6d255c05d [file] [log] [blame]
[email protected]0777cfc2011-02-14 09:25:301// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]c2ad1e32009-11-04 19:29:582// 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
avi9b6f42932015-12-26 22:15:147#include <stddef.h>
8#include <stdint.h>
[email protected]5035f682011-03-13 21:17:209#include <string.h>
10
robert.bradford0bf0dd802016-06-17 20:11:0411#include "base/sys_byteorder.h"
[email protected]c2ad1e32009-11-04 19:29:5812
13namespace base {
14
15// Implementation of SHA-1. Only handles data in byte-sized blocks,
16// which simplifies the code a fair bit.
17
[email protected]c2ad1e32009-11-04 19:29:5818// Identifier names follow notation in FIPS PUB 180-3, where you'll
19// also find a description of the algorithm:
20// http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf
21
22// Usage example:
23//
24// SecureHashAlgorithm sha;
25// while(there is data to hash)
26// sha.Update(moredata, size of data);
27// sha.Final();
28// memcpy(somewhere, sha.Digest(), 20);
29//
30// to reuse the instance of sha, call sha.Init();
31
32// TODO(jhawkins): Replace this implementation with a per-platform
[email protected]94d557e2010-06-23 21:41:4033// implementation using each platform's crypto library. See
34// http://crbug.com/47218
[email protected]c2ad1e32009-11-04 19:29:5835
36class SecureHashAlgorithm {
37 public:
38 SecureHashAlgorithm() { Init(); }
39
40 static const int kDigestSizeBytes;
41
42 void Init();
43 void Update(const void* data, size_t nbytes);
44 void Final();
45
46 // 20 bytes of message digest.
47 const unsigned char* Digest() const {
48 return reinterpret_cast<const unsigned char*>(H);
49 }
50
51 private:
52 void Pad();
53 void Process();
54
avi9b6f42932015-12-26 22:15:1455 uint32_t A, B, C, D, E;
[email protected]c2ad1e32009-11-04 19:29:5856
avi9b6f42932015-12-26 22:15:1457 uint32_t H[5];
[email protected]c2ad1e32009-11-04 19:29:5858
59 union {
avi9b6f42932015-12-26 22:15:1460 uint32_t W[80];
61 uint8_t M[64];
[email protected]c2ad1e32009-11-04 19:29:5862 };
63
avi9b6f42932015-12-26 22:15:1464 uint32_t cursor;
65 uint64_t l;
[email protected]c2ad1e32009-11-04 19:29:5866};
67
avi9b6f42932015-12-26 22:15:1468static inline uint32_t f(uint32_t t, uint32_t B, uint32_t C, uint32_t D) {
[email protected]c2ad1e32009-11-04 19:29:5869 if (t < 20) {
70 return (B & C) | ((~B) & D);
71 } else if (t < 40) {
72 return B ^ C ^ D;
73 } else if (t < 60) {
74 return (B & C) | (B & D) | (C & D);
75 } else {
76 return B ^ C ^ D;
77 }
78}
79
avi9b6f42932015-12-26 22:15:1480static inline uint32_t S(uint32_t n, uint32_t X) {
[email protected]c2ad1e32009-11-04 19:29:5881 return (X << n) | (X >> (32-n));
82}
83
avi9b6f42932015-12-26 22:15:1484static inline uint32_t K(uint32_t t) {
[email protected]c2ad1e32009-11-04 19:29:5885 if (t < 20) {
86 return 0x5a827999;
87 } else if (t < 40) {
88 return 0x6ed9eba1;
89 } else if (t < 60) {
90 return 0x8f1bbcdc;
91 } else {
92 return 0xca62c1d6;
93 }
94}
95
[email protected]c2ad1e32009-11-04 19:29:5896const int SecureHashAlgorithm::kDigestSizeBytes = 20;
97
98void SecureHashAlgorithm::Init() {
[email protected]0777cfc2011-02-14 09:25:3099 A = 0;
100 B = 0;
101 C = 0;
102 D = 0;
103 E = 0;
[email protected]c2ad1e32009-11-04 19:29:58104 cursor = 0;
105 l = 0;
106 H[0] = 0x67452301;
107 H[1] = 0xefcdab89;
108 H[2] = 0x98badcfe;
109 H[3] = 0x10325476;
110 H[4] = 0xc3d2e1f0;
111}
112
113void SecureHashAlgorithm::Final() {
114 Pad();
115 Process();
116
117 for (int t = 0; t < 5; ++t)
robert.bradford0bf0dd802016-06-17 20:11:04118 H[t] = ByteSwap(H[t]);
[email protected]c2ad1e32009-11-04 19:29:58119}
120
121void SecureHashAlgorithm::Update(const void* data, size_t nbytes) {
avi9b6f42932015-12-26 22:15:14122 const uint8_t* d = reinterpret_cast<const uint8_t*>(data);
[email protected]c2ad1e32009-11-04 19:29:58123 while (nbytes--) {
124 M[cursor++] = *d++;
125 if (cursor >= 64)
126 Process();
127 l += 8;
128 }
129}
130
131void SecureHashAlgorithm::Pad() {
132 M[cursor++] = 0x80;
133
134 if (cursor > 64-8) {
135 // pad out to next block
136 while (cursor < 64)
137 M[cursor++] = 0;
138
139 Process();
140 }
141
[email protected]5c5a2022014-07-14 14:46:09142 while (cursor < 64-8)
[email protected]c2ad1e32009-11-04 19:29:58143 M[cursor++] = 0;
144
[email protected]5c5a2022014-07-14 14:46:09145 M[cursor++] = (l >> 56) & 0xff;
146 M[cursor++] = (l >> 48) & 0xff;
147 M[cursor++] = (l >> 40) & 0xff;
148 M[cursor++] = (l >> 32) & 0xff;
149 M[cursor++] = (l >> 24) & 0xff;
150 M[cursor++] = (l >> 16) & 0xff;
151 M[cursor++] = (l >> 8) & 0xff;
152 M[cursor++] = l & 0xff;
[email protected]c2ad1e32009-11-04 19:29:58153}
154
155void SecureHashAlgorithm::Process() {
avi9b6f42932015-12-26 22:15:14156 uint32_t t;
[email protected]c2ad1e32009-11-04 19:29:58157
158 // Each a...e corresponds to a section in the FIPS 180-3 algorithm.
159
160 // a.
161 //
162 // W and M are in a union, so no need to memcpy.
163 // memcpy(W, M, sizeof(M));
164 for (t = 0; t < 16; ++t)
robert.bradford0bf0dd802016-06-17 20:11:04165 W[t] = ByteSwap(W[t]);
[email protected]c2ad1e32009-11-04 19:29:58166
167 // b.
168 for (t = 16; t < 80; ++t)
169 W[t] = S(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]);
170
171 // c.
172 A = H[0];
173 B = H[1];
174 C = H[2];
175 D = H[3];
176 E = H[4];
177
178 // d.
179 for (t = 0; t < 80; ++t) {
avi9b6f42932015-12-26 22:15:14180 uint32_t TEMP = S(5, A) + f(t, B, C, D) + E + W[t] + K(t);
[email protected]c2ad1e32009-11-04 19:29:58181 E = D;
182 D = C;
183 C = S(30, B);
184 B = A;
185 A = TEMP;
186 }
187
188 // e.
189 H[0] += A;
190 H[1] += B;
191 H[2] += C;
192 H[3] += D;
193 H[4] += E;
194
195 cursor = 0;
196}
197
Henrik Grunellfc4ffc72017-11-30 11:56:44198std::string SHA1HashString(const std::string& str) {
[email protected]5035f682011-03-13 21:17:20199 char hash[SecureHashAlgorithm::kDigestSizeBytes];
Henrik Grunellfc4ffc72017-11-30 11:56:44200 SHA1HashBytes(reinterpret_cast<const unsigned char*>(str.c_str()),
[email protected]5035f682011-03-13 21:17:20201 str.length(), reinterpret_cast<unsigned char*>(hash));
202 return std::string(hash, SecureHashAlgorithm::kDigestSizeBytes);
203}
204
205void SHA1HashBytes(const unsigned char* data, size_t len,
206 unsigned char* hash) {
[email protected]c2ad1e32009-11-04 19:29:58207 SecureHashAlgorithm sha;
[email protected]5035f682011-03-13 21:17:20208 sha.Update(data, len);
[email protected]c2ad1e32009-11-04 19:29:58209 sha.Final();
[email protected]5035f682011-03-13 21:17:20210
211 memcpy(hash, sha.Digest(), SecureHashAlgorithm::kDigestSizeBytes);
[email protected]c2ad1e32009-11-04 19:29:58212}
213
214} // namespace base