8237995: Enhance certificate processing
Reviewed-by: weijun, rhalade, ahgross, erikj
This commit is contained in:
parent
9291e60892
commit
62a03bd387
make
CompileToolsJdk.gmkToolsJdk.gmk
data/blacklistedcertsconverter
jdk/src/classes/build/tools/blacklistedcertsconverter
src/java.base/share/classes/sun/security/util
test/jdk/sun/security/lib
@ -56,7 +56,8 @@ $(eval $(call SetupJavaCompilation, BUILD_TOOLS_JDK, \
|
|||||||
DISABLED_WARNINGS := options, \
|
DISABLED_WARNINGS := options, \
|
||||||
JAVAC_FLAGS := \
|
JAVAC_FLAGS := \
|
||||||
--add-exports java.desktop/sun.awt=ALL-UNNAMED \
|
--add-exports java.desktop/sun.awt=ALL-UNNAMED \
|
||||||
--add-exports java.base/sun.text=ALL-UNNAMED, \
|
--add-exports java.base/sun.text=ALL-UNNAMED \
|
||||||
|
--add-exports java.base/sun.security.util=ALL-UNNAMED, \
|
||||||
))
|
))
|
||||||
|
|
||||||
TARGETS += $(BUILD_TOOLS_JDK)
|
TARGETS += $(BUILD_TOOLS_JDK)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2011, 2019, 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.
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
#
|
#
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
# This code is free software; you can redistribute it and/or modify it
|
||||||
@ -68,6 +68,7 @@ TOOL_TZDB = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
|
|||||||
build.tools.tzdb.TzdbZoneRulesCompiler
|
build.tools.tzdb.TzdbZoneRulesCompiler
|
||||||
|
|
||||||
TOOL_BLACKLISTED_CERTS = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
|
TOOL_BLACKLISTED_CERTS = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
|
||||||
|
--add-exports java.base/sun.security.util=ALL-UNNAMED \
|
||||||
build.tools.blacklistedcertsconverter.BlacklistedCertsConverter
|
build.tools.blacklistedcertsconverter.BlacklistedCertsConverter
|
||||||
|
|
||||||
TOOL_MAKEJAVASECURITY = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
|
TOOL_MAKEJAVASECURITY = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
#! java BlacklistedCertsConverter SHA-256
|
#! java BlacklistedCertsConverter SHA-256
|
||||||
|
|
||||||
# The line above must be the first line of the blacklisted.certs.pem
|
# The line above must be the first line of this file. Do not
|
||||||
# file inside src/share/lib/security/. It will be ignored if added in
|
# remove it.
|
||||||
# src/closed/share/lib/security/blacklisted.certs.pem.
|
|
||||||
|
|
||||||
// Subject: CN=Digisign Server ID (Enrich),
|
// Subject: CN=Digisign Server ID (Enrich),
|
||||||
// OU=457608-K,
|
// OU=457608-K,
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -25,14 +25,24 @@
|
|||||||
|
|
||||||
package build.tools.blacklistedcertsconverter;
|
package build.tools.blacklistedcertsconverter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.math.BigInteger;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
|
import java.security.PublicKey;
|
||||||
import java.security.cert.Certificate;
|
import java.security.cert.Certificate;
|
||||||
import java.security.cert.CertificateFactory;
|
import java.security.cert.CertificateFactory;
|
||||||
import java.security.cert.X509Certificate;
|
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.Collection;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
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
|
* Converts blacklisted.certs.pem from System.in to blacklisted.certs in
|
||||||
@ -75,8 +85,8 @@ public class BlacklistedCertsConverter {
|
|||||||
// Output sorted so that it's easy to locate an entry.
|
// Output sorted so that it's easy to locate an entry.
|
||||||
Set<String> fingerprints = new TreeSet<>();
|
Set<String> fingerprints = new TreeSet<>();
|
||||||
for (Certificate cert: certs) {
|
for (Certificate cert: certs) {
|
||||||
fingerprints.add(
|
fingerprints.addAll(
|
||||||
getCertificateFingerPrint(mdAlg, (X509Certificate)cert));
|
getCertificateFingerPrints(mdAlg, (X509Certificate)cert));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (String s: fingerprints) {
|
for (String s: fingerprints) {
|
||||||
@ -97,17 +107,90 @@ public class BlacklistedCertsConverter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 {
|
String mdAlg, X509Certificate cert) throws Exception {
|
||||||
byte[] encCertInfo = cert.getEncoded();
|
List<String> fingerprints = new ArrayList<>();
|
||||||
|
for (byte[] encoding : altEncodings(cert)) {
|
||||||
MessageDigest md = MessageDigest.getInstance(mdAlg);
|
MessageDigest md = MessageDigest.getInstance(mdAlg);
|
||||||
byte[] digest = md.digest(encCertInfo);
|
byte[] digest = md.digest(encoding);
|
||||||
StringBuffer buf = new StringBuffer();
|
StringBuffer buf = new StringBuffer();
|
||||||
for (int i = 0; i < digest.length; i++) {
|
for (int i = 0; i < digest.length; i++) {
|
||||||
byte2hex(digest[i], buf);
|
byte2hex(digest[i], buf);
|
||||||
}
|
}
|
||||||
return buf.toString();
|
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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -29,7 +29,7 @@ import java.security.AccessController;
|
|||||||
import java.security.PrivilegedAction;
|
import java.security.PrivilegedAction;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
import java.util.*;
|
import java.util.Properties;
|
||||||
|
|
||||||
import jdk.internal.util.StaticProperty;
|
import jdk.internal.util.StaticProperty;
|
||||||
import sun.security.x509.X509CertImpl;
|
import sun.security.x509.X509CertImpl;
|
||||||
@ -58,10 +58,6 @@ public final class UntrustedCertificates {
|
|||||||
"lib/security/blacklisted.certs");
|
"lib/security/blacklisted.certs");
|
||||||
try (FileInputStream fin = new FileInputStream(f)) {
|
try (FileInputStream fin = new FileInputStream(f)) {
|
||||||
props.load(fin);
|
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) {
|
} catch (IOException fnfe) {
|
||||||
if (debug != null) {
|
if (debug != null) {
|
||||||
debug.println("Error parsing blacklisted.certs");
|
debug.println("Error parsing blacklisted.certs");
|
||||||
@ -73,21 +69,6 @@ public final class UntrustedCertificates {
|
|||||||
algorithm = props.getProperty(ALGORITHM_KEY);
|
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.
|
* Checks if a certificate is untrusted.
|
||||||
*
|
*
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 8011402 8211969
|
* @bug 8011402 8211969 8237995
|
||||||
* @summary Move blacklisting certificate logic from hard code to data
|
* @summary Move blacklisting certificate logic from hard code to data
|
||||||
* @modules java.base/sun.security.util
|
* @modules java.base/sun.security.util
|
||||||
*/
|
*/
|
||||||
@ -99,7 +99,8 @@ public class CheckBlacklistedCerts {
|
|||||||
System.out.println("There are " + acount + " algorithms");
|
System.out.println("There are " + acount + " algorithms");
|
||||||
failed = true;
|
failed = true;
|
||||||
}
|
}
|
||||||
if (ccount != blacklisted.size()
|
// There are two unique fingerprints for each RSA certificate
|
||||||
|
if (ccount != blacklisted.size() * 2
|
||||||
&& !blacklisted.isEmpty()) {
|
&& !blacklisted.isEmpty()) {
|
||||||
System.out.println("Wrong blacklisted.certs size: "
|
System.out.println("Wrong blacklisted.certs size: "
|
||||||
+ ccount + " fingerprints, "
|
+ ccount + " fingerprints, "
|
||||||
|
Loading…
x
Reference in New Issue
Block a user