summaryrefslogtreecommitdiff
path: root/shacal2.cpp
blob: 37ba9899f1c151fe257ca9f8a09cb7e139fe1c51 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
// shacal2.cpp - written by Kevin Springle, 2003
//
// Portions of this code were derived from
// Wei Dai's implementation of SHA-2
//
// Jack Lloyd and the Botan team allowed Crypto++ to use parts of
// Botan's implementation under the same license as Crypto++
// is released. The code for SHACAL2_Enc_ProcessAndXorBlock_SHANI
// below is Botan's x86_encrypt_blocks with minor tweaks. Many thanks
// to the Botan team. Also see http://github.com/randombit/botan/.
//
// The original code and all modifications are in the public domain.

#include "pch.h"
#include "config.h"
#include "shacal2.h"
#include "misc.h"
#include "cpu.h"

NAMESPACE_BEGIN(CryptoPP)

// SHACAL-2 function and round definitions

#define S0(x) (rotrConstant<2>(x)^rotrConstant<13>(x)^rotrConstant<22>(x))
#define S1(x) (rotrConstant<6>(x)^rotrConstant<11>(x)^rotrConstant<25>(x))
#define s0(x) (rotrConstant<7>(x)^rotrConstant<18>(x)^(x>>3))
#define s1(x) (rotrConstant<17>(x)^rotrConstant<19>(x)^(x>>10))

#define Ch(x,y,z) (z^(x&(y^z)))
#define Maj(x,y,z) ((x&y)|(z&(x|y)))

/* R is the SHA-256 round function. */
/* This macro increments the k argument as a side effect. */
#define R(a,b,c,d,e,f,g,h,k) \
	h+=S1(e)+Ch(e,f,g)+*k++;d+=h;h+=S0(a)+Maj(a,b,c);

/* P is the inverse of the SHA-256 round function. */
/* This macro decrements the k argument as a side effect. */
#define P(a,b,c,d,e,f,g,h,k) \
	h-=S0(a)+Maj(a,b,c);d-=h;h-=S1(e)+Ch(e,f,g)+*--k;

#if CRYPTOPP_SHANI_AVAILABLE
extern void SHACAL2_Enc_ProcessAndXorBlock_SHANI(const word32* subKeys,
                const byte *inBlock, const byte *xorBlock, byte *outBlock);
#endif

std::string SHACAL2::Base::AlgorithmProvider() const
{
#if CRYPTOPP_SHANI_AVAILABLE
    if (HasSHA())
        return "SHANI";
#endif
	return "C++";
}

void SHACAL2::Base::UncheckedSetKey(const byte *userKey, unsigned int keylen, const NameValuePairs &)
{
	AssertValidKeyLength(keylen);

	word32 *rk = m_key;
	unsigned int i;

	// 32-bit GCC 5.4 hack... m_key.size() returns 0. Note: this surfaced after changing
	// m_key to FixedSizeAlignedSecBlock at commit 1ab1e08ac5b5a0d63374de0c.
	GetUserKey(BIG_ENDIAN_ORDER, rk, 64, userKey, keylen);
	for (i = 0; i < 48; i++, rk++)
	{
		rk[16] = rk[0] + s0(rk[1]) + rk[9] + s1(rk[14]);
		rk[0] += K[i];
	}
	for (i = 48; i < 64; i++, rk++)
	{
		rk[0] += K[i];
	}
}

typedef BlockGetAndPut<word32, BigEndian> Block;

void SHACAL2::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
{
#if CRYPTOPP_SHANI_AVAILABLE
	if (HasSHA())
	{
		SHACAL2_Enc_ProcessAndXorBlock_SHANI(m_key, inBlock, xorBlock, outBlock);
		return;
	}
#endif

	word32 a, b, c, d, e, f, g, h;
	const word32 *rk = m_key;

	/*
	 * map byte array block to cipher state:
	 */
	Block::Get(inBlock)(a)(b)(c)(d)(e)(f)(g)(h);

	// Perform SHA-256 transformation.

	/* 64 operations, partially loop unrolled */
	for (unsigned int j=0; j<64; j+=8)
	{
		R(a,b,c,d,e,f,g,h,rk);
		R(h,a,b,c,d,e,f,g,rk);
		R(g,h,a,b,c,d,e,f,rk);
		R(f,g,h,a,b,c,d,e,rk);
		R(e,f,g,h,a,b,c,d,rk);
		R(d,e,f,g,h,a,b,c,rk);
		R(c,d,e,f,g,h,a,b,rk);
		R(b,c,d,e,f,g,h,a,rk);
	}

	/*
	 * map cipher state to byte array block:
	 */

	Block::Put(xorBlock, outBlock)(a)(b)(c)(d)(e)(f)(g)(h);
}

void SHACAL2::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
{
	word32 a, b, c, d, e, f, g, h;
	const word32 *rk = m_key + 64;

	/*
	 * map byte array block to cipher state:
	 */
	Block::Get(inBlock)(a)(b)(c)(d)(e)(f)(g)(h);

	// Perform inverse SHA-256 transformation.

	/* 64 operations, partially loop unrolled */
	for (unsigned int j=0; j<64; j+=8)
	{
		P(b,c,d,e,f,g,h,a,rk);
		P(c,d,e,f,g,h,a,b,rk);
		P(d,e,f,g,h,a,b,c,rk);
		P(e,f,g,h,a,b,c,d,rk);
		P(f,g,h,a,b,c,d,e,rk);
		P(g,h,a,b,c,d,e,f,rk);
		P(h,a,b,c,d,e,f,g,rk);
		P(a,b,c,d,e,f,g,h,rk);
	}

	/*
	 * map cipher state to byte array block:
	 */

	Block::Put(xorBlock, outBlock)(a)(b)(c)(d)(e)(f)(g)(h);
}

// The SHACAL-2 round constants are identical to the SHA-256 round constants.
const word32 SHACAL2::Base::K[64] =
{
	0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
	0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
	0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
	0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
	0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
	0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
	0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
	0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
	0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
	0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
	0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
	0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
	0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
	0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
	0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
	0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};

NAMESPACE_END