[go: nahoru, domu]

blob: 1232e6391f58f214206f3208925991878795b42b [file] [log] [blame]
finnur@chromium.org0777cfc2011-02-14 09:25:301// Copyright (c) 2011 The Chromium Authors. All rights reserved.
jhawkins@chromium.orgc2ad1e32009-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>
hans@chromium.org5035f682011-03-13 21:17:209#include <string.h>
10
robert.bradford0bf0dd802016-06-17 20:11:0411#include "base/sys_byteorder.h"
jhawkins@chromium.orgc2ad1e32009-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
jhawkins@chromium.orgc2ad1e32009-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
wtc@chromium.org94d557e2010-06-23 21:41:4033// implementation using each platform's crypto library. See
34// http://crbug.com/47218
jhawkins@chromium.orgc2ad1e32009-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;
jhawkins@chromium.orgc2ad1e32009-11-04 19:29:5856
avi9b6f42932015-12-26 22:15:1457 uint32_t H[5];
jhawkins@chromium.orgc2ad1e32009-11-04 19:29:5858
59 union {
avi9b6f42932015-12-26 22:15:1460 uint32_t W[80];
61 uint8_t M[64];
jhawkins@chromium.orgc2ad1e32009-11-04 19:29:5862 };
63
avi9b6f42932015-12-26 22:15:1464 uint32_t cursor;
65 uint64_t l;
jhawkins@chromium.orgc2ad1e32009-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) {
Tom Anderson68a48f7a2018-09-11 17:52:3969 if (t < 20)
jhawkins@chromium.orgc2ad1e32009-11-04 19:29:5870 return (B & C) | ((~B) & D);
Tom Anderson68a48f7a2018-09-11 17:52:3971 if (t < 40)
jhawkins@chromium.orgc2ad1e32009-11-04 19:29:5872 return B ^ C ^ D;
Tom Anderson68a48f7a2018-09-11 17:52:3973 if (t < 60)
jhawkins@chromium.orgc2ad1e32009-11-04 19:29:5874 return (B & C) | (B & D) | (C & D);
Tom Anderson68a48f7a2018-09-11 17:52:3975 return B ^ C ^ D;
jhawkins@chromium.orgc2ad1e32009-11-04 19:29:5876}
77
avi9b6f42932015-12-26 22:15:1478static inline uint32_t S(uint32_t n, uint32_t X) {
jhawkins@chromium.orgc2ad1e32009-11-04 19:29:5879 return (X << n) | (X >> (32-n));
80}
81
avi9b6f42932015-12-26 22:15:1482static inline uint32_t K(uint32_t t) {
Tom Anderson68a48f7a2018-09-11 17:52:3983 if (t < 20)
jhawkins@chromium.orgc2ad1e32009-11-04 19:29:5884 return 0x5a827999;
Tom Anderson68a48f7a2018-09-11 17:52:3985 if (t < 40)
jhawkins@chromium.orgc2ad1e32009-11-04 19:29:5886 return 0x6ed9eba1;
Tom Anderson68a48f7a2018-09-11 17:52:3987 if (t < 60)
jhawkins@chromium.orgc2ad1e32009-11-04 19:29:5888 return 0x8f1bbcdc;
Tom Anderson68a48f7a2018-09-11 17:52:3989 return 0xca62c1d6;
jhawkins@chromium.orgc2ad1e32009-11-04 19:29:5890}
91
jhawkins@chromium.orgc2ad1e32009-11-04 19:29:5892const int SecureHashAlgorithm::kDigestSizeBytes = 20;
93
94void SecureHashAlgorithm::Init() {
finnur@chromium.org0777cfc2011-02-14 09:25:3095 A = 0;
96 B = 0;
97 C = 0;
98 D = 0;
99 E = 0;
jhawkins@chromium.orgc2ad1e32009-11-04 19:29:58100 cursor = 0;
101 l = 0;
102 H[0] = 0x67452301;
103 H[1] = 0xefcdab89;
104 H[2] = 0x98badcfe;
105 H[3] = 0x10325476;
106 H[4] = 0xc3d2e1f0;
107}
108
109void SecureHashAlgorithm::Final() {
110 Pad();
111 Process();
112
jdoerrie6c6229352018-10-22 15:55:43113 for (auto& t : H)
114 t = ByteSwap(t);
jhawkins@chromium.orgc2ad1e32009-11-04 19:29:58115}
116
117void SecureHashAlgorithm::Update(const void* data, size_t nbytes) {
avi9b6f42932015-12-26 22:15:14118 const uint8_t* d = reinterpret_cast<const uint8_t*>(data);
jhawkins@chromium.orgc2ad1e32009-11-04 19:29:58119 while (nbytes--) {
120 M[cursor++] = *d++;
121 if (cursor >= 64)
122 Process();
123 l += 8;
124 }
125}
126
127void SecureHashAlgorithm::Pad() {
128 M[cursor++] = 0x80;
129
130 if (cursor > 64-8) {
131 // pad out to next block
132 while (cursor < 64)
133 M[cursor++] = 0;
134
135 Process();
136 }
137
wtc@chromium.org5c5a2022014-07-14 14:46:09138 while (cursor < 64-8)
jhawkins@chromium.orgc2ad1e32009-11-04 19:29:58139 M[cursor++] = 0;
140
wtc@chromium.org5c5a2022014-07-14 14:46:09141 M[cursor++] = (l >> 56) & 0xff;
142 M[cursor++] = (l >> 48) & 0xff;
143 M[cursor++] = (l >> 40) & 0xff;
144 M[cursor++] = (l >> 32) & 0xff;
145 M[cursor++] = (l >> 24) & 0xff;
146 M[cursor++] = (l >> 16) & 0xff;
147 M[cursor++] = (l >> 8) & 0xff;
148 M[cursor++] = l & 0xff;
jhawkins@chromium.orgc2ad1e32009-11-04 19:29:58149}
150
151void SecureHashAlgorithm::Process() {
avi9b6f42932015-12-26 22:15:14152 uint32_t t;
jhawkins@chromium.orgc2ad1e32009-11-04 19:29:58153
154 // Each a...e corresponds to a section in the FIPS 180-3 algorithm.
155
156 // a.
157 //
158 // W and M are in a union, so no need to memcpy.
159 // memcpy(W, M, sizeof(M));
160 for (t = 0; t < 16; ++t)
robert.bradford0bf0dd802016-06-17 20:11:04161 W[t] = ByteSwap(W[t]);
jhawkins@chromium.orgc2ad1e32009-11-04 19:29:58162
163 // b.
164 for (t = 16; t < 80; ++t)
165 W[t] = S(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]);
166
167 // c.
168 A = H[0];
169 B = H[1];
170 C = H[2];
171 D = H[3];
172 E = H[4];
173
174 // d.
175 for (t = 0; t < 80; ++t) {
avi9b6f42932015-12-26 22:15:14176 uint32_t TEMP = S(5, A) + f(t, B, C, D) + E + W[t] + K(t);
jhawkins@chromium.orgc2ad1e32009-11-04 19:29:58177 E = D;
178 D = C;
179 C = S(30, B);
180 B = A;
181 A = TEMP;
182 }
183
184 // e.
185 H[0] += A;
186 H[1] += B;
187 H[2] += C;
188 H[3] += D;
189 H[4] += E;
190
191 cursor = 0;
192}
193
Henrik Grunellfc4ffc72017-11-30 11:56:44194std::string SHA1HashString(const std::string& str) {
hans@chromium.org5035f682011-03-13 21:17:20195 char hash[SecureHashAlgorithm::kDigestSizeBytes];
Henrik Grunellfc4ffc72017-11-30 11:56:44196 SHA1HashBytes(reinterpret_cast<const unsigned char*>(str.c_str()),
hans@chromium.org5035f682011-03-13 21:17:20197 str.length(), reinterpret_cast<unsigned char*>(hash));
198 return std::string(hash, SecureHashAlgorithm::kDigestSizeBytes);
199}
200
201void SHA1HashBytes(const unsigned char* data, size_t len,
202 unsigned char* hash) {
jhawkins@chromium.orgc2ad1e32009-11-04 19:29:58203 SecureHashAlgorithm sha;
hans@chromium.org5035f682011-03-13 21:17:20204 sha.Update(data, len);
jhawkins@chromium.orgc2ad1e32009-11-04 19:29:58205 sha.Final();
hans@chromium.org5035f682011-03-13 21:17:20206
207 memcpy(hash, sha.Digest(), SecureHashAlgorithm::kDigestSizeBytes);
jhawkins@chromium.orgc2ad1e32009-11-04 19:29:58208}
209
210} // namespace base