1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.github.tonywasher.joceanus.gordianknot.impl.ext.engines;
18
19 import org.bouncycastle.util.Memoable;
20
21
22
23
24
25 @SuppressWarnings("checkstyle:MagicNumber")
26 public class GordianZuc256Engine
27 extends GordianZuc128Engine {
28
29
30
31 private static final byte[] EK_D = {
32 0b0100010, 0b0101111, 0b0100100, 0b0101010, 0b1101101, 0b1000000, 0b1000000, 0b1000000,
33 0b1000000, 0b1000000, 0b1000000, 0b1000000, 0b1000000, 0b1010010, 0b0010000, 0b0110000
34 };
35
36
37
38
39 private static final byte[] EK_D32 = {
40 0b0100010, 0b0101111, 0b0100101, 0b0101010, 0b1101101, 0b1000000, 0b1000000, 0b1000000,
41 0b1000000, 0b1000000, 0b1000000, 0b1000000, 0b1000000, 0b1010010, 0b0010000, 0b0110000
42 };
43
44
45
46
47 private static final byte[] EK_D64 = {
48 0b0100011, 0b0101111, 0b0100100, 0b0101010, 0b1101101, 0b1000000, 0b1000000, 0b1000000,
49 0b1000000, 0b1000000, 0b1000000, 0b1000000, 0b1000000, 0b1010010, 0b0010000, 0b0110000
50 };
51
52
53
54
55 private static final byte[] EK_D128 = {
56 0b0100011, 0b0101111, 0b0100101, 0b0101010, 0b1101101, 0b1000000, 0b1000000, 0b1000000,
57 0b1000000, 0b1000000, 0b1000000, 0b1000000, 0b1000000, 0b1010010, 0b0010000, 0b0110000
58 };
59
60
61
62
63 private byte[] theD;
64
65
66
67
68 public GordianZuc256Engine() {
69 theD = EK_D;
70 }
71
72
73
74
75
76
77 public GordianZuc256Engine(final int pLength) {
78 switch (pLength) {
79 case 32:
80 theD = EK_D32;
81 break;
82 case 64:
83 theD = EK_D64;
84 break;
85 case 128:
86 theD = EK_D128;
87 break;
88 default:
89 throw new IllegalArgumentException("Unsupported length: " + pLength);
90 }
91 }
92
93
94
95
96
97
98 private GordianZuc256Engine(final GordianZuc256Engine pSource) {
99 super(pSource);
100 }
101
102 @Override
103 protected int getMaxIterations() {
104 return 625;
105 }
106
107 @Override
108 public String getAlgorithmName() {
109 return "Zuc-256";
110 }
111
112
113
114
115
116
117
118
119
120
121 private static int makeU31(final byte a, final byte b, final byte c, final byte d) {
122 return (((a & 0xFF) << 23) | ((b & 0xFF) << 16) | ((c & 0xFF) << 8) | (d & 0xFF));
123 }
124
125 @Override
126 protected void setKeyAndIV(final int[] pLFSR,
127 final byte[] k,
128 final byte[] iv) {
129
130 if (k == null || k.length != 32) {
131 throw new IllegalArgumentException("A key of 32 bytes is needed");
132 }
133 if (iv == null || iv.length != 25) {
134 throw new IllegalArgumentException("An IV of 25 bytes is needed");
135 }
136
137
138 pLFSR[0] = makeU31(k[0], theD[0], k[21], k[16]);
139 pLFSR[1] = makeU31(k[1], theD[1], k[22], k[17]);
140 pLFSR[2] = makeU31(k[2], theD[2], k[23], k[18]);
141 pLFSR[3] = makeU31(k[3], theD[3], k[24], k[19]);
142 pLFSR[4] = makeU31(k[4], theD[4], k[25], k[20]);
143 pLFSR[5] = makeU31(iv[0], (byte) (theD[5] | (iv[17] & 0x3F)), k[5], k[26]);
144 pLFSR[6] = makeU31(iv[1], (byte) (theD[6] | (iv[18] & 0x3F)), k[6], k[27]);
145 pLFSR[7] = makeU31(iv[10], (byte) (theD[7] | (iv[19] & 0x3F)), k[7], iv[2]);
146 pLFSR[8] = makeU31(k[8], (byte) (theD[8] | (iv[20] & 0x3F)), iv[3], iv[11]);
147 pLFSR[9] = makeU31(k[9], (byte) (theD[9] | (iv[21] & 0x3F)), iv[12], iv[4]);
148 pLFSR[10] = makeU31(iv[5], (byte) (theD[10] | (iv[22] & 0x3F)), k[10], k[28]);
149 pLFSR[11] = makeU31(k[11], (byte) (theD[11] | (iv[23] & 0x3F)), iv[6], iv[13]);
150 pLFSR[12] = makeU31(k[12], (byte) (theD[12] | (iv[24] & 0x3F)), iv[7], iv[14]);
151 pLFSR[13] = makeU31(k[13], theD[13], iv[15], iv[8]);
152 pLFSR[14] = makeU31(k[14], (byte) (theD[14] | ((k[31] >>> 4) & 0xF)), iv[16], iv[9]);
153 pLFSR[15] = makeU31(k[15], (byte) (theD[15] | (k[31] & 0xF)), k[30], k[29]);
154 }
155
156 @Override
157 public GordianZuc256Engine copy() {
158 return new GordianZuc256Engine(this);
159 }
160
161 @Override
162 public void reset(final Memoable pState) {
163 final GordianZuc256Engine e = (GordianZuc256Engine) pState;
164 super.reset(pState);
165 theD = e.theD;
166 }
167 }