Uploaded image for project: 'WSS4J'
  1. WSS4J
  2. WSS-583

crypto.verifyTrust can fail when the DN of the issuer is more than once in the truststore

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Minor
    • Resolution: Fixed
    • 2.1.6
    • 2.2.0, 2.1.7
    • WSS4J Core
    • None

    Description

      crypto.verifyTrust can fail when the DN of the issuer is more than once in the truststore

      lets assume the following situation of 2 totally separated PKI,

      • PKI 1
        ROOT CA A <- INTERMEDIATE CA A <- END CERT A
      • PKI 2
        ROOT CA B <- INTERMEDIATE CA B <- END CERT B
      • Subject Distinguished Name of INTERMEDIATE CA A happens to be equal to Subject Distinguished Name of INTERMEDIATE CA B
      • truststore contains CA's of the 2 PKI: it contains ROOT CA A, ROOT CA B, INTERMEDIATE CA A & INTERMEDIATE CA B

      -> the CertPath object constructed in verifyTrust method in the org.apache.wss4j.common.crypto.Merlin class can contain the intermediate of PKI2 even
      if the end certificate is cryptograhically signed by intermediate of PKI 1, hence the PKIX CertPathValidator fails

      this is because there is only a string comparison when determining the issuer of a certificate before putting it to the CertPath object, i think there should be a signature verification too before putting the issuer on the CertPath object

      reproducer (java 8 / wss4j-ws-security-common-2.1.6 )

      Validate.java
      import java.security.cert.X509Certificate;
      import java.security.cert.CertificateFactory;
      import java.io.ByteArrayInputStream;
      import java.util.Properties;
      import org.apache.wss4j.common.crypto.Crypto;
      import org.apache.wss4j.common.crypto.CryptoFactory;
      import java.util.Base64;
      
      public class Validate {
      
      
      public static void main(String[] args) {
        try {
           //end cert A
           byte [] decoded = Base64.getDecoder().decode("MIIC+DCCAeCgAwIBAgIBBDANBgkqhkiG9w0BAQUFADAaMRgwFgYDVQQDEw9JTlRFUk1FRElBVEUgQ0EwHhcNMTYwNzE2MTYwMjAwWhcNMjYwNzE2MTUwNDAwWjBGMUQwQgYDVQQDEztFTkQgQ0VSVCBTSUdORUQgQlkgSU5URVJNRURJQVRFIFRIQVQgSVMgU0lHTkVEIEJZIFJPT1QgQ0EgQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANokxXPsi4KargS5z/IqtYTvNqpcWwEUjwAMuCwgymQsZDqBU8N9oUS4aLqZErZ9T8vUrNFuHEdqKDo9iH5gY3JOirlhFD05wxBxsHF9lUcCI/hXT3VBfEIW6xGnkhCJxV/ye5Yq7uM1UWFhVAxWgNlZnOsP/uMU1EUmhwqFEYum/JfWbLQZCb3G7Oraxatq2NNIk+Huvca9cEgqNXYdiBaaPyU390iML1PN9rKTGlLaWoCLj9VyuaIsOrsD+MF6MJx16p6O4G7P7lx8fZkxbk0y5keF0WNEyBnZ9+YiVOY8EPLQVB/GySBLK0n9Z4RV2RNIL+rAuw61gn05+gpXrLsCAwEAAaMdMBswDAYDVR0TAQH/BAIwADALBgNVHQ8EBAMCBaAwDQYJKoZIhvcNAQEFBQADggEBAFJyt2LMeO7QEjZI82N5VcMTVSlKDee0E2pzHeMPOip80wD+/Xx+PKkTyRiuSHwwK6yz/URf6P1ucHbUMIwcXTKiCY5/2imJlzC8CXoLNnwfduBP3MzyBz1L6ecV6fXJkwWzBjhaPZmZ2cISmkiNIK0vobT6PZ/ikmtCk2zyU6XFNTHssSGmZrBS6Muk+O0iT+v1DU6A7T2122cIEu5GEaR3cidcRi0c4Y4yZ8+vP8JqrQZmHe35FyHKvu/+z9/GYCQsbOT5x5ybhB3jtE60qIzYDNaOfmoxKW3b4JUpGpE5fzAz+9jwbtixjZGh2KPU/KsXBv0bIeM8qo7/aV23XbM=");
           //end cert B
           //byte [] decoded = Base64.getDecoder().decode("MIIC+DCCAeCgAwIBAgIBAzANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDEw9JTlRFUk1FRElBVEUgQ0EwHhcNMTYwNzE2MTUyMDAwWhcNMjYwNzE2MTUwNzAwWjBGMUQwQgYDVQQDEztFTkQgQ0VSVCBTSUdORUQgQlkgSU5URVJNRURJQVRFIFRIQVQgSVMgU0lHTkVEIEJZIFJPT1QgQ0EgQjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN4Z8W4mmFoKWpCK4u427dE/mogExnerWufa1gvUfeQqUiZfln8VzUZmJMFsQy3y2Ze6T3Hj2ao1AuKUT2ouZS5MLSeKrN+UOEoqkYeb/vSNZQETJGEPhqvuEeHPbrpUqK90ioqhVRq+YDeesYO5f9LGcjSOin16aMx7voeJh+DQ1/3EpcydQs13aaC9mwpFJfqRKQzMnVAYkowO9gT8EoM57FVz8LWimXjnHZuZaRIriUA8jxSsA2AUa2M/4Nuza1idbrAwhWZO7J4IVkp0PzSucx71ebiSwE8kDPOy86SEURDnSEtOcvpiOVbGCaAc+4vNH/OVjcSluDBUDIwBmScCAwEAAaMdMBswDAYDVR0TAQH/BAIwADALBgNVHQ8EBAMCBaAwDQYJKoZIhvcNAQELBQADggEBAEyjZ55G4YbZR6P7QhbsQN4OrNLEJZYC822FmXVQjM540izo5sLtx2D8sR6JweGDnEtOFKgWrdwkILRrNWaZ+qws4mHYOhCcOgy/XQ1OLOHgetNu6TWvbLr6sjBGEkGABGJ6NPhpv+Z9N8qtHL9u/9e/HVkVK3e4sMtejic1t9LVlJ8mkHGBJ5qu/3jIzcuHncyXX9G/Pqsw/jkIWXSRgZQEyORpxE7J4VvFwr+D5A72bozLxgpIqSOE+xsUFXvTL89p4jlCrGeqQj/TLAKapltLcwNWljVGp4Qlk1aOM5FDIQV+eUd9y/zWcHusx1NqxI6qx9V6NjQRpvTDezZyyVg=");
           X509Certificate[] certs = new X509Certificate[1];
           certs[0]= (X509Certificate)CertificateFactory.getInstance("X.509").generateCertificate(new ByteArrayInputStream(decoded));
           Properties p = new Properties();
           p.setProperty("org.apache.ws.security.crypto.merlin.truststore.file", "truststore.jks");
           p.setProperty("org.apache.ws.security.crypto.merlin.truststore.type", "jks");
           p.setProperty("org.apache.ws.security.crypto.merlin.truststore.password", "wss4j");
           Crypto crypto = CryptoFactory.getInstance(p);
           crypto.verifyTrust(certs, false,null);
          } 
          catch (Exception e) {
             e.printStackTrace();
          }
      
      }
      }
      

      output of java -Dorg.slf4j.simpleLogger.defaultLogLevel=trace -Djava.security.debug=certpath Validate

      [main] DEBUG org.apache.wss4j.common.crypto.Merlin - The TrustStore truststore.jks of type jks has been loaded
      [main] DEBUG org.apache.wss4j.common.crypto.Merlin - Searching keystore for cert with issuer CN=INTERMEDIATE CA and serial 4
      [main] DEBUG org.apache.wss4j.common.crypto.Merlin - Keystore alias root ca b has issuer CN=ROOT CA B and serial 1
      [main] DEBUG org.apache.wss4j.common.crypto.Merlin - Keystore alias root ca a has issuer CN=ROOT CA A and serial 1
      [main] DEBUG org.apache.wss4j.common.crypto.Merlin - Keystore alias intermediate ca signed by root ca b has issuer CN=ROOT CA B and serial 2
      [main] DEBUG org.apache.wss4j.common.crypto.Merlin - Keystore alias intermediate ca signed by root ca a has issuer CN=ROOT CA A and serial 2
      [main] DEBUG org.apache.wss4j.common.crypto.Merlin - No issuer serial match found in keystore
      [main] DEBUG org.apache.wss4j.common.crypto.Merlin - Searching keystore for cert with Subject CN=INTERMEDIATE CA
      [main] DEBUG org.apache.wss4j.common.crypto.Merlin - Subject certificate match found using keystore alias intermediate ca signed by root ca b
      [main] DEBUG org.apache.wss4j.common.crypto.Merlin - Preparing to validate certificate path for issuer CN=INTERMEDIATE CA
      certpath: PKIXCertPathValidator.engineValidate()...
      certpath: X509CertSelector.match(SN: 2
        Issuer: CN=ROOT CA A
        Subject: CN=INTERMEDIATE CA)
      certpath: X509CertSelector.match: subject DNs don't match
      certpath: NO - don't try this trustedCert
      certpath: X509CertSelector.match(SN: 1
        Issuer: CN=ROOT CA B
        Subject: CN=ROOT CA B)
      certpath: X509CertSelector.match returning: true
      certpath: YES - try this trustedCert
      certpath: anchor.getTrustedCert().getSubjectX500Principal() = CN=ROOT CA B
      certpath: --------------------------------------------------------------
      certpath: Executing PKIX certification path validation algorithm.
      certpath: Checking cert1 - Subject: CN=INTERMEDIATE CA
      certpath: Set of critical extensions: {2.5.29.19}
      certpath: -Using checker1 ... [sun.security.provider.certpath.UntrustedChecker]
      certpath: -checker1 validation succeeded
      certpath: -Using checker2 ... [sun.security.provider.certpath.AlgorithmChecker]
      certpath: -checker2 validation succeeded
      certpath: -Using checker3 ... [sun.security.provider.certpath.KeyChecker]
      certpath: KeyChecker.verifyCAKeyUsage() ---checking CA key usage...
      certpath: KeyChecker.verifyCAKeyUsage() CA key usage verified.
      certpath: -checker3 validation succeeded
      certpath: -Using checker4 ... [sun.security.provider.certpath.ConstraintsChecker]
      certpath: ---checking basic constraints...
      certpath: i = 1, maxPathLength = 2
      certpath: after processing, maxPathLength = 1
      certpath: basic constraints verified.
      certpath: ---checking name constraints...
      certpath: prevNC = null, newNC = null
      certpath: mergedNC = null
      certpath: name constraints verified.
      certpath: -checker4 validation succeeded
      certpath: -Using checker5 ... [sun.security.provider.certpath.PolicyChecker]
      certpath: PolicyChecker.checkPolicy() ---checking certificate policies...
      certpath: PolicyChecker.checkPolicy() certIndex = 1
      certpath: PolicyChecker.checkPolicy() BEFORE PROCESSING: explicitPolicy = 3
      certpath: PolicyChecker.checkPolicy() BEFORE PROCESSING: policyMapping = 3
      certpath: PolicyChecker.checkPolicy() BEFORE PROCESSING: inhibitAnyPolicy = 3
      certpath: PolicyChecker.checkPolicy() BEFORE PROCESSING: policyTree = anyPolicy  ROOT
      
      certpath: PolicyChecker.processPolicies() no policies present in cert
      certpath: PolicyChecker.checkPolicy() AFTER PROCESSING: explicitPolicy = 2
      certpath: PolicyChecker.checkPolicy() AFTER PROCESSING: policyMapping = 2
      certpath: PolicyChecker.checkPolicy() AFTER PROCESSING: inhibitAnyPolicy = 2
      certpath: PolicyChecker.checkPolicy() AFTER PROCESSING: policyTree = null
      certpath: PolicyChecker.checkPolicy() certificate policies verified
      certpath: -checker5 validation succeeded
      certpath: -Using checker6 ... [sun.security.provider.certpath.BasicChecker]
      certpath: ---checking timestamp:Sat Jul 16 19:02:50 CEST 2016...
      certpath: timestamp verified.
      certpath: ---checking subject/issuer name chaining...
      certpath: subject/issuer name chaining verified.
      certpath: ---checking signature...
      certpath: signature verified.
      certpath: BasicChecker.updateState issuer: CN=ROOT CA B; subject: CN=INTERMEDIATE CA; serial#: 2
      certpath: -checker6 validation succeeded
      certpath: 
      cert1 validation succeeded.
      
      certpath: Checking cert2 - Subject: CN=END CERT SIGNED BY INTERMEDIATE THAT IS SIGNED BY ROOT CA A
      certpath: Set of critical extensions: {2.5.29.19}
      certpath: -Using checker1 ... [sun.security.provider.certpath.UntrustedChecker]
      certpath: -checker1 validation succeeded
      certpath: -Using checker2 ... [sun.security.provider.certpath.AlgorithmChecker]
      certpath: -checker2 validation succeeded
      certpath: -Using checker3 ... [sun.security.provider.certpath.KeyChecker]
      certpath: -checker3 validation succeeded
      certpath: -Using checker4 ... [sun.security.provider.certpath.ConstraintsChecker]
      certpath: ---checking basic constraints...
      certpath: i = 2, maxPathLength = 1
      certpath: after processing, maxPathLength = 1
      certpath: basic constraints verified.
      certpath: ---checking name constraints...
      certpath: prevNC = null, newNC = null
      certpath: mergedNC = null
      certpath: name constraints verified.
      certpath: -checker4 validation succeeded
      certpath: -Using checker5 ... [sun.security.provider.certpath.PolicyChecker]
      certpath: PolicyChecker.checkPolicy() ---checking certificate policies...
      certpath: PolicyChecker.checkPolicy() certIndex = 2
      certpath: PolicyChecker.checkPolicy() BEFORE PROCESSING: explicitPolicy = 2
      certpath: PolicyChecker.checkPolicy() BEFORE PROCESSING: policyMapping = 2
      certpath: PolicyChecker.checkPolicy() BEFORE PROCESSING: inhibitAnyPolicy = 2
      certpath: PolicyChecker.checkPolicy() BEFORE PROCESSING: policyTree = null
      certpath: PolicyChecker.processPolicies() no policies present in cert
      certpath: PolicyChecker.checkPolicy() AFTER PROCESSING: explicitPolicy = 2
      certpath: PolicyChecker.checkPolicy() AFTER PROCESSING: policyMapping = 2
      certpath: PolicyChecker.checkPolicy() AFTER PROCESSING: inhibitAnyPolicy = 2
      certpath: PolicyChecker.checkPolicy() AFTER PROCESSING: policyTree = null
      certpath: PolicyChecker.checkPolicy() certificate policies verified
      certpath: -checker5 validation succeeded
      certpath: -Using checker6 ... [sun.security.provider.certpath.BasicChecker]
      certpath: ---checking timestamp:Sat Jul 16 19:02:50 CEST 2016...
      certpath: timestamp verified.
      certpath: ---checking subject/issuer name chaining...
      certpath: subject/issuer name chaining verified.
      certpath: ---checking signature...
      certpath: X509CertSelector.match(SN: 1
        Issuer: CN=ROOT CA A
        Subject: CN=ROOT CA A)
      certpath: X509CertSelector.match: subject DNs don't match
      certpath: NO - don't try this trustedCert
      certpath: X509CertSelector.match(SN: 2
        Issuer: CN=ROOT CA B
        Subject: CN=INTERMEDIATE CA)
      certpath: X509CertSelector.match: subject DNs don't match
      certpath: NO - don't try this trustedCert
      org.apache.wss4j.common.ext.WSSecurityException: Error during certificate path validation: signature check failed
      Original Exception was java.security.cert.CertPathValidatorException: signature check failed
      	at org.apache.wss4j.common.crypto.Merlin.verifyTrust(Merlin.java:895)
      	at Validate.main(Validate.java:25)
      Caused by: java.security.cert.CertPathValidatorException: signature check failed
      	at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:135)
      	at sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:212)
      	at sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:140)
      	at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:79)
      	at java.security.cert.CertPathValidator.validate(CertPathValidator.java:292)
      	at org.apache.wss4j.common.crypto.Merlin.verifyTrust(Merlin.java:890)
      	... 1 more
      Caused by: java.security.SignatureException: Signature does not match.
      	at sun.security.x509.X509CertImpl.verify(X509CertImpl.java:449)
      	at sun.security.provider.certpath.BasicChecker.verifySignature(BasicChecker.java:166)
      	at sun.security.provider.certpath.BasicChecker.check(BasicChecker.java:147)
      	at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:125)
      	... 6 more
      

      Attachments

        1. truststore.jks
          3 kB
          Jo Van Hoof
        2. certificates.zip
          6 kB
          Jo Van Hoof

        Activity

          People

            coheigea Colm O hEigeartaigh
            jok- Jo Van Hoof
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: