Crypto++  8.8
Free C++ class library of cryptographic schemes
shacal2.cpp
1 // shacal2.cpp - written by Kevin Springle, 2003
2 //
3 // Portions of this code were derived from
4 // Wei Dai's implementation of SHA-2
5 //
6 // Jack Lloyd and the Botan team allowed Crypto++ to use parts of
7 // Botan's implementation under the same license as Crypto++
8 // is released. The code for SHACAL2_Enc_ProcessAndXorBlock_SHANI
9 // below is Botan's x86_encrypt_blocks with minor tweaks. Many thanks
10 // to the Botan team. Also see http://github.com/randombit/botan/.
11 //
12 // The original code and all modifications are in the public domain.
13 
14 #include "pch.h"
15 #include "config.h"
16 #include "shacal2.h"
17 #include "misc.h"
18 #include "cpu.h"
19 
20 NAMESPACE_BEGIN(CryptoPP)
21 
22 // SHACAL-2 function and round definitions
23 
24 #define S0(x) (rotrConstant<2>(x)^rotrConstant<13>(x)^rotrConstant<22>(x))
25 #define S1(x) (rotrConstant<6>(x)^rotrConstant<11>(x)^rotrConstant<25>(x))
26 #define s0(x) (rotrConstant<7>(x)^rotrConstant<18>(x)^(x>>3))
27 #define s1(x) (rotrConstant<17>(x)^rotrConstant<19>(x)^(x>>10))
28 
29 #define Ch(x,y,z) (z^(x&(y^z)))
30 #define Maj(x,y,z) ((x&y)|(z&(x|y)))
31 
32 /* R is the SHA-256 round function. */
33 /* This macro increments the k argument as a side effect. */
34 #define R(a,b,c,d,e,f,g,h,k) \
35  h+=S1(e)+Ch(e,f,g)+*k++;d+=h;h+=S0(a)+Maj(a,b,c);
36 
37 /* P is the inverse of the SHA-256 round function. */
38 /* This macro decrements the k argument as a side effect. */
39 #define P(a,b,c,d,e,f,g,h,k) \
40  h-=S0(a)+Maj(a,b,c);d-=h;h-=S1(e)+Ch(e,f,g)+*--k;
41 
42 #if CRYPTOPP_SHANI_AVAILABLE
43 extern void SHACAL2_Enc_ProcessAndXorBlock_SHANI(const word32* subKeys,
44  const byte *inBlock, const byte *xorBlock, byte *outBlock);
45 #endif
46 
47 std::string SHACAL2::Base::AlgorithmProvider() const
48 {
49 #if CRYPTOPP_SHANI_AVAILABLE
50  if (HasSHA())
51  return "SHANI";
52 #endif
53  return "C++";
54 }
55 
56 void SHACAL2::Base::UncheckedSetKey(const byte *userKey, unsigned int keylen, const NameValuePairs &)
57 {
58  AssertValidKeyLength(keylen);
59 
60  word32 *rk = m_key;
61  unsigned int i;
62 
63  // 32-bit GCC 5.4 hack... m_key.size() returns 0. Note: this surfaced after changing
64  // m_key to FixedSizeAlignedSecBlock at commit 1ab1e08ac5b5a0d63374de0c.
65  GetUserKey(BIG_ENDIAN_ORDER, rk, 64, userKey, keylen);
66  for (i = 0; i < 48; i++, rk++)
67  {
68  rk[16] = rk[0] + s0(rk[1]) + rk[9] + s1(rk[14]);
69  rk[0] += K[i];
70  }
71  for (i = 48; i < 64; i++, rk++)
72  {
73  rk[0] += K[i];
74  }
75 }
76 
78 
79 void SHACAL2::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
80 {
81 #if CRYPTOPP_SHANI_AVAILABLE
82  if (HasSHA())
83  {
84  SHACAL2_Enc_ProcessAndXorBlock_SHANI(m_key, inBlock, xorBlock, outBlock);
85  return;
86  }
87 #endif
88 
89  word32 a, b, c, d, e, f, g, h;
90  const word32 *rk = m_key;
91 
92  /*
93  * map byte array block to cipher state:
94  */
95  Block::Get(inBlock)(a)(b)(c)(d)(e)(f)(g)(h);
96 
97  // Perform SHA-256 transformation.
98 
99  /* 64 operations, partially loop unrolled */
100  for (unsigned int j=0; j<64; j+=8)
101  {
102  R(a,b,c,d,e,f,g,h,rk);
103  R(h,a,b,c,d,e,f,g,rk);
104  R(g,h,a,b,c,d,e,f,rk);
105  R(f,g,h,a,b,c,d,e,rk);
106  R(e,f,g,h,a,b,c,d,rk);
107  R(d,e,f,g,h,a,b,c,rk);
108  R(c,d,e,f,g,h,a,b,rk);
109  R(b,c,d,e,f,g,h,a,rk);
110  }
111 
112  /*
113  * map cipher state to byte array block:
114  */
115 
116  Block::Put(xorBlock, outBlock)(a)(b)(c)(d)(e)(f)(g)(h);
117 }
118 
119 void SHACAL2::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
120 {
121  word32 a, b, c, d, e, f, g, h;
122  const word32 *rk = m_key + 64;
123 
124  /*
125  * map byte array block to cipher state:
126  */
127  Block::Get(inBlock)(a)(b)(c)(d)(e)(f)(g)(h);
128 
129  // Perform inverse SHA-256 transformation.
130 
131  /* 64 operations, partially loop unrolled */
132  for (unsigned int j=0; j<64; j+=8)
133  {
134  P(b,c,d,e,f,g,h,a,rk);
135  P(c,d,e,f,g,h,a,b,rk);
136  P(d,e,f,g,h,a,b,c,rk);
137  P(e,f,g,h,a,b,c,d,rk);
138  P(f,g,h,a,b,c,d,e,rk);
139  P(g,h,a,b,c,d,e,f,rk);
140  P(h,a,b,c,d,e,f,g,rk);
141  P(a,b,c,d,e,f,g,h,rk);
142  }
143 
144  /*
145  * map cipher state to byte array block:
146  */
147 
148  Block::Put(xorBlock, outBlock)(a)(b)(c)(d)(e)(f)(g)(h);
149 }
150 
151 // The SHACAL-2 round constants are identical to the SHA-256 round constants.
152 const word32 SHACAL2::Base::K[64] =
153 {
154  0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
155  0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
156  0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
157  0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
158  0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
159  0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
160  0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
161  0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
162  0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
163  0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
164  0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
165  0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
166  0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
167  0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
168  0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
169  0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
170 };
171 
172 NAMESPACE_END
Interface for retrieving values given their names.
Definition: cryptlib.h:327
Access a block of memory.
Definition: misc.h:3016
Library configuration file.
unsigned int word32
32-bit unsigned datatype
Definition: config_int.h:72
Functions for CPU features and intrinsics.
@ BIG_ENDIAN_ORDER
byte order is big-endian
Definition: cryptlib.h:152
Utility functions for the Crypto++ library.
void GetUserKey(ByteOrder order, T *out, size_t outlen, const byte *in, size_t inlen)
Copy bytes in a buffer to an array of elements in big-endian order.
Definition: misc.h:2500
Crypto++ library namespace.
Precompiled header file.
Classes for the SHACAL-2 block cipher.
Access a block of memory.
Definition: misc.h:3053