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