1// serpent.cpp - written and placed in the public domain by Wei Dai
2
3#include "pch.h"
4#include "serpent.h"
5#include "misc.h"
6
7#include "serpentp.h"
8
9NAMESPACE_BEGIN(CryptoPP)
10
11void Serpent_KeySchedule(word32 *k, unsigned int rounds, const byte *userKey, size_t keylen)
12{
13	FixedSizeSecBlock<word32, 8> k0;
14	GetUserKey(LITTLE_ENDIAN_ORDER, k0.begin(), 8, userKey, keylen);
15	if (keylen < 32)
16		k0[keylen/4] |= word32(1) << ((keylen%4)*8);
17
18	word32 t = k0[7];
19	unsigned int i;
20	for (i = 0; i < 8; ++i)
21		k[i] = k0[i] = t = rotlFixed(k0[i] ^ k0[(i+3)%8] ^ k0[(i+5)%8] ^ t ^ 0x9e3779b9 ^ i, 11);
22	for (i = 8; i < 4*(rounds+1); ++i)
23		k[i] = t = rotlFixed(k[i-8] ^ k[i-5] ^ k[i-3] ^ t ^ 0x9e3779b9 ^ i, 11);
24	k -= 20;
25
26	word32 a,b,c,d,e;
27	for (i=0; i<rounds/8; i++)
28	{
29		afterS2(LK); afterS2(S3); afterS3(SK);
30		afterS1(LK); afterS1(S2); afterS2(SK);
31		afterS0(LK); afterS0(S1); afterS1(SK);
32		beforeS0(LK); beforeS0(S0); afterS0(SK);
33		k += 8*4;
34		afterS6(LK); afterS6(S7); afterS7(SK);
35		afterS5(LK); afterS5(S6); afterS6(SK);
36		afterS4(LK); afterS4(S5); afterS5(SK);
37		afterS3(LK); afterS3(S4); afterS4(SK);
38	}
39	afterS2(LK); afterS2(S3); afterS3(SK);
40}
41
42void Serpent::Base::UncheckedSetKey(const byte *userKey, unsigned int keylen, const NameValuePairs &)
43{
44	AssertValidKeyLength(keylen);
45	Serpent_KeySchedule(m_key, 32, userKey, keylen);
46}
47
48typedef BlockGetAndPut<word32, LittleEndian> Block;
49
50void Serpent::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
51{
52	word32 a, b, c, d, e;
53
54	Block::Get(inBlock)(a)(b)(c)(d);
55
56	const word32 *k = m_key;
57	unsigned int i=1;
58
59	do
60	{
61		beforeS0(KX); beforeS0(S0); afterS0(LT);
62		afterS0(KX); afterS0(S1); afterS1(LT);
63		afterS1(KX); afterS1(S2); afterS2(LT);
64		afterS2(KX); afterS2(S3); afterS3(LT);
65		afterS3(KX); afterS3(S4); afterS4(LT);
66		afterS4(KX); afterS4(S5); afterS5(LT);
67		afterS5(KX); afterS5(S6); afterS6(LT);
68		afterS6(KX); afterS6(S7);
69
70		if (i == 4)
71			break;
72
73		++i;
74		c = b;
75		b = e;
76		e = d;
77		d = a;
78		a = e;
79		k += 32;
80		beforeS0(LT);
81	}
82	while (true);
83
84	afterS7(KX);
85
86	Block::Put(xorBlock, outBlock)(d)(e)(b)(a);
87}
88
89void Serpent::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
90{
91	word32 a, b, c, d, e;
92
93	Block::Get(inBlock)(a)(b)(c)(d);
94
95	const word32 *k = m_key + 96;
96	unsigned int i=4;
97
98	beforeI7(KX);
99	goto start;
100
101	do
102	{
103		c = b;
104		b = d;
105		d = e;
106		k -= 32;
107		beforeI7(ILT);
108start:
109		            beforeI7(I7); afterI7(KX);
110		afterI7(ILT); afterI7(I6); afterI6(KX);
111		afterI6(ILT); afterI6(I5); afterI5(KX);
112		afterI5(ILT); afterI5(I4); afterI4(KX);
113		afterI4(ILT); afterI4(I3); afterI3(KX);
114		afterI3(ILT); afterI3(I2); afterI2(KX);
115		afterI2(ILT); afterI2(I1); afterI1(KX);
116		afterI1(ILT); afterI1(I0); afterI0(KX);
117	}
118	while (--i != 0);
119
120	Block::Put(xorBlock, outBlock)(a)(d)(b)(e);
121}
122
123NAMESPACE_END
124