Coverage Report

Created: 2025-04-24 07:09

/src/mcl/include/cybozu/sha2.hpp
Line
Count
Source (jump to first uncovered line)
1
#pragma once
2
/**
3
  @file
4
  @brief SHA-256, SHA-512 class
5
  @author MITSUNARI Shigeo(@herumi)
6
  @license modified new BSD license
7
  http://opensource.org/licenses/BSD-3-Clause
8
*/
9
#if !defined(CYBOZU_DONT_USE_OPENSSL) && !defined(MCL_DONT_USE_OPENSSL)
10
  #define CYBOZU_USE_OPENSSL_SHA
11
#endif
12
13
#ifndef CYBOZU_DONT_USE_STRING
14
#include <string>
15
#endif
16
#include <memory.h>
17
18
#ifdef CYBOZU_USE_OPENSSL_SHA
19
20
#ifndef CYBOZU_USE_OPENSSL_NEW_HASH
21
#ifndef _MSC_VER
22
#define CYBOZU_USE_OPENSSL_NEW_HASH 1
23
#endif
24
#endif
25
26
#ifdef __APPLE__
27
  #pragma GCC diagnostic push
28
  #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
29
#endif
30
#if CYBOZU_USE_OPENSSL_NEW_HASH == 1
31
#include <openssl/evp.h>
32
#include <assert.h>
33
#else
34
#include <openssl/sha.h>
35
#endif
36
#ifdef _MSC_VER
37
  #include <cybozu/link_libeay32.hpp>
38
#endif
39
40
#ifdef __APPLE__
41
  #pragma GCC diagnostic pop
