diff --git a/src/java.base/share/classes/com/sun/crypto/provider/CipherBlockChaining.java b/src/java.base/share/classes/com/sun/crypto/provider/CipherBlockChaining.java index 4bd7faea722..c084d6edd55 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/CipherBlockChaining.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/CipherBlockChaining.java @@ -59,10 +59,15 @@ class CipherBlockChaining extends FeedbackCipher { // variables for save/restore calls private byte[] rSave = null; + // chunkSize is a multiple of block size and used to divide up + // input data to trigger the intrinsic. + private final int chunkSize; + CipherBlockChaining(SymmetricCipher embeddedCipher) { super(embeddedCipher); k = new byte[blockSize]; r = new byte[blockSize]; + chunkSize = blockSize * 6400; } /** @@ -148,8 +153,18 @@ class CipherBlockChaining extends FeedbackCipher { ArrayUtil.blockSizeCheck(plainLen, blockSize); ArrayUtil.nullAndBoundsCheck(plain, plainOffset, plainLen); ArrayUtil.nullAndBoundsCheck(cipher, cipherOffset, plainLen); - return implEncrypt(plain, plainOffset, plainLen, - cipher, cipherOffset); + int processed = 0; + for (; plainLen > chunkSize; cipherOffset += chunkSize, + plainOffset += chunkSize, plainLen -= chunkSize) { + processed += + implEncrypt(plain, plainOffset, chunkSize, cipher, cipherOffset); + } + // note: above loop always leaves some data to process (more than zero, + // less than or equal to chunkSize) so this last call can be + // unconditional + processed += + implEncrypt(plain, plainOffset, plainLen, cipher, cipherOffset); + return processed; } @IntrinsicCandidate @@ -199,7 +214,18 @@ class CipherBlockChaining extends FeedbackCipher { ArrayUtil.blockSizeCheck(cipherLen, blockSize); ArrayUtil.nullAndBoundsCheck(cipher, cipherOffset, cipherLen); ArrayUtil.nullAndBoundsCheck(plain, plainOffset, cipherLen); - return implDecrypt(cipher, cipherOffset, cipherLen, plain, plainOffset); + int processed = 0; + for (; cipherLen > chunkSize; cipherOffset += chunkSize, + plainOffset += chunkSize, cipherLen -= chunkSize) { + processed += + implDecrypt(cipher, cipherOffset, chunkSize, plain, plainOffset); + } + // note: above loop always leaves some data to process (more than zero, + // less than or equal to chunkSize) so this last call can be + // unconditional + processed += + implDecrypt(cipher, cipherOffset, cipherLen, plain, plainOffset); + return processed; } @IntrinsicCandidate diff --git a/test/micro/org/openjdk/bench/javax/crypto/full/AESBench.java b/test/micro/org/openjdk/bench/javax/crypto/full/AESBench.java index 7e1eecdace4..f04e5d015a2 100644 --- a/test/micro/org/openjdk/bench/javax/crypto/full/AESBench.java +++ b/test/micro/org/openjdk/bench/javax/crypto/full/AESBench.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,9 @@ package org.openjdk.bench.javax.crypto.full; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.Param; import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.infra.Blackhole; +import java.security.GeneralSecurityException; +import org.openjdk.jmh.annotations.Fork; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; @@ -36,9 +39,10 @@ import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidParameterSpecException; +@Fork(jvmArgsAppend = {"-Xms20g", "-Xmx20g", "-XX:+UseZGC"}) public class AESBench extends CryptoBase { - public static final int SET_SIZE = 128; + public static final int SET_SIZE = 8; @Param({"AES/ECB/NoPadding", "AES/ECB/PKCS5Padding", "AES/CBC/NoPadding", "AES/CBC/PKCS5Padding"}) private String algorithm; @@ -53,6 +57,7 @@ public class AESBench extends CryptoBase { byte[][] encryptedData; private Cipher encryptCipher; private Cipher decryptCipher; + private byte[] outBuffer; int index = 0; @Setup @@ -66,6 +71,7 @@ public class AESBench extends CryptoBase { decryptCipher.init(Cipher.DECRYPT_MODE, ks, encryptCipher.getParameters()); data = fillRandom(new byte[SET_SIZE][dataSize]); encryptedData = fillEncrypted(data, encryptCipher); + outBuffer = new byte[dataSize + 128]; // extra space for tag, etc } @Benchmark @@ -75,6 +81,13 @@ public class AESBench extends CryptoBase { return encryptCipher.doFinal(d); } + @Benchmark + public void encrypt2(Blackhole bh) throws GeneralSecurityException { + byte[] d = data[index]; + index = (index +1) % SET_SIZE; + bh.consume(encryptCipher.doFinal(d, 0, d.length, outBuffer)); + } + @Benchmark public byte[] decrypt() throws BadPaddingException, IllegalBlockSizeException { byte[] e = encryptedData[index]; @@ -82,4 +95,11 @@ public class AESBench extends CryptoBase { return decryptCipher.doFinal(e); } + @Benchmark + public void decrypt2(Blackhole bh) throws GeneralSecurityException { + byte[] e = encryptedData[index]; + index = (index +1) % SET_SIZE; + bh.consume(decryptCipher.doFinal(e, 0, e.length, outBuffer)); + } + }