Skip to content

Commit

Permalink
8237995: Enhance certificate processing
Browse files Browse the repository at this point in the history
Reviewed-by: weijun, rhalade, ahgross, erikj
  • Loading branch information
seanjmullan committed May 6, 2020
1 parent 665cb7d commit cd62bab
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 41 deletions.
3 changes: 2 additions & 1 deletion make/CompileToolsJdk.gmk
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ $(eval $(call SetupJavaCompilation, BUILD_TOOLS_JDK, \
DISABLED_WARNINGS := options, \
JAVAC_FLAGS := \
--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)
Expand Down
3 changes: 2 additions & 1 deletion make/ToolsJdk.gmk
Original file line number Diff line number Diff line change
@@ -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.
#
# This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -68,6 +68,7 @@ TOOL_TZDB = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
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 \
Expand Down
5 changes: 2 additions & 3 deletions make/data/blacklistedcertsconverter/blacklisted.certs.pem
Original file line number Diff line number Diff line change
@@ -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,
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand Down Expand Up @@ -75,8 +85,8 @@ public static void main(String[] args) throws Exception {
// 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) {
Expand All @@ -97,17 +107,90 @@ private static void byte2hex(byte b, StringBuffer buf) {
}

/**
* 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]);
}

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();
}
return buf.toString();
DerOutputStream tmp = new DerOutputStream();
tmp.write(DerValue.tag_Sequence, bytes);
return new DerValue(tmp.toByteArray());
}
}
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -58,10 +58,6 @@ public Void run() {
"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");
Expand All @@ -73,21 +69,6 @@ public Void run() {
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.
*
Expand Down
7 changes: 4 additions & 3 deletions test/jdk/sun/security/lib/CheckBlacklistedCerts.java
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
*/
Expand Down Expand Up @@ -99,7 +99,8 @@ public static void main(String[] args) throws Exception {
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, "
Expand Down

0 comments on commit cd62bab

Please sign in to comment.