42
#endif
43
44
namespace cybozu {
45
46
#if CYBOZU_USE_OPENSSL_NEW_HASH == 1
47
namespace local {
48
49
template<size_t MD_SIZE_>
50
struct NewHash {
51
  static const size_t MD_SIZE = MD_SIZE_;
52
  EVP_MD_CTX *mdctx_;
53
  const EVP_MD *md_;
54
  explicit NewHash(const char *name)
55
    : mdctx_(EVP_MD_CTX_new())
56
    , md_(EVP_get_digestbyname(name))
57
  {
58
    if (md_ == 0) {
59
      fprintf(stderr, "fatal error NewHash %s\n", name);
60
    }
61
    assert(md_);
62
  }
63
  ~NewHash()
64
  {
65
    EVP_MD_CTX_free(mdctx_);
66
  }
67
  void clear()
68
  {
69
    EVP_MD_CTX_reset(mdctx_);
70
    EVP_DigestInit_ex(mdctx_, md_, NULL);
71
  }
72
  void update(const void *buf, size_t bufSize)
73
  {
74
    EVP_DigestUpdate(mdctx_, buf, bufSize);
75
  }
76
  size_t digest(void *md, size_t mdSize, const void *buf, size_t bufSize)
77
  {
78
    if (mdSize < MD_SIZE) return 0;
79
    update(buf, bufSize);
80
    unsigned int len;
81
    EVP_DigestFinal_ex(mdctx_, (unsigned char*)md, &len);
82
    assert(len == MD_SIZE);
83
    return MD_SIZE;
84
  }
85
};
86
87
} // local
88
#endif
89
90
class Sha256 {
91
#if CYBOZU_USE_OPENSSL_NEW_HASH == 1
92
  local::NewHash<32> ctx_;
93
#else
94
  SHA256_CTX ctx_;
95
#endif
96
public:
97
  Sha256()
98
#if CYBOZU_USE_OPENSSL_NEW_HASH == 1
99
    : ctx_("sha256")
100
#endif
101
  {
102
    clear();
103
  }
104
  void clear()
105
  {
106
#if CYBOZU_USE_OPENSSL_NEW_HASH == 1
107
    ctx_.clear();
108
#else
109
    SHA256_Init(&ctx_);
110
#endif
111
  }
112
  void update(const void *buf, size_t bufSize)
113
  {
114
#if CYBOZU_USE_OPENSSL_NEW_HASH == 1
115
    ctx_.update(buf, bufSize);
116
#else
117
    SHA256_Update(&ctx_, buf, bufSize);
118
#endif
119
  }
120
  size_t digest(void *md, size_t mdSize, const void *buf, size_t bufSize)
121
  {
122
#if CYBOZU_USE_OPENSSL_NEW_HASH == 1
123
    return ctx_.digest(md, mdSize, buf, bufSize);
124
#else
125
    if (mdSize < SHA256_DIGEST_LENGTH) return 0;
126
    update(buf, bufSize);
127
    SHA256_Final(reinterpret_cast<uint8_t*>(md), &ctx_);
128
    return SHA256_DIGEST_LENGTH;
129
#endif
130
  }
131
#ifndef CYBOZU_DONT_USE_STRING
132
  void update(const std::string& buf)
133
  {
134
    update(buf.c_str(), buf.size());
135
  }
136
  std::string digest(const std::string& buf)
137
  {
138
    return digest(buf.c_str(), buf.size());
139
  }
140
  std::string digest(const void *buf, size_t bufSize)
141
  {
142
#if CYBOZU_USE_OPENSSL_NEW_HASH == 1
143
    std::string md(ctx_.MD_SIZE, 0);
144
#else
145
    std::string md(SHA256_DIGEST_LENGTH, 0);
146
#endif
147
    digest(&md[0], md.size(), buf, bufSize);
148
    return md;
149
  }
150
#endif
151
};
152
153
class Sha512 {
154
#if CYBOZU_USE_OPENSSL_NEW_HASH == 1
155
  local::NewHash<64> ctx_;
156
#else
157
  SHA512_CTX ctx_;
158
#endif
159
public:
160
  Sha512()
161
#if CYBOZU_USE_OPENSSL_NEW_HASH == 1
162
    : ctx_("sha512")
163
#endif
164
  {
165
    clear();
166
  }
167
  void clear()
168
  {
169
#if CYBOZU_USE_OPENSSL_NEW_HASH == 1
170
    ctx_.clear();
171
#else
172
    SHA512_Init(&ctx_);
173
#endif
174
  }
175
  void update(const void *buf, size_t bufSize)
176
  {
177
#if CYBOZU_USE_OPENSSL_NEW_HASH == 1
178
    ctx_.update(buf, bufSize);
179
#else
180
    SHA512_Update(&ctx_, buf, bufSize);
181
#endif
182
  }
183
  size_t digest(void *md, size_t mdSize, const void *buf, size_t bufSize)
184
  {
185
#if CYBOZU_USE_OPENSSL_NEW_HASH == 1
186
    return ctx_.digest(md, mdSize, buf, bufSize);
187
#else
188
    if (mdSize < SHA512_DIGEST_LENGTH) return 0;
189
    update(buf, bufSize);
190
    SHA512_Final(reinterpret_cast<uint8_t*>(md), &ctx_);
191
    return SHA512_DIGEST_LENGTH;
192
#endif
193
  }
194
#ifndef CYBOZU_DONT_USE_STRING
195
  void update(const std::string& buf)
196
  {
197
    update(buf.c_str(), buf.size());
198
  }
199
  std::string digest(const std::string& buf)
200
  {
201
    return digest(buf.c_str(), buf.size());
202
  }
203
  std::string digest(const void *buf, size_t bufSize)
204
  {
205
#if CYBOZU_USE_OPENSSL_NEW_HASH == 1
206
    std::string md(ctx_.MD_SIZE, 0);
207
#else
208
    std::string md(SHA512_DIGEST_LENGTH, 0);
209
#endif
210
    digest(&md[0], md.size(), buf, bufSize);
211
    return md;
212
  }
213
#endif
214
};
215
216
} // cybozu
217
218
#else
219
220
#include <cybozu/endian.hpp>
221
#include <memory.h>
222
#include <assert.h>
223
224
namespace cybozu {
225
226
namespace sha2_local {
227
228
template<class T>
229
15.1k
T min_(T x, T y) { return x < y ? x : y;; }
230
231
inline uint32_t rot32(uint32_t x, int s)
232
8.18M
{
233
#ifdef _MSC_VER
234
  return _rotr(x, s);
235
#else
236
8.18M
  return (x >> s) | (x << (32 - s));
237
8.18M
#endif
238
8.18M
}
239
240
inline uint64_t rot64(uint64_t x, int s)
241
0
{
242
#ifdef _MSC_VER
243
  return _rotr64(x, s);
244
#else
245
0
  return (x >> s) | (x << (64 - s));
246
0
#endif
247
0
}
248
249
template<class T>
250
struct Common {
251
  void term(uint8_t *buf, size_t bufSize)
252
5.66k
  {
253
5.66k
    assert(bufSize < T::blockSize_);
254
234
    T& self = static_cast<T&>(*this);
255
234
    const uint64_t totalSize = self.totalSize_ + bufSize;
256
257
234
    buf[bufSize] = uint8_t(0x80); /* top bit = 1 */
258
234
    memset(&buf[bufSize + 1], 0, T::blockSize_ - bufSize - 1);
259
234
    if (bufSize >= T::blockSize_ - T::msgLenByte_) {
260
0
      self.round(buf);
261
0
      memset(buf, 0, T::blockSize_ - 8); // clear stack
262
0
    }
263
234
    cybozu::Set64bitAsBE(&buf[T::blockSize_ - 8], totalSize * 8);
264
234
    self.round(buf);
265
234
  }
cybozu::sha2_local::Common<cybozu::Sha256>::term(unsigned char*, unsigned long)
Line
Count
Source
252
5.66k
  {
253
5.66k
    assert(bufSize < T::blockSize_);
254
234
    T& self = static_cast<T&>(*this);
255
234
    const uint64_t totalSize = self.totalSize_ + bufSize;
256
257
234
    buf[bufSize] = uint8_t(0x80); /* top bit = 1 */
258
234
    memset(&buf[bufSize + 1], 0, T::blockSize_ - bufSize - 1);
259
234
    if (bufSize >= T::blockSize_ - T::msgLenByte_) {
260
0
      self.round(buf);
261
0
      memset(buf, 0, T::blockSize_ - 8); // clear stack
262
0
    }
263
234
    cybozu::Set64bitAsBE(&buf[T::blockSize_ - 8], totalSize * 8);
264
234
    self.round(buf);
265
234
  }
Unexecuted instantiation: cybozu::sha2_local::Common<cybozu::Sha512>::term(unsigned char*, unsigned long)
266
  void inner_update(const uint8_t *buf, size_t bufSize)
267
23.9k
  {
268
23.9k
    T& self = static_cast<T&>(*this);
269
23.9k
    if (bufSize == 0) return;
270
21.5k
    if (self.roundBufSize_ > 0) {
271
15.1k
      size_t size = sha2_local::min_(T::blockSize_ - self.roundBufSize_, bufSize);
272
15.1k
      memcpy(self.roundBuf_ + self.roundBufSize_, buf, size);
273
15.1k
      self.roundBufSize_ += size;
274
15.1k
      buf += size;
275
15.1k
      bufSize -= size;
276
15.1k
    }
277
21.5k
    if (self.roundBufSize_ == T::blockSize_) {
278
2.22k
      self.round(self.roundBuf_);
279
2.22k
      self.roundBufSize_ = 0;
280
2.22k
    }
281
27.6k
    while (bufSize >= T::blockSize_) {
282
6.09k
      assert(self.roundBufSize_ == 0);
283
6.09k
      self.round(buf);
284
6.09k
      buf += T::blockSize_;
285
6.09k
      bufSize -= T::blockSize_;
286
6.09k
    }
287
21.5k
    if (bufSize > 0) {
288
7.81k
      assert(bufSize < T::blockSize_);
289
7.81k
      assert(self.roundBufSize_ == 0);
290
7.81k
      memcpy(self.roundBuf_, buf, bufSize);
291
7.81k
      self.roundBufSize_ = bufSize;
292
7.81k
    }
293
21.5k
    assert(self.roundBufSize_ < T::blockSize_);
294
21.5k
  }
cybozu::sha2_local::Common<cybozu::Sha256>::inner_update(unsigned char const*, unsigned long)
Line
Count
Source
267
23.9k
  {
268
23.9k
    T& self = static_cast<T&>(*this);
269
23.9k
    if (bufSize == 0) return;
270
21.5k
    if (self.roundBufSize_ > 0) {
271
15.1k
      size_t size = sha2_local::min_(T::blockSize_ - self.roundBufSize_, bufSize);
272
15.1k
      memcpy(self.roundBuf_ + self.roundBufSize_, buf, size);
273
15.1k
      self.roundBufSize_ += size;
274
15.1k
      buf += size;
275
15.1k
      bufSize -= size;
276
15.1k
    }
277
21.5k
    if (self.roundBufSize_ == T::blockSize_) {
278
2.22k
      self.round(self.roundBuf_);
279
2.22k
      self.roundBufSize_ = 0;
280
2.22k
    }
281
27.6k
    while (bufSize >= T::blockSize_) {
282
6.09k
      assert(self.roundBufSize_ == 0);
283
6.09k
      self.round(buf);
284
6.09k
      buf += T::blockSize_;
285
6.09k
      bufSize -= T::blockSize_;
286
6.09k
    }
287
21.5k
    if (bufSize > 0) {
288
7.81k
      assert(bufSize < T::blockSize_);
289
7.81k
      assert(self.roundBufSize_ == 0);
290
7.81k
      memcpy(self.roundBuf_, buf, bufSize);
291
7.81k
      self.roundBufSize_ = bufSize;
292
7.81k
    }
293
21.5k
    assert(self.roundBufSize_ < T::blockSize_);
294
21.5k
  }
Unexecuted instantiation: cybozu::sha2_local::Common<cybozu::Sha512>::inner_update(unsigned char const*, unsigned long)
295
};
296
297
} // cybozu::sha2_local
298
299
class Sha256 : public sha2_local::Common<Sha256> {
300
  friend struct sha2_local::Common<Sha256>;
301
private:
302
  static const size_t blockSize_ = 64;
303
  static const size_t hSize_ = 8;
304
  static const size_t msgLenByte_ = 8;
305
  uint64_t totalSize_;
306
  size_t roundBufSize_;
307
  uint8_t roundBuf_[blockSize_];
308
  uint32_t h_[hSize_];
309
  static const size_t outByteSize_ = hSize_ * sizeof(uint32_t);
310
  const uint32_t *k_;
311
312
  template<size_t i0, size_t i1, size_t i2, size_t i3, size_t i4, size_t i5, size_t i6, size_t i7>
313
  void round1(uint32_t *s, uint32_t *w, int i)
314
909k
  {
315
909k
    using namespace sha2_local;
316
909k
    uint32_t e = s[i4];
317
909k
    uint32_t h = s[i7];
318
909k
    h += rot32(e, 6) ^ rot32(e, 11) ^ rot32(e, 25);
319
909k
    uint32_t f = s[i5];
320
909k
    uint32_t g = s[i6];
321
909k
    h += g ^ (e & (f ^ g));
322
909k
    h += k_[i];
323
909k
    h += w[i];
324
909k
    s[i3] += h;
325
909k
    uint32_t a = s[i0];
326
909k
    uint32_t b = s[i1];
327
909k
    uint32_t c = s[i2];
328
909k
    h += rot32(a, 2) ^ rot32(a, 13) ^ rot32(a, 22);
329
909k
    h += ((a | b) & c) | (a & b);
330
909k
    s[i7] = h;
331
909k
  }
void cybozu::Sha256::round1<0ul, 1ul, 2ul, 3ul, 4ul, 5ul, 6ul, 7ul>(unsigned int*, unsigned int*, int)
Line
Count
Source
314
113k
  {
315
113k
    using namespace sha2_local;
316
113k
    uint32_t e = s[i4];
317
113k
    uint32_t h = s[i7];
318
113k
    h += rot32(e, 6) ^ rot32(e, 11) ^ rot32(e, 25);
319
113k
    uint32_t f = s[i5];
320
113k
    uint32_t g = s[i6];
321
113k
    h += g ^ (e & (f ^ g));
322
113k
    h += k_[i];
323
113k
    h += w[i];
324
113k
    s[i3] += h;
325
113k
    uint32_t a = s[i0];
326
113k
    uint32_t b = s[i1];
327
113k
    uint32_t c = s[i2];
328
113k
    h += rot32(a, 2) ^ rot32(a, 13) ^ rot32(a, 22);
329
113k
    h += ((a | b) & c) | (a & b);
330
113k
    s[i7] = h;
331
113k
  }
void cybozu::Sha256::round1<7ul, 0ul, 1ul, 2ul, 3ul, 4ul, 5ul, 6ul>(unsigned int*, unsigned int*, int)
Line
Count
Source
314
113k
  {
315
113k
    using namespace sha2_local;
316
113k
    uint32_t e = s[i4];
317
113k
    uint32_t h = s[i7];
318
113k
    h += rot32(e, 6) ^ rot32(e, 11) ^ rot32(e, 25);
319
113k
    uint32_t f = s[i5];
320
113k
    uint32_t g = s[i6];
321
113k
    h += g ^ (e & (f ^ g));
322
113k
    h += k_[i];
323
113k
    h += w[i];
324
113k
    s[i3] += h;
325
113k
    uint32_t a = s[i0];
326
113k
    uint32_t b = s[i1];
327
113k
    uint32_t c = s[i2];
328
113k
    h += rot32(a, 2) ^ rot32(a, 13) ^ rot32(a, 22);
329
113k
    h += ((a | b) & c) | (a & b);
330
113k
    s[i7] = h;
331
113k
  }
void cybozu::Sha256::round1<6ul, 7ul, 0ul, 1ul, 2ul, 3ul, 4ul, 5ul>(unsigned int*, unsigned int*, int)
Line
Count
Source
314
113k
  {
315
113k
    using namespace sha2_local;
316
113k
    uint32_t e = s[i4];
317
113k
    uint32_t h = s[i7];
318
113k
    h += rot32(e, 6) ^ rot32(e, 11) ^ rot32(e, 25);
319
113k
    uint32_t f = s[i5];
320
113k
    uint32_t g = s[i6];
321
113k
    h += g ^ (e & (f ^ g));
322
113k
    h += k_[i];
323
113k
    h += w[i];
324
113k
    s[i3] += h;
325
113k
    uint32_t a = s[i0];
326
113k
    uint32_t b = s[i1];
327
113k
    uint32_t c = s[i2];
328
113k
    h += rot32(a, 2) ^ rot32(a, 13) ^ rot32(a, 22);
329
113k
    h += ((a | b) & c) | (a & b);
330
113k
    s[i7] = h;
331
113k
  }
void cybozu::Sha256::round1<5ul, 6ul, 7ul, 0ul, 1ul, 2ul, 3ul, 4ul>(unsigned int*, unsigned int*, int)
Line
Count
Source
314
113k
  {
315
113k
    using namespace sha2_local;
316
113k
    uint32_t e = s[i4];
317
113k
    uint32_t h = s[i7];
318
113k
    h += rot32(e, 6) ^ rot32(e, 11) ^ rot32(e, 25);
319
113k
    uint32_t f = s[i5];
320
113k
    uint32_t g = s[i6];
321
113k
    h += g ^ (e & (f ^ g));
322
113k
    h += k_[i];
323
113k
    h += w[i];
324
113k
    s[i3] += h;
325
113k
    uint32_t a = s[i0];
326
113k
    uint32_t b = s[i1];
327
113k
    uint32_t c = s[i2];
328
113k
    h += rot32(a, 2) ^ rot32(a, 13) ^ rot32(a, 22);
329
113k
    h += ((a | b) & c) | (a & b);
330
113k
    s[i7] = h;
331
113k
  }
void cybozu::Sha256::round1<4ul, 5ul, 6ul, 7ul, 0ul, 1ul, 2ul, 3ul>(unsigned int*, unsigned int*, int)
Line
Count
Source
314
113k
  {
315
113k
    using namespace sha2_local;
316
113k
    uint32_t e = s[i4];
317
113k
    uint32_t h = s[i7];
318
113k
    h += rot32(e, 6) ^ rot32(e, 11) ^ rot32(e, 25);
319
113k
    uint32_t f = s[i5];
320
113k
    uint32_t g = s[i6];
321
113k
    h += g ^ (e & (f ^ g));
322
113k
    h += k_[i];
323
113k
    h += w[i];
324
113k
    s[i3] += h;
325
113k
    uint32_t a = s[i0];
326
113k
    uint32_t b = s[i1];
327
113k
    uint32_t c = s[i2];
328
113k
    h += rot32(a, 2) ^ rot32(a, 13) ^ rot32(a, 22);
329
113k
    h += ((a | b) & c) | (a & b);
330
113k
    s[i7] = h;
331
113k
  }
void cybozu::Sha256::round1<3ul, 4ul, 5ul, 6ul, 7ul, 0ul, 1ul, 2ul>(unsigned int*, unsigned int*, int)
Line
Count
Source
314
113k
  {
315
113k
    using namespace sha2_local;
316
113k
    uint32_t e = s[i4];
317
113k
    uint32_t h = s[i7];
318
113k
    h += rot32(e, 6) ^ rot32(e, 11) ^ rot32(e, 25);
319
113k
    uint32_t f = s[i5];
320
113k
    uint32_t g = s[i6];
321
113k
    h += g ^ (e & (f ^ g));
322
113k
    h += k_[i];
323
113k
    h += w[i];
324
113k
    s[i3] += h;
325
113k
    uint32_t a = s[i0];
326
113k
    uint32_t b = s[i1];
327
113k
    uint32_t c = s[i2];
328
113k
    h += rot32(a, 2) ^ rot32(a, 13) ^ rot32(a, 22);
329
113k
    h += ((a | b) & c) | (a & b);
330
113k
    s[i7] = h;
331
113k
  }
void cybozu::Sha256::round1<2ul, 3ul, 4ul, 5ul, 6ul, 7ul, 0ul, 1ul>(unsigned int*, unsigned int*, int)
Line
Count
Source
314
113k
  {
315
113k
    using namespace sha2_local;
316
113k
    uint32_t e = s[i4];
317
113k
    uint32_t h = s[i7];
318
113k
    h += rot32(e, 6) ^ rot32(e, 11) ^ rot32(e, 25);
319
113k
    uint32_t f = s[i5];
320
113k
    uint32_t g = s[i6];
321
113k
    h += g ^ (e & (f ^ g));
322
113k
    h += k_[i];
323
113k
    h += w[i];
324
113k
    s[i3] += h;
325
113k
    uint32_t a = s[i0];
326
113k
    uint32_t b = s[i1];
327
113k
    uint32_t c = s[i2];
328
113k
    h += rot32(a, 2) ^ rot32(a, 13) ^ rot32(a, 22);
329
113k
    h += ((a | b) & c) | (a & b);
330
113k
    s[i7] = h;
331
113k
  }
void cybozu::Sha256::round1<1ul, 2ul, 3ul, 4ul, 5ul, 6ul, 7ul, 0ul>(unsigned int*, unsigned int*, int)
Line
Count
Source
314
113k
  {
315
113k
    using namespace sha2_local;
316
113k
    uint32_t e = s[i4];
317
113k
    uint32_t h = s[i7];
318
113k
    h += rot32(e, 6) ^ rot32(e, 11) ^ rot32(e, 25);
319
113k
    uint32_t f = s[i5];
320
113k
    uint32_t g = s[i6];
321
113k
    h += g ^ (e & (f ^ g));
322
113k
    h += k_[i];
323
113k
    h += w[i];
324
113k
    s[i3] += h;
325
113k
    uint32_t a = s[i0];
326
113k
    uint32_t b = s[i1];
327
113k
    uint32_t c = s[i2];
328
113k
    h += rot32(a, 2) ^ rot32(a, 13) ^ rot32(a, 22);
329
113k
    h += ((a | b) & c) | (a & b);
330
113k
    s[i7] = h;
331
113k
  }
332
  /**
333
    @param buf [in] buffer(64byte)
334
  */
335
  void round(const uint8_t *buf)
336
14.2k
  {
337
14.2k
    using namespace sha2_local;
338
14.2k
    uint32_t w[64];
339
241k
    for (int i = 0; i < 16; i++) {
340
227k
      w[i] = cybozu::Get32bitAsBE(&buf[i * 4]);
341
227k
    }
342
696k
    for (int i = 16 ; i < 64; i++) {
343
682k
      uint32_t t = w[i - 15];
344
682k
      uint32_t s0 = rot32(t, 7) ^ rot32(t, 18) ^ (t >> 3);
345
682k
      t = w[i - 2];
346
682k
      uint32_t s1 = rot32(t, 17) ^ rot32(t, 19) ^ (t >> 10);
347
682k
      w[i] = w[i - 16] + s0 + w[i - 7] + s1;
348
682k
    }
349
14.2k
    uint32_t s[8];
350
127k
    for (int i = 0; i < 8; i++) {
351
113k
      s[i] = h_[i];
352
113k
    }
353
127k
    for (int i = 0; i < 64; i += 8) {
354
113k
      round1<0, 1, 2, 3, 4, 5, 6, 7>(s, w, i + 0);
355
113k
      round1<7, 0, 1, 2, 3, 4, 5, 6>(s, w, i + 1);
356
113k
      round1<6, 7, 0, 1, 2, 3, 4, 5>(s, w, i + 2);
357
113k
      round1<5, 6, 7, 0, 1, 2, 3, 4>(s, w, i + 3);
358
113k
      round1<4, 5, 6, 7, 0, 1, 2, 3>(s, w, i + 4);
359
113k
      round1<3, 4, 5, 6, 7, 0, 1, 2>(s, w, i + 5);
360
113k
      round1<2, 3, 4, 5, 6, 7, 0, 1>(s, w, i + 6);
361
113k
      round1<1, 2, 3, 4, 5, 6, 7, 0>(s, w, i + 7);
362
113k
    }
363
127k
    for (int i = 0; i < 8; i++) {
364
113k
      h_[i] += s[i];
365
113k
    }
366
14.2k
    totalSize_ += blockSize_;
367
14.2k
  }
368
public:
369
  Sha256()
370
740
  {
371
740
    clear();
372
740
  }
373
  void clear()
374
5.66k
  {
375
5.66k
    static const uint32_t kTbl[] = {
376
5.66k
      0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
377
5.66k
      0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
378
5.66k
      0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
379
5.66k
      0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
380
5.66k
      0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
381
5.66k
      0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
382
5.66k
      0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
383
5.66k
      0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
384
5.66k
    };
385
5.66k
    k_ = kTbl;
386
5.66k
    totalSize_ = 0;
387
5.66k
    roundBufSize_ = 0;
388
5.66k
    h_[0] = 0x6a09e667;
389
5.66k
    h_[1] = 0xbb67ae85;
390
5.66k
    h_[2] = 0x3c6ef372;
391
5.66k
    h_[3] = 0xa54ff53a;
392
5.66k
    h_[4] = 0x510e527f;
393
5.66k
    h_[5] = 0x9b05688c;
394
5.66k
    h_[6] = 0x1f83d9ab;
395
5.66k
    h_[7] = 0x5be0cd19;
396
5.66k
  }
397
  void update(const void *buf, size_t bufSize)
398
23.9k
  {
399
23.9k
    inner_update(reinterpret_cast<const uint8_t*>(buf), bufSize);
400
23.9k
  }
401
  size_t digest(void *md, size_t mdSize, const void *buf, size_t bufSize)
402
5.66k
  {
403
5.66k
    if (mdSize < outByteSize_) return 0;
404
5.66k
    update(buf, bufSize);
405
5.66k
    term(roundBuf_, roundBufSize_);
406
5.66k
    char *p = reinterpret_cast<char*>(md);
407
50.9k
    for (size_t i = 0; i < hSize_; i++) {
408
45.3k
      cybozu::Set32bitAsBE(&p[i * sizeof(h_[0])], h_[i]);
409
45.3k
    }
410
5.66k
    return outByteSize_;
411
5.66k
  }
412
#ifndef CYBOZU_DONT_USE_STRING
413
  void update(const std::string& buf)
414
0
  {
415
0
    update(buf.c_str(), buf.size());
416
0
  }
417
  std::string digest(const std::string& buf)
418
0
  {
419
0
    return digest(buf.c_str(), buf.size());
420
0
  }
421
  std::string digest(const void *buf, size_t bufSize)
422
0
  {
423
0
    std::string md(outByteSize_, 0);
424
0
    digest(&md[0], md.size(), buf, bufSize);
425
0
    return md;
426
0
  }
427
#endif
428
};
429
430
class Sha512 : public sha2_local::Common<Sha512> {
431
  friend struct sha2_local::Common<Sha512>;
432
private:
433
  static const size_t blockSize_ = 128;
434
  static const size_t hSize_ = 8;
435
  static const size_t msgLenByte_ = 16;
436
  uint64_t totalSize_;
437
  size_t roundBufSize_;
438
  uint8_t roundBuf_[blockSize_];
439
  uint64_t h_[hSize_];
440
  static const size_t outByteSize_ = hSize_ * sizeof(uint64_t);
441
  const uint64_t *k_;
442
443
  template<size_t i0, size_t i1, size_t i2, size_t i3, size_t i4, size_t i5, size_t i6, size_t i7>
444
  void round1(uint64_t *S, const uint64_t *w, size_t i)
445
0
  {
446
0
    using namespace sha2_local;
447
0
    uint64_t& a = S[i0];
448
0
    uint64_t& b = S[i1];
449
0
    uint64_t& c = S[i2];
450
0
    uint64_t& d = S[i3];
451
0
    uint64_t& e = S[i4];
452
0
    uint64_t& f = S[i5];
453
0
    uint64_t& g = S[i6];
454
0
    uint64_t& h = S[i7];
455
456
0
    uint64_t s1 = rot64(e, 14) ^ rot64(e, 18) ^ rot64(e, 41);
457
0
    uint64_t ch = g ^ (e & (f ^ g));
458
0
    uint64_t t0 = h + s1 + ch + k_[i] + w[i];
459
0
    uint64_t s0 = rot64(a, 28) ^ rot64(a, 34) ^ rot64(a, 39);
460
0
    uint64_t maj = ((a | b) & c) | (a & b);
461
0
    uint64_t t1 = s0 + maj;
462
0
    d += t0;
463
0
    h = t0 + t1;
464
0
  }
Unexecuted instantiation: void cybozu::Sha512::round1<0ul, 1ul, 2ul, 3ul, 4ul, 5ul, 6ul, 7ul>(unsigned long*, unsigned long const*, unsigned long)
Unexecuted instantiation: void cybozu::Sha512::round1<7ul, 0ul, 1ul, 2ul, 3ul, 4ul, 5ul, 6ul>(unsigned long*, unsigned long const*, unsigned long)
Unexecuted instantiation: void cybozu::Sha512::round1<6ul, 7ul, 0ul, 1ul, 2ul, 3ul, 4ul, 5ul>(unsigned long*, unsigned long const*, unsigned long)
Unexecuted instantiation: void cybozu::Sha512::round1<5ul, 6ul, 7ul, 0ul, 1ul, 2ul, 3ul, 4ul>(unsigned long*, unsigned long const*, unsigned long)
Unexecuted instantiation: void cybozu::Sha512::round1<4ul, 5ul, 6ul, 7ul, 0ul, 1ul, 2ul, 3ul>(unsigned long*, unsigned long const*, unsigned long)
Unexecuted instantiation: void cybozu::Sha512::round1<3ul, 4ul, 5ul, 6ul, 7ul, 0ul, 1ul, 2ul>(unsigned long*, unsigned long const*, unsigned long)
Unexecuted instantiation: void cybozu::Sha512::round1<2ul, 3ul, 4ul, 5ul, 6ul, 7ul, 0ul, 1ul>(unsigned long*, unsigned long const*, unsigned long)
Unexecuted instantiation: void cybozu::Sha512::round1<1ul, 2ul, 3ul, 4ul, 5ul, 6ul, 7ul, 0ul>(unsigned long*, unsigned long const*, unsigned long)
465
  /**
466
    @param buf [in] buffer(64byte)
467
  */
468
  void round(const uint8_t *buf)
469
0
  {
470
0
    using namespace sha2_local;
471
0
    uint64_t w[80];
472
0
    for (int i = 0; i < 16; i++) {
473
0
      w[i] = cybozu::Get64bitAsBE(&buf[i * 8]);
474
0
    }
475
0
    for (int i = 16 ; i < 80; i++) {
476
0
      uint64_t t = w[i - 15];
477
0
      uint64_t s0 = rot64(t, 1) ^ rot64(t, 8) ^ (t >> 7);
478
0
      t = w[i - 2];
479
0
      uint64_t s1 = rot64(t, 19) ^ rot64(t, 61) ^ (t >> 6);
480
0
      w[i] = w[i - 16] + s0 + w[i - 7] + s1;
481
0
    }
482
0
    uint64_t s[8];
483
0
    for (int i = 0; i < 8; i++) {
484
0
      s[i] = h_[i];
485
0
    }
486
0
    for (int i = 0; i < 80; i += 8) {
487
0
      round1<0, 1, 2, 3, 4, 5, 6, 7>(s, w, i + 0);
488
0
      round1<7, 0, 1, 2, 3, 4, 5, 6>(s, w, i + 1);
489
0
      round1<6, 7, 0, 1, 2, 3, 4, 5>(s, w, i + 2);
490
0
      round1<5, 6, 7, 0, 1, 2, 3, 4>(s, w, i + 3);
491
0
      round1<4, 5, 6, 7, 0, 1, 2, 3>(s, w, i + 4);
492
0
      round1<3, 4, 5, 6, 7, 0, 1, 2>(s, w, i + 5);
493
0
      round1<2, 3, 4, 5, 6, 7, 0, 1>(s, w, i + 6);
494
0
      round1<1, 2, 3, 4, 5, 6, 7, 0>(s, w, i + 7);
495
0
    }
496
0
    for (int i = 0; i < 8; i++) {
497
0
      h_[i] += s[i];
498
0
    }
499
0
    totalSize_ += blockSize_;
500
0
  }
501
public:
502
  Sha512()
503
0
  {
504
0
    clear();
505
0
  }
506
  void clear()
507
0
  {
508
0
    static const uint64_t kTbl[] = {
509
0
        0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL,
510
0
        0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
511
0
        0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
512
0
        0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
513
0
        0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, 0x983e5152ee66dfabULL,
514
0
        0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
515
0
        0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL,
516
0
        0x53380d139d95b3dfULL, 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
517
0
        0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
518
0
        0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
519
0
        0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL,
520
0
        0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
521
0
        0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, 0xca273eceea26619cULL,
522
0
        0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
523
0
        0x113f9804bef90daeULL, 0x1b710b35131c471bULL, 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
524
0
        0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
525
0
    };
526
0
    k_ = kTbl;
527
0
    totalSize_ = 0;
528
0
    roundBufSize_ = 0;
529
0
    h_[0] = 0x6a09e667f3bcc908ull;
530
0
    h_[1] = 0xbb67ae8584caa73bull;
531
0
    h_[2] = 0x3c6ef372fe94f82bull;
532
0
    h_[3] = 0xa54ff53a5f1d36f1ull;
533
0
    h_[4] = 0x510e527fade682d1ull;
534
0
    h_[5] = 0x9b05688c2b3e6c1full;
535
0
    h_[6] = 0x1f83d9abfb41bd6bull;
536
0
    h_[7] = 0x5be0cd19137e2179ull;
537
0
  }
538
  void update(const void *buf, size_t bufSize)
539
0
  {
540
0
    inner_update(reinterpret_cast<const uint8_t*>(buf), bufSize);
541
0
  }
542
  size_t digest(void *md, size_t mdSize, const void *buf, size_t bufSize)
543
0
  {
544
0
    if (mdSize < outByteSize_) return 0;
545
0
    update(buf, bufSize);
546
0
    term(roundBuf_, roundBufSize_);
547
0
    char *p = reinterpret_cast<char*>(md);
548
0
    for (size_t i = 0; i < hSize_; i++) {
549
0
      cybozu::Set64bitAsBE(&p[i * sizeof(h_[0])], h_[i]);
550
0
    }
551
0
    return outByteSize_;
552
0
  }
553
#ifndef CYBOZU_DONT_USE_STRING
554
  void update(const std::string& buf)
555
0
  {
556
0
    update(buf.c_str(), buf.size());
557
0
  }
558
  std::string digest(const std::string& buf)
559
0
  {
560
0
    return digest(buf.c_str(), buf.size());
561
0
  }
562
  std::string digest(const void *buf, size_t bufSize)
563
0
  {
564
0
    std::string md(outByteSize_, 0);
565
0
    digest(&md[0], md.size(), buf, bufSize);
566
0
    return md;
567
0
  }
568
#endif
569
};
570
571
} // cybozu
572
573
#endif
574
575
namespace cybozu {
576
577
/*
578
  HMAC-SHA-256
579
  hmac must have 32 bytes buffer
580
*/
581
inline void hmac256(void *hmac, const void *key, size_t keySize, const void *msg, size_t msgSize)
582
0
{
583
0
  const uint8_t ipad = 0x36;
584
0
  const uint8_t opad = 0x5c;
585
0
  uint8_t k[64];
586
0
  Sha256 hash;
587
0
  if (keySize > 64) {
588
0
    hash.digest(k, 32, key, keySize);
589
0
    hash.clear();
590
0
    keySize = 32;
591
0
  } else {
592
0
    memcpy(k, key, keySize);
593
0
  }
594
0
  for (size_t i = 0; i < keySize; i++) {
595
0
    k[i] = k[i] ^ ipad;
596
0
  }
597
0
  memset(k + keySize, ipad, 64 - keySize);
598
0
  hash.update(k, 64);
599
0
  hash.digest(hmac, 32, msg, msgSize);
600
0
  hash.clear();
601
0
  for (size_t i = 0; i < 64; i++) {
602
0
    k[i] = k[i] ^ (ipad ^ opad);
603
0
  }
604
0
  hash.update(k, 64);
605
0
  hash.digest(hmac, 32, hmac, 32);
606
0
}
607
608
} // cybozu