changeset 53504:adc949b07eeb

8237995: Enhance certificate processing Reviewed-by: weijun, rhalade, ahgross, erikj, mbalao, andrew
author mullan
date Wed, 06 May 2020 07:25:59 -0400
parents e8b4096c7091
children 52fbbaed4d22
files make/CompileToolsJdk.gmk make/ToolsJdk.gmk make/data/blacklistedcertsconverter/blacklisted.certs.pem make/jdk/src/classes/build/tools/blacklistedcertsconverter/BlacklistedCertsConverter.java src/java.base/share/classes/sun/security/util/UntrustedCertificates.java test/jdk/sun/security/lib/CheckBlacklistedCerts.java
diffstat 6 files changed, 106 insertions(+), 40 deletions(-) [+]
line wrap: on
line diff
--- a/make/CompileToolsJdk.gmk	Mon Jun 22 14:30:37 2020 +0100
+++ b/make/CompileToolsJdk.gmk	Wed May 06 07:25:59 2020 -0400
@@ -55,6 +55,7 @@
     ADD_JAVAC_FLAGS := \
         --add-exports java.desktop/sun.awt=ALL-UNNAMED \
         --add-exports java.base/sun.text=ALL-UNNAMED \
+        --add-exports java.base/sun.security.util=ALL-UNNAMED \
         , \
 ))
 
--- a/make/ToolsJdk.gmk	Mon Jun 22 14:30:37 2020 +0100
+++ b/make/ToolsJdk.gmk	Wed May 06 07:25:59 2020 -0400
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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
@@ -74,6 +74,7 @@
     build.tools.tzdb.TzdbZoneRulesCompiler
 
 TOOL_BLACKLISTED_CERTS = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
+    --add-exports java.base/sun.security.util=ALL-UNNAMED \
     build.tools.blacklistedcertsconverter.BlacklistedCertsConverter
 
 TOOL_MAKEJAVASECURITY = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
--- a/make/data/blacklistedcertsconverter/blacklisted.certs.pem	Mon Jun 22 14:30:37 2020 +0100
+++ b/make/data/blacklistedcertsconverter/blacklisted.certs.pem	Wed May 06 07:25:59 2020 -0400
@@ -1,8 +1,7 @@
 #! java BlacklistedCertsConverter SHA-256
 
-# The line above must be the first line of the blacklisted.certs.pem
-# file inside src/share/lib/security/. It will be ignored if added in
-# src/closed/share/lib/security/blacklisted.certs.pem.
+# The line above must be the first line of this file. Do not
+# remove it.
 
 // Subject: CN=Digisign Server ID (Enrich),
 //          OU=457608-K,
--- a/make/jdk/src/classes/build/tools/blacklistedcertsconverter/BlacklistedCertsConverter.java	Mon Jun 22 14:30:37 2020 +0100
+++ b/make/jdk/src/classes/build/tools/blacklistedcertsconverter/BlacklistedCertsConverter.java	Wed May 06 07:25:59 2020 -0400
@@ -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
@@ -25,14 +25,24 @@
 
 package build.tools.blacklistedcertsconverter;
 
+import java.io.IOException;
+import java.math.BigInteger;
 import java.security.MessageDigest;
+import java.security.PublicKey;
 import java.security.cert.Certificate;
 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;
 
 /**
  * Converts blacklisted.certs.pem from System.in to blacklisted.certs in
@@ -75,8 +85,8 @@
         // Output sorted so that it's easy to locate an entry.
         Set<String> fingerprints = new TreeSet<>();
         for (Certificate cert: certs) {
-            fingerprints.add(
-                    getCertificateFingerPrint(mdAlg, (X509Certificate)cert));
+            fingerprints.addAll(
+                getCertificateFingerPrints(mdAlg, (X509Certificate)cert));
         }
 
         for (String s: fingerprints) {
@@ -97,17 +107,90 @@
     }
 
     /**
-     * Gets the requested finger print of the certificate.
+     * Computes the possible fingerprints of the certificate.
      */
-    private static String getCertificateFingerPrint(
+    private static List<String> getCertificateFingerPrints(
             String mdAlg, X509Certificate cert) throws Exception {
-        byte[] encCertInfo = cert.getEncoded();
-        MessageDigest md = MessageDigest.getInstance(mdAlg);
-        byte[] digest = md.digest(encCertInfo);
-        StringBuffer buf = new StringBuffer();
-        for (int i = 0; i < digest.length; i++) {
-            byte2hex(digest[i], buf);
+        List<String> fingerprints = new ArrayList<>();
+        for (byte[] encoding : altEncodings(cert)) {
+            MessageDigest md = MessageDigest.getInstance(mdAlg);
+            byte[] digest = md.digest(encoding);
+            StringBuffer buf = new StringBuffer();
+            for (int i = 0; i < digest.length; i++) {
+                byte2hex(digest[i], buf);
+            }
+            fingerprints.add(buf.toString());
+        }
+        return fingerprints;
+    }
+
+    private static List<byte[]> altEncodings(X509Certificate c)
+            throws Exception {
+        List<byte[]> 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<DerValue> algIds = Arrays.asList(seq[1], altAlgId(seq[1]));
+
+        List<DerValue> 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 buf.toString();
+
+        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());
     }
 }
--- a/src/java.base/share/classes/sun/security/util/UntrustedCertificates.java	Mon Jun 22 14:30:37 2020 +0100
+++ b/src/java.base/share/classes/sun/security/util/UntrustedCertificates.java	Wed May 06 07:25:59 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -29,7 +29,7 @@
 import java.security.PrivilegedAction;
 import java.security.cert.X509Certificate;
 import java.security.cert.CertificateException;
-import java.util.*;
+import java.util.Properties;
 
 import jdk.internal.util.StaticProperty;
 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<Object,Object> 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.
      *
--- a/test/jdk/sun/security/lib/CheckBlacklistedCerts.java	Mon Jun 22 14:30:37 2020 +0100
+++ b/test/jdk/sun/security/lib/CheckBlacklistedCerts.java	Wed May 06 07:25:59 2020 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, 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 8211969
+ * @bug 8011402 8211969 8237995
  * @summary Move blacklisting certificate logic from hard code to data
  * @modules java.base/sun.security.util
  */
@@ -99,7 +99,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, "