From 944b81fb7ac00561d4bb0f06e82a8f3c74e87a7f Mon Sep 17 00:00:00 2001 From: Miguel Aranda Date: Wed, 21 Oct 2026 13:11:57 +0000 Subject: [PATCH] Project import generated by Copybara. PiperOrigin-RevId: 1003883255 --- README.md | 10 +- build.gradle | 2 +- .../jni/main/cpp/conscrypt/native_crypto.cc | 70 +- .../conscrypt/AbstractConscryptEngine.java | 3 +- .../conscrypt/AbstractConscryptSocket.java | 3 +- .../main/java/org/conscrypt/Conscrypt.java | 17 +- .../java/org/conscrypt/ConscryptEngine.java | 5 +- .../org/conscrypt/ConscryptEngineSocket.java | 4 +- .../org/conscrypt/Java8EngineWrapper.java | 6 +- .../main/java/org/conscrypt/NativeSsl.java | 4 +- .../java/org/conscrypt/OpenSSLAeadCipher.java | 9 +- .../org/conscrypt/OpenSSLAeadCipherAES.java | 2 +- .../conscrypt/OpenSSLAeadCipherChaCha20.java | 2 +- .../java/org/conscrypt/OpenSSLCipher.java | 70 +- .../org/conscrypt/OpenSSLCipherChaCha20.java | 7 +- .../java/org/conscrypt/OpenSSLEvpCipher.java | 19 +- .../org/conscrypt/OpenSSLEvpCipherAES.java | 18 +- .../org/conscrypt/OpenSSLEvpCipherARC4.java | 9 +- .../org/conscrypt/OpenSSLEvpCipherDESEDE.java | 19 +- .../java/org/conscrypt/OpenSSLSocketImpl.java | 3 +- .../javax/net/ssl/SSLSocketImplTest.java | 13 +- .../javax/net/ssl/SSLSocketTest.java | 6 +- .../org/conscrypt/ConscryptEngineTest.java | 21 + .../org/conscrypt/ConscryptSocketTest.java | 12 +- .../java/org/conscrypt/OpenSSLCipherTest.java | 794 ++++++++++++++++-- .../src/main/java/org/conscrypt/Platform.java | 4 + 26 files changed, 883 insertions(+), 249 deletions(-) diff --git a/README.md b/README.md index 63fcece31..c7f5f6a12 100644 --- a/README.md +++ b/README.md @@ -150,7 +150,7 @@ Use the [os-maven-plugin](https://github.com/trustin/os-maven-plugin) to add the org.conscrypt conscrypt-openjdk - 2.7.0 + 2.8.0 ${os.detected.classifier} ``` @@ -173,7 +173,7 @@ buildscript { apply plugin: "com.google.osdetector" dependencies { - compile 'org.conscrypt:conscrypt-openjdk:2.7.0:' + osdetector.classifier + compile 'org.conscrypt:conscrypt-openjdk:2.8.0:' + osdetector.classifier } ``` @@ -191,14 +191,14 @@ To depend on the uber jar, simply use the `conscrypt-openjdk-uber` artifacts. org.conscrypt conscrypt-openjdk-uber - 2.6.3 + 2.8.0 ``` ##### Gradle ```gradle dependencies { - compile 'org.conscrypt:conscrypt-openjdk-uber:2.7.0' + compile 'org.conscrypt:conscrypt-openjdk-uber:2.8.0' } ``` @@ -211,7 +211,7 @@ arm64-v8a. ```gradle dependencies { - implementation 'org.conscrypt:conscrypt-android:2.7.0' + implementation 'org.conscrypt:conscrypt-android:2.8.0' } ``` diff --git a/build.gradle b/build.gradle index 99899c9aa..bee5ea23e 100644 --- a/build.gradle +++ b/build.gradle @@ -2,5 +2,5 @@ description = 'Conscrypt is an alternate Java Security Provider that uses Boring subprojects { // Keep this in `subprojects` for scripts and ease of use. Migrate to properties later. - version = "2.8.0" + version = "2.8-SNAPSHOT" } diff --git a/common/src/jni/main/cpp/conscrypt/native_crypto.cc b/common/src/jni/main/cpp/conscrypt/native_crypto.cc index 4dadabdeb..04491bfd0 100644 --- a/common/src/jni/main/cpp/conscrypt/native_crypto.cc +++ b/common/src/jni/main/cpp/conscrypt/native_crypto.cc @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include #include #include @@ -39,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -55,6 +59,7 @@ #include #include +#include #include #include #include @@ -65,7 +70,6 @@ using conscrypt::AppData; using conscrypt::BioInputStream; using conscrypt::BioOutputStream; using conscrypt::BioStream; -using conscrypt::CompatibilityCloseMonitor; using conscrypt::NativeCrypto; using conscrypt::SslError; @@ -156,6 +160,22 @@ static T* fromContextObject(JNIEnv* env, jobject contextObject) { return ref; } +namespace { + +template +jobject createNativeRef(JNIEnv* env, jclass clazz, jmethodID ctor, bssl::UniquePtr obj) { + if (obj == nullptr) { + return nullptr; + } + jobject ref = env->NewObject(clazz, ctor, reinterpret_cast(obj.get())); + if (ref != nullptr) { + OWNERSHIP_TRANSFERRED(obj); + } + return ref; +} + +} // namespace + /** * Converts a Java byte[] two's complement to an OpenSSL BIGNUM. Returns a * non-null BIGNUM on success. If the return value is nullptr, there is a @@ -4413,11 +4433,9 @@ static jint NativeCrypto_EVP_MD_size(JNIEnv* env, jclass, jlong evpMdRef) { return result; } -static jlong evpDigestSignVerifyInit(JNIEnv* env, - int (*init_func)(EVP_MD_CTX*, EVP_PKEY_CTX**, const EVP_MD*, - ENGINE*, EVP_PKEY*), - const char* jniName, jobject evpMdCtxRef, jlong evpMdRef, - jobject pkeyRef) { +template +static jlong evpDigestSignVerifyInit(JNIEnv* env, InitFunc init_func, const char* jniName, + jobject evpMdCtxRef, jlong evpMdRef, jobject pkeyRef) { EVP_MD_CTX* mdCtx = fromContextObject(env, evpMdCtxRef); if (mdCtx == nullptr) { JNI_TRACE("%s => mdCtx == null", jniName); @@ -6038,16 +6056,17 @@ static jobject NativeCrypto_EVP_HPKE_CTX_setup_base_mode_recipient( infoLen = optionalInfo->size(); } + ScopedByteArrayRO enc(env, encArray); + if (enc.get() == nullptr) { + return nullptr; + } + bssl::UniquePtr ctx(EVP_HPKE_CTX_new()); if (ctx == nullptr) { conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate EVP_HPKE_CTX"); ERR_clear_error(); return nullptr; } - ScopedByteArrayRO enc(env, encArray); - if (enc.get() == nullptr) { - return nullptr; - } if (!EVP_HPKE_CTX_setup_recipient( /* ctx= */ ctx.get(), /* key= */ key.get(), @@ -6061,15 +6080,8 @@ static jobject NativeCrypto_EVP_HPKE_CTX_setup_base_mode_recipient( return nullptr; } - ScopedLocalRef ctxObject( - env, env->NewObject(conscrypt::jniutil::nativeRefHpkeCtxClass, - conscrypt::jniutil::nativeRefHpkeCtxClass_constructor, - reinterpret_cast(ctx.get()))); - if (ctxObject.get() == nullptr) { - return nullptr; - } - ctx.release(); - return ctxObject.release(); + return createNativeRef(env, conscrypt::jniutil::nativeRefHpkeCtxClass, + conscrypt::jniutil::nativeRefHpkeCtxClass_constructor, std::move(ctx)); } static jobjectArray NativeCrypto_EVP_HPKE_CTX_setup_base_mode_sender(JNIEnv* env, jclass, @@ -6160,15 +6172,13 @@ static jobjectArray NativeCrypto_EVP_HPKE_CTX_setup_base_mode_sender(JNIEnv* env return {}; } ScopedLocalRef ctxObject( - env, env->NewObject(conscrypt::jniutil::nativeRefHpkeCtxClass, - conscrypt::jniutil::nativeRefHpkeCtxClass_constructor, - reinterpret_cast(ctx.get()))); + env, createNativeRef(env, conscrypt::jniutil::nativeRefHpkeCtxClass, + conscrypt::jniutil::nativeRefHpkeCtxClass_constructor, std::move(ctx))); if (ctxObject.get() == nullptr) { return {}; } - ctx.release(); - env->SetObjectArrayElement(result.get(), 0, ctxObject.release()); - env->SetObjectArrayElement(result.get(), 1, encArray.release()); + env->SetObjectArrayElement(result.get(), 0, ctxObject.get()); + env->SetObjectArrayElement(result.get(), 1, encArray.get()); return result.release(); } @@ -6268,16 +6278,14 @@ static jobjectArray NativeCrypto_EVP_HPKE_CTX_setup_base_mode_sender_with_seed_f } ScopedLocalRef ctxObject( - env, env->NewObject(conscrypt::jniutil::nativeRefHpkeCtxClass, - conscrypt::jniutil::nativeRefHpkeCtxClass_constructor, - reinterpret_cast(ctx.get()))); + env, createNativeRef(env, conscrypt::jniutil::nativeRefHpkeCtxClass, + conscrypt::jniutil::nativeRefHpkeCtxClass_constructor, std::move(ctx))); if (ctxObject.get() == nullptr) { return nullptr; } - ctx.release(); - env->SetObjectArrayElement(result.get(), 0, ctxObject.release()); - env->SetObjectArrayElement(result.get(), 1, encArray.release()); + env->SetObjectArrayElement(result.get(), 0, ctxObject.get()); + env->SetObjectArrayElement(result.get(), 1, encArray.get()); return result.release(); } diff --git a/common/src/main/java/org/conscrypt/AbstractConscryptEngine.java b/common/src/main/java/org/conscrypt/AbstractConscryptEngine.java index 0b588ac09..b66439d88 100644 --- a/common/src/main/java/org/conscrypt/AbstractConscryptEngine.java +++ b/common/src/main/java/org/conscrypt/AbstractConscryptEngine.java @@ -17,7 +17,6 @@ package org.conscrypt; import java.nio.ByteBuffer; -import java.security.PrivateKey; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngineResult; @@ -30,6 +29,8 @@ abstract class AbstractConscryptEngine extends SSLEngine { abstract void setBufferAllocator(BufferAllocator bufferAllocator); + abstract String getGroupName(); + /** * Returns the maximum overhead, in bytes, of sealing a record with SSL. */ diff --git a/common/src/main/java/org/conscrypt/AbstractConscryptSocket.java b/common/src/main/java/org/conscrypt/AbstractConscryptSocket.java index 27f8d99ce..d3ed956a3 100644 --- a/common/src/main/java/org/conscrypt/AbstractConscryptSocket.java +++ b/common/src/main/java/org/conscrypt/AbstractConscryptSocket.java @@ -29,7 +29,6 @@ import java.net.SocketAddress; import java.net.SocketException; import java.nio.channels.SocketChannel; -import java.security.PrivateKey; import java.util.ArrayList; import java.util.List; @@ -515,7 +514,7 @@ public String toString() { public abstract void setNamedGroups(String[] namedGroups); - abstract String getCurveNameForTesting(); + abstract String getGroupName(); /** * Returns the hostname that was supplied during socket creation. No DNS resolution is diff --git a/common/src/main/java/org/conscrypt/Conscrypt.java b/common/src/main/java/org/conscrypt/Conscrypt.java index f31227f11..838012600 100644 --- a/common/src/main/java/org/conscrypt/Conscrypt.java +++ b/common/src/main/java/org/conscrypt/Conscrypt.java @@ -23,7 +23,6 @@ import java.lang.reflect.Method; import java.nio.ByteBuffer; import java.security.KeyManagementException; -import java.security.PrivateKey; import java.security.Provider; import java.security.cert.X509Certificate; import java.util.Properties; @@ -381,6 +380,22 @@ public static void setNamedGroups(SSLSocket socket, String[] namedGroups) { toConscrypt(socket).setNamedGroups(namedGroups); } + /** + * Returns the name of the curve or named group used during the TLS handshake, or {@code null} + * if the handshake has not completed. + */ + public static String getGroupName(SSLSocket socket) { + return toConscrypt(socket).getGroupName(); + } + + /** + * Returns the name of the curve or named group used during the TLS handshake, or {@code null} + * if the handshake has not completed. + */ + public static String getGroupName(SSLEngine engine) { + return toConscrypt(engine).getGroupName(); + } + /** * This method enables Server Name Indication (SNI) and overrides the hostname supplied * during socket creation. If the hostname is not a valid SNI hostname, the SNI extension diff --git a/common/src/main/java/org/conscrypt/ConscryptEngine.java b/common/src/main/java/org/conscrypt/ConscryptEngine.java index e25873123..61486908b 100644 --- a/common/src/main/java/org/conscrypt/ConscryptEngine.java +++ b/common/src/main/java/org/conscrypt/ConscryptEngine.java @@ -214,8 +214,9 @@ public void setNamedGroups(String[] namedGroups) { sslParameters.setNamedGroups(namedGroups); } - String getCurveNameForTesting() { - return ssl.getCurveNameForTesting(); + @Override + String getGroupName() { + return ssl.getGroupName(); } /** diff --git a/common/src/main/java/org/conscrypt/ConscryptEngineSocket.java b/common/src/main/java/org/conscrypt/ConscryptEngineSocket.java index 3eb64a2c9..3725755d7 100644 --- a/common/src/main/java/org/conscrypt/ConscryptEngineSocket.java +++ b/common/src/main/java/org/conscrypt/ConscryptEngineSocket.java @@ -466,8 +466,8 @@ public final void setNamedGroups(String[] namedGroups) { } @Override - public final String getCurveNameForTesting() { - return engine.getCurveNameForTesting(); + public final String getGroupName() { + return engine.getGroupName(); } /** diff --git a/common/src/main/java/org/conscrypt/Java8EngineWrapper.java b/common/src/main/java/org/conscrypt/Java8EngineWrapper.java index 2b5eef18b..f94ab75e9 100644 --- a/common/src/main/java/org/conscrypt/Java8EngineWrapper.java +++ b/common/src/main/java/org/conscrypt/Java8EngineWrapper.java @@ -19,7 +19,6 @@ import static org.conscrypt.Preconditions.checkNotNull; import java.nio.ByteBuffer; -import java.security.PrivateKey; import java.util.List; import java.util.function.BiFunction; @@ -72,6 +71,11 @@ void setBufferAllocator(BufferAllocator bufferAllocator) { delegate.setBufferAllocator(bufferAllocator); } + @Override + String getGroupName() { + return delegate.getGroupName(); + } + @Override int maxSealOverhead() { return delegate.maxSealOverhead(); diff --git a/common/src/main/java/org/conscrypt/NativeSsl.java b/common/src/main/java/org/conscrypt/NativeSsl.java index a073a39d7..d9d61c30e 100644 --- a/common/src/main/java/org/conscrypt/NativeSsl.java +++ b/common/src/main/java/org/conscrypt/NativeSsl.java @@ -30,9 +30,7 @@ import org.conscrypt.SSLParametersImpl.PSKCallbacks; import org.conscrypt.metrics.TlsEncryptedClientHelloHandshake; -import java.io.FileDescriptor; import java.io.IOException; -import java.net.SocketException; import java.nio.charset.StandardCharsets; import java.security.InvalidKeyException; import java.security.PrivateKey; @@ -145,7 +143,7 @@ String getCipherSuite() { } } - String getCurveNameForTesting() { + String getGroupName() { lock.readLock().lock(); try { return isClosed() ? null : NativeCrypto.SSL_get_curve_name(ssl, this); diff --git a/common/src/main/java/org/conscrypt/OpenSSLAeadCipher.java b/common/src/main/java/org/conscrypt/OpenSSLAeadCipher.java index f38726fe2..41167f06e 100644 --- a/common/src/main/java/org/conscrypt/OpenSSLAeadCipher.java +++ b/common/src/main/java/org/conscrypt/OpenSSLAeadCipher.java @@ -24,6 +24,7 @@ import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; import java.util.Arrays; +import java.util.Locale; import javax.crypto.BadPaddingException; import javax.crypto.IllegalBlockSizeException; @@ -86,9 +87,7 @@ public abstract class OpenSSLAeadCipher extends OpenSSLCipher { */ int tagLengthInBytes; - protected OpenSSLAeadCipher() { - super(Padding.NOPADDING); - } + protected OpenSSLAeadCipher() {} private void checkInitialization() { if (mustInitialize) { @@ -432,8 +431,8 @@ int doFinalInternal(byte[] input, int inputOffset, int inputLen, byte[] output, } @Override - void checkSupportedPadding(Padding padding) throws NoSuchPaddingException { - if (padding != Padding.NOPADDING) { + protected void engineSetPadding(String paddingStr) throws NoSuchPaddingException { + if (!paddingStr.toUpperCase(Locale.US).equals("NOPADDING")) { throw new NoSuchPaddingException("Must be NoPadding for AEAD ciphers"); } } diff --git a/common/src/main/java/org/conscrypt/OpenSSLAeadCipherAES.java b/common/src/main/java/org/conscrypt/OpenSSLAeadCipherAES.java index 026701702..82a8c56dd 100644 --- a/common/src/main/java/org/conscrypt/OpenSSLAeadCipherAES.java +++ b/common/src/main/java/org/conscrypt/OpenSSLAeadCipherAES.java @@ -49,7 +49,7 @@ String getBaseCipherName() { } @Override - int getCipherBlockSize() { + protected int engineGetBlockSize() { return AES_BLOCK_SIZE; } diff --git a/common/src/main/java/org/conscrypt/OpenSSLAeadCipherChaCha20.java b/common/src/main/java/org/conscrypt/OpenSSLAeadCipherChaCha20.java index 4630d68ab..0bbdb9fa1 100644 --- a/common/src/main/java/org/conscrypt/OpenSSLAeadCipherChaCha20.java +++ b/common/src/main/java/org/conscrypt/OpenSSLAeadCipherChaCha20.java @@ -39,7 +39,7 @@ String getBaseCipherName() { } @Override - int getCipherBlockSize() { + protected int engineGetBlockSize() { return 0; } diff --git a/common/src/main/java/org/conscrypt/OpenSSLCipher.java b/common/src/main/java/org/conscrypt/OpenSSLCipher.java index 9a472248b..52aa130ef 100644 --- a/common/src/main/java/org/conscrypt/OpenSSLCipher.java +++ b/common/src/main/java/org/conscrypt/OpenSSLCipher.java @@ -30,13 +30,11 @@ import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Arrays; -import java.util.Locale; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.CipherSpi; import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.ShortBufferException; import javax.crypto.spec.IvParameterSpec; @@ -47,29 +45,6 @@ */ @Internal public abstract class OpenSSLCipher extends CipherSpi { - /** - * Paddings that a block cipher may support. - */ - enum Padding { - NOPADDING, - PKCS5PADDING, - PKCS7PADDING, - ; - - public static Padding getNormalized(String value) { - Padding p = Padding.valueOf(value.toUpperCase(Locale.US)); - if (p == PKCS7PADDING) { - return PKCS5PADDING; - } - return p; - } - } - - /** - * The current cipher padding. - */ - private Padding padding = Padding.PKCS5PADDING; - /** * May be used when reseting the cipher instance after calling * {@code doFinal}. @@ -86,16 +61,8 @@ public static Padding getNormalized(String value) { */ private boolean encrypting; - /** - * The block size of the current cipher. - */ - private int blockSize; - - OpenSSLCipher() {} - OpenSSLCipher(Padding padding) { - this.padding = padding; - blockSize = getCipherBlockSize(); + OpenSSLCipher() { } /** @@ -129,14 +96,6 @@ abstract int updateInternal(byte[] input, int inputOffset, int inputLen, byte[] */ abstract void checkSupportedKeySize(int keySize) throws InvalidKeyException; - /** - * Checks whether the cipher supports this particular cipher {@code padding} - * and throws {@code NoSuchPaddingException} if it doesn't. - */ - abstract void checkSupportedPadding(Padding padding) throws NoSuchPaddingException; - - abstract int getCipherBlockSize(); - boolean supportsVariableSizeKey() { return false; } @@ -145,33 +104,6 @@ boolean supportsVariableSizeIv() { return false; } - @Override - protected void engineSetPadding(String paddingStr) throws NoSuchPaddingException { - final Padding padding; - try { - padding = Padding.getNormalized(paddingStr); - } catch (IllegalArgumentException e) { - NoSuchPaddingException newE = - new NoSuchPaddingException("No such padding: " + paddingStr); - newE.initCause(e); - throw newE; - } - checkSupportedPadding(padding); - this.padding = padding; - } - - /** - * Returns the padding type for which this cipher is initialized. - */ - Padding getPadding() { - return padding; - } - - @Override - protected int engineGetBlockSize() { - return blockSize; - } - /** * The size of output if {@code doFinal()} is called with this * {@code inputLen}. If padding is enabled and the size of the input puts it diff --git a/common/src/main/java/org/conscrypt/OpenSSLCipherChaCha20.java b/common/src/main/java/org/conscrypt/OpenSSLCipherChaCha20.java index d5f0db0eb..7be0dad59 100644 --- a/common/src/main/java/org/conscrypt/OpenSSLCipherChaCha20.java +++ b/common/src/main/java/org/conscrypt/OpenSSLCipherChaCha20.java @@ -22,6 +22,7 @@ import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; import java.util.Arrays; +import java.util.Locale; import javax.crypto.BadPaddingException; import javax.crypto.IllegalBlockSizeException; @@ -184,14 +185,14 @@ protected void engineSetMode(String modeStr) throws NoSuchAlgorithmException { } @Override - void checkSupportedPadding(Padding padding) throws NoSuchPaddingException { - if (padding != Padding.NOPADDING) { + protected void engineSetPadding(String paddingStr) throws NoSuchPaddingException { + if (!paddingStr.toUpperCase(Locale.US).equals("NOPADDING")) { throw new NoSuchPaddingException("Must be NoPadding"); } } @Override - int getCipherBlockSize() { + protected int engineGetBlockSize() { return 0; } diff --git a/common/src/main/java/org/conscrypt/OpenSSLEvpCipher.java b/common/src/main/java/org/conscrypt/OpenSSLEvpCipher.java index 0aac510ee..85d4fd1b2 100644 --- a/common/src/main/java/org/conscrypt/OpenSSLEvpCipher.java +++ b/common/src/main/java/org/conscrypt/OpenSSLEvpCipher.java @@ -31,11 +31,24 @@ @Internal public abstract class OpenSSLEvpCipher extends OpenSSLCipher { + /** + * Paddings that a block cipher may support. + */ + enum Padding { + NOPADDING, + PKCS5PADDING, + } + /** * Native pointer for the OpenSSL EVP_CIPHER context. */ private final EVP_CIPHER_CTX cipherCtx = new EVP_CIPHER_CTX(NativeCrypto.EVP_CIPHER_CTX_new()); + /** + * The current cipher padding. + */ + Padding padding; + /** * Whether the cipher has processed any data yet. EVP_CIPHER doesn't * like calling "doFinal()" in decryption mode without processing any @@ -49,7 +62,7 @@ public abstract class OpenSSLEvpCipher extends OpenSSLCipher { private int modeBlockSize; protected OpenSSLEvpCipher(Padding padding) { - super(padding); + this.padding = padding; } @Override @@ -101,7 +114,7 @@ void engineInitInternal(byte[] encodedKey, AlgorithmParameterSpec params, Secure } // OpenSSL only supports PKCS5 Padding. - NativeCrypto.EVP_CIPHER_CTX_set_padding(cipherCtx, getPadding() == Padding.PKCS5PADDING); + NativeCrypto.EVP_CIPHER_CTX_set_padding(cipherCtx, padding == Padding.PKCS5PADDING); modeBlockSize = NativeCrypto.EVP_CIPHER_CTX_block_size(cipherCtx); calledUpdate = false; } @@ -245,7 +258,7 @@ int getOutputSizeForFinal(int inputLen) { } else { final int buffered = NativeCrypto.get_EVP_CIPHER_CTX_buf_len(cipherCtx); - if (getPadding() == Padding.NOPADDING) { + if (padding == Padding.NOPADDING) { return buffered + inputLen; } else { final boolean finalUsed = NativeCrypto.get_EVP_CIPHER_CTX_final_used(cipherCtx); diff --git a/common/src/main/java/org/conscrypt/OpenSSLEvpCipherAES.java b/common/src/main/java/org/conscrypt/OpenSSLEvpCipherAES.java index 581dee59e..8ebe29797 100644 --- a/common/src/main/java/org/conscrypt/OpenSSLEvpCipherAES.java +++ b/common/src/main/java/org/conscrypt/OpenSSLEvpCipherAES.java @@ -52,13 +52,15 @@ protected void engineSetMode(String modeStr) throws NoSuchAlgorithmException { } @Override - void checkSupportedPadding(Padding padding) throws NoSuchPaddingException { - switch (padding) { - case NOPADDING: - case PKCS5PADDING: - return; - default: - throw new NoSuchPaddingException("Unsupported padding " + padding.toString()); + protected void engineSetPadding(String paddingStr) throws NoSuchPaddingException { + String upperPaddingStr = paddingStr.toUpperCase(Locale.US); + if (upperPaddingStr.equals("NOPADDING")) { + padding = Padding.NOPADDING; + } else if (upperPaddingStr.equals("PKCS5PADDING") + || upperPaddingStr.equals("PKCS7PADDING")) { + padding = Padding.PKCS5PADDING; + } else { + throw new NoSuchPaddingException("No such padding: " + paddingStr); } } @@ -109,7 +111,7 @@ long getCipherType(int keyLength) { } @Override - int getCipherBlockSize() { + protected int engineGetBlockSize() { return AES_BLOCK_SIZE; } diff --git a/common/src/main/java/org/conscrypt/OpenSSLEvpCipherARC4.java b/common/src/main/java/org/conscrypt/OpenSSLEvpCipherARC4.java index f281e4305..45c83fe10 100644 --- a/common/src/main/java/org/conscrypt/OpenSSLEvpCipherARC4.java +++ b/common/src/main/java/org/conscrypt/OpenSSLEvpCipherARC4.java @@ -18,6 +18,7 @@ import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; +import java.util.Locale; import javax.crypto.NoSuchPaddingException; @@ -49,14 +50,14 @@ protected void engineSetMode(String modeStr) throws NoSuchAlgorithmException { } @Override - void checkSupportedPadding(Padding padding) throws NoSuchPaddingException { - if (padding != Padding.NOPADDING) { - throw new NoSuchPaddingException("Unsupported padding " + padding.toString()); + protected void engineSetPadding(String paddingStr) throws NoSuchPaddingException { + if (!paddingStr.toUpperCase(Locale.US).equals("NOPADDING")) { + throw new NoSuchPaddingException("Unsupported padding " + paddingStr); } } @Override - int getCipherBlockSize() { + protected int engineGetBlockSize() { return 0; } diff --git a/common/src/main/java/org/conscrypt/OpenSSLEvpCipherDESEDE.java b/common/src/main/java/org/conscrypt/OpenSSLEvpCipherDESEDE.java index 88c26fdce..ed5110264 100644 --- a/common/src/main/java/org/conscrypt/OpenSSLEvpCipherDESEDE.java +++ b/common/src/main/java/org/conscrypt/OpenSSLEvpCipherDESEDE.java @@ -18,6 +18,7 @@ import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; +import java.util.Locale; import javax.crypto.NoSuchPaddingException; @@ -77,18 +78,20 @@ protected void engineSetMode(String modeStr) throws NoSuchAlgorithmException { } @Override - void checkSupportedPadding(Padding padding) throws NoSuchPaddingException { - switch (padding) { - case NOPADDING: - case PKCS5PADDING: - return; - default: - throw new NoSuchPaddingException("Unsupported padding " + padding.toString()); + protected void engineSetPadding(String paddingStr) throws NoSuchPaddingException { + String upperPaddingStr = paddingStr.toUpperCase(Locale.US); + if (upperPaddingStr.equals("NOPADDING")) { + padding = Padding.NOPADDING; + } else if (upperPaddingStr.equals("PKCS5PADDING") + || upperPaddingStr.equals("PKCS7PADDING")) { + padding = Padding.PKCS5PADDING; + } else { + throw new NoSuchPaddingException("No such padding: " + paddingStr); } } @Override - int getCipherBlockSize() { + protected int engineGetBlockSize() { return DES_BLOCK_SIZE; } } diff --git a/common/src/main/java/org/conscrypt/OpenSSLSocketImpl.java b/common/src/main/java/org/conscrypt/OpenSSLSocketImpl.java index d4caf673c..232a98ea1 100644 --- a/common/src/main/java/org/conscrypt/OpenSSLSocketImpl.java +++ b/common/src/main/java/org/conscrypt/OpenSSLSocketImpl.java @@ -23,7 +23,6 @@ import java.net.SocketException; import java.security.PrivateKey; -import javax.net.ssl.SSLException; import javax.net.ssl.SSLSession; /** @@ -146,5 +145,5 @@ public final void setAlpnProtocols(byte[] protocols) { @Override public abstract void setNamedGroups(String[] namedGroups); - @Override public abstract String getCurveNameForTesting(); + @Override public abstract String getGroupName(); } diff --git a/common/src/test/java/org/conscrypt/javax/net/ssl/SSLSocketImplTest.java b/common/src/test/java/org/conscrypt/javax/net/ssl/SSLSocketImplTest.java index ac00a97e9..08408baff 100644 --- a/common/src/test/java/org/conscrypt/javax/net/ssl/SSLSocketImplTest.java +++ b/common/src/test/java/org/conscrypt/javax/net/ssl/SSLSocketImplTest.java @@ -23,7 +23,6 @@ import org.conscrypt.AllocatedBuffer; import org.conscrypt.BufferAllocator; import org.conscrypt.Conscrypt; -import org.conscrypt.OpenSSLSocketImpl; import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; @@ -50,8 +49,8 @@ public void teardown() throws InterruptedException { assertTrue(executor.awaitTermination(5, TimeUnit.SECONDS)); } - String getCurveName(SSLSocket socket) { - return ((OpenSSLSocketImpl) socket).getCurveNameForTesting(); + String getGroupName(SSLSocket socket) { + return Conscrypt.getGroupName(socket); } private Future runAsync(Callable callable) { @@ -138,8 +137,8 @@ public void socket_setNamedGroups_works() throws Exception { s.get(); c.get(); // This must works even if sslParametersSupportsNamedGroups is false. - assertEquals("P-384", getCurveName(client)); - assertEquals("P-384", getCurveName(server)); + assertEquals("P-384", getGroupName(client)); + assertEquals("P-384", getGroupName(server)); client.close(); server.close(); context.close(); @@ -168,8 +167,8 @@ public void socketFactory_setNamedGroups_works() throws Exception { s.get(); c.get(); // This must works even if sslParametersSupportsNamedGroups is false. - assertEquals("P-384", getCurveName(client)); - assertEquals("P-384", getCurveName(server)); + assertEquals("P-384", getGroupName(client)); + assertEquals("P-384", getGroupName(server)); client.close(); server.close(); context.close(); diff --git a/common/src/test/java/org/conscrypt/javax/net/ssl/SSLSocketTest.java b/common/src/test/java/org/conscrypt/javax/net/ssl/SSLSocketTest.java index d8a5b8de1..3e2f540f7 100644 --- a/common/src/test/java/org/conscrypt/javax/net/ssl/SSLSocketTest.java +++ b/common/src/test/java/org/conscrypt/javax/net/ssl/SSLSocketTest.java @@ -99,9 +99,9 @@ public class SSLSocketTest { private static final TestSSLContext testSslContext = TestSSLContext.create(); String getCurveName(SSLSocket socket) throws Exception { - Method getCurveNameMethod = socket.getClass().getMethod("getCurveNameForTesting"); - getCurveNameMethod.setAccessible(true); - return (String) getCurveNameMethod.invoke(socket); + Method getGroupNameMethod = socket.getClass().getMethod("getGroupName"); + getGroupNameMethod.setAccessible(true); + return (String) getGroupNameMethod.invoke(socket); } /** diff --git a/openjdk/src/test/java/org/conscrypt/ConscryptEngineTest.java b/openjdk/src/test/java/org/conscrypt/ConscryptEngineTest.java index 656ed38a9..37db6ec32 100644 --- a/openjdk/src/test/java/org/conscrypt/ConscryptEngineTest.java +++ b/openjdk/src/test/java/org/conscrypt/ConscryptEngineTest.java @@ -291,6 +291,27 @@ public void exchangeLargeMessage() throws Exception { exchangeMessage(inputBuffer, clientEngine, serverEngine); } + String getGroupName(SSLEngine engine) { + return Conscrypt.getGroupName(engine); + } + + @Test + public void getGroupName_works() throws Exception { + setupEngines(TestKeyStore.getClient(), TestKeyStore.getServer()); + + assertNull(getGroupName(clientEngine)); + assertNull(getGroupName(serverEngine)); + + doHandshake(true); + + String clientGroupName = getGroupName(clientEngine); + String serverGroupName = getGroupName(serverEngine); + assertTrue("Unexpected client group: " + clientGroupName, + clientGroupName.equals("X25519") || clientGroupName.equals("X25519MLKEM768")); + assertTrue("Unexpected server group: " + serverGroupName, + serverGroupName.equals("X25519") || serverGroupName.equals("X25519MLKEM768")); + } + @Test public void alpnWithProtocolListShouldSucceed() throws Exception { setupEngines(TestKeyStore.getClient(), TestKeyStore.getServer()); diff --git a/openjdk/src/test/java/org/conscrypt/ConscryptSocketTest.java b/openjdk/src/test/java/org/conscrypt/ConscryptSocketTest.java index 5a010bec2..6a70ede47 100644 --- a/openjdk/src/test/java/org/conscrypt/ConscryptSocketTest.java +++ b/openjdk/src/test/java/org/conscrypt/ConscryptSocketTest.java @@ -454,12 +454,12 @@ public void test_handshake() throws Exception { // By default, BoringSSL supports curves "X25519", "P-256" and "P-384". // X25519 gets priority, so that curve will be used in the handshake here. // We also allow for X25519MLKEM768, as that may be the default in the future. - String serverCurve = connection.server.getCurveNameForTesting(); - String clientCurve = connection.client.getCurveNameForTesting(); - assertTrue("Unexpected server curve: " + serverCurve, - serverCurve.equals("X25519") || serverCurve.equals("X25519MLKEM768")); - assertTrue("Unexpected client curve: " + clientCurve, - clientCurve.equals("X25519") || clientCurve.equals("X25519MLKEM768")); + String serverGroupName = connection.server.getGroupName(); + String clientGroupName = connection.client.getGroupName(); + assertTrue("Unexpected server group: " + serverGroupName, + serverGroupName.equals("X25519") || serverGroupName.equals("X25519MLKEM768")); + assertTrue("Unexpected client group: " + clientGroupName, + clientGroupName.equals("X25519") || clientGroupName.equals("X25519MLKEM768")); } @Test diff --git a/openjdk/src/test/java/org/conscrypt/OpenSSLCipherTest.java b/openjdk/src/test/java/org/conscrypt/OpenSSLCipherTest.java index b4fdad4c0..dda0d1941 100644 --- a/openjdk/src/test/java/org/conscrypt/OpenSSLCipherTest.java +++ b/openjdk/src/test/java/org/conscrypt/OpenSSLCipherTest.java @@ -127,12 +127,12 @@ public static void setUp() { TestUtils.assumeAllowsUnsignedCrypto(); } - private static void assertDecryptsToExpectedPlaintext( - String transformation, String keyAlg, byte[] keyBytes, AlgorithmParameterSpec paramSpec, - byte[] ciphertext, byte[] expectedPlaintext) throws Exception { - Cipher cipher = Cipher.getInstance(transformation, CONSCRYPT_PROVIDER); + private static void assertDecryptsToExpectedPlaintext(Cipher cipher, SecretKey key, + AlgorithmParameterSpec paramSpec, + byte[] ciphertext, + byte[] expectedPlaintext) + throws Exception { assertEquals(CONSCRYPT_PROVIDER, cipher.getProvider()); - SecretKey key = new SecretKeySpec(keyBytes, keyAlg); if (paramSpec == null) { cipher.init(Cipher.DECRYPT_MODE, key); } else { @@ -165,13 +165,18 @@ private static void assertRejectsKey(String transformation, String keyAlg, byte[ @Test public void decrypt_aesEcbNoPadding() throws Exception { - assertDecryptsToExpectedPlaintext("AES/ECB/NoPadding", "AES", key16, null, + Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding", CONSCRYPT_PROVIDER); + assertEquals(16, cipher.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key16, "AES"), null, ciphertextAes128EcbNopad, plaintext16); - assertDecryptsToExpectedPlaintext("AES/ECB/NoPadding", "AES", key24, null, + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key24, "AES"), null, ciphertextAes192EcbNopad, plaintext16); - assertDecryptsToExpectedPlaintext("AES/ECB/NoPadding", "AES", key32, null, + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key32, "AES"), null, ciphertextAes256EcbNopad, plaintext16); - assertDecryptsToExpectedPlaintext("Aes/EcB/noPadDing", "aEs", key32, null, + + Cipher cipherMixedCase = Cipher.getInstance("Aes/EcB/noPadDing", CONSCRYPT_PROVIDER); + assertEquals(16, cipherMixedCase.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipherMixedCase, new SecretKeySpec(key32, "aEs"), null, ciphertextAes256EcbNopad, plaintext16); } @@ -179,13 +184,15 @@ public void decrypt_aesEcbNoPadding() throws Exception { public void decrypt_aesEcbPkcs5Padding_andAliases() throws Exception { for (String transformation : new String[] {"AES/ECB/PKCS5Padding", "AES/ECB/PKCS7Padding", "Aes/EcB/pkcs5Padding"}) { - assertDecryptsToExpectedPlaintext(transformation, "AES", key16, null, + Cipher cipher = Cipher.getInstance(transformation, CONSCRYPT_PROVIDER); + assertEquals(16, cipher.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key16, "AES"), null, ciphertextAes128EcbPkcs5, plaintextVar); - assertDecryptsToExpectedPlaintext(transformation, "AES", key24, null, + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key24, "AES"), null, ciphertextAes192EcbPkcs5, plaintextVar); - assertDecryptsToExpectedPlaintext(transformation, "AES", key32, null, + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key32, "AES"), null, ciphertextAes256EcbPkcs5, plaintextVar); - assertDecryptsToExpectedPlaintext(transformation, "aEs", key16, null, + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key16, "aEs"), null, ciphertextAes128EcbPkcs5, plaintextVar); } } @@ -193,13 +200,18 @@ public void decrypt_aesEcbPkcs5Padding_andAliases() throws Exception { @Test public void decrypt_aesCbcNoPadding() throws Exception { IvParameterSpec iv = new IvParameterSpec(iv16); - assertDecryptsToExpectedPlaintext("AES/CBC/NoPadding", "AES", key16, iv, + Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding", CONSCRYPT_PROVIDER); + assertEquals(16, cipher.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key16, "AES"), iv, ciphertextAes128CbcNopad, plaintext16); - assertDecryptsToExpectedPlaintext("AES/CBC/NoPadding", "AES", key24, iv, + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key24, "AES"), iv, ciphertextAes192CbcNopad, plaintext16); - assertDecryptsToExpectedPlaintext("AES/CBC/NoPadding", "AES", key32, iv, + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key32, "AES"), iv, ciphertextAes256CbcNopad, plaintext16); - assertDecryptsToExpectedPlaintext("Aes/CbC/noPadding", "aEs", key32, iv, + + Cipher cipherMixedCase = Cipher.getInstance("Aes/CbC/noPadding", CONSCRYPT_PROVIDER); + assertEquals(16, cipherMixedCase.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipherMixedCase, new SecretKeySpec(key32, "aEs"), iv, ciphertextAes256CbcNopad, plaintext16); } @@ -208,13 +220,15 @@ public void decrypt_aesCbcPkcs5Padding_andAliases() throws Exception { IvParameterSpec iv = new IvParameterSpec(iv16); for (String transformation : new String[] {"AES/CBC/PKCS5Padding", "AES/CBC/PKCS7Padding", "Aes/CbC/pkcs5Padding"}) { - assertDecryptsToExpectedPlaintext(transformation, "AES", key16, iv, + Cipher cipher = Cipher.getInstance(transformation, CONSCRYPT_PROVIDER); + assertEquals(16, cipher.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key16, "AES"), iv, ciphertextAes128CbcPkcs5, plaintextVar); - assertDecryptsToExpectedPlaintext(transformation, "AES", key24, iv, + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key24, "AES"), iv, ciphertextAes192CbcPkcs5, plaintextVar); - assertDecryptsToExpectedPlaintext(transformation, "AES", key32, iv, + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key32, "AES"), iv, ciphertextAes256CbcPkcs5, plaintextVar); - assertDecryptsToExpectedPlaintext(transformation, "aEs", key16, iv, + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key16, "aEs"), iv, ciphertextAes128CbcPkcs5, plaintextVar); } } @@ -222,21 +236,31 @@ public void decrypt_aesCbcPkcs5Padding_andAliases() throws Exception { @Test public void decrypt_aesCtrNoPadding() throws Exception { IvParameterSpec iv = new IvParameterSpec(iv16); - assertDecryptsToExpectedPlaintext("AES/CTR/NoPadding", "AES", key16, iv, + Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding", CONSCRYPT_PROVIDER); + assertEquals(16, cipher.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key16, "AES"), iv, ciphertextAes128CtrNopad, plaintextVar); - assertDecryptsToExpectedPlaintext("AES/CTR/NoPadding", "AES", key24, iv, + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key24, "AES"), iv, ciphertextAes192CtrNopad, plaintextVar); - assertDecryptsToExpectedPlaintext("AES/CTR/NoPadding", "AES", key32, iv, + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key32, "AES"), iv, ciphertextAes256CtrNopad, plaintextVar); - assertDecryptsToExpectedPlaintext("aEs/CtR/noPadding", "aEs", key32, iv, + + Cipher cipherMixedCase = Cipher.getInstance("aEs/CtR/noPadding", CONSCRYPT_PROVIDER); + assertEquals(16, cipherMixedCase.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipherMixedCase, new SecretKeySpec(key32, "aEs"), iv, ciphertextAes256CtrNopad, plaintextVar); } @Test public void decrypt_aes128EcbNoPadding() throws Exception { - assertDecryptsToExpectedPlaintext("AES_128/ECB/NoPadding", "AES", key16, null, + Cipher cipher = Cipher.getInstance("AES_128/ECB/NoPadding", CONSCRYPT_PROVIDER); + assertEquals(16, cipher.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key16, "AES"), null, ciphertextAes128EcbNopad, plaintext16); - assertDecryptsToExpectedPlaintext("aEs_128/EcB/noPadding", "aEs", key16, null, + + Cipher cipherMixedCase = Cipher.getInstance("aEs_128/EcB/noPadding", CONSCRYPT_PROVIDER); + assertEquals(16, cipherMixedCase.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipherMixedCase, new SecretKeySpec(key16, "aEs"), null, ciphertextAes128EcbNopad, plaintext16); } @@ -245,19 +269,26 @@ public void decrypt_aes128EcbPkcs5Padding_andAliases() throws Exception { for (String transformation : new String[] {"AES_128/ECB/PKCS5Padding", "AES_128/ECB/PKCS7Padding", "aEs_128/EcB/pkcs5Padding"}) { - assertDecryptsToExpectedPlaintext(transformation, "AES", key16, null, + Cipher cipher = Cipher.getInstance(transformation, CONSCRYPT_PROVIDER); + assertEquals(16, cipher.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key16, "AES"), null, ciphertextAes128EcbPkcs5, plaintextVar); - assertDecryptsToExpectedPlaintext(transformation, "aEs", key16, null, + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key16, "aEs"), null, ciphertextAes128EcbPkcs5, plaintextVar); } } @Test public void decrypt_aes128CbcNoPadding() throws Exception { - assertDecryptsToExpectedPlaintext("AES_128/CBC/NoPadding", "AES", key16, + Cipher cipher = Cipher.getInstance("AES_128/CBC/NoPadding", CONSCRYPT_PROVIDER); + assertEquals(16, cipher.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key16, "AES"), new IvParameterSpec(iv16), ciphertextAes128CbcNopad, plaintext16); - assertDecryptsToExpectedPlaintext("aEs_128/CbC/noPadding", "aEs", key16, + + Cipher cipherMixedCase = Cipher.getInstance("aEs_128/CbC/noPadding", CONSCRYPT_PROVIDER); + assertEquals(16, cipherMixedCase.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipherMixedCase, new SecretKeySpec(key16, "aEs"), new IvParameterSpec(iv16), ciphertextAes128CbcNopad, plaintext16); } @@ -280,9 +311,11 @@ public void decrypt_aes128CbcPkcs5Padding_andAliases() throws Exception { }; for (String transformation : transformations) { - assertDecryptsToExpectedPlaintext(transformation, "AES", key16, iv, + Cipher cipher = Cipher.getInstance(transformation, CONSCRYPT_PROVIDER); + assertEquals(16, cipher.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key16, "AES"), iv, ciphertextAes128CbcPkcs5, plaintextVar); - assertDecryptsToExpectedPlaintext(transformation, "aEs", key16, iv, + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key16, "aEs"), iv, ciphertextAes128CbcPkcs5, plaintextVar); } } @@ -294,23 +327,47 @@ public void decrypt_pbeWithHmacSHA1AndAES128_withEcbMode() throws Exception { // PBEWithHmacSHA1AndAES_128/ECB/PKCS5Padding is an alias for // AES_128/ECB/PKCS5Padding and PBEWithHmacSHA1AndAES_128/ECB/NoPadding is an alias for // AES_128/ECB/NoPadding. - assertDecryptsToExpectedPlaintext("PBEWithHmacSHA1AndAES_128/ECB/PKCS5Padding", "AES", - key16, null, ciphertextAes128EcbPkcs5, plaintextVar); - assertDecryptsToExpectedPlaintext("PBEWithHmacSHA1AndAES_128/ECB/PKCS7Padding", "AES", - key16, null, ciphertextAes128EcbPkcs5, plaintextVar); - assertDecryptsToExpectedPlaintext("PBEWithHmacSHA1AndAES_128/ECB/NoPadding", "AES", - key16, null, ciphertextAes128EcbNopad, plaintext16); - assertDecryptsToExpectedPlaintext("pbeWithHmacSHA1AndAES_128/ecb/pkcs5Padding", "aEs", - key16, null, ciphertextAes128EcbPkcs5, plaintextVar); - assertDecryptsToExpectedPlaintext("pbeWithHmacSHA1AndAES_128/ecb/nopadding", "aEs", - key16, null, ciphertextAes128EcbNopad, plaintext16); + Cipher cipher1 = Cipher.getInstance("PBEWithHmacSHA1AndAES_128/ECB/PKCS5Padding", + CONSCRYPT_PROVIDER); + assertEquals(16, cipher1.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher1, new SecretKeySpec(key16, "AES"), null, + ciphertextAes128EcbPkcs5, plaintextVar); + + Cipher cipher2 = Cipher.getInstance("PBEWithHmacSHA1AndAES_128/ECB/PKCS7Padding", + CONSCRYPT_PROVIDER); + assertEquals(16, cipher2.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher2, new SecretKeySpec(key16, "AES"), null, + ciphertextAes128EcbPkcs5, plaintextVar); + + Cipher cipher3 = + Cipher.getInstance("PBEWithHmacSHA1AndAES_128/ECB/NoPadding", CONSCRYPT_PROVIDER); + assertEquals(16, cipher3.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher3, new SecretKeySpec(key16, "AES"), null, + ciphertextAes128EcbNopad, plaintext16); + + Cipher cipher4 = Cipher.getInstance("pbeWithHmacSHA1AndAES_128/ecb/pkcs5Padding", + CONSCRYPT_PROVIDER); + assertEquals(16, cipher4.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher4, new SecretKeySpec(key16, "aEs"), null, + ciphertextAes128EcbPkcs5, plaintextVar); + + Cipher cipher5 = + Cipher.getInstance("pbeWithHmacSHA1AndAES_128/ecb/nopadding", CONSCRYPT_PROVIDER); + assertEquals(16, cipher5.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher5, new SecretKeySpec(key16, "aEs"), null, + ciphertextAes128EcbNopad, plaintext16); } @Test public void decrypt_aes256EcbNoPadding() throws Exception { - assertDecryptsToExpectedPlaintext("AES_256/ECB/NoPadding", "AES", key32, null, + Cipher cipher = Cipher.getInstance("AES_256/ECB/NoPadding", CONSCRYPT_PROVIDER); + assertEquals(16, cipher.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key32, "AES"), null, ciphertextAes256EcbNopad, plaintext16); - assertDecryptsToExpectedPlaintext("aEs_256/EcB/noPadding", "aEs", key32, null, + + Cipher cipherMixedCase = Cipher.getInstance("aEs_256/EcB/noPadding", CONSCRYPT_PROVIDER); + assertEquals(16, cipherMixedCase.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipherMixedCase, new SecretKeySpec(key32, "aEs"), null, ciphertextAes256EcbNopad, plaintext16); } @@ -319,19 +376,26 @@ public void decrypt_aes256EcbPkcs5Padding_andAliases() throws Exception { for (String transformation : new String[] {"AES_256/ECB/PKCS5Padding", "AES_256/ECB/PKCS7Padding", "aEs_256/EcB/pkcs5Padding"}) { - assertDecryptsToExpectedPlaintext(transformation, "AES", key32, null, + Cipher cipher = Cipher.getInstance(transformation, CONSCRYPT_PROVIDER); + assertEquals(16, cipher.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key32, "AES"), null, ciphertextAes256EcbPkcs5, plaintextVar); - assertDecryptsToExpectedPlaintext(transformation, "aEs", key32, null, + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key32, "aEs"), null, ciphertextAes256EcbPkcs5, plaintextVar); } } @Test public void decrypt_aes256CbcNoPadding() throws Exception { - assertDecryptsToExpectedPlaintext("AES_256/CBC/NoPadding", "AES", key32, + Cipher cipher = Cipher.getInstance("AES_256/CBC/NoPadding", CONSCRYPT_PROVIDER); + assertEquals(16, cipher.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key32, "AES"), new IvParameterSpec(iv16), ciphertextAes256CbcNopad, plaintext16); - assertDecryptsToExpectedPlaintext("aEs_256/CbC/noPadding", "aEs", key32, + + Cipher cipherMixedCase = Cipher.getInstance("aEs_256/CbC/noPadding", CONSCRYPT_PROVIDER); + assertEquals(16, cipherMixedCase.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipherMixedCase, new SecretKeySpec(key32, "aEs"), new IvParameterSpec(iv16), ciphertextAes256CbcNopad, plaintext16); } @@ -347,9 +411,11 @@ public void decrypt_aes256CbcPkcs5Padding_andAliases() throws Exception { "PBEWithHmacSHA1AndAES_256/CBC/PKCS5Padding", "pbeWithHmacSHA1AndAES_256/cbc/pkcs5Padding"}; for (String transformation : transformations) { - assertDecryptsToExpectedPlaintext(transformation, "AES", key32, iv, + Cipher cipher = Cipher.getInstance(transformation, CONSCRYPT_PROVIDER); + assertEquals(16, cipher.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key32, "AES"), iv, ciphertextAes256CbcPkcs5, plaintextVar); - assertDecryptsToExpectedPlaintext(transformation, "aEs", key32, iv, + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key32, "aEs"), iv, ciphertextAes256CbcPkcs5, plaintextVar); } } @@ -358,16 +424,21 @@ public void decrypt_aes256CbcPkcs5Padding_andAliases() throws Exception { public void decrypt_pbeWithHmacSHA1AndAES256_withEcbMode() throws Exception { // PBEWithHmacSHA1AndAES_256 is an alias for AES_256/CBC/PKCS5PADDING, but // the Cipher.getInstance allows to use a different mode/padding. - assertDecryptsToExpectedPlaintext("PBEWithHmacSHA1AndAES_256/ECB/PKCS5Padding", "AES", - key32, null, ciphertextAes256EcbPkcs5, plaintextVar); + Cipher cipher = Cipher.getInstance("PBEWithHmacSHA1AndAES_256/ECB/PKCS5Padding", + CONSCRYPT_PROVIDER); + assertEquals(16, cipher.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key32, "AES"), null, + ciphertextAes256EcbPkcs5, plaintextVar); } @Test public void decrypt_desedeCbcNoPadding() throws Exception { IvParameterSpec iv = new IvParameterSpec(iv8); - assertDecryptsToExpectedPlaintext("DESEDE/CBC/NoPadding", "DESEDE", key16, iv, + Cipher cipher = Cipher.getInstance("DESEDE/CBC/NoPadding", CONSCRYPT_PROVIDER); + assertEquals(8, cipher.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key16, "DESEDE"), iv, ciphertextDesede16CbcNopad, plaintext8); - assertDecryptsToExpectedPlaintext("DESEDE/CBC/NoPadding", "DESEDE", key24, iv, + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key24, "DESEDE"), iv, ciphertextDesede24CbcNopad, plaintext8); } @@ -376,9 +447,11 @@ public void decrypt_desedeCbcPkcs5Padding_andAliases() throws Exception { IvParameterSpec iv = new IvParameterSpec(iv8); for (String transformation : new String[] {"DESEDE/CBC/PKCS5Padding", "DESEDE/CBC/PKCS7Padding"}) { - assertDecryptsToExpectedPlaintext(transformation, "DESEDE", key16, iv, + Cipher cipher = Cipher.getInstance(transformation, CONSCRYPT_PROVIDER); + assertEquals(8, cipher.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key16, "DESEDE"), iv, ciphertextDesede16CbcPkcs5, plaintextVar); - assertDecryptsToExpectedPlaintext(transformation, "DESEDE", key24, iv, + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key24, "DESEDE"), iv, ciphertextDesede24CbcPkcs5, plaintextVar); } } @@ -402,8 +475,10 @@ public void decrypt_arc4_andAliases() throws Exception { "OID.1.2.840.113549.3.4/ECB/NoPadding", }; for (String transformation : transformations) { - assertDecryptsToExpectedPlaintext(transformation, "ARC4", key16, null, ciphertextArc4, - plaintextVar); + Cipher cipher = Cipher.getInstance(transformation, CONSCRYPT_PROVIDER); + assertEquals(0, cipher.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key16, "ARC4"), null, + ciphertextArc4, plaintextVar); } } @@ -428,26 +503,35 @@ public void decrypt_aesGcmNoPadding_andAliases() throws Exception { "2.16.840.1.101.3.4.1.46/GCM/NoPadding", }; for (String transformation : transformations) { - assertDecryptsToExpectedPlaintext(transformation, "AES", key16, spec, + Cipher cipher = Cipher.getInstance(transformation, CONSCRYPT_PROVIDER); + assertEquals(16, cipher.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key16, "AES"), spec, ciphertextAes128Gcm, plaintextVar); - assertDecryptsToExpectedPlaintext(transformation, "AES", key32, spec, + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key32, "AES"), spec, ciphertextAes256Gcm, plaintextVar); } } @Test public void decrypt_aes128GcmNoPadding() throws Exception { - assertDecryptsToExpectedPlaintext("AES_128/GCM/NoPadding", "AES", key16, + Cipher cipher = Cipher.getInstance("AES_128/GCM/NoPadding", CONSCRYPT_PROVIDER); + assertEquals(16, cipher.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key16, "AES"), new GCMParameterSpec(128, iv12), ciphertextAes128Gcm, plaintextVar); } @Test public void decrypt_aes256GcmNoPadding() throws Exception { - assertDecryptsToExpectedPlaintext("AES_256/GCM/NoPadding", "AES", key32, + Cipher cipher = Cipher.getInstance("AES_256/GCM/NoPadding", CONSCRYPT_PROVIDER); + assertEquals(16, cipher.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key32, "AES"), new GCMParameterSpec(128, iv12), ciphertextAes256Gcm, plaintextVar); - assertDecryptsToExpectedPlaintext("aEs_256/gcm/noPadding", "aEs", key32, + + Cipher cipherMixedCase = Cipher.getInstance("aEs_256/gcm/noPadding", CONSCRYPT_PROVIDER); + assertEquals(16, cipherMixedCase.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipherMixedCase, new SecretKeySpec(key32, "aEs"), new GCMParameterSpec(128, iv12), ciphertextAes256Gcm, plaintextVar); } @@ -455,42 +539,66 @@ public void decrypt_aes256GcmNoPadding() throws Exception { @Test public void decrypt_aesGcmSivNoPadding() throws Exception { GCMParameterSpec spec = new GCMParameterSpec(128, iv12); - assertDecryptsToExpectedPlaintext("AES/GCM-SIV/NoPadding", "AES", key16, spec, + Cipher cipher = Cipher.getInstance("AES/GCM-SIV/NoPadding", CONSCRYPT_PROVIDER); + assertEquals(16, cipher.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key16, "AES"), spec, ciphertextAes128GcmSiv, plaintextVar); - assertDecryptsToExpectedPlaintext("AES/GCM-SIV/NoPadding", "AES", key32, spec, + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key32, "AES"), spec, ciphertextAes256GcmSiv, plaintextVar); - assertDecryptsToExpectedPlaintext("aEs/gcm-siv/noPadding", "aEs", key16, spec, + + Cipher cipherMixedCase = Cipher.getInstance("aEs/gcm-siv/noPadding", CONSCRYPT_PROVIDER); + assertEquals(16, cipherMixedCase.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipherMixedCase, new SecretKeySpec(key16, "aEs"), spec, ciphertextAes128GcmSiv, plaintextVar); - assertDecryptsToExpectedPlaintext("aEs/gcm-siv/noPadding", "aEs", key32, spec, + assertDecryptsToExpectedPlaintext(cipherMixedCase, new SecretKeySpec(key32, "aEs"), spec, ciphertextAes256GcmSiv, plaintextVar); } @Test public void decrypt_aes128GcmSivNoPadding() throws Exception { - assertDecryptsToExpectedPlaintext("AES_128/GCM-SIV/NoPadding", "AES", key16, + Cipher cipher = Cipher.getInstance("AES_128/GCM-SIV/NoPadding", CONSCRYPT_PROVIDER); + assertEquals(16, cipher.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key16, "AES"), new GCMParameterSpec(128, iv12), ciphertextAes128GcmSiv, plaintextVar); - assertDecryptsToExpectedPlaintext("aEs_128/gcm-siv/noPadding", "aEs", key16, + + Cipher cipherMixedCase = + Cipher.getInstance("aEs_128/gcm-siv/noPadding", CONSCRYPT_PROVIDER); + assertEquals(16, cipherMixedCase.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipherMixedCase, new SecretKeySpec(key16, "aEs"), new GCMParameterSpec(128, iv12), ciphertextAes128GcmSiv, plaintextVar); } @Test public void decrypt_aes256GcmSivNoPadding() throws Exception { - assertDecryptsToExpectedPlaintext("AES_256/GCM-SIV/NoPadding", "AES", key32, + Cipher cipher = Cipher.getInstance("AES_256/GCM-SIV/NoPadding", CONSCRYPT_PROVIDER); + assertEquals(16, cipher.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key32, "AES"), new GCMParameterSpec(128, iv12), ciphertextAes256GcmSiv, plaintextVar); - assertDecryptsToExpectedPlaintext("aEs_256/gcm-siv/noPadding", "aEs", key32, + + Cipher cipherMixedCase = + Cipher.getInstance("aEs_256/gcm-siv/noPadding", CONSCRYPT_PROVIDER); + assertEquals(16, cipherMixedCase.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipherMixedCase, new SecretKeySpec(key32, "aEs"), new GCMParameterSpec(128, iv12), ciphertextAes256GcmSiv, plaintextVar); } @Test public void decrypt_chaCha20() throws Exception { - assertDecryptsToExpectedPlaintext("ChaCha20", "ChaCha20", key32, new IvParameterSpec(iv12), - ciphertextChaCha20, plaintextVar); - assertDecryptsToExpectedPlaintext("cHaCha20", "cHaCha20", key32, new IvParameterSpec(iv12), - ciphertextChaCha20, plaintextVar); + Cipher cipher = Cipher.getInstance("ChaCha20", CONSCRYPT_PROVIDER); + assertEquals(0, cipher.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key32, "ChaCha20"), + new IvParameterSpec(iv12), ciphertextChaCha20, + plaintextVar); + + Cipher cipherMixedCase = Cipher.getInstance("cHaCha20", CONSCRYPT_PROVIDER); + assertEquals(0, cipherMixedCase.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipherMixedCase, new SecretKeySpec(key32, "cHaCha20"), + new IvParameterSpec(iv12), ciphertextChaCha20, + plaintextVar); } @Test @@ -504,9 +612,11 @@ public void decrypt_chaCha20Poly1305_andAliases() throws Exception { "ChaCha20-Poly1305/Poly1305/NoPadding", "chacha20-poly1305/poly1305/nopadding", }) { - assertDecryptsToExpectedPlaintext(transformation, "ChaCha20", key32, iv, + Cipher cipher = Cipher.getInstance(transformation, CONSCRYPT_PROVIDER); + assertEquals(0, cipher.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key32, "ChaCha20"), iv, ciphertextChaCha20Poly1305, plaintextVar); - assertDecryptsToExpectedPlaintext(transformation, "chacha20", key32, iv, + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key32, "chacha20"), iv, ciphertextChaCha20Poly1305, plaintextVar); } } @@ -522,9 +632,11 @@ public void decrypt_xChaCha20Poly1305_andAliases() throws Exception { "XChaCha20-Poly1305/Poly1305/NoPadding", "xchacha20-poly1305/poly1305/nopadding", }) { - assertDecryptsToExpectedPlaintext(transformation, "XChaCha20", key32, iv, + Cipher cipher = Cipher.getInstance(transformation, CONSCRYPT_PROVIDER); + assertEquals(0, cipher.getBlockSize()); + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key32, "XChaCha20"), iv, ciphertextXChaCha20Poly1305, plaintextVar); - assertDecryptsToExpectedPlaintext(transformation, "xchacha20", key32, iv, + assertDecryptsToExpectedPlaintext(cipher, new SecretKeySpec(key32, "xchacha20"), iv, ciphertextXChaCha20Poly1305, plaintextVar); } } @@ -675,4 +787,526 @@ public void initWith24ByteKey_xChaCha20Poly1305_andAliases_throws() throws Excep assertRejectsKey(transformation, "XChaCha20", key24, iv); } } + + // ========================================================================= + // 3. Cipher.getOutputSize Tests + // ========================================================================= + + @Test + public void getOutputSize_aesEcbNoPadding() throws Exception { + Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding", CONSCRYPT_PROVIDER); + SecretKey key = new SecretKeySpec(key16, "AES"); + + cipher.init(Cipher.ENCRYPT_MODE, key); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(5, cipher.getOutputSize(5)); + assertEquals(16, cipher.getOutputSize(16)); + assertEquals(67, cipher.getOutputSize(67)); + + cipher.init(Cipher.DECRYPT_MODE, key); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(5, cipher.getOutputSize(5)); + assertEquals(16, cipher.getOutputSize(16)); + assertEquals(67, cipher.getOutputSize(67)); + } + + @Test + public void getOutputSize_aesEcbPkcs5Padding() throws Exception { + Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding", CONSCRYPT_PROVIDER); + SecretKey key = new SecretKeySpec(key16, "AES"); + + cipher.init(Cipher.ENCRYPT_MODE, key); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(16, cipher.getOutputSize(0)); + assertEquals(16, cipher.getOutputSize(5)); + assertEquals(32, cipher.getOutputSize(16)); + assertEquals(80, cipher.getOutputSize(67)); + + cipher.init(Cipher.DECRYPT_MODE, key); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(16, cipher.getOutputSize(5)); + assertEquals(16, cipher.getOutputSize(16)); + assertEquals(80, cipher.getOutputSize(67)); + } + + @Test + public void getOutputSize_aesCbcNoPadding() throws Exception { + Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding", CONSCRYPT_PROVIDER); + SecretKey key = new SecretKeySpec(key16, "AES"); + IvParameterSpec iv = new IvParameterSpec(iv16); + + cipher.init(Cipher.ENCRYPT_MODE, key, iv); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(5, cipher.getOutputSize(5)); + assertEquals(16, cipher.getOutputSize(16)); + assertEquals(67, cipher.getOutputSize(67)); + + cipher.init(Cipher.DECRYPT_MODE, key, iv); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(5, cipher.getOutputSize(5)); + assertEquals(16, cipher.getOutputSize(16)); + assertEquals(67, cipher.getOutputSize(67)); + } + + @Test + public void getOutputSize_aesCbcPkcs5Padding() throws Exception { + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", CONSCRYPT_PROVIDER); + SecretKey key = new SecretKeySpec(key16, "AES"); + IvParameterSpec iv = new IvParameterSpec(iv16); + + cipher.init(Cipher.ENCRYPT_MODE, key, iv); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(16, cipher.getOutputSize(0)); + assertEquals(16, cipher.getOutputSize(5)); + assertEquals(32, cipher.getOutputSize(16)); + assertEquals(80, cipher.getOutputSize(67)); + + cipher.init(Cipher.DECRYPT_MODE, key, iv); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(16, cipher.getOutputSize(5)); + assertEquals(16, cipher.getOutputSize(16)); + assertEquals(80, cipher.getOutputSize(67)); + } + + @Test + public void getOutputSize_aesCtrNoPadding() throws Exception { + Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding", CONSCRYPT_PROVIDER); + SecretKey key = new SecretKeySpec(key16, "AES"); + IvParameterSpec iv = new IvParameterSpec(iv16); + + cipher.init(Cipher.ENCRYPT_MODE, key, iv); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(5, cipher.getOutputSize(5)); + assertEquals(16, cipher.getOutputSize(16)); + assertEquals(67, cipher.getOutputSize(67)); + + cipher.init(Cipher.DECRYPT_MODE, key, iv); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(5, cipher.getOutputSize(5)); + assertEquals(16, cipher.getOutputSize(16)); + assertEquals(67, cipher.getOutputSize(67)); + } + + @Test + public void getOutputSize_aes128EcbNoPadding() throws Exception { + Cipher cipher = Cipher.getInstance("AES_128/ECB/NoPadding", CONSCRYPT_PROVIDER); + SecretKey key = new SecretKeySpec(key16, "AES"); + + cipher.init(Cipher.ENCRYPT_MODE, key); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(5, cipher.getOutputSize(5)); + assertEquals(16, cipher.getOutputSize(16)); + assertEquals(67, cipher.getOutputSize(67)); + + cipher.init(Cipher.DECRYPT_MODE, key); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(5, cipher.getOutputSize(5)); + assertEquals(16, cipher.getOutputSize(16)); + assertEquals(67, cipher.getOutputSize(67)); + } + + @Test + public void getOutputSize_aes128EcbPkcs5Padding() throws Exception { + Cipher cipher = Cipher.getInstance("AES_128/ECB/PKCS5Padding", CONSCRYPT_PROVIDER); + SecretKey key = new SecretKeySpec(key16, "AES"); + + cipher.init(Cipher.ENCRYPT_MODE, key); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(16, cipher.getOutputSize(0)); + assertEquals(16, cipher.getOutputSize(5)); + assertEquals(32, cipher.getOutputSize(16)); + assertEquals(80, cipher.getOutputSize(67)); + + cipher.init(Cipher.DECRYPT_MODE, key); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(16, cipher.getOutputSize(5)); + assertEquals(16, cipher.getOutputSize(16)); + assertEquals(80, cipher.getOutputSize(67)); + } + + @Test + public void getOutputSize_aes128CbcNoPadding() throws Exception { + Cipher cipher = Cipher.getInstance("AES_128/CBC/NoPadding", CONSCRYPT_PROVIDER); + SecretKey key = new SecretKeySpec(key16, "AES"); + IvParameterSpec iv = new IvParameterSpec(iv16); + + cipher.init(Cipher.ENCRYPT_MODE, key, iv); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(5, cipher.getOutputSize(5)); + assertEquals(16, cipher.getOutputSize(16)); + assertEquals(67, cipher.getOutputSize(67)); + + cipher.init(Cipher.DECRYPT_MODE, key, iv); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(5, cipher.getOutputSize(5)); + assertEquals(16, cipher.getOutputSize(16)); + assertEquals(67, cipher.getOutputSize(67)); + } + + @Test + public void getOutputSize_aes128CbcPkcs5Padding() throws Exception { + Cipher cipher = Cipher.getInstance("AES_128/CBC/PKCS5Padding", CONSCRYPT_PROVIDER); + SecretKey key = new SecretKeySpec(key16, "AES"); + IvParameterSpec iv = new IvParameterSpec(iv16); + + cipher.init(Cipher.ENCRYPT_MODE, key, iv); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(16, cipher.getOutputSize(0)); + assertEquals(16, cipher.getOutputSize(5)); + assertEquals(32, cipher.getOutputSize(16)); + assertEquals(80, cipher.getOutputSize(67)); + + cipher.init(Cipher.DECRYPT_MODE, key, iv); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(16, cipher.getOutputSize(5)); + assertEquals(16, cipher.getOutputSize(16)); + assertEquals(80, cipher.getOutputSize(67)); + } + + @Test + public void getOutputSize_aes256EcbNoPadding() throws Exception { + Cipher cipher = Cipher.getInstance("AES_256/ECB/NoPadding", CONSCRYPT_PROVIDER); + SecretKey key = new SecretKeySpec(key32, "AES"); + + cipher.init(Cipher.ENCRYPT_MODE, key); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(5, cipher.getOutputSize(5)); + assertEquals(16, cipher.getOutputSize(16)); + assertEquals(67, cipher.getOutputSize(67)); + + cipher.init(Cipher.DECRYPT_MODE, key); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(5, cipher.getOutputSize(5)); + assertEquals(16, cipher.getOutputSize(16)); + assertEquals(67, cipher.getOutputSize(67)); + } + + @Test + public void getOutputSize_aes256EcbPkcs5Padding() throws Exception { + Cipher cipher = Cipher.getInstance("AES_256/ECB/PKCS5Padding", CONSCRYPT_PROVIDER); + SecretKey key = new SecretKeySpec(key32, "AES"); + + cipher.init(Cipher.ENCRYPT_MODE, key); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(16, cipher.getOutputSize(0)); + assertEquals(16, cipher.getOutputSize(5)); + assertEquals(32, cipher.getOutputSize(16)); + assertEquals(80, cipher.getOutputSize(67)); + + cipher.init(Cipher.DECRYPT_MODE, key); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(16, cipher.getOutputSize(5)); + assertEquals(16, cipher.getOutputSize(16)); + assertEquals(80, cipher.getOutputSize(67)); + } + + @Test + public void getOutputSize_aes256CbcNoPadding() throws Exception { + Cipher cipher = Cipher.getInstance("AES_256/CBC/NoPadding", CONSCRYPT_PROVIDER); + SecretKey key = new SecretKeySpec(key32, "AES"); + IvParameterSpec iv = new IvParameterSpec(iv16); + + cipher.init(Cipher.ENCRYPT_MODE, key, iv); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(5, cipher.getOutputSize(5)); + assertEquals(16, cipher.getOutputSize(16)); + assertEquals(67, cipher.getOutputSize(67)); + + cipher.init(Cipher.DECRYPT_MODE, key, iv); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(5, cipher.getOutputSize(5)); + assertEquals(16, cipher.getOutputSize(16)); + assertEquals(67, cipher.getOutputSize(67)); + } + + @Test + public void getOutputSize_aes256CbcPkcs5Padding() throws Exception { + Cipher cipher = Cipher.getInstance("AES_256/CBC/PKCS5Padding", CONSCRYPT_PROVIDER); + SecretKey key = new SecretKeySpec(key32, "AES"); + IvParameterSpec iv = new IvParameterSpec(iv16); + + cipher.init(Cipher.ENCRYPT_MODE, key, iv); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(16, cipher.getOutputSize(0)); + assertEquals(16, cipher.getOutputSize(5)); + assertEquals(32, cipher.getOutputSize(16)); + assertEquals(80, cipher.getOutputSize(67)); + + cipher.init(Cipher.DECRYPT_MODE, key, iv); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(16, cipher.getOutputSize(5)); + assertEquals(16, cipher.getOutputSize(16)); + assertEquals(80, cipher.getOutputSize(67)); + } + + @Test + public void getOutputSize_desedeCbcNoPadding() throws Exception { + Cipher cipher = Cipher.getInstance("DESEDE/CBC/NoPadding", CONSCRYPT_PROVIDER); + SecretKey key = new SecretKeySpec(key24, "DESEDE"); + IvParameterSpec iv = new IvParameterSpec(iv8); + + cipher.init(Cipher.ENCRYPT_MODE, key, iv); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(5, cipher.getOutputSize(5)); + assertEquals(16, cipher.getOutputSize(16)); + assertEquals(67, cipher.getOutputSize(67)); + + cipher.init(Cipher.DECRYPT_MODE, key, iv); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(5, cipher.getOutputSize(5)); + assertEquals(16, cipher.getOutputSize(16)); + assertEquals(67, cipher.getOutputSize(67)); + } + + @Test + public void getOutputSize_desedeCbcPkcs5Padding() throws Exception { + Cipher cipher = Cipher.getInstance("DESEDE/CBC/PKCS5Padding", CONSCRYPT_PROVIDER); + SecretKey key = new SecretKeySpec(key24, "DESEDE"); + IvParameterSpec iv = new IvParameterSpec(iv8); + + cipher.init(Cipher.ENCRYPT_MODE, key, iv); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(8, cipher.getOutputSize(0)); + assertEquals(8, cipher.getOutputSize(5)); + assertEquals(24, cipher.getOutputSize(16)); + assertEquals(72, cipher.getOutputSize(67)); + + cipher.init(Cipher.DECRYPT_MODE, key, iv); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(8, cipher.getOutputSize(5)); + assertEquals(16, cipher.getOutputSize(16)); + assertEquals(72, cipher.getOutputSize(67)); + } + + @Test + public void getOutputSize_arc4() throws Exception { + Cipher cipher = Cipher.getInstance("ARC4", CONSCRYPT_PROVIDER); + SecretKey key = new SecretKeySpec(key16, "ARC4"); + + cipher.init(Cipher.ENCRYPT_MODE, key); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(5, cipher.getOutputSize(5)); + assertEquals(16, cipher.getOutputSize(16)); + assertEquals(67, cipher.getOutputSize(67)); + + cipher.init(Cipher.DECRYPT_MODE, key); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(5, cipher.getOutputSize(5)); + assertEquals(16, cipher.getOutputSize(16)); + assertEquals(67, cipher.getOutputSize(67)); + } + + @Test + public void getOutputSize_aesGcmNoPadding() throws Exception { + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", CONSCRYPT_PROVIDER); + SecretKey key = new SecretKeySpec(key16, "AES"); + GCMParameterSpec spec = new GCMParameterSpec(128, iv12); + + cipher.init(Cipher.ENCRYPT_MODE, key, spec); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(16, cipher.getOutputSize(0)); + assertEquals(21, cipher.getOutputSize(5)); + assertEquals(32, cipher.getOutputSize(16)); + assertEquals(83, cipher.getOutputSize(67)); + + cipher.init(Cipher.DECRYPT_MODE, key, spec); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(0, cipher.getOutputSize(5)); + assertEquals(0, cipher.getOutputSize(16)); + assertEquals(51, cipher.getOutputSize(67)); + } + + @Test + public void getOutputSize_aes128GcmNoPadding() throws Exception { + Cipher cipher = Cipher.getInstance("AES_128/GCM/NoPadding", CONSCRYPT_PROVIDER); + SecretKey key = new SecretKeySpec(key16, "AES"); + GCMParameterSpec spec = new GCMParameterSpec(128, iv12); + + cipher.init(Cipher.ENCRYPT_MODE, key, spec); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(16, cipher.getOutputSize(0)); + assertEquals(21, cipher.getOutputSize(5)); + assertEquals(32, cipher.getOutputSize(16)); + assertEquals(83, cipher.getOutputSize(67)); + + cipher.init(Cipher.DECRYPT_MODE, key, spec); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(0, cipher.getOutputSize(5)); + assertEquals(0, cipher.getOutputSize(16)); + assertEquals(51, cipher.getOutputSize(67)); + } + + @Test + public void getOutputSize_aes256GcmNoPadding() throws Exception { + Cipher cipher = Cipher.getInstance("AES_256/GCM/NoPadding", CONSCRYPT_PROVIDER); + SecretKey key = new SecretKeySpec(key32, "AES"); + GCMParameterSpec spec = new GCMParameterSpec(128, iv12); + + cipher.init(Cipher.ENCRYPT_MODE, key, spec); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(16, cipher.getOutputSize(0)); + assertEquals(21, cipher.getOutputSize(5)); + assertEquals(32, cipher.getOutputSize(16)); + assertEquals(83, cipher.getOutputSize(67)); + + cipher.init(Cipher.DECRYPT_MODE, key, spec); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(0, cipher.getOutputSize(5)); + assertEquals(0, cipher.getOutputSize(16)); + assertEquals(51, cipher.getOutputSize(67)); + } + + @Test + public void getOutputSize_aesGcmSivNoPadding() throws Exception { + Cipher cipher = Cipher.getInstance("AES/GCM-SIV/NoPadding", CONSCRYPT_PROVIDER); + SecretKey key = new SecretKeySpec(key16, "AES"); + GCMParameterSpec spec = new GCMParameterSpec(128, iv12); + + cipher.init(Cipher.ENCRYPT_MODE, key, spec); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(16, cipher.getOutputSize(0)); + assertEquals(21, cipher.getOutputSize(5)); + assertEquals(32, cipher.getOutputSize(16)); + assertEquals(83, cipher.getOutputSize(67)); + + cipher.init(Cipher.DECRYPT_MODE, key, spec); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(0, cipher.getOutputSize(5)); + assertEquals(0, cipher.getOutputSize(16)); + assertEquals(51, cipher.getOutputSize(67)); + } + + @Test + public void getOutputSize_aes128GcmSivNoPadding() throws Exception { + Cipher cipher = Cipher.getInstance("AES_128/GCM-SIV/NoPadding", CONSCRYPT_PROVIDER); + SecretKey key = new SecretKeySpec(key16, "AES"); + GCMParameterSpec spec = new GCMParameterSpec(128, iv12); + + cipher.init(Cipher.ENCRYPT_MODE, key, spec); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(16, cipher.getOutputSize(0)); + assertEquals(21, cipher.getOutputSize(5)); + assertEquals(32, cipher.getOutputSize(16)); + assertEquals(83, cipher.getOutputSize(67)); + + cipher.init(Cipher.DECRYPT_MODE, key, spec); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(0, cipher.getOutputSize(5)); + assertEquals(0, cipher.getOutputSize(16)); + assertEquals(51, cipher.getOutputSize(67)); + } + + @Test + public void getOutputSize_aes256GcmSivNoPadding() throws Exception { + Cipher cipher = Cipher.getInstance("AES_256/GCM-SIV/NoPadding", CONSCRYPT_PROVIDER); + SecretKey key = new SecretKeySpec(key32, "AES"); + GCMParameterSpec spec = new GCMParameterSpec(128, iv12); + + cipher.init(Cipher.ENCRYPT_MODE, key, spec); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(16, cipher.getOutputSize(0)); + assertEquals(21, cipher.getOutputSize(5)); + assertEquals(32, cipher.getOutputSize(16)); + assertEquals(83, cipher.getOutputSize(67)); + + cipher.init(Cipher.DECRYPT_MODE, key, spec); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(0, cipher.getOutputSize(5)); + assertEquals(0, cipher.getOutputSize(16)); + assertEquals(51, cipher.getOutputSize(67)); + } + + @Test + public void getOutputSize_chaCha20() throws Exception { + Cipher cipher = Cipher.getInstance("ChaCha20", CONSCRYPT_PROVIDER); + SecretKey key = new SecretKeySpec(key32, "ChaCha20"); + IvParameterSpec iv = new IvParameterSpec(iv12); + + cipher.init(Cipher.ENCRYPT_MODE, key, iv); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(5, cipher.getOutputSize(5)); + assertEquals(16, cipher.getOutputSize(16)); + assertEquals(67, cipher.getOutputSize(67)); + + cipher.init(Cipher.DECRYPT_MODE, key, iv); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(5, cipher.getOutputSize(5)); + assertEquals(16, cipher.getOutputSize(16)); + assertEquals(67, cipher.getOutputSize(67)); + } + + @Test + public void getOutputSize_chaCha20Poly1305() throws Exception { + Cipher cipher = Cipher.getInstance("ChaCha20/Poly1305/NoPadding", CONSCRYPT_PROVIDER); + SecretKey key = new SecretKeySpec(key32, "ChaCha20"); + IvParameterSpec iv = new IvParameterSpec(iv12); + + cipher.init(Cipher.ENCRYPT_MODE, key, iv); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(16, cipher.getOutputSize(0)); + assertEquals(21, cipher.getOutputSize(5)); + assertEquals(32, cipher.getOutputSize(16)); + assertEquals(83, cipher.getOutputSize(67)); + + cipher.init(Cipher.DECRYPT_MODE, key, iv); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(0, cipher.getOutputSize(5)); + assertEquals(0, cipher.getOutputSize(16)); + assertEquals(51, cipher.getOutputSize(67)); + } + + @Test + public void getOutputSize_xChaCha20Poly1305() throws Exception { + Cipher cipher = Cipher.getInstance("XChaCha20/Poly1305/NoPadding", CONSCRYPT_PROVIDER); + SecretKey key = new SecretKeySpec(key32, "XChaCha20"); + IvParameterSpec iv = new IvParameterSpec(iv24); + + cipher.init(Cipher.ENCRYPT_MODE, key, iv); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(16, cipher.getOutputSize(0)); + assertEquals(21, cipher.getOutputSize(5)); + assertEquals(32, cipher.getOutputSize(16)); + assertEquals(83, cipher.getOutputSize(67)); + + cipher.init(Cipher.DECRYPT_MODE, key, iv); + assertThrows(IllegalArgumentException.class, () -> cipher.getOutputSize(-67)); + assertEquals(0, cipher.getOutputSize(0)); + assertEquals(0, cipher.getOutputSize(5)); + assertEquals(0, cipher.getOutputSize(16)); + assertEquals(51, cipher.getOutputSize(67)); + } } diff --git a/platform/src/main/java/org/conscrypt/Platform.java b/platform/src/main/java/org/conscrypt/Platform.java index a755cedc3..5d3d03af9 100644 --- a/platform/src/main/java/org/conscrypt/Platform.java +++ b/platform/src/main/java/org/conscrypt/Platform.java @@ -646,6 +646,10 @@ public static boolean isPakeSupported() { return true; } + public static boolean isPqcKemKdfSupported() { + return Flags.pqcKemKdfApi(); + } + /** * Controls whether Post-Quantum Cryptography (X25519MLKEM768) is included in the default * TLS named groups for this application.