Skip to content

Commit 59c3a66

Browse files
committed
added property for servers that don't enforce ECDSA groups
1 parent 081c816 commit 59c3a66

File tree

6 files changed

+76
-81
lines changed

6 files changed

+76
-81
lines changed

TLS-Server-Scanner/src/main/java/de/rub/nds/tlsscanner/serverscanner/probe/InvalidCurveProbe.java

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,11 @@
4949
import de.rub.nds.tlsscanner.serverscanner.report.result.VersionSuiteListPair;
5050
import de.rub.nds.tlsscanner.serverscanner.vectorStatistics.DistributionTest;
5151
import java.util.HashMap;
52+
import java.util.HashSet;
5253
import java.util.LinkedList;
5354
import java.util.List;
5455
import java.util.Map;
56+
import java.util.Set;
5557

5658
/**
5759
*
@@ -675,7 +677,7 @@ private boolean groupQualifiedForCiphersuite(NamedGroup testGroup, CipherSuite t
675677
}
676678

677679
private List<NamedGroup> getRequiredGroups(NamedGroup testGroup, CipherSuite testCipher) {
678-
List<NamedGroup> requiredGroups = new LinkedList<>();
680+
Set<NamedGroup> requiredGroups = new HashSet<>();
679681
if (testCipher.isTLS13()) {
680682
if (namedCurveWitnessesTls13.get(testGroup).getEcdsaPkGroupEphemeral() != null
681683
&& namedCurveWitnessesTls13.get(testGroup).getEcdsaPkGroupEphemeral() != testGroup) {
@@ -688,27 +690,22 @@ private List<NamedGroup> getRequiredGroups(NamedGroup testGroup, CipherSuite tes
688690
} else {
689691
// RSA ciphersuites don't require any additional groups
690692
if (AlgorithmResolver.getKeyExchangeAlgorithm(testCipher) == KeyExchangeAlgorithm.ECDHE_ECDSA) {
691-
if (namedCurveWitnesses.get(testGroup).getEcdsaPkGroupEphemeral() != null &&
692-
namedCurveWitnesses.get(testGroup).getEcdsaPkGroupEphemeral() != testGroup) {
693+
if (namedCurveWitnesses.get(testGroup).getEcdsaPkGroupEphemeral() != null
694+
&& namedCurveWitnesses.get(testGroup).getEcdsaPkGroupEphemeral() != testGroup) {
693695
requiredGroups.add(namedCurveWitnesses.get(testGroup).getEcdsaPkGroupEphemeral());
694696
}
695697
if (namedCurveWitnesses.get(testGroup).getEcdsaSigGroupEphemeral() != null
696698
&& namedCurveWitnesses.get(testGroup).getEcdsaSigGroupEphemeral() != testGroup) {
697699
requiredGroups.add(namedCurveWitnesses.get(testGroup).getEcdsaSigGroupEphemeral());
698700
}
699701
} else if (AlgorithmResolver.getKeyExchangeAlgorithm(testCipher) == KeyExchangeAlgorithm.ECDH_ECDSA) {
700-
if (namedCurveWitnesses.get(testGroup).getEcdsaPkGroupStatic() != null &&
701-
namedCurveWitnesses.get(testGroup).getEcdsaPkGroupStatic() != testGroup) {
702-
requiredGroups.add(namedCurveWitnesses.get(testGroup).getEcdsaPkGroupStatic());
703-
}
704702
if (namedCurveWitnesses.get(testGroup).getEcdsaSigGroupStatic() != null
705703
&& namedCurveWitnesses.get(testGroup).getEcdsaSigGroupStatic() != testGroup) {
706704
requiredGroups.add(namedCurveWitnesses.get(testGroup).getEcdsaSigGroupStatic());
707705
}
708706
}
709707
}
710-
return requiredGroups;
711-
708+
return new LinkedList<>(requiredGroups);
712709
}
713710

714711
private boolean benignHandshakeSuccessfull(InvalidCurveVector vector) {

TLS-Server-Scanner/src/main/java/de/rub/nds/tlsscanner/serverscanner/probe/NamedCurvesProbe.java

Lines changed: 53 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,6 @@
1818
import de.rub.nds.tlsattacker.core.constants.SignatureAndHashAlgorithm;
1919
import de.rub.nds.tlsattacker.core.protocol.message.ECDHEServerKeyExchangeMessage;
2020
import de.rub.nds.tlsattacker.core.protocol.message.HandshakeMessage;
21-
import de.rub.nds.tlsattacker.core.protocol.message.ServerHelloMessage;
22-
import de.rub.nds.tlsattacker.core.protocol.message.extension.KeyShareExtensionMessage;
23-
import de.rub.nds.tlsattacker.core.protocol.message.extension.keyshare.KeyShareStoreEntry;
2421
import de.rub.nds.tlsattacker.core.state.State;
2522
import de.rub.nds.tlsattacker.core.state.TlsContext;
2623
import de.rub.nds.tlsattacker.core.workflow.ParallelExecutor;
@@ -55,7 +52,6 @@ public class NamedCurvesProbe extends TlsProbe {
5552
private boolean testUsingTls13 = true;
5653

5754
// curves used for ecdsa in key exchange
58-
private List<NamedGroup> ecdsaPkGroupsStatic;
5955
private List<NamedGroup> ecdsaPkGroupsEphemeral;
6056
private List<NamedGroup> ecdsaPkGroupsTls13;
6157

@@ -64,6 +60,8 @@ public class NamedCurvesProbe extends TlsProbe {
6460
private List<NamedGroup> ecdsaCertSigGroupsEphemeral;
6561
private List<NamedGroup> ecdsaCertSigGroupsTls13;
6662

63+
private TestResult ignoresEcdsaGroupDisparity = TestResult.FALSE;
64+
6765
public NamedCurvesProbe(ScannerConfig config, ParallelExecutor parallelExecutor) {
6866
super(parallelExecutor, ProbeType.NAMED_GROUPS, config);
6967
}
@@ -83,7 +81,7 @@ public ProbeResult executeTest() {
8381
groupsRsa = getSupportedNamedGroupsRsa();
8482
}
8583
if (testUsingEcdsaStatic) {
86-
groupsEcdsaStatic = getSupportedNamedGroupsEcdsa(getEcdsaStaticCiphersuites(), ecdsaPkGroupsStatic,
84+
groupsEcdsaStatic = getSupportedNamedGroupsEcdsa(getEcdsaStaticCiphersuites(), null,
8785
ecdsaCertSigGroupsStatic);
8886
}
8987
if (testUsingEcdsaEphemeral) {
@@ -101,7 +99,7 @@ public ProbeResult executeTest() {
10199
groupsEcdsaStatic, groupsEcdsaEphemeral);
102100

103101
return new NamedGroupResult(overallSupported, groupsTls13, supportsExplicitPrime, supportsExplicitChar2,
104-
groupsDependOnCiphersuite);
102+
groupsDependOnCiphersuite, ignoresEcdsaGroupDisparity);
105103
} catch (Exception E) {
106104
LOGGER.error("Could not scan for " + getProbeName(), E);
107105
return getCouldNotExecuteResult();
@@ -140,54 +138,57 @@ private Map<NamedGroup, NamedCurveWitness> getSupportedNamedGroupsEcdsa(List<Cip
140138
Config tlsConfig = getBasicConfig();
141139
tlsConfig.setDefaultClientSupportedCiphersuites(cipherSuites);
142140
List<NamedGroup> toTestList = new ArrayList<>(Arrays.asList(NamedGroup.values()));
141+
142+
TlsContext context;
143+
NamedGroup selectedGroup = null;
144+
NamedGroup certificateGroup = null;
145+
NamedGroup certificateSigGroup = null;
146+
// place signing groups at the bottom of the list, the server should
147+
// choose
148+
// all other first
143149
if (pkGroups != null) {
144-
TlsContext context;
145-
NamedGroup selectedGroup = null;
146-
NamedGroup certificateGroup = null;
147-
NamedGroup certificateSigGroup = null;
148-
// place signing groups at the bottom of the list, the server should
149-
// choose
150-
// all other first
151150
placeRequiredGroupsLast(toTestList, pkGroups);
152-
if (sigGroups != null) {
153-
placeRequiredGroupsLast(toTestList, sigGroups);
154-
}
155-
156-
do {
157-
context = testCurves(toTestList, tlsConfig);
151+
}
152+
if (sigGroups != null) {
153+
placeRequiredGroupsLast(toTestList, sigGroups);
154+
}
158155

159-
if (context != null) {
156+
do {
157+
context = testCurves(toTestList, tlsConfig);
160158

161-
selectedGroup = context.getSelectedGroup();
162-
certificateGroup = context.getEcCertificateCurve();
163-
certificateSigGroup = context.getEcCertificateSignatureCurve();
159+
if (context != null) {
164160

165-
// remove groups that are not required by the server even
166-
// if they are used for the certificate or KEX signature
167-
if (!toTestList.contains(certificateGroup)) {
168-
certificateGroup = null;
169-
}
170-
if (!toTestList.contains(certificateSigGroup)) {
171-
certificateSigGroup = null;
172-
}
161+
selectedGroup = context.getSelectedGroup();
162+
certificateGroup = context.getEcCertificateCurve();
163+
certificateSigGroup = context.getEcCertificateSignatureCurve();
173164

174-
if (!toTestList.contains(selectedGroup)) {
175-
LOGGER.debug("Server chose a Curve we did not offer!");
176-
break;
177-
}
178-
if (cipherSuites.get(0).isEphemeral()) {
179-
namedCurveMap.put(selectedGroup, new NamedCurveWitness(null, certificateGroup, null,
180-
certificateSigGroup, context.getSelectedCipherSuite()));
181-
} else {
182-
namedCurveMap.put(selectedGroup, new NamedCurveWitness(certificateGroup, null,
183-
certificateSigGroup, null, context.getSelectedCipherSuite()));
165+
// remove groups that are not required by the server even
166+
// if they are used for the certificate or KEX signature
167+
if (!toTestList.contains(certificateGroup) && certificateSigGroup != null) {
168+
ignoresEcdsaGroupDisparity = TestResult.TRUE;
169+
certificateGroup = null;
170+
}
171+
if (!toTestList.contains(certificateSigGroup) && certificateSigGroup != null) {
172+
ignoresEcdsaGroupDisparity = TestResult.TRUE;
173+
certificateSigGroup = null;
174+
}
184175

185-
}
176+
if (!toTestList.contains(selectedGroup)) {
177+
LOGGER.debug("Server chose a Curve we did not offer!");
178+
break;
179+
}
180+
if (cipherSuites.get(0).isEphemeral()) {
181+
namedCurveMap.put(selectedGroup, new NamedCurveWitness(certificateGroup, null, certificateSigGroup,
182+
context.getSelectedCipherSuite()));
183+
} else {
184+
namedCurveMap.put(selectedGroup,
185+
new NamedCurveWitness(null, certificateSigGroup, null, context.getSelectedCipherSuite()));
186186

187-
toTestList.remove(selectedGroup);
188187
}
189-
} while (context != null && toTestList.size() > 0);
190-
}
188+
189+
toTestList.remove(selectedGroup);
190+
}
191+
} while (context != null && toTestList.size() > 0);
191192
return namedCurveMap;
192193
}
193194

@@ -276,7 +277,6 @@ public void adjustConfig(SiteReport report) {
276277
if (report.getResult(AnalyzedProperty.SUPPORTS_TLS_1_3) != TestResult.TRUE) {
277278
testUsingTls13 = false;
278279
}
279-
ecdsaPkGroupsStatic = report.getEcdsaPkGroupsStatic();
280280
ecdsaPkGroupsEphemeral = report.getEcdsaPkGroupsEphemeral();
281281
ecdsaPkGroupsTls13 = report.getEcdsaPkGroupsTls13();
282282

@@ -288,7 +288,7 @@ public void adjustConfig(SiteReport report) {
288288
@Override
289289
public ProbeResult getCouldNotExecuteResult() {
290290
return new NamedGroupResult(new HashMap<>(), new HashMap<>(), TestResult.COULD_NOT_TEST,
291-
TestResult.COULD_NOT_TEST, TestResult.COULD_NOT_TEST);
291+
TestResult.COULD_NOT_TEST, TestResult.COULD_NOT_TEST, TestResult.COULD_NOT_TEST);
292292
}
293293

294294
private TestResult getExplicitCurveSupport(EllipticCurveType curveType) {
@@ -377,11 +377,13 @@ private Map<NamedGroup, NamedCurveWitness> getTls13SupportedGroups() {
377377
certificateGroup = context.getEcCertificateCurve();
378378
certificateSigGroup = context.getEcCertificateSignatureCurve();
379379

380-
if (!toTestList.contains(certificateGroup)) {
380+
if (!toTestList.contains(certificateGroup) && certificateGroup != null) {
381+
ignoresEcdsaGroupDisparity = TestResult.TRUE;
381382
certificateGroup = null;
382383
}
383384

384-
if (!toTestList.contains(certificateSigGroup)) {
385+
if (!toTestList.contains(certificateSigGroup) && certificateSigGroup != null) {
386+
ignoresEcdsaGroupDisparity = TestResult.TRUE;
385387
certificateSigGroup = null;
386388
}
387389

@@ -391,8 +393,8 @@ private Map<NamedGroup, NamedCurveWitness> getTls13SupportedGroups() {
391393
break;
392394
}
393395

394-
namedCurveMap.put(selectedGroup, new NamedCurveWitness(null, certificateGroup, null,
395-
certificateSigGroup, context.getSelectedCipherSuite()));
396+
namedCurveMap.put(selectedGroup, new NamedCurveWitness(certificateGroup, null, certificateSigGroup,
397+
context.getSelectedCipherSuite()));
396398
toTestList.remove(selectedGroup);
397399
}
398400
} while (context != null && !toTestList.isEmpty());
@@ -461,7 +463,6 @@ private Map<NamedGroup, NamedCurveWitness> composeFullMap(Map<NamedGroup, NamedC
461463
}
462464
if (groupsEcdsaStatic.containsKey(group)) {
463465
witness.getCipherSuites().addAll(groupsEcdsaStatic.get(group).getCipherSuites());
464-
witness.setEcdsaPkGroupStatic(groupsEcdsaStatic.get(group).getEcdsaPkGroupStatic());
465466
witness.setEcdsaSigGroupStatic(groupsEcdsaStatic.get(group).getEcdsaSigGroupStatic());
466467
}
467468
if (groupsEcdsaEphemeral.containsKey(group)) {

TLS-Server-Scanner/src/main/java/de/rub/nds/tlsscanner/serverscanner/probe/namedcurve/NamedCurveWitness.java

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ public class NamedCurveWitness {
2121
private Set<CipherSuite> cipherSuites;
2222

2323
// the curves used to generate an ecdsa sig inside the key ex. message
24-
private NamedGroup ecdsaPkGroupStatic;
2524
private NamedGroup ecdsaPkGroupEphemeral;
2625

2726
// the curve used to sign the cert that bears the server's signing key
@@ -32,9 +31,8 @@ public NamedCurveWitness() {
3231
cipherSuites = new HashSet<>();
3332
}
3433

35-
public NamedCurveWitness(NamedGroup ecdsaPkGroupStatic, NamedGroup ecdsaPkGroupEphemeral,
36-
NamedGroup ecdsaSigGroupStatic, NamedGroup ecdsaSigGroupEphemeral, CipherSuite cipherSuite) {
37-
this.ecdsaPkGroupStatic = ecdsaPkGroupStatic;
34+
public NamedCurveWitness(NamedGroup ecdsaPkGroupEphemeral, NamedGroup ecdsaSigGroupStatic,
35+
NamedGroup ecdsaSigGroupEphemeral, CipherSuite cipherSuite) {
3836
this.ecdsaPkGroupEphemeral = ecdsaPkGroupEphemeral;
3937
this.ecdsaSigGroupStatic = ecdsaSigGroupStatic;
4038
this.ecdsaSigGroupEphemeral = ecdsaSigGroupEphemeral;
@@ -47,10 +45,6 @@ public NamedCurveWitness(CipherSuite cipherSuite) {
4745
cipherSuites.add(cipherSuite);
4846
}
4947

50-
public NamedGroup getEcdsaPkGroupStatic() {
51-
return ecdsaPkGroupStatic;
52-
}
53-
5448
public NamedGroup getEcdsaPkGroupEphemeral() {
5549
return ecdsaPkGroupEphemeral;
5650
}
@@ -93,10 +87,6 @@ public boolean isFoundUsingEcdsaEphemeralCipher() {
9387
return false;
9488
}
9589

96-
public void setEcdsaPkGroupStatic(NamedGroup ecdsaPkGroupStatic) {
97-
this.ecdsaPkGroupStatic = ecdsaPkGroupStatic;
98-
}
99-
10090
public void setEcdsaPkGroupEphemeral(NamedGroup ecdsaPkGroupEphemeral) {
10191
this.ecdsaPkGroupEphemeral = ecdsaPkGroupEphemeral;
10292
}

TLS-Server-Scanner/src/main/java/de/rub/nds/tlsscanner/serverscanner/report/AnalyzedProperty.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ public enum AnalyzedProperty {
179179
* does it ignore the sig hash algorithms
180180
*/
181181
IGNORES_OFFERED_SIG_HASH_ALGOS(AnalyzedPropertyCategory.QUIRKS),
182+
/**
183+
* does it accept that named groups for ecdsa are missing
184+
*/
185+
IGNORES_ECDSA_GROUP_DISPARITY(AnalyzedPropertyCategory.QUIRKS),
182186
VULNERABLE_TO_SESSION_TICKET_ZERO_KEY(AnalyzedPropertyCategory.ATTACKS),
183187
VULNERABLE_TO_DIRECT_RACCOON(AnalyzedPropertyCategory.ATTACKS),
184188
VULNERABLE_TO_BLEICHENBACHER(AnalyzedPropertyCategory.ATTACKS),

