Skip to content

bouncycastle failures related to TLS 1.3 Hybrid Key Exchange - DER input not an octet string #2247

@cushon

Description

@cushon

I am seeing a regression that affects bouncycastle when testing with the latest JDK EA builds that include the changes for JEP 527: Post-Quantum Hybrid Key Exchange for TLS 1.3.

In JDK versions that include those changes, the following test fails.

import java.net.HttpURLConnection;
import java.net.URL;
import java.security.Security;
import java.time.Duration;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public final class DownloadTest {

  private static final Duration TIMEOUT = Duration.ofSeconds(1);

  public static void main(String[] args) throws Exception {

    if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
      Security.insertProviderAt(new BouncyCastleProvider(), 1);
    }

    String url = "https://storage.googleapis.com/diagnostic_service_storage/google_wifi_512dp.png";
    HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
    connection.setReadTimeout((int) TIMEOUT.toMillis());
    connection.setConnectTimeout((int) TIMEOUT.toMillis());
    connection.setRequestMethod("GET");
    connection.connect();
  }
}
$ java -Djdk.tls.namedGroups=X25519MLKEM768 -cp bcprov-jdk18on-1.83.jar DownloadTest.java
...
Exception in thread "main" javax.net.ssl.SSLException: (bad_record_mac) mac check in GCM failed
	at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:132)
	at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:375)
	at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:318)
	at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:313)
	at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:123)
	at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1506)
	at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1421)
	at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:455)
	at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:426)
	at java.base/sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:490)
	at java.base/sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:187)
	at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:141)
	at DownloadTest.main(DownloadTest.java:22)
Caused by: javax.crypto.AEADBadTagException: mac check in GCM failed
	at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
	at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:483)
	at org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher$AEADGenericBlockCipher.doFinal(Unknown Source)
	at org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineDoFinal(Unknown Source)
	at java.base/javax.crypto.CipherSpi.bufferCrypt(CipherSpi.java:788)
	at java.base/javax.crypto.CipherSpi.engineDoFinal(CipherSpi.java:723)
	at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2539)
	at java.base/sun.security.ssl.SSLCipher$T13GcmReadCipherGenerator$GcmReadCipher.decrypt(SSLCipher.java:1909)
	at java.base/sun.security.ssl.SSLSocketInputRecord.decodeInputRecord(SSLSocketInputRecord.java:264)
	at java.base/sun.security.ssl.SSLSocketInputRecord.decode(SSLSocketInputRecord.java:181)
	at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:111)
	at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1506)
	at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1421)
	at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:455)
	at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:426)
	at java.base/sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:490)
	at java.base/sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:187)
	at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:141)
	at DownloadTest.main(DownloadTest.java:22)

I was initially investigating this problem on a different machine, where the same repro fails with a different error, the DER input not an octet string crash below:

javax.net.ssl.SSLHandshakeException: Could not generate secret
        at java.base/sun.security.ssl.KAKeyDerivation.t13DeriveKey(KAKeyDerivation.java:228)
        at java.base/sun.security.ssl.KAKeyDerivation.deriveKey(KAKeyDerivation.java:87)
        at java.base/sun.security.ssl.ServerHello$T13ServerHelloConsumer.consume(ServerHello.java:1347)
        at java.base/sun.security.ssl.ServerHello$ServerHelloConsumer.onServerHello(ServerHello.java:1061)
        at java.base/sun.security.ssl.ServerHello$ServerHelloConsumer.consume(ServerHello.java:941)
        at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:421)
        at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:477)
        at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:448)
        at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:198)
        at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:172)
        at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1506)
        at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1421)
        at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:455)
        at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:426)
        at java.base/sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:490)
        at java.base/sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:187)
        at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:141)
        at DownloadTest.download(DownloadTest.java:26)
        ... 21 trimmed
Caused by: java.security.InvalidKeyException: Cannot parse input
        at java.base/sun.security.pkcs.NamedPKCS8Key.<init>(NamedPKCS8Key.java:95)
        at java.base/sun.security.provider.NamedKeyFactory.fromPKCS8(NamedKeyFactory.java:160)
        at java.base/sun.security.provider.NamedKeyFactory.engineTranslateKey(NamedKeyFactory.java:272)
        at java.base/sun.security.provider.NamedKEM.engineNewDecapsulator(NamedKEM.java:96)
        at java.base/javax.crypto.KEM$DelayedKEM.newDecapsulator(KEM.java:508)
        at java.base/javax.crypto.KEM.newDecapsulator(KEM.java:770)
        at java.base/javax.crypto.KEM.newDecapsulator(KEM.java:751)
        at java.base/sun.security.ssl.Hybrid$KEMImpl.engineNewDecapsulator(Hybrid.java:292)
        at java.base/javax.crypto.KEM.newDecapsulator(KEM.java:771)
        at java.base/javax.crypto.KEM.newDecapsulator(KEM.java:751)
        at java.base/sun.security.ssl.KAKeyDerivation.t13DeriveKey(KAKeyDerivation.java:214)
        ... 39 more
Caused by: java.io.IOException: DER input not an octet string
        at java.base/sun.security.util.DerInputStream.getOctetString(DerInputStream.java:155)
        at java.base/sun.security.pkcs.NamedPKCS8Key.<init>(NamedPKCS8Key.java:93)
        ... 49 more

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions