Path: blob/master/src/java.base/share/classes/sun/security/provider/certpath/PKIX.java
41161 views
/*1* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24package sun.security.provider.certpath;2526import java.security.InvalidAlgorithmParameterException;27import java.security.PublicKey;28import java.security.Timestamp;29import java.security.cert.*;30import java.security.interfaces.DSAPublicKey;31import java.util.*;32import javax.security.auth.x500.X500Principal;3334import sun.security.util.Debug;35import sun.security.validator.Validator;3637/**38* Common utility methods and classes used by the PKIX CertPathValidator and39* CertPathBuilder implementation.40*/41class PKIX {4243private static final Debug debug = Debug.getInstance("certpath");4445private PKIX() { }4647static boolean isDSAPublicKeyWithoutParams(PublicKey publicKey) {48return (publicKey instanceof DSAPublicKey &&49((DSAPublicKey)publicKey).getParams() == null);50}5152static ValidatorParams checkParams(CertPath cp, CertPathParameters params)53throws InvalidAlgorithmParameterException54{55if (!(params instanceof PKIXParameters)) {56throw new InvalidAlgorithmParameterException("inappropriate "57+ "params, must be an instance of PKIXParameters");58}59return new ValidatorParams(cp, (PKIXParameters)params);60}6162static BuilderParams checkBuilderParams(CertPathParameters params)63throws InvalidAlgorithmParameterException64{65if (!(params instanceof PKIXBuilderParameters)) {66throw new InvalidAlgorithmParameterException("inappropriate "67+ "params, must be an instance of PKIXBuilderParameters");68}69return new BuilderParams((PKIXBuilderParameters)params);70}7172/**73* PKIXParameters that are shared by the PKIX CertPathValidator74* implementation. Provides additional functionality and avoids75* unnecessary cloning.76*/77static class ValidatorParams {78private final PKIXParameters params;79private CertPath certPath;80private List<PKIXCertPathChecker> checkers;81private List<CertStore> stores;82private boolean gotDate;83private Date date;84private Set<String> policies;85private boolean gotConstraints;86private CertSelector constraints;87private Set<TrustAnchor> anchors;88private List<X509Certificate> certs;89private Timestamp timestamp;90private String variant = Validator.VAR_GENERIC;9192ValidatorParams(CertPath cp, PKIXParameters params)93throws InvalidAlgorithmParameterException94{95this(params);96if (!cp.getType().equals("X.509") && !cp.getType().equals("X509")) {97throw new InvalidAlgorithmParameterException("inappropriate "98+ "CertPath type specified, must be X.509 or X509");99}100this.certPath = cp;101}102103ValidatorParams(PKIXParameters params)104throws InvalidAlgorithmParameterException105{106if (params instanceof PKIXExtendedParameters) {107timestamp = ((PKIXExtendedParameters) params).getTimestamp();108variant = ((PKIXExtendedParameters) params).getVariant();109}110111this.anchors = params.getTrustAnchors();112// Make sure that none of the trust anchors include name constraints113// (not supported).114for (TrustAnchor anchor : this.anchors) {115if (anchor.getNameConstraints() != null) {116throw new InvalidAlgorithmParameterException117("name constraints in trust anchor not supported");118}119}120this.params = params;121}122123CertPath certPath() {124return certPath;125}126// called by CertPathBuilder after path has been built127void setCertPath(CertPath cp) {128this.certPath = cp;129}130List<X509Certificate> certificates() {131if (certs == null) {132if (certPath == null) {133certs = Collections.emptyList();134} else {135// Reverse the ordering for validation so that the target136// cert is the last certificate137@SuppressWarnings("unchecked")138List<X509Certificate> xc = new ArrayList<>139((List<X509Certificate>)certPath.getCertificates());140Collections.reverse(xc);141certs = xc;142}143}144return certs;145}146List<PKIXCertPathChecker> certPathCheckers() {147if (checkers == null)148checkers = params.getCertPathCheckers();149return checkers;150}151List<CertStore> certStores() {152if (stores == null)153stores = params.getCertStores();154return stores;155}156Date date() {157if (!gotDate) {158// use timestamp if checking signed code that is159// timestamped, otherwise use date parameter160if (timestamp != null &&161(variant.equals(Validator.VAR_CODE_SIGNING) ||162variant.equals(Validator.VAR_PLUGIN_CODE_SIGNING))) {163date = timestamp.getTimestamp();164} else {165date = params.getDate();166if (date == null)167date = new Date();168}169gotDate = true;170}171return date;172}173Set<String> initialPolicies() {174if (policies == null)175policies = params.getInitialPolicies();176return policies;177}178CertSelector targetCertConstraints() {179if (!gotConstraints) {180constraints = params.getTargetCertConstraints();181gotConstraints = true;182}183return constraints;184}185Set<TrustAnchor> trustAnchors() {186return anchors;187}188boolean revocationEnabled() {189return params.isRevocationEnabled();190}191boolean policyMappingInhibited() {192return params.isPolicyMappingInhibited();193}194boolean explicitPolicyRequired() {195return params.isExplicitPolicyRequired();196}197boolean policyQualifiersRejected() {198return params.getPolicyQualifiersRejected();199}200String sigProvider() { return params.getSigProvider(); }201boolean anyPolicyInhibited() { return params.isAnyPolicyInhibited(); }202203// in rare cases we need access to the original params, for example204// in order to clone CertPathCheckers before building a new chain205PKIXParameters getPKIXParameters() {206return params;207}208209String variant() {210return variant;211}212}213214static class BuilderParams extends ValidatorParams {215private PKIXBuilderParameters params;216private List<CertStore> stores;217private X500Principal targetSubject;218219BuilderParams(PKIXBuilderParameters params)220throws InvalidAlgorithmParameterException221{222super(params);223checkParams(params);224}225private void checkParams(PKIXBuilderParameters params)226throws InvalidAlgorithmParameterException227{228CertSelector sel = targetCertConstraints();229if (!(sel instanceof X509CertSelector)) {230throw new InvalidAlgorithmParameterException("the "231+ "targetCertConstraints parameter must be an "232+ "X509CertSelector");233}234this.params = params;235this.targetSubject = getTargetSubject(236certStores(), (X509CertSelector)targetCertConstraints());237}238@Override List<CertStore> certStores() {239if (stores == null) {240// reorder CertStores so that local CertStores are tried first241stores = new ArrayList<>(params.getCertStores());242Collections.sort(stores, new CertStoreComparator());243}244return stores;245}246int maxPathLength() { return params.getMaxPathLength(); }247PKIXBuilderParameters params() { return params; }248X500Principal targetSubject() { return targetSubject; }249250/**251* Returns the target subject DN from the first X509Certificate that252* is fetched that matches the specified X509CertSelector.253*/254private static X500Principal getTargetSubject(List<CertStore> stores,255X509CertSelector sel)256throws InvalidAlgorithmParameterException257{258X500Principal subject = sel.getSubject();259if (subject != null) {260return subject;261}262X509Certificate cert = sel.getCertificate();263if (cert != null) {264subject = cert.getSubjectX500Principal();265}266if (subject != null) {267return subject;268}269for (CertStore store : stores) {270try {271Collection<? extends Certificate> certs =272(Collection<? extends Certificate>)273store.getCertificates(sel);274if (!certs.isEmpty()) {275X509Certificate xc =276(X509Certificate)certs.iterator().next();277return xc.getSubjectX500Principal();278}279} catch (CertStoreException e) {280// ignore but log it281if (debug != null) {282debug.println("BuilderParams.getTargetSubjectDN: " +283"non-fatal exception retrieving certs: " + e);284e.printStackTrace();285}286}287}288throw new InvalidAlgorithmParameterException289("Could not determine unique target subject");290}291}292293/**294* A CertStoreException with additional information about the type of295* CertStore that generated the exception.296*/297static class CertStoreTypeException extends CertStoreException {298@java.io.Serial299private static final long serialVersionUID = 7463352639238322556L;300301private final String type;302303CertStoreTypeException(String type, CertStoreException cse) {304super(cse.getMessage(), cse.getCause());305this.type = type;306}307String getType() {308return type;309}310}311312/**313* Comparator that orders CertStores so that local CertStores come before314* remote CertStores.315*/316private static class CertStoreComparator implements Comparator<CertStore> {317@Override318public int compare(CertStore store1, CertStore store2) {319if (store1.getType().equals("Collection") ||320store1.getCertStoreParameters() instanceof321CollectionCertStoreParameters) {322return -1;323} else {324return 1;325}326}327}328}329330331