TLS-Server-Scanner/src/main/java/de/rub/nds/tlsscanner/serverscanner/report/SiteReportPrinter.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,26 +1584,25 @@ public StringBuilder appendCurves(StringBuilder builder) {
15841584
builder.append("\n ECDSA Required Groups:");
15851585
if (witness.getEcdsaPkGroupEphemeral() != null && witness.getEcdsaPkGroupEphemeral() != group) {
15861586
builder.append("\n ").append(witness.getEcdsaPkGroupEphemeral())
1587-
.append(" (Ephemeral Certificate Public Key)");
1587+
.append(" (Certificate Public Key - Ephemeral Cipher Suite)");
15881588
}
15891589
if (witness.getEcdsaSigGroupEphemeral() != null && witness.getEcdsaSigGroupEphemeral() != group) {
15901590
builder.append("\n ").append(witness.getEcdsaSigGroupEphemeral())
1591-
.append(" (Ephemeral Certificate Signature)");
1592-
}
1593-
if (witness.getEcdsaPkGroupStatic() != null && witness.getEcdsaPkGroupStatic() != group) {
1594-
builder.append("\n ").append(witness.getEcdsaPkGroupStatic())
1595-
.append(" (Static Certificate Public Key)");
1591+
.append(" (Certificate Signature - Ephemeral Cipher Suite)");
15961592
}
15971593
if (witness.getEcdsaSigGroupStatic() != null && witness.getEcdsaSigGroupStatic() != group) {
15981594
builder.append("\n ").append(witness.getEcdsaSigGroupStatic())
1599-
.append(" (Static Certificate Signature)");
1595+
.append(" (Certificate Signature - Static Cipher Suite)");
16001596
}
16011597
}
16021598
builder.append("\n");
16031599
}
16041600
if (report.getResult(AnalyzedProperty.GROUPS_DEPEND_ON_CIPHER) == TestResult.TRUE) {
16051601
prettyAppend(builder, "Not all Groups are supported for all Cipher Suites");
16061602
}
1603+
if (report.getResult(AnalyzedProperty.IGNORES_ECDSA_GROUP_DISPARITY) == TestResult.TRUE) {
1604+
prettyAppend(builder, "Groups required for ECDSA validation are not enforced", AnsiColor.YELLOW);
1605+
}
16071606
} else {
16081607
builder.append("none\n");
16091608
}

