20 * or visit www.oracle.com if you need additional information or have
21 * questions.
22 */
23
24 package benchmark.crypto;
25
26 import org.openjdk.jmh.annotations.*;
27 import jdk.incubator.vector.*;
28 import java.util.Arrays;
29
30 @State(Scope.Thread)
31 @BenchmarkMode(Mode.Throughput)
32 @Fork(value = 1, jvmArgsPrepend = {"--add-modules=jdk.incubator.vector"})
33 @Warmup(iterations = 3, time = 3)
34 @Measurement(iterations = 8, time = 2)
35 public class ChaChaBench {
36
37 @Param({"16384", "65536"})
38 private int dataSize;
39
40 private ChaChaVector cc20_S128 = makeCC20(Vector.Shape.S_128_BIT);
41 private ChaChaVector cc20_S256 = makeCC20(Vector.Shape.S_256_BIT);
42 private ChaChaVector cc20_S512 = makeCC20(Vector.Shape.S_512_BIT);
43
44 private byte[] in;
45 private byte[] out;
46
47 private byte[] key = new byte[32];
48 private byte[] nonce = new byte[12];
49 private long counter = 0;
50
51 private static ChaChaVector makeCC20(Vector.Shape shape) {
52 ChaChaVector cc20 = new ChaChaVector(shape);
53 runKAT(cc20);
54 return cc20;
55 }
56
57 @Setup
58 public void setup() {
59
60 in = new byte[dataSize];
61 out = new byte[dataSize];
62 }
63
64 @Benchmark
65 public void encrypt128() {
66 cc20_S128.chacha20(key, nonce, counter, in, out);
67 }
68
69 @Benchmark
70 public void encrypt256() {
71 cc20_S256.chacha20(key, nonce, counter, in, out);
72 }
73
74 @Benchmark
75 public void encrypt512() {
76 cc20_S512.chacha20(key, nonce, counter, in, out);
77 }
78
79 private static class ChaChaVector {
80
81 private static final int[] STATE_CONSTANTS =
82 new int[]{0x61707865, 0x3320646e, 0x79622d32, 0x6b206574};
83
84 private final Vector.Species<Integer> intSpecies;
85 private final int numBlocks;
86
87 private final Vector.Shuffle<Integer> rot1;
88 private final Vector.Shuffle<Integer> rot2;
89 private final Vector.Shuffle<Integer> rot3;
90
91 private final IntVector counterAdd;
92
93 private final Vector.Shuffle<Integer> shuf0;
94 private final Vector.Shuffle<Integer> shuf1;
95 private final Vector.Shuffle<Integer> shuf2;
96 private final Vector.Shuffle<Integer> shuf3;
97
98 private final Vector.Mask<Integer> mask0;
99 private final Vector.Mask<Integer> mask1;
100 private final Vector.Mask<Integer> mask2;
101 private final Vector.Mask<Integer> mask3;
102
103 private final int[] state;
104
105 public ChaChaVector(Vector.Shape shape) {
106 this.intSpecies = Vector.Species.of(Integer.class, shape);
107 this.numBlocks = intSpecies.length() / 4;
108
109 this.rot1 = makeRotate(1);
110 this.rot2 = makeRotate(2);
111 this.rot3 = makeRotate(3);
112
113 this.counterAdd = makeCounterAdd();
114
115 this.shuf0 = makeRearrangeShuffle(0);
116 this.shuf1 = makeRearrangeShuffle(1);
117 this.shuf2 = makeRearrangeShuffle(2);
118 this.shuf3 = makeRearrangeShuffle(3);
119
120 this.mask0 = makeRearrangeMask(0);
121 this.mask1 = makeRearrangeMask(1);
122 this.mask2 = makeRearrangeMask(2);
123 this.mask3 = makeRearrangeMask(3);
124
125 this.state = new int[numBlocks * 16];
126 }
127
128 private Vector.Shuffle<Integer> makeRotate(int amount) {
129 int[] shuffleArr = new int[intSpecies.length()];
130
131 for (int i = 0; i < intSpecies.length(); i ++) {
132 int offset = (i / 4) * 4;
133 shuffleArr[i] = offset + ((i + amount) % 4);
134 }
135
136 return IntVector.shuffleFromValues(intSpecies, shuffleArr);
137 }
138
139 private IntVector makeCounterAdd() {
140 int[] addArr = new int[intSpecies.length()];
141 for(int i = 0; i < numBlocks; i++) {
142 addArr[4 * i] = numBlocks;
143 }
144 return IntVector.fromArray(intSpecies, addArr, 0);
145 }
146
147 private Vector.Shuffle<Integer> makeRearrangeShuffle(int order) {
148 int[] shuffleArr = new int[intSpecies.length()];
149 int start = order * 4;
150 for (int i = 0; i < shuffleArr.length; i++) {
151 shuffleArr[i] = (i % 4) + start;
152 }
153 return IntVector.shuffleFromArray(intSpecies, shuffleArr, 0);
154 }
155
156 private Vector.Mask<Integer> makeRearrangeMask(int order) {
157 boolean[] maskArr = new boolean[intSpecies.length()];
158 int start = order * 4;
159 if (start < maskArr.length) {
160 for (int i = 0; i < 4; i++) {
161 maskArr[i + start] = true;
162 }
163 }
164
165 return IntVector.maskFromValues(intSpecies, maskArr);
166 }
167
168 public void makeState(byte[] key, byte[] nonce, long counter,
169 int[] out) {
170
171 // first field is constants
172 for (int i = 0; i < 4; i++) {
173 for (int j = 0; j < numBlocks; j++) {
174 out[4*j + i] = STATE_CONSTANTS[i];
175 }
176 }
177
178 // second field is first part of key
179 int fieldStart = 4 * numBlocks;
180 for (int i = 0; i < 4; i++) {
181 int keyInt = 0;
182 for (int j = 0; j < 4; j++) {
183 keyInt += (0xFF & key[4 * i + j]) << 8 * j;
184 }
185 for (int j = 0; j < numBlocks; j++) {
226 int len = intSpecies.length();
227
228 IntVector sa = IntVector.fromArray(intSpecies, state, 0);
229 IntVector sb = IntVector.fromArray(intSpecies, state, len);
230 IntVector sc = IntVector.fromArray(intSpecies, state, 2 * len);
231 IntVector sd = IntVector.fromArray(intSpecies, state, 3 * len);
232
233 int stateLenBytes = state.length * 4;
234 int numStates = (in.length + stateLenBytes - 1) / stateLenBytes;
235 for (int j = 0; j < numStates; j++){
236
237 IntVector a = sa;
238 IntVector b = sb;
239 IntVector c = sc;
240 IntVector d = sd;
241
242 for (int i = 0; i < 10; i++) {
243 // first round
244 a = a.add(b);
245 d = d.xor(a);
246 d = d.rotateL(16);
247
248 c = c.add(d);
249 b = b.xor(c);
250 b = b.rotateL(12);
251
252 a = a.add(b);
253 d = d.xor(a);
254 d = d.rotateL(8);
255
256 c = c.add(d);
257 b = b.xor(c);
258 b = b.rotateL(7);
259
260 // makeRotate
261 b = b.rearrange(rot1);
262 c = c.rearrange(rot2);
263 d = d.rearrange(rot3);
264
265 // second round
266 a = a.add(b);
267 d = d.xor(a);
268 d = d.rotateL(16);
269
270 c = c.add(d);
271 b = b.xor(c);
272 b = b.rotateL(12);
273
274 a = a.add(b);
275 d = d.xor(a);
276 d = d.rotateL(8);
277
278 c = c.add(d);
279 b = b.xor(c);
280 b = b.rotateL(7);
281
282 // makeRotate
283 b = b.rearrange(rot3);
284 c = c.rearrange(rot2);
285 d = d.rearrange(rot1);
286 }
287
288 a = a.add(sa);
289 b = b.add(sb);
290 c = c.add(sc);
291 d = d.add(sd);
292
293 // rearrange the vectors
294 if (intSpecies.length() == 4) {
295 // no rearrange needed
296 } else if (intSpecies.length() == 8) {
297 IntVector a_r = a.rearrange(b, shuf0, mask1);
298 IntVector b_r = c.rearrange(d, shuf0, mask1);
299 IntVector c_r = a.rearrange(b, shuf1, mask1);
300 IntVector d_r = c.rearrange(d, shuf1, mask1);
|
20 * or visit www.oracle.com if you need additional information or have
21 * questions.
22 */
23
24 package benchmark.crypto;
25
26 import org.openjdk.jmh.annotations.*;
27 import jdk.incubator.vector.*;
28 import java.util.Arrays;
29
30 @State(Scope.Thread)
31 @BenchmarkMode(Mode.Throughput)
32 @Fork(value = 1, jvmArgsPrepend = {"--add-modules=jdk.incubator.vector"})
33 @Warmup(iterations = 3, time = 3)
34 @Measurement(iterations = 8, time = 2)
35 public class ChaChaBench {
36
37 @Param({"16384", "65536"})
38 private int dataSize;
39
40 private ChaChaVector cc20_S128 = makeCC20(VectorShape.S_128_BIT);
41 private ChaChaVector cc20_S256 = makeCC20(VectorShape.S_256_BIT);
42 private ChaChaVector cc20_S512 = makeCC20(VectorShape.S_512_BIT);
43
44 private byte[] in;
45 private byte[] out;
46
47 private byte[] key = new byte[32];
48 private byte[] nonce = new byte[12];
49 private long counter = 0;
50
51 private static ChaChaVector makeCC20(VectorShape shape) {
52 ChaChaVector cc20 = new ChaChaVector(shape);
53 runKAT(cc20);
54 return cc20;
55 }
56
57 @Setup
58 public void setup() {
59
60 in = new byte[dataSize];
61 out = new byte[dataSize];
62 }
63
64 @Benchmark
65 public void encrypt128() {
66 cc20_S128.chacha20(key, nonce, counter, in, out);
67 }
68
69 @Benchmark
70 public void encrypt256() {
71 cc20_S256.chacha20(key, nonce, counter, in, out);
72 }
73
74 @Benchmark
75 public void encrypt512() {
76 cc20_S512.chacha20(key, nonce, counter, in, out);
77 }
78
79 private static class ChaChaVector {
80
81 private static final int[] STATE_CONSTANTS =
82 new int[]{0x61707865, 0x3320646e, 0x79622d32, 0x6b206574};
83
84 private final VectorSpecies<Integer> intSpecies;
85 private final int numBlocks;
86
87 private final VectorShuffle<Integer> rot1;
88 private final VectorShuffle<Integer> rot2;
89 private final VectorShuffle<Integer> rot3;
90
91 private final IntVector counterAdd;
92
93 private final VectorShuffle<Integer> shuf0;
94 private final VectorShuffle<Integer> shuf1;
95 private final VectorShuffle<Integer> shuf2;
96 private final VectorShuffle<Integer> shuf3;
97
98 private final VectorMask<Integer> mask0;
99 private final VectorMask<Integer> mask1;
100 private final VectorMask<Integer> mask2;
101 private final VectorMask<Integer> mask3;
102
103 private final int[] state;
104
105 public ChaChaVector(VectorShape shape) {
106 this.intSpecies = VectorSpecies.of(Integer.class, shape);
107 this.numBlocks = intSpecies.length() / 4;
108
109 this.rot1 = makeRotate(1);
110 this.rot2 = makeRotate(2);
111 this.rot3 = makeRotate(3);
112
113 this.counterAdd = makeCounterAdd();
114
115 this.shuf0 = makeRearrangeShuffle(0);
116 this.shuf1 = makeRearrangeShuffle(1);
117 this.shuf2 = makeRearrangeShuffle(2);
118 this.shuf3 = makeRearrangeShuffle(3);
119
120 this.mask0 = makeRearrangeMask(0);
121 this.mask1 = makeRearrangeMask(1);
122 this.mask2 = makeRearrangeMask(2);
123 this.mask3 = makeRearrangeMask(3);
124
125 this.state = new int[numBlocks * 16];
126 }
127
128 private VectorShuffle<Integer> makeRotate(int amount) {
129 int[] shuffleArr = new int[intSpecies.length()];
130
131 for (int i = 0; i < intSpecies.length(); i ++) {
132 int offset = (i / 4) * 4;
133 shuffleArr[i] = offset + ((i + amount) % 4);
134 }
135
136 return VectorShuffle.fromValues(intSpecies, shuffleArr);
137 }
138
139 private IntVector makeCounterAdd() {
140 int[] addArr = new int[intSpecies.length()];
141 for(int i = 0; i < numBlocks; i++) {
142 addArr[4 * i] = numBlocks;
143 }
144 return IntVector.fromArray(intSpecies, addArr, 0);
145 }
146
147 private VectorShuffle<Integer> makeRearrangeShuffle(int order) {
148 int[] shuffleArr = new int[intSpecies.length()];
149 int start = order * 4;
150 for (int i = 0; i < shuffleArr.length; i++) {
151 shuffleArr[i] = (i % 4) + start;
152 }
153 return VectorShuffle.fromArray(intSpecies, shuffleArr, 0);
154 }
155
156 private VectorMask<Integer> makeRearrangeMask(int order) {
157 boolean[] maskArr = new boolean[intSpecies.length()];
158 int start = order * 4;
159 if (start < maskArr.length) {
160 for (int i = 0; i < 4; i++) {
161 maskArr[i + start] = true;
162 }
163 }
164
165 return VectorMask.fromValues(intSpecies, maskArr);
166 }
167
168 public void makeState(byte[] key, byte[] nonce, long counter,
169 int[] out) {
170
171 // first field is constants
172 for (int i = 0; i < 4; i++) {
173 for (int j = 0; j < numBlocks; j++) {
174 out[4*j + i] = STATE_CONSTANTS[i];
175 }
176 }
177
178 // second field is first part of key
179 int fieldStart = 4 * numBlocks;
180 for (int i = 0; i < 4; i++) {
181 int keyInt = 0;
182 for (int j = 0; j < 4; j++) {
183 keyInt += (0xFF & key[4 * i + j]) << 8 * j;
184 }
185 for (int j = 0; j < numBlocks; j++) {
226 int len = intSpecies.length();
227
228 IntVector sa = IntVector.fromArray(intSpecies, state, 0);
229 IntVector sb = IntVector.fromArray(intSpecies, state, len);
230 IntVector sc = IntVector.fromArray(intSpecies, state, 2 * len);
231 IntVector sd = IntVector.fromArray(intSpecies, state, 3 * len);
232
233 int stateLenBytes = state.length * 4;
234 int numStates = (in.length + stateLenBytes - 1) / stateLenBytes;
235 for (int j = 0; j < numStates; j++){
236
237 IntVector a = sa;
238 IntVector b = sb;
239 IntVector c = sc;
240 IntVector d = sd;
241
242 for (int i = 0; i < 10; i++) {
243 // first round
244 a = a.add(b);
245 d = d.xor(a);
246 d = d.rotateLeft(16);
247
248 c = c.add(d);
249 b = b.xor(c);
250 b = b.rotateLeft(12);
251
252 a = a.add(b);
253 d = d.xor(a);
254 d = d.rotateLeft(8);
255
256 c = c.add(d);
257 b = b.xor(c);
258 b = b.rotateLeft(7);
259
260 // makeRotate
261 b = b.rearrange(rot1);
262 c = c.rearrange(rot2);
263 d = d.rearrange(rot3);
264
265 // second round
266 a = a.add(b);
267 d = d.xor(a);
268 d = d.rotateLeft(16);
269
270 c = c.add(d);
271 b = b.xor(c);
272 b = b.rotateLeft(12);
273
274 a = a.add(b);
275 d = d.xor(a);
276 d = d.rotateLeft(8);
277
278 c = c.add(d);
279 b = b.xor(c);
280 b = b.rotateLeft(7);
281
282 // makeRotate
283 b = b.rearrange(rot3);
284 c = c.rearrange(rot2);
285 d = d.rearrange(rot1);
286 }
287
288 a = a.add(sa);
289 b = b.add(sb);
290 c = c.add(sc);
291 d = d.add(sd);
292
293 // rearrange the vectors
294 if (intSpecies.length() == 4) {
295 // no rearrange needed
296 } else if (intSpecies.length() == 8) {
297 IntVector a_r = a.rearrange(b, shuf0, mask1);
298 IntVector b_r = c.rearrange(d, shuf0, mask1);
299 IntVector c_r = a.rearrange(b, shuf1, mask1);
300 IntVector d_r = c.rearrange(d, shuf1, mask1);
|