Skip to content

[AI] Fix RSA PSS signature verification with self-signed certificates (#191) #220

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1453,11 +1453,11 @@ public Config() {
}

public void setDefaultRsaSsaPssSalt(byte[] salt) {
System.arraycopy(defaultRsaSsaPssSalt, 0, salt, 0, defaultRsaSsaPssSalt.length);
this.defaultRsaSsaPssSalt = salt.clone();
}

public byte[] getDefaultRsaSsaPssSalt() {
return defaultRsaSsaPssSalt;
return defaultRsaSsaPssSalt.clone();
}

public Point getDefaultClientEphemeralEcPublicKey() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import de.rub.nds.tlsattacker.core.workflow.chooser.Chooser;
import de.rub.nds.x509attacker.chooser.X509Chooser;
import java.math.BigInteger;
import java.util.Arrays;
import java.security.SecureRandom;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

Expand Down Expand Up @@ -239,14 +239,16 @@ private void computeRsaPssSignature(
.getChooser()
.getSubjectRsaPrivateKey();
byte[] salt = chooser.getConfig().getDefaultRsaSsaPssSalt();
if (salt.length > algorithm.getBitLength() / 8) {
LOGGER.debug("Default PSS salt is too long, truncating");
salt = Arrays.copyOfRange(salt, 0, algorithm.getBitLength() / 8);
} else if (salt.length < algorithm.getBitLength() / 8) {
LOGGER.debug("Default PSS salt is too short, padding");
byte[] newSalt = new byte[algorithm.getBitLength() / 8];
System.arraycopy(salt, 0, newSalt, 0, salt.length);
salt = newSalt;
int expectedSaltLength = algorithm.getBitLength() / 8;

if (salt.length != expectedSaltLength) {
LOGGER.debug(
"PSS salt length does not match hash length. Generating new random salt of length: "
+ expectedSaltLength);
// Generate a new random salt with the correct length
salt = new byte[expectedSaltLength];
SecureRandom random = new SecureRandom();
random.nextBytes(salt);
}
calculator.computeRsaPssSignature(
computations,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,22 @@
package de.rub.nds.tlsattacker.core.crypto;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;

import de.rub.nds.protocol.crypto.signature.RsaSsaPssSignatureComputations;
import de.rub.nds.protocol.crypto.signature.SignatureCalculator;
import de.rub.nds.protocol.crypto.signature.SignatureComputations;
import de.rub.nds.tlsattacker.core.config.Config;
import de.rub.nds.tlsattacker.core.constants.SignatureAndHashAlgorithm;
import de.rub.nds.tlsattacker.core.state.State;
import de.rub.nds.tlsattacker.core.workflow.chooser.Chooser;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

Expand Down Expand Up @@ -64,4 +69,43 @@ void testComputeSignature(SignatureAndHashAlgorithm algorithm) {
chooser, algorithm, value, computations));
}
}

@Test
void testRsaPssSaltHandling() {
// Test with different salt lengths to ensure proper random salt generation
SignatureAndHashAlgorithm[] pssAlgorithms = {
SignatureAndHashAlgorithm.RSA_PSS_RSAE_SHA256,
SignatureAndHashAlgorithm.RSA_PSS_RSAE_SHA384,
SignatureAndHashAlgorithm.RSA_PSS_RSAE_SHA512
};

for (SignatureAndHashAlgorithm algorithm : pssAlgorithms) {
// Test with incorrect salt length (should generate new random salt)
Config config = chooser.getConfig();
config.setDefaultRsaSsaPssSalt(new byte[10]); // Incorrect length

RsaSsaPssSignatureComputations computations = new RsaSsaPssSignatureComputations();
byte[] testData = new byte[] {0x01, 0x02, 0x03, 0x04};

assertDoesNotThrow(
() ->
tlsSignatureUtil.computeSignature(
chooser, algorithm, testData, computations));

// Verify that salt was generated with correct length
byte[] salt = computations.getSalt().getValue();
int expectedSaltLength = algorithm.getHashAlgorithm().getBitLength() / 8;
assertEquals(
expectedSaltLength,
salt.length,
"Salt length should match hash algorithm output length for " + algorithm);

// Verify that salt is not all zeros (was properly randomized)
byte[] allZeros = new byte[expectedSaltLength];
assertNotEquals(
Arrays.toString(allZeros),
Arrays.toString(salt),
"Salt should be randomized, not all zeros");
}
}
}