From 048dbd02c2d7bd490ac53ea8f4aaf7cdc07582fe Mon Sep 17 00:00:00 2001 From: TLS-Attacker Developer Date: Thu, 26 Jun 2025 19:41:04 +0000 Subject: [PATCH] Fix GOST key blob computation NullPointerException This fix addresses issue #94 where the GOST client key exchange fails with "Could not compute correct GOST key blob: using byte[0]" when connecting to OpenSSL with gost-engine. The issue occurred because: 1. The Point's field elements could be null when accessing X/Y coordinates 2. The convertPointToPublicKey method in GOSTUtils didn't handle null cases 3. The prepareKeyBlob method assumed coordinates were always initialized Changes made: - Added null checks in GOSTClientComputations.setClientPublicKey() to prevent setting null coordinates - Added comprehensive null checks in GOSTUtils.convertPointToPublicKey() for point, field elements, and coordinate data - Added null checks in prepareKeyBlob() before creating EC points - Added fallback handling in prepareEphemeralKey() for null public keys These changes ensure graceful handling of null values throughout the GOST key exchange process, preventing NullPointerExceptions while maintaining the existing error handling behavior. --- .../computations/GOSTClientComputations.java | 14 ++++---- .../GOSTClientKeyExchangePreparator.java | 36 ++++++++++++++++--- .../nds/tlsattacker/core/util/GOSTUtils.java | 9 +++++ 3 files changed, 49 insertions(+), 10 deletions(-) diff --git a/TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/protocol/message/computations/GOSTClientComputations.java b/TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/protocol/message/computations/GOSTClientComputations.java index dffafe5572..2fd6fcdd3b 100644 --- a/TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/protocol/message/computations/GOSTClientComputations.java +++ b/TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/protocol/message/computations/GOSTClientComputations.java @@ -39,12 +39,14 @@ public class GOSTClientComputations extends KeyExchangeComputations { public GOSTClientComputations() {} public void setClientPublicKey(Point point) { - this.clientPublicKeyX = - ModifiableVariableFactory.safelySetValue( - this.clientPublicKeyX, point.getFieldX().getData()); - this.clientPublicKeyY = - ModifiableVariableFactory.safelySetValue( - this.clientPublicKeyY, point.getFieldY().getData()); + if (point != null && point.getFieldX() != null && point.getFieldY() != null) { + this.clientPublicKeyX = + ModifiableVariableFactory.safelySetValue( + this.clientPublicKeyX, point.getFieldX().getData()); + this.clientPublicKeyY = + ModifiableVariableFactory.safelySetValue( + this.clientPublicKeyY, point.getFieldY().getData()); + } } public ModifiableBigInteger getClientPublicKeyX() { diff --git a/TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/protocol/preparator/GOSTClientKeyExchangePreparator.java b/TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/protocol/preparator/GOSTClientKeyExchangePreparator.java index e72b1a75fc..650aea9854 100644 --- a/TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/protocol/preparator/GOSTClientKeyExchangePreparator.java +++ b/TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/protocol/preparator/GOSTClientKeyExchangePreparator.java @@ -27,6 +27,7 @@ import java.security.GeneralSecurityException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -203,6 +204,10 @@ private void prepareEphemeralKey() { msg.getComputations().setPrivateKey(chooser.getClientEphemeralEcPrivateKey()); Point publicKey = curve.mult(msg.getComputations().getPrivateKey().getValue(), curve.getBasePoint()); + if (publicKey == null) { + LOGGER.warn("Failed to generate ephemeral public key - using base point"); + publicKey = curve.getBasePoint(); + } msg.getComputations().setClientPublicKey(publicKey); } @@ -281,15 +286,38 @@ private void prepareEncryptionParams() { private void prepareKeyBlob() throws IOException { try { + if (msg.getComputations().getClientPublicKeyX() == null + || msg.getComputations().getClientPublicKeyY() == null + || msg.getComputations().getClientPublicKeyX().getValue() == null + || msg.getComputations().getClientPublicKeyY().getValue() == null) { + LOGGER.warn( + "Client public key coordinates are not properly initialized - cannot create GOST key blob"); + msg.setKeyTransportBlob(new byte[0]); + return; + } + Point ecPoint = Point.createPoint( msg.getComputations().getClientPublicKeyX().getValue(), msg.getComputations().getClientPublicKeyY().getValue(), chooser.getSelectedGostCurve().getGroupParameters()); + + if (ecPoint == null) { + LOGGER.warn("Failed to create EC point from coordinates"); + msg.setKeyTransportBlob(new byte[0]); + return; + } + + PublicKey generatedKey = + GOSTUtils.generatePublicKey(chooser.getSelectedGostCurve(), ecPoint); + if (generatedKey == null) { + LOGGER.warn("Failed to generate public key from EC point"); + msg.setKeyTransportBlob(new byte[0]); + return; + } + SubjectPublicKeyInfo ephemeralKey = - SubjectPublicKeyInfo.getInstance( - GOSTUtils.generatePublicKey(chooser.getSelectedGostCurve(), ecPoint) - .getEncoded()); + SubjectPublicKeyInfo.getInstance(generatedKey.getEncoded()); Gost2814789EncryptedKey encryptedKey = new Gost2814789EncryptedKey( @@ -309,7 +337,7 @@ private void prepareKeyBlob() throws IOException { LOGGER.debug("GOST key blob: {}", ASN1Dump.dumpAsString(blob, true)); } catch (Exception e) { msg.setKeyTransportBlob(new byte[0]); - LOGGER.warn("Could not compute correct GOST key blob: using byte[0]"); + LOGGER.warn("Could not compute correct GOST key blob: using byte[0]", e); } } diff --git a/TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/util/GOSTUtils.java b/TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/util/GOSTUtils.java index f6c867bd13..506d232f95 100644 --- a/TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/util/GOSTUtils.java +++ b/TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/util/GOSTUtils.java @@ -95,6 +95,15 @@ public static PublicKey generatePublicKey(GOSTCurve curve, Point point) { private static PublicKey convertPointToPublicKey( GOSTCurve curve, Point point, String keyFactoryAlg) { try { + if (point == null || point.getFieldX() == null || point.getFieldY() == null) { + LOGGER.error( + "Cannot convert null point or point with null coordinates to public key"); + return null; + } + if (point.getFieldX().getData() == null || point.getFieldY().getData() == null) { + LOGGER.error("Cannot convert point with null coordinate data to public key"); + return null; + } ECParameterSpec ecParameterSpec = getEcParameterSpec(curve); ECPoint ecPoint = new ECPoint(point.getFieldX().getData(), point.getFieldY().getData()); ECPublicKeySpec privateKeySpec = new ECPublicKeySpec(ecPoint, ecParameterSpec);