1 /*
2  * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 package org.openjdk.bench.javax.crypto.full;
24 
25 import org.openjdk.jmh.annotations.Benchmark;
26 import org.openjdk.jmh.annotations.Param;
27 import org.openjdk.jmh.annotations.Setup;
28 
29 import javax.crypto.*;
30 import javax.crypto.spec.*;
31 import java.security.*;
32 import java.security.spec.*;
33 
34 
35 public abstract class CipherBench extends CryptoBase {
36 
37     @Param({})
38     private String permutation;
39 
40     @Param({})
41     private String mode;
42 
43     @Param({})
44     private String padding;
45 
46     @Param({})
47     private int keyLength;
48 
49     @Param({})
50     private int dataSize;
51 
52     private int decryptCount = 0;
53     private byte[] data;
54     private byte[][] encryptedData = new byte[2][];
55     private byte[] outBuffer;
56     private Cipher[] encryptCipher = new Cipher[2];
57     private Cipher decryptCipher;
58     protected SecretKeySpec ks;
59     protected byte[] iv;
60 
ivLength()61     protected abstract int ivLength();
makeParameterSpec()62     protected abstract AlgorithmParameterSpec makeParameterSpec();
63 
init(Cipher c, int mode, SecretKeySpec ks)64     protected void init(Cipher c, int mode, SecretKeySpec ks)
65         throws GeneralSecurityException {
66 
67         if (iv == null) {
68             iv = fillSecureRandom(new byte[ivLength()]);
69         }
70 
71         // toggle some bits in the IV to get around IV reuse defenses
72         iv[0] ^= 0xFF;
73         AlgorithmParameterSpec paramSpec = makeParameterSpec();
74 
75         c.init(mode, ks, paramSpec);
76     }
77 
init(Cipher c, int mode, SecretKeySpec ks, Cipher fromCipher)78     protected void init(Cipher c, int mode, SecretKeySpec ks, Cipher fromCipher)
79         throws GeneralSecurityException {
80 
81         AlgorithmParameters params = fromCipher.getParameters();
82         c.init(mode, ks, fromCipher.getParameters());
83     }
84 
85     @Setup
setup()86     public void setup() throws GeneralSecurityException {
87         setupProvider();
88 
89         String transform = permutation + "/" + mode + "/" + padding;
90         byte[] keystring = fillSecureRandom(new byte[keyLength / 8]);
91         ks = new SecretKeySpec(keystring, permutation);
92         data = fillRandom(new byte[dataSize]);
93         for (int i = 0; i < 2; i++) {
94             encryptCipher[i] = makeCipher(prov, transform);
95             init(encryptCipher[i], Cipher.ENCRYPT_MODE, ks);
96             encryptedData[i] = encryptCipher[i].doFinal(data);
97         }
98         outBuffer = new byte[dataSize + 128]; // extra space for tag, etc
99         decryptCipher = makeCipher(prov, transform);
100     }
101 
102     @Benchmark
encrypt()103     public void encrypt() throws GeneralSecurityException {
104         init(encryptCipher[1], Cipher.ENCRYPT_MODE, ks);
105         encryptCipher[1].doFinal(data, 0, data.length, outBuffer);
106     }
107 
108     @Benchmark
decrypt()109     public void decrypt() throws GeneralSecurityException {
110         init(decryptCipher, Cipher.DECRYPT_MODE, ks,
111             encryptCipher[decryptCount]);
112         decryptCipher.doFinal(encryptedData[decryptCount], 0,
113             encryptedData[decryptCount].length, outBuffer);
114         decryptCount = (decryptCount + 1) % 2;
115     }
116 
117     public static class GCM extends CipherBench {
118 
119         @Param({"AES"})
120         private String permutation;
121 
122         @Param({"GCM"})
123         private String mode;
124 
125         @Param({"NoPadding"})
126         private String padding;
127 
128         @Param({"128", "256"})
129         private int keyLength;
130 
131         @Param({"1024", "" + 16 * 1024})
132         private int dataSize;
133 
ivLength()134         protected int ivLength() {
135             return 32;
136         }
makeParameterSpec()137         protected AlgorithmParameterSpec makeParameterSpec() {
138             return new GCMParameterSpec(96, iv, 0, 16);
139         }
140 
141         private byte[] aad;
142 
init(Cipher c, int mode, SecretKeySpec ks)143         protected void init(Cipher c, int mode, SecretKeySpec ks)
144             throws GeneralSecurityException {
145 
146             if (aad == null) {
147                 aad = fillSecureRandom(new byte[5]);
148             }
149 
150             super.init(c, mode, ks);
151             c.updateAAD(aad);
152         }
153 
init(Cipher c, int mode, SecretKeySpec ks, Cipher fromCipher)154         protected void init(Cipher c, int mode, SecretKeySpec ks,
155             Cipher fromCipher) throws GeneralSecurityException {
156 
157             super.init(c, mode, ks, fromCipher);
158             c.updateAAD(aad);
159         }
160     }
161 
162     public static class CTR extends CipherBench {
163 
164         @Param({"AES"})
165         private String permutation;
166 
167         @Param({"CTR"})
168         private String mode;
169 
170         @Param({"NoPadding"})
171         private String padding;
172 
173         @Param({"128", "256"})
174         private int keyLength;
175 
176         @Param({"1024", "" + 16 * 1024})
177         private int dataSize;
178 
ivLength()179         protected int ivLength() {
180             return 16;
181         }
makeParameterSpec()182         protected AlgorithmParameterSpec makeParameterSpec() {
183             return new IvParameterSpec(iv);
184         }
185     }
186 
187     public static class ChaCha20Poly1305 extends CipherBench {
188 
189         @Param({"ChaCha20-Poly1305"})
190         private String permutation;
191 
192         @Param({"None"})
193         private String mode;
194 
195         @Param({"NoPadding"})
196         private String padding;
197 
198         @Param({"256"})
199         private int keyLength;
200 
201         @Param({"1024", "" + 16 * 1024})
202         private int dataSize;
203 
ivLength()204         protected int ivLength() {
205             return 12;
206         }
makeParameterSpec()207         protected AlgorithmParameterSpec makeParameterSpec() {
208             return new IvParameterSpec(iv);
209         }
210     }
211 
212     public static class ChaCha20 extends CipherBench {
213 
214         @Param({"ChaCha20"})
215         private String permutation;
216 
217         @Param({"None"})
218         private String mode;
219 
220         @Param({"NoPadding"})
221         private String padding;
222 
223         @Param({"256"})
224         private int keyLength;
225 
226         @Param({"1024", "" + 16 * 1024})
227         private int dataSize;
228 
ivLength()229         protected int ivLength() {
230             return 12;
231         }
makeParameterSpec()232         protected AlgorithmParameterSpec makeParameterSpec() {
233             return new ChaCha20ParameterSpec(iv, 0);
234         }
235 
init(Cipher c, int mode, SecretKeySpec ks, Cipher fromCipher)236         protected void init(Cipher c, int mode, SecretKeySpec ks,
237             Cipher fromCipher) throws GeneralSecurityException {
238 
239             AlgorithmParameterSpec paramSpec =
240                 new ChaCha20ParameterSpec(fromCipher.getIV(), 0);
241             c.init(mode, ks, paramSpec);
242         }
243     }
244 }
245