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