Line | Count | Source |
1 | | // shark.cpp - originally written and placed in the public domain by Wei Dai |
2 | | |
3 | | #include "pch.h" |
4 | | #include "shark.h" |
5 | | #include "misc.h" |
6 | | #include "modes.h" |
7 | | #include "gf256.h" |
8 | | |
9 | | #if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE |
10 | | # pragma GCC diagnostic ignored "-Wmissing-braces" |
11 | | #endif |
12 | | |
13 | | NAMESPACE_BEGIN(CryptoPP) |
14 | | |
15 | | static word64 SHARKTransform(word64 a) |
16 | 675 | { |
17 | 675 | static const byte iG[8][8] = { |
18 | 675 | {0xe7, 0x30, 0x90, 0x85, 0xd0, 0x4b, 0x91, 0x41}, |
19 | 675 | {0x53, 0x95, 0x9b, 0xa5, 0x96, 0xbc, 0xa1, 0x68}, |
20 | 675 | {0x02, 0x45, 0xf7, 0x65, 0x5c, 0x1f, 0xb6, 0x52}, |
21 | 675 | {0xa2, 0xca, 0x22, 0x94, 0x44, 0x63, 0x2a, 0xa2}, |
22 | 675 | {0xfc, 0x67, 0x8e, 0x10, 0x29, 0x75, 0x85, 0x71}, |
23 | 675 | {0x24, 0x45, 0xa2, 0xcf, 0x2f, 0x22, 0xc1, 0x0e}, |
24 | 675 | {0xa1, 0xf1, 0x71, 0x40, 0x91, 0x27, 0x18, 0xa5}, |
25 | 675 | {0x56, 0xf4, 0xaf, 0x32, 0xd2, 0xa4, 0xdc, 0x71} |
26 | 675 | }; |
27 | | |
28 | 675 | word64 result=0; |
29 | 675 | GF256 gf256(0xf5); |
30 | 6.07k | for (unsigned int i=0; i<8; i++) |
31 | 48.6k | for(unsigned int j=0; j<8; j++) |
32 | 43.2k | result ^= word64(gf256.Multiply(iG[i][j], GF256::Element(a>>(56-8*j)))) << (56-8*i); |
33 | 675 | return result; |
34 | 675 | } |
35 | | |
36 | | void SHARK::Base::UncheckedSetKey(const byte *key, unsigned int keyLen, const NameValuePairs ¶ms) |
37 | 150 | { |
38 | 150 | AssertValidKeyLength(keyLen); |
39 | | |
40 | 150 | m_rounds = GetRoundsAndThrowIfInvalid(params, this); |
41 | 150 | m_roundKeys.New(m_rounds+1); |
42 | | |
43 | | // concatenate key enough times to fill a |
44 | 8.55k | for (unsigned int i=0; i<(m_rounds+1)*8; i++) |
45 | 8.40k | ((byte *)m_roundKeys.begin())[i] = key[i%keyLen]; |
46 | | |
47 | 150 | SHARK::Encryption e; |
48 | 150 | e.InitForKeySetup(); |
49 | 150 | byte IV[8] = {0,0,0,0,0,0,0,0}; |
50 | 150 | CFB_Mode_ExternalCipher::Encryption cfb(e, IV); |
51 | | |
52 | 150 | cfb.ProcessString((byte *)m_roundKeys.begin(), (m_rounds+1)*8); |
53 | | |
54 | 150 | ConditionalByteReverse(BIG_ENDIAN_ORDER, m_roundKeys.begin(), m_roundKeys.begin(), (m_rounds+1)*8); |
55 | | |
56 | 150 | m_roundKeys[m_rounds] = SHARKTransform(m_roundKeys[m_rounds]); |
57 | | |
58 | 150 | if (!IsForwardTransformation()) |
59 | 75 | { |
60 | 75 | unsigned int i; |
61 | | |
62 | | // transform encryption round keys into decryption round keys |
63 | 300 | for (i=0; i<m_rounds/2; i++) |
64 | 225 | std::swap(m_roundKeys[i], m_roundKeys[m_rounds-i]); |
65 | | |
66 | 450 | for (i=1; i<m_rounds; i++) |
67 | 375 | m_roundKeys[i] = SHARKTransform(m_roundKeys[i]); |
68 | 75 | } |
69 | | |
70 | 150 | #if (CRYPTOPP_LITTLE_ENDIAN) |
71 | 150 | m_roundKeys[0] = ByteReverse(m_roundKeys[0]); |
72 | 150 | m_roundKeys[m_rounds] = ByteReverse(m_roundKeys[m_rounds]); |
73 | 150 | #endif |
74 | 150 | } |
75 | | |
76 | | // construct an SHARK_Enc object with fixed round keys, to be used to initialize actual round keys |
77 | | void SHARK::Enc::InitForKeySetup() |
78 | 150 | { |
79 | 150 | m_rounds = DEFAULT_ROUNDS; |
80 | 150 | m_roundKeys.New(DEFAULT_ROUNDS+1); |
81 | | |
82 | 1.05k | for (unsigned int i=0; i<DEFAULT_ROUNDS; i++) |
83 | 900 | m_roundKeys[i] = cbox[0][i]; |
84 | | |
85 | 150 | m_roundKeys[DEFAULT_ROUNDS] = SHARKTransform(cbox[0][DEFAULT_ROUNDS]); |
86 | | |
87 | 150 | #if (CRYPTOPP_LITTLE_ENDIAN) |
88 | 150 | m_roundKeys[0] = ByteReverse(m_roundKeys[0]); |
89 | 150 | m_roundKeys[m_rounds] = ByteReverse(m_roundKeys[m_rounds]); |
90 | 150 | #endif |
91 | 150 | } |
92 | | |
93 | | void SHARK::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const |
94 | 1.19k | { |
95 | 1.19k | CRYPTOPP_ASSERT(IsAlignedOn(inBlock,GetAlignmentOf<word64>())); |
96 | 1.19k | word64 tmp = *(word64 *)(void *)inBlock ^ m_roundKeys[0]; |
97 | | |
98 | 1.19k | ByteOrder order = GetNativeByteOrder(); |
99 | 1.19k | tmp = cbox[0][GetByte(order, tmp, 0)] ^ cbox[1][GetByte(order, tmp, 1)] |
100 | 1.19k | ^ cbox[2][GetByte(order, tmp, 2)] ^ cbox[3][GetByte(order, tmp, 3)] |
101 | 1.19k | ^ cbox[4][GetByte(order, tmp, 4)] ^ cbox[5][GetByte(order, tmp, 5)] |
102 | 1.19k | ^ cbox[6][GetByte(order, tmp, 6)] ^ cbox[7][GetByte(order, tmp, 7)] |
103 | 1.19k | ^ m_roundKeys[1]; |
104 | | |
105 | 5.99k | for(unsigned int i=2; i<m_rounds; i++) |
106 | 4.79k | { |
107 | 4.79k | tmp = cbox[0][GETBYTE(tmp, 7)] ^ cbox[1][GETBYTE(tmp, 6)] |
108 | 4.79k | ^ cbox[2][GETBYTE(tmp, 5)] ^ cbox[3][GETBYTE(tmp, 4)] |
109 | 4.79k | ^ cbox[4][GETBYTE(tmp, 3)] ^ cbox[5][GETBYTE(tmp, 2)] |
110 | 4.79k | ^ cbox[6][GETBYTE(tmp, 1)] ^ cbox[7][GETBYTE(tmp, 0)] |
111 | 4.79k | ^ m_roundKeys[i]; |
112 | 4.79k | } |
113 | | |
114 | 1.19k | PutBlock<byte, BigEndian>(xorBlock, outBlock) |
115 | 1.19k | (sbox[GETBYTE(tmp, 7)]) |
116 | 1.19k | (sbox[GETBYTE(tmp, 6)]) |
117 | 1.19k | (sbox[GETBYTE(tmp, 5)]) |
118 | 1.19k | (sbox[GETBYTE(tmp, 4)]) |
119 | 1.19k | (sbox[GETBYTE(tmp, 3)]) |
120 | 1.19k | (sbox[GETBYTE(tmp, 2)]) |
121 | 1.19k | (sbox[GETBYTE(tmp, 1)]) |
122 | 1.19k | (sbox[GETBYTE(tmp, 0)]); |
123 | | |
124 | 1.19k | CRYPTOPP_ASSERT(IsAlignedOn(outBlock,GetAlignmentOf<word64>())); |
125 | 1.19k | *(word64 *)(void *)outBlock ^= m_roundKeys[m_rounds]; |
126 | 1.19k | } |
127 | | |
128 | | void SHARK::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const |
129 | 150 | { |
130 | 150 | CRYPTOPP_ASSERT(IsAlignedOn(inBlock,GetAlignmentOf<word64>())); |
131 | 150 | word64 tmp = *(word64 *)(void *)inBlock ^ m_roundKeys[0]; |
132 | | |
133 | 150 | ByteOrder order = GetNativeByteOrder(); |
134 | 150 | tmp = cbox[0][GetByte(order, tmp, 0)] ^ cbox[1][GetByte(order, tmp, 1)] |
135 | 150 | ^ cbox[2][GetByte(order, tmp, 2)] ^ cbox[3][GetByte(order, tmp, 3)] |
136 | 150 | ^ cbox[4][GetByte(order, tmp, 4)] ^ cbox[5][GetByte(order, tmp, 5)] |
137 | 150 | ^ cbox[6][GetByte(order, tmp, 6)] ^ cbox[7][GetByte(order, tmp, 7)] |
138 | 150 | ^ m_roundKeys[1]; |
139 | | |
140 | 750 | for(unsigned int i=2; i<m_rounds; i++) |
141 | 600 | { |
142 | 600 | tmp = cbox[0][GETBYTE(tmp, 7)] ^ cbox[1][GETBYTE(tmp, 6)] |
143 | 600 | ^ cbox[2][GETBYTE(tmp, 5)] ^ cbox[3][GETBYTE(tmp, 4)] |
144 | 600 | ^ cbox[4][GETBYTE(tmp, 3)] ^ cbox[5][GETBYTE(tmp, 2)] |
145 | 600 | ^ cbox[6][GETBYTE(tmp, 1)] ^ cbox[7][GETBYTE(tmp, 0)] |
146 | 600 | ^ m_roundKeys[i]; |
147 | 600 | } |
148 | | |
149 | 150 | PutBlock<byte, BigEndian>(xorBlock, outBlock) |
150 | 150 | (sbox[GETBYTE(tmp, 7)]) |
151 | 150 | (sbox[GETBYTE(tmp, 6)]) |
152 | 150 | (sbox[GETBYTE(tmp, 5)]) |
153 | 150 | (sbox[GETBYTE(tmp, 4)]) |
154 | 150 | (sbox[GETBYTE(tmp, 3)]) |
155 | 150 | (sbox[GETBYTE(tmp, 2)]) |
156 | 150 | (sbox[GETBYTE(tmp, 1)]) |
157 | 150 | (sbox[GETBYTE(tmp, 0)]); |
158 | | |
159 | 150 | CRYPTOPP_ASSERT(IsAlignedOn(outBlock,GetAlignmentOf<word64>())); |
160 | 150 | *(word64 *)(void *)outBlock ^= m_roundKeys[m_rounds]; |
161 | 150 | } |
162 | | |
163 | | NAMESPACE_END |