Anope IRC Services  Version 2.0
enc_sha256.cpp
Go to the documentation of this file.
1 /* This module generates and compares password hashes using SHA256 algorithms.
2  *
3  * If an intruder gets access to your system or uses a brute force attack,
4  * salt will not provide much value.
5  * IMPORTANT: DATA HASHES CANNOT BE "DECRYPTED" BACK TO PLAIN TEXT.
6  *
7  * Modified for Anope.
8  * (C) 2003-2014 Anope Team
9  * Contact us at team@anope.org
10  *
11  * Taken from InspIRCd ( www.inspircd.org )
12  * see http://wiki.inspircd.org/Credits
13  *
14  * This program is free but copyrighted software; see
15  * the file COPYING for details.
16  */
17 
18 /* FIPS 180-2 SHA-224/256/384/512 implementation
19  * Last update: 05/23/2005
20  * Issue date: 04/30/2005
21  *
22  * Copyright (C) 2005 Olivier Gay <olivier.gay@a3.epfl.ch>
23  * All rights reserved.
24  *
25  * Redistribution and use in source and binary forms, with or without
26  * modification, are permitted provided that the following conditions
27  * are met:
28  * 1. Redistributions of source code must retain the above copyright
29  * notice, this list of conditions and the following disclaimer.
30  * 2. Redistributions in binary form must reproduce the above copyright
31  * notice, this list of conditions and the following disclaimer in the
32  * documentation and/or other materials provided with the distribution.
33  * 3. Neither the name of the project nor the names of its contributors
34  * may be used to endorse or promote products derived from this software
35  * without specific prior written permission.
36  *
37  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
38  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
40  * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
41  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
42  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
43  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
45  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  */
49 
50 #include "module.h"
51 #include "modules/encryption.h"
52 
53 static const unsigned SHA256_DIGEST_SIZE = 256 / 8;
54 static const unsigned SHA256_BLOCK_SIZE = 512 / 8;
55 
56 inline static uint32_t SHFR(uint32_t x, uint32_t n) { return x >> n; }
57 inline static uint32_t ROTR(uint32_t x, uint32_t n) { return (x >> n) | (x << ((sizeof(x) << 3) - n)); }
58 inline static uint32_t ROTL(uint32_t x, uint32_t n) { return (x << n) | (x >> ((sizeof(x) << 3) - n)); }
59 inline static uint32_t CH(uint32_t x, uint32_t y, uint32_t z) { return (x & y) ^ (~x & z); }
60 inline static uint32_t MAJ(uint32_t x, uint32_t y, uint32_t z) { return (x & y) ^ (x & z) ^ (y & z); }
61 
62 inline static uint32_t SHA256_F1(uint32_t x) { return ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22); }
63 inline static uint32_t SHA256_F2(uint32_t x) { return ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25); }
64 inline static uint32_t SHA256_F3(uint32_t x) { return ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3); }
65 inline static uint32_t SHA256_F4(uint32_t x) { return ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10); }
66 
67 inline static void UNPACK32(unsigned x, unsigned char *str)
68 {
69  str[3] = static_cast<uint8_t>(x);
70  str[2] = static_cast<uint8_t>(x >> 8);
71  str[1] = static_cast<uint8_t>(x >> 16);
72  str[0] = static_cast<uint8_t>(x >> 24);
73 }
74 
75 inline static void PACK32(unsigned char *str, uint32_t &x)
76 {
77  x = static_cast<uint32_t>(str[3]) | static_cast<uint32_t>(str[2]) << 8 | static_cast<uint32_t>(str[1]) << 16 | static_cast<uint32_t>(str[0]) << 24;
78 }
79 
80 /* Macros used for loops unrolling */
81 
82 inline static void SHA256_SCR(uint32_t w[64], int i)
83 {
84  w[i] = SHA256_F4(w[i - 2]) + w[i - 7] + SHA256_F3(w[i - 15]) + w[i - 16];
85 }
86 
87 static const uint32_t sha256_h0[8] =
88 {
89  0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
90  0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
91 };
92 
93 static const uint32_t sha256_k[64] =
94 {
95  0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
96  0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
97  0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
98  0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
99  0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
100  0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
101  0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
102  0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
103  0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
104  0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
105  0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
106  0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
107  0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
108  0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
109  0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
110  0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
111 };
112 
116 {
117  void Transform(unsigned char *message, unsigned block_nb)
118  {
119  uint32_t w[64], wv[8];
120  unsigned char *sub_block;
121  for (unsigned i = 1; i <= block_nb; ++i)
122  {
123  int j;
124  sub_block = message + ((i - 1) << 6);
125 
126  for (j = 0; j < 16; ++j)
127  PACK32(&sub_block[j << 2], w[j]);
128  for (j = 16; j < 64; ++j)
129  SHA256_SCR(w, j);
130  for (j = 0; j < 8; ++j)
131  wv[j] = this->h[j];
132  for (j = 0; j < 64; ++j)
133  {
134  uint32_t t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + sha256_k[j] + w[j];
135  uint32_t t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
136  wv[7] = wv[6];
137  wv[6] = wv[5];
138  wv[5] = wv[4];
139  wv[4] = wv[3] + t1;
140  wv[3] = wv[2];
141  wv[2] = wv[1];
142  wv[1] = wv[0];
143  wv[0] = t1 + t2;
144  }
145  for (j = 0; j < 8; ++j)
146  this->h[j] += wv[j];
147  }
148  }
149 
150  unsigned tot_len;
151  unsigned len;
152  unsigned char block[2 * SHA256_BLOCK_SIZE];
153  uint32_t h[8];
154  unsigned char digest[SHA256_DIGEST_SIZE];
155 
156  public:
158  {
159  if (iv != NULL)
160  {
161  if (iv->second != 8)
162  throw CoreException("Invalid IV size");
163  for (int i = 0; i < 8; ++i)
164  this->h[i] = iv->first[i];
165  }
166  else
167  for (int i = 0; i < 8; ++i)
168  this->h[i] = sha256_h0[i];
169 
170  this->tot_len = 0;
171  this->len = 0;
172  memset(this->block, 0, sizeof(this->block));
173  memset(this->digest, 0, sizeof(this->digest));
174  }
175 
176  void Update(const unsigned char *message, size_t mlen) anope_override
177  {
178  unsigned tmp_len = SHA256_BLOCK_SIZE - this->len, rem_len = mlen < tmp_len ? mlen : tmp_len;
179 
180  memcpy(&this->block[this->len], message, rem_len);
181  if (this->len + mlen < SHA256_BLOCK_SIZE)
182  {
183  this->len += mlen;
184  return;
185  }
186  unsigned new_len = mlen - rem_len, block_nb = new_len / SHA256_BLOCK_SIZE;
187  unsigned char *shifted_message = new unsigned char[mlen - rem_len];
188  memcpy(shifted_message, message + rem_len, mlen - rem_len);
189  this->Transform(this->block, 1);
190  this->Transform(shifted_message, block_nb);
191  rem_len = new_len % SHA256_BLOCK_SIZE;
192  memcpy(this->block, &shifted_message[block_nb << 6], rem_len);
193  delete [] shifted_message;
194  this->len = rem_len;
195  this->tot_len += (block_nb + 1) << 6;
196  }
197 
199  {
200  unsigned block_nb = 1 + ((SHA256_BLOCK_SIZE - 9) < (this->len % SHA256_BLOCK_SIZE));
201  unsigned len_b = (this->tot_len + this->len) << 3;
202  unsigned pm_len = block_nb << 6;
203  memset(this->block + this->len, 0, pm_len - this->len);
204  this->block[this->len] = 0x80;
205  UNPACK32(len_b, this->block + pm_len - 4);
206  this->Transform(this->block, block_nb);
207  for (int i = 0 ; i < 8; ++i)
208  UNPACK32(this->h[i], &this->digest[i << 2]);
209  }
210 
212  {
213  Encryption::Hash hash;
214  hash.first = this->digest;
215  hash.second = SHA256_DIGEST_SIZE;
216  return hash;
217  }
218 };
219 
221 {
222  public:
223  SHA256Provider(Module *creator) : Encryption::Provider(creator, "sha256") { }
224 
226  {
227  return new SHA256Context(iv);
228  }
229 
231  {
232  Encryption::IV iv;
233  iv.first = sha256_h0;
234  iv.second = sizeof(sha256_h0) / sizeof(uint32_t);
235  return iv;
236  }
237 };
238 
239 class ESHA256 : public Module
240 {
242 
243  unsigned iv[8];
244  bool use_iv;
245 
246  /* initializes the IV with a new random value */
247  void NewRandomIV()
248  {
249  for (int i = 0; i < 8; ++i)
250  iv[i] = static_cast<uint32_t>(rand());
251  }
252 
253  /* returns the IV as base64-encrypted string */
255  {
256  char buf[33];
257  for (int i = 0; i < 8; ++i)
258  UNPACK32(iv[i], reinterpret_cast<unsigned char *>(&buf[i << 2]));
259  buf[32] = '\0';
260  return Anope::Hex(buf, 32);
261  }
262 
263  /* splits the appended IV from the password string so it can be used for the next encryption */
264  /* password format: <hashmethod>:<password_b64>:<iv_b64> */
265  void GetIVFromPass(const Anope::string &password)
266  {
267  size_t pos = password.find(':');
268  Anope::string buf = password.substr(password.find(':', pos + 1) + 1, password.length());
269  char buf2[33];
270  Anope::Unhex(buf, buf2, sizeof(buf2));
271  for (int i = 0 ; i < 8; ++i)
272  PACK32(reinterpret_cast<unsigned char *>(&buf2[i << 2]), iv[i]);
273  }
274 
275  public:
276  ESHA256(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, ENCRYPTION | VENDOR),
277  sha256provider(this)
278  {
279 
280 
281  use_iv = false;
282  }
283 
285  {
286  if (!use_iv)
287  NewRandomIV();
288  else
289  use_iv = false;
290 
291  Encryption::IV initilization(this->iv, 8);
292  SHA256Context ctx(&initilization);
293  ctx.Update(reinterpret_cast<const unsigned char *>(src.c_str()), src.length());
294  ctx.Finalize();
295 
296  Encryption::Hash hash = ctx.GetFinalizedHash();
297 
298  std::stringstream buf;
299  buf << "sha256:" << Anope::Hex(reinterpret_cast<const char *>(hash.first), hash.second) << ":" << GetIVString();
300  Log(LOG_DEBUG_2) << "(enc_sha256) hashed password from [" << src << "] to [" << buf.str() << " ]";
301  dest = buf.str();
302  return EVENT_ALLOW;
303  }
304 
306  {
307  const NickAlias *na = NickAlias::Find(req->GetAccount());
308  if (na == NULL)
309  return;
310  NickCore *nc = na->nc;
311 
312  size_t pos = nc->pass.find(':');
313  if (pos == Anope::string::npos)
314  return;
315  Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos);
316  if (!hash_method.equals_cs("sha256"))
317  return;
318 
319  GetIVFromPass(nc->pass);
320  use_iv = true;
321  Anope::string buf;
322  this->OnEncrypt(req->GetPassword(), buf);
323  if (nc->pass.equals_cs(buf))
324  {
325  /* if we are NOT the first module in the list,
326  * we want to re-encrypt the pass with the new encryption
327  */
329  Anope::Encrypt(req->GetPassword(), nc->pass);
330  req->Success(this);
331  }
332  }
333 };
334 
Serialize::Reference< NickCore > nc
Definition: account.h:47
static NickAlias * Find(const Anope::string &nick)
Definition: nickalias.cpp:121
bool equals_cs(const char *_str) const
Definition: anope.h:74
SHA256Provider(Module *creator)
Definition: enc_sha256.cpp:223
void NewRandomIV()
Definition: enc_sha256.cpp:247
unsigned iv[8]
Definition: enc_sha256.cpp:243
Anope::string GetIVString()
Definition: enc_sha256.cpp:254
void Update(const unsigned char *message, size_t mlen) anope_override
Definition: enc_sha256.cpp:176
EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) anope_override
Definition: enc_sha256.cpp:284
static uint32_t SHA256_F3(uint32_t x)
Definition: enc_sha256.cpp:64
Encryption::Hash GetFinalizedHash() anope_override
Definition: enc_sha256.cpp:211
unsigned char digest[SHA256_DIGEST_SIZE]
Definition: enc_sha256.cpp:154
Definition: users.h:34
unsigned char block[2 *SHA256_BLOCK_SIZE]
Definition: enc_sha256.cpp:152
static uint32_t ROTL(uint32_t x, uint32_t n)
Definition: enc_sha256.cpp:58
static const uint32_t sha256_k[64]
Definition: enc_sha256.cpp:93
static const unsigned SHA256_DIGEST_SIZE
Definition: enc_sha256.cpp:53
static uint32_t SHFR(uint32_t x, uint32_t n)
Definition: enc_sha256.cpp:56
static void UNPACK32(unsigned x, unsigned char *str)
Definition: enc_sha256.cpp:67
Anope::string pass
Definition: account.h:115
CoreExport string Hex(const string &data)
Definition: misc.cpp:546
bool use_iv
Definition: enc_sha256.cpp:244
string substr(size_type pos=0, size_type n=npos) const
Definition: anope.h:277
static void SHA256_SCR(uint32_t w[64], int i)
Definition: enc_sha256.cpp:82
Encryption::IV GetDefaultIV() anope_override
Definition: enc_sha256.cpp:230
size_type length() const
Definition: anope.h:131
static uint32_t ROTR(uint32_t x, uint32_t n)
Definition: enc_sha256.cpp:57
std::pair< const unsigned char *, size_t > Hash
Definition: encryption.h:15
static uint32_t SHA256_F2(uint32_t x)
Definition: enc_sha256.cpp:63
static uint32_t CH(uint32_t x, uint32_t y, uint32_t z)
Definition: enc_sha256.cpp:59
uint32_t h[8]
Definition: enc_sha256.cpp:153
static const size_type npos
Definition: anope.h:44
unsigned len
Definition: enc_sha256.cpp:151
std::pair< const uint32_t *, size_t > IV
Definition: encryption.h:16
static uint32_t MAJ(uint32_t x, uint32_t y, uint32_t z)
Definition: enc_sha256.cpp:60
void OnCheckAuthentication(User *, IdentifyRequest *req) anope_override
Definition: enc_sha256.cpp:305
#define anope_override
Definition: services.h:56
SHA256Context(Encryption::IV *iv)
Definition: enc_sha256.cpp:157
unsigned tot_len
Definition: enc_sha256.cpp:150
Encryption::Context * CreateContext(Encryption::IV *iv) anope_override
Definition: enc_sha256.cpp:225
ESHA256(const Anope::string &modname, const Anope::string &creator)
Definition: enc_sha256.cpp:276
static uint32_t SHA256_F4(uint32_t x)
Definition: enc_sha256.cpp:65
EventReturn
Definition: modules.h:129
#define MODULE_INIT(x)
Definition: modules.h:45
static Module * FindFirstOf(ModType type)
void GetIVFromPass(const Anope::string &password)
Definition: enc_sha256.cpp:265
void Finalize() anope_override
Definition: enc_sha256.cpp:198
static const uint32_t sha256_h0[8]
Definition: enc_sha256.cpp:87
void Transform(unsigned char *message, unsigned block_nb)
Definition: enc_sha256.cpp:117
static const unsigned SHA256_BLOCK_SIZE
Definition: enc_sha256.cpp:54
CoreExport void Encrypt(const Anope::string &src, Anope::string &dest)
Definition: misc.cpp:511
SHA256Provider sha256provider
Definition: enc_sha256.cpp:241
Definition: logger.h:53
static uint32_t SHA256_F1(uint32_t x)
Definition: enc_sha256.cpp:62
iterator begin()
Definition: anope.h:282
size_type find(const string &_str, size_type pos=0) const
Definition: anope.h:192
Provider(Module *creator, const Anope::string &sname)
Definition: encryption.h:30
CoreExport void Unhex(const string &src, string &dest)
Definition: misc.cpp:575
static void PACK32(unsigned char *str, uint32_t &x)
Definition: enc_sha256.cpp:75