mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8270946: X509CertImpl.getFingerprint should not return the empty String
Reviewed-by: weijun
This commit is contained in:
parent
45d277feb0
commit
fc80a6b493
6 changed files with 216 additions and 36 deletions
|
@ -70,8 +70,14 @@ public class AnchorCertificates {
|
|||
if (alias.contains(" [jdk")) {
|
||||
X509Certificate cert = (X509Certificate) cacerts
|
||||
.getCertificate(alias);
|
||||
certs.add(X509CertImpl.getFingerprint(HASH, cert));
|
||||
certIssuers.add(cert.getSubjectX500Principal());
|
||||
String fp =
|
||||
X509CertImpl.getFingerprint(HASH, cert, debug);
|
||||
// only add trust anchor if fingerprint can
|
||||
// be calculated
|
||||
if (fp != null) {
|
||||
certs.add(fp);
|
||||
certIssuers.add(cert.getSubjectX500Principal());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -93,8 +99,8 @@ public class AnchorCertificates {
|
|||
* @return true if the certificate is a JDK trust anchor
|
||||
*/
|
||||
public static boolean contains(X509Certificate cert) {
|
||||
String key = X509CertImpl.getFingerprint(HASH, cert);
|
||||
boolean result = certs.contains(key);
|
||||
String key = X509CertImpl.getFingerprint(HASH, cert, debug);
|
||||
boolean result = (key == null ? false : certs.contains(key));
|
||||
if (result && debug != null) {
|
||||
debug.println("AnchorCertificate.contains: matched " +
|
||||
cert.getSubjectX500Principal());
|
||||
|
|
|
@ -28,7 +28,6 @@ import java.io.*;
|
|||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.Properties;
|
||||
|
||||
import jdk.internal.util.StaticProperty;
|
||||
|
@ -80,17 +79,9 @@ public final class UntrustedCertificates {
|
|||
if (algorithm == null) {
|
||||
return false;
|
||||
}
|
||||
String key;
|
||||
if (cert instanceof X509CertImpl) {
|
||||
key = ((X509CertImpl)cert).getFingerprint(algorithm);
|
||||
} else {
|
||||
try {
|
||||
key = new X509CertImpl(cert.getEncoded()).getFingerprint(algorithm);
|
||||
} catch (CertificateException cee) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return props.containsKey(key);
|
||||
// if fingerprint cannot be calculated, also treat it as untrusted
|
||||
String key = X509CertImpl.getFingerprint(algorithm, cert, debug);
|
||||
return (key == null || props.containsKey(key));
|
||||
}
|
||||
|
||||
private UntrustedCertificates() {}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2021, 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
|
||||
|
@ -32,6 +32,7 @@ import java.util.Date;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import sun.security.util.Debug;
|
||||
import sun.security.x509.X509CertImpl;
|
||||
|
||||
/**
|
||||
|
@ -40,6 +41,8 @@ import sun.security.x509.X509CertImpl;
|
|||
*/
|
||||
final class SymantecTLSPolicy {
|
||||
|
||||
private static final Debug debug = Debug.getInstance("certpath");
|
||||
|
||||
// SHA-256 certificate fingerprints of distrusted roots
|
||||
private static final Set<String> FINGERPRINTS = Set.of(
|
||||
// cacerts alias: geotrustglobalca
|
||||
|
@ -154,14 +157,24 @@ final class SymantecTLSPolicy {
|
|||
static void checkDistrust(X509Certificate[] chain)
|
||||
throws ValidatorException {
|
||||
X509Certificate anchor = chain[chain.length-1];
|
||||
if (FINGERPRINTS.contains(fingerprint(anchor))) {
|
||||
String fp = fingerprint(anchor);
|
||||
if (fp == null) {
|
||||
throw new ValidatorException("Cannot generate fingerprint for "
|
||||
+ "trust anchor of TLS server certificate");
|
||||
}
|
||||
if (FINGERPRINTS.contains(fp)) {
|
||||
Date notBefore = chain[0].getNotBefore();
|
||||
LocalDate ldNotBefore = LocalDate.ofInstant(notBefore.toInstant(),
|
||||
ZoneOffset.UTC);
|
||||
// check if chain goes through one of the subCAs
|
||||
if (chain.length > 2) {
|
||||
X509Certificate subCA = chain[chain.length-2];
|
||||
LocalDate distrustDate = EXEMPT_SUBCAS.get(fingerprint(subCA));
|
||||
fp = fingerprint(subCA);
|
||||
if (fp == null) {
|
||||
throw new ValidatorException("Cannot generate fingerprint "
|
||||
+ "for intermediate CA of TLS server certificate");
|
||||
}
|
||||
LocalDate distrustDate = EXEMPT_SUBCAS.get(fp);
|
||||
if (distrustDate != null) {
|
||||
// reject if certificate is issued after specified date
|
||||
checkNotBefore(ldNotBefore, distrustDate, anchor);
|
||||
|
@ -174,9 +187,7 @@ final class SymantecTLSPolicy {
|
|||
}
|
||||
|
||||
private static String fingerprint(X509Certificate cert) {
|
||||
return (cert instanceof X509CertImpl)
|
||||
? ((X509CertImpl)cert).getFingerprint("SHA-256")
|
||||
: X509CertImpl.getFingerprint("SHA-256", cert);
|
||||
return X509CertImpl.getFingerprint("SHA-256", cert, debug);
|
||||
}
|
||||
|
||||
private static void checkNotBefore(LocalDate notBeforeDate,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2021, 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
|
||||
|
@ -1917,25 +1917,57 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
|
|||
private ConcurrentHashMap<String,String> fingerprints =
|
||||
new ConcurrentHashMap<>(2);
|
||||
|
||||
public String getFingerprint(String algorithm) {
|
||||
private String getFingerprint(String algorithm, Debug debug) {
|
||||
return fingerprints.computeIfAbsent(algorithm,
|
||||
x -> getFingerprint(x, this));
|
||||
x -> {
|
||||
try {
|
||||
return getFingerprintInternal(x, getEncodedInternal(), debug);
|
||||
} catch (CertificateEncodingException e) {
|
||||
if (debug != null) {
|
||||
debug.println("Cannot encode certificate: " + e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static String getFingerprintInternal(String algorithm,
|
||||
byte[] encodedCert, Debug debug) {
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance(algorithm);
|
||||
byte[] digest = md.digest(encodedCert);
|
||||
return HexFormat.of().withUpperCase().formatHex(digest);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
if (debug != null) {
|
||||
debug.println("Cannot create " + algorithm
|
||||
+ " MessageDigest: " + e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the requested finger print of the certificate. The result
|
||||
* Gets the requested fingerprint of the certificate. The result
|
||||
* only contains 0-9 and A-F. No small case, no colon.
|
||||
*
|
||||
* @param algorithm the MessageDigest algorithm
|
||||
* @param cert the X509Certificate
|
||||
* @return the fingerprint, or null if it cannot be calculated because
|
||||
* of an exception
|
||||
*/
|
||||
public static String getFingerprint(String algorithm,
|
||||
X509Certificate cert) {
|
||||
try {
|
||||
byte[] encCertInfo = cert.getEncoded();
|
||||
MessageDigest md = MessageDigest.getInstance(algorithm);
|
||||
byte[] digest = md.digest(encCertInfo);
|
||||
return HexFormat.of().withUpperCase().formatHex(digest);
|
||||
} catch (NoSuchAlgorithmException | CertificateEncodingException e) {
|
||||
// ignored
|
||||
X509Certificate cert, Debug debug) {
|
||||
if (cert instanceof X509CertImpl) {
|
||||
return ((X509CertImpl)cert).getFingerprint(algorithm, debug);
|
||||
} else {
|
||||
try {
|
||||
return getFingerprintInternal(algorithm, cert.getEncoded(), debug);
|
||||
} catch (CertificateEncodingException e) {
|
||||
if (debug != null) {
|
||||
debug.println("Cannot encode certificate: " + e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue