# HG changeset patch # User yan # Date 1599839931 -10800 # Node ID 2cde484ef2487666fb2e97d1c48ad9c65a634e8c # Parent 06c643a674d202f5a3ef16aedf225014f169079b 8237995: Enhance certificate processing Reviewed-by: bae, dcherepanov diff -r 06c643a674d2 -r 2cde484ef248 src/share/classes/sun/security/util/UntrustedCertificates.java --- a/src/share/classes/sun/security/util/UntrustedCertificates.java Wed May 20 08:07:25 2020 -0400 +++ b/src/share/classes/sun/security/util/UntrustedCertificates.java Fri Sep 11 18:58:51 2020 +0300 @@ -31,7 +31,7 @@ import java.security.PrivilegedAction; import java.security.cert.X509Certificate; import java.security.cert.CertificateException; -import java.util.*; +import java.util.Properties; import sun.security.x509.X509CertImpl; /** @@ -58,10 +58,6 @@ "lib/security/blacklisted.certs"); try (FileInputStream fin = new FileInputStream(f)) { props.load(fin); - // It's said that the fingerprint could contain colons - for (Map.Entry e: props.entrySet()) { - e.setValue(stripColons(e.getValue())); - } } catch (IOException fnfe) { if (debug != null) { debug.println("Error parsing blacklisted.certs"); @@ -73,21 +69,6 @@ algorithm = props.getProperty(ALGORITHM_KEY); } - private static String stripColons(Object input) { - String s = (String)input; - char[] letters = s.toCharArray(); - int pos = 0; - for (int i = 0; i < letters.length; i++) { - if (letters[i] != ':') { - if (i != pos) { - letters[pos] = letters[i]; - } - pos++; - } - } - if (pos == letters.length) return s; - else return new String(letters, 0, pos); - } /** * Checks if a certificate is untrusted. * diff -r 06c643a674d2 -r 2cde484ef248 src/share/lib/security/BlacklistedCertsConverter.java --- a/src/share/lib/security/BlacklistedCertsConverter.java Wed May 20 08:07:25 2020 -0400 +++ b/src/share/lib/security/BlacklistedCertsConverter.java Fri Sep 11 18:58:51 2020 +0300 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,13 +21,26 @@ * questions. */ +import java.io.IOException; +import java.math.BigInteger; import java.security.MessageDigest; +import java.security.PublicKey; import java.security.NoSuchAlgorithmException; import java.security.cert.Certificate; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; +import java.security.interfaces.ECPublicKey; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +import sun.security.util.DerInputStream; +import sun.security.util.DerOutputStream; +import sun.security.util.DerValue; /** * This is the tool to convert blacklisted.certs.pem to blacklisted.certs. @@ -48,9 +61,14 @@ Collection certs = cf.generateCertificates(System.in); System.out.println("Algorithm=" + mdAlg); + Set fingerprints = new TreeSet<>(); for (Certificate cert: certs) { - System.out.println( - getCertificateFingerPrint(mdAlg, (X509Certificate)cert)); + fingerprints.addAll( + getCertificateFingerPrints(mdAlg, (X509Certificate)cert)); + } + + for (String s: fingerprints) { + System.out.println(s); } } @@ -67,23 +85,90 @@ } /** - * Gets the requested finger print of the certificate. + * Gets the requested fingerprints of the certificate. */ - private static String getCertificateFingerPrint(String mdAlg, - X509Certificate cert) { - String fingerPrint = ""; - try { - byte[] encCertInfo = cert.getEncoded(); + private static List getCertificateFingerPrints( + String mdAlg, X509Certificate cert) throws Exception { + List fingerprints = new ArrayList<>(); + for (byte[] encoding : altEncodings(cert)) { MessageDigest md = MessageDigest.getInstance(mdAlg); - byte[] digest = md.digest(encCertInfo); + byte[] digest = md.digest(encoding); StringBuffer buf = new StringBuffer(); for (int i = 0; i < digest.length; i++) { byte2hex(digest[i], buf); } - fingerPrint = buf.toString(); - } catch (NoSuchAlgorithmException | CertificateEncodingException e) { - // ignored + fingerprints.add(buf.toString()); + } + return fingerprints; + } + + private static List altEncodings(X509Certificate c) + throws Exception { + List result = new ArrayList<>(); + + DerValue d = new DerValue(c.getEncoded()); + DerValue[] seq = new DerValue[3]; + // tbsCertificate + seq[0] = d.data.getDerValue(); + // signatureAlgorithm + seq[1] = d.data.getDerValue(); + // signature + seq[2] = d.data.getDerValue(); + + List algIds = Arrays.asList(seq[1], altAlgId(seq[1])); + + List sigs; + PublicKey p = c.getPublicKey(); + if (p instanceof ECPublicKey) { + ECPublicKey ep = (ECPublicKey) p; + BigInteger mod = ep.getParams().getOrder(); + sigs = Arrays.asList(seq[2], altSig(mod, seq[2])); + } else { + sigs = Arrays.asList(seq[2]); } - return fingerPrint; + + for (DerValue algId : algIds) { + for (DerValue sig : sigs) { + DerOutputStream tmp = new DerOutputStream(); + tmp.putDerValue(seq[0]); + tmp.putDerValue(algId); + tmp.putDerValue(sig); + DerOutputStream tmp2 = new DerOutputStream(); + tmp2.write(DerValue.tag_Sequence, tmp); + result.add(tmp2.toByteArray()); + } + } + return result; + } + + private static DerValue altSig(BigInteger mod, DerValue sig) + throws IOException { + byte[] sigBits = sig.getBitString(); + DerInputStream in = + new DerInputStream(sigBits, 0, sigBits.length, false); + DerValue[] values = in.getSequence(2); + BigInteger r = values[0].getBigInteger(); + BigInteger s = values[1].getBigInteger(); + BigInteger s2 = s.negate().mod(mod); + DerOutputStream out = new DerOutputStream(); + out.putInteger(r); + out.putInteger(s2); + DerOutputStream tmp = new DerOutputStream(); + tmp.putBitString(new DerValue(DerValue.tag_Sequence, + out.toByteArray()).toByteArray()); + return new DerValue(tmp.toByteArray()); + } + + private static DerValue altAlgId(DerValue algId) throws IOException { + DerInputStream in = algId.toDerInputStream(); + DerOutputStream bytes = new DerOutputStream(); + bytes.putOID(in.getOID()); + // encode parameters as NULL if not present or omit if NULL + if (in.available() == 0) { + bytes.putNull(); + } + DerOutputStream tmp = new DerOutputStream(); + tmp.write(DerValue.tag_Sequence, bytes); + return new DerValue(tmp.toByteArray()); } } diff -r 06c643a674d2 -r 2cde484ef248 src/share/lib/security/blacklisted.certs --- a/src/share/lib/security/blacklisted.certs Wed May 20 08:07:25 2020 -0400 +++ b/src/share/lib/security/blacklisted.certs Fri Sep 11 18:58:51 2020 +0300 @@ -1,20 +1,39 @@ -Algorithm=SHA-256 -76A45A496031E4DD2D7ED23E8F6FF97DBDEA980BAAC8B0BA94D7EDB551348645 -4CBBF8256BC9888A8007B2F386940A2E394378B0D903CBB3863C5A6394B889CE -D24566BF315F4E597D6E381C87119FB4198F5E9E2607F5F4AB362EF7E2E7672F -14E6D2764A4B06701C6CBC376A253775F79C782FBCB6C0EE6F99DE4BA1024ADD -D3A936E1A7775A45217C8296A1F22AC5631DCDEC45594099E78EEEBBEDCBA967 -5E83124D68D24E8E177E306DF643D5EA99C5A94D6FC34B072F7544A1CABB7C7B -9ED8F9B0E8E42A1656B8E1DD18F42BA42DC06FE52686173BA2FC70E756F207DC -FDEDB5BDFCB67411513A61AEE5CB5B5D7C52AF06028EFC996CC1B05B1D6CEA2B -A686FEE577C88AB664D0787ECDFFF035F4806F3DE418DC9E4D516324FFF02083 -4FEE0163686ECBD65DB968E7494F55D84B25486D438E9DE558D629D28CD4D176 -8A1BD21661C60015065212CC98B1ABB50DFD14C872A208E66BAE890F25C448AF -B8686723E415534BC0DBD16326F9486F85B0B0799BF6639334E61DAAE67F36CD -3946901F46B0071E90D78279E82FABABCA177231A704BE72C5B0E8918566EA66 -31C8FD37DB9B56E708B03D1F01848B068C6DA66F36FB5D82C008C6040FA3E133 -450F1B421BB05C8609854884559C323319619E8B06B001EA2DCBB74A23AA3BE2 -FC02FD48DB92D4DCE6F11679D38354CF750CFC7F584A520EB90BDE80E241F2BD -DF21016B00FC54F9FE3BC8B039911BB216E9162FAD2FD14D990AB96E951B49BE -F5B6F88F75D391A4B1EB336F9E201239FB6B1377DB8CFA7B84736216E5AFFFD7 -EC30C9C3065A06BB07DC5B1C6B497F370C1CA65C0F30C08E042BA6BCECC78F2C +Algorithm=SHA-256 +03DB9E5E79FE6117177F81C11595AF598CB176AF766290DBCEB2C318B32E39A2 +08C396C006A21055D00826A5781A5CCFCE2C8D053AB3C197637A4A7A5BB9A650 +14E6D2764A4B06701C6CBC376A253775F79C782FBCB6C0EE6F99DE4BA1024ADD +1C5E6985ACC09221DBD1A4B7BBC6D3A8C3F8540D19F20763A9537FDD42B4FFE7 +1F6BF8A3F2399AF7FD04516C2719C566CBAD51F412738F66D0457E1E6BDE6F2D +2A464E4113141352C7962FBD1706ED4B88533EF24D7BBA6CCC5D797FD202F1C4 +31C8FD37DB9B56E708B03D1F01848B068C6DA66F36FB5D82C008C6040FA3E133 +3946901F46B0071E90D78279E82FABABCA177231A704BE72C5B0E8918566EA66 +3E11CF90719F6FB44D94EAC9A156B89BEBE7B8598F28EC58913F2BFCAF91D0C0 +423279423B9FC8CB06F1BB7C3B247522B948D5F18939F378ECC901126DE40BFB +450F1B421BB05C8609854884559C323319619E8B06B001EA2DCBB74A23AA3BE2 +4CBBF8256BC9888A8007B2F386940A2E394378B0D903CBB3863C5A6394B889CE +4FEE0163686ECBD65DB968E7494F55D84B25486D438E9DE558D629D28CD4D176 +535D04DFCE027C70BD5F8A9E0AD4F218E9AFDCF5BBCF9B6DE0D81E148E2E3172 +568FAF38D9F155F624838E2181B1CEB4D8459305EE652B0F810C97C3611BFE19 +585CFE6B7436CBD4E732763A2137D7F49599BA9B1790E688FCEC799C58EB84A6 +5E83124D68D24E8E177E306DF643D5EA99C5A94D6FC34B072F7544A1CABB7C7B +71CB00749B9130FB2707A2664BFF958D0FCC8E161D9674C7450BA0FC2BEAF9D3 +76A45A496031E4DD2D7ED23E8F6FF97DBDEA980BAAC8B0BA94D7EDB551348645 +8A1BD21661C60015065212CC98B1ABB50DFD14C872A208E66BAE890F25C448AF +9ED8F9B0E8E42A1656B8E1DD18F42BA42DC06FE52686173BA2FC70E756F207DC +9FADCE80D62A959F9930D748488C1E22E821F4E1E4A43584B848C2FC11E04D77 +A686FEE577C88AB664D0787ECDFFF035F4806F3DE418DC9E4D516324FFF02083 +A90132CEA1D4F7185E4F688EFFD16F6AC14DFD78356A807599A5DABBEEF3333E +B8686723E415534BC0DBD16326F9486F85B0B0799BF6639334E61DAAE67F36CD +C0D1F42B9F4BF7ACC045B7BB5D4805E10737F67B6310CE505248D543D0D5FE07 +D0156949F1381943442C6974E9B5B49EF441BB799EF20477B90A89C3F33620CE +D151962D954970501C60079258EBCFA38502E0A9F03CD640322B08C0A3117FE5 +D24566BF315F4E597D6E381C87119FB4198F5E9E2607F5F4AB362EF7E2E7672F +D3A936E1A7775A45217C8296A1F22AC5631DCDEC45594099E78EEEBBEDCBA967 +D6CEAE5D9E047FAF7D797858D229AC991AD44316D1E2A37A21926D763153593A +DF21016B00FC54F9FE3BC8B039911BB216E9162FAD2FD14D990AB96E951B49BE +E0E740E4B0F8B3548181FF75B5372FAF4C70B99EC995D694ED0FB91B03FF8D21 +EC30C9C3065A06BB07DC5B1C6B497F370C1CA65C0F30C08E042BA6BCECC78F2C +F5B6F88F75D391A4B1EB336F9E201239FB6B1377DB8CFA7B84736216E5AFFFD7 +FBB12938ABD86C125796EDF4162D291028890A7D6C0C1CCA75FD4B95EBFA7A1A +FC02FD48DB92D4DCE6F11679D38354CF750CFC7F584A520EB90BDE80E241F2BD +FDEDB5BDFCB67411513A61AEE5CB5B5D7C52AF06028EFC996CC1B05B1D6CEA2B diff -r 06c643a674d2 -r 2cde484ef248 test/lib/security/CheckBlacklistedCerts.java --- a/test/lib/security/CheckBlacklistedCerts.java Wed May 20 08:07:25 2020 -0400 +++ b/test/lib/security/CheckBlacklistedCerts.java Fri Sep 11 18:58:51 2020 +0300 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8011402 + * @bug 8011402 8237995 * @summary Move blacklisting certificate logic from hard code to data */ @@ -115,7 +115,8 @@ System.out.println("There are " + acount + " algorithms"); failed = true; } - if (ccount != blacklisted.size() + // There are two unique fingerprints for each RSA certificate + if (ccount != blacklisted.size() * 2 && !blacklisted.isEmpty()) { System.out.println("Wrong blacklisted.certs size: " + ccount + " fingerprints, "