TLS-Server-Scanner/src/main/java/de/rub/nds/tlsscanner/serverscanner/report/result/NamedGroupResult.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,19 @@ public class NamedGroupResult extends ProbeResult {
3030
private final TestResult supportsExplicitPrime;
3131
private final TestResult supportsExplicitChar2;
3232
private final TestResult groupsDependOnCiphersuite;
33+
private final TestResult ignoresEcdsaGroupDisparity;
3334

3435
public NamedGroupResult(Map<NamedGroup, NamedCurveWitness> namedGroupsMap,
3536
Map<NamedGroup, NamedCurveWitness> namedGroupsMapTls13, TestResult supportsExplicitPrime,
36-
TestResult supportsExplicitChar2, TestResult groupsDependOnCiphersuite) {
37+
TestResult supportsExplicitChar2, TestResult groupsDependOnCiphersuite,
38+
TestResult ignoresEcdsaGroupDisparity) {
3739
super(ProbeType.NAMED_GROUPS);
3840
this.namedGroupsMap = namedGroupsMap;
3941
this.namedGroupsMapTls13 = namedGroupsMapTls13;
4042
this.supportsExplicitPrime = supportsExplicitPrime;
4143
this.supportsExplicitChar2 = supportsExplicitChar2;
4244
this.groupsDependOnCiphersuite = groupsDependOnCiphersuite;
45+
this.ignoresEcdsaGroupDisparity = ignoresEcdsaGroupDisparity;
4346
}
4447

4548
@Override
@@ -61,6 +64,7 @@ public void mergeData(SiteReport report) {
6164
report.putResult(AnalyzedProperty.SUPPORTS_EXPLICIT_PRIME_CURVE, supportsExplicitPrime);
6265
report.putResult(AnalyzedProperty.SUPPORTS_EXPLICIT_CHAR2_CURVE, supportsExplicitChar2);
6366
report.putResult(AnalyzedProperty.GROUPS_DEPEND_ON_CIPHER, groupsDependOnCiphersuite);
67+
report.putResult(AnalyzedProperty.IGNORES_ECDSA_GROUP_DISPARITY, ignoresEcdsaGroupDisparity);
6468
}
6569

6670
}

0 commit comments

Comments
 (0)