Path: blob/master/src/java.base/share/classes/sun/security/provider/certpath/PKIX.java
67848 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 Date timestampDate;91private String variant = Validator.VAR_GENERIC;9293ValidatorParams(CertPath cp, PKIXParameters params)94throws InvalidAlgorithmParameterException95{96this(params);97if (!cp.getType().equals("X.509") && !cp.getType().equals("X509")) {98throw new InvalidAlgorithmParameterException("inappropriate "99+ "CertPath type specified, must be X.509 or X509");100}101this.certPath = cp;102}103104ValidatorParams(PKIXParameters params)105throws InvalidAlgorithmParameterException106{107if (params instanceof PKIXExtendedParameters) {108timestamp = ((PKIXExtendedParameters) params).getTimestamp();109variant = ((PKIXExtendedParameters) params).getVariant();110}111112this.anchors = params.getTrustAnchors();113// Make sure that none of the trust anchors include name constraints114// (not supported).115for (TrustAnchor anchor : this.anchors) {116if (anchor.getNameConstraints() != null) {117throw new InvalidAlgorithmParameterException118("name constraints in trust anchor not supported");119}120}121this.params = params;122}123124CertPath certPath() {125return certPath;126}127// called by CertPathBuilder after path has been built128void setCertPath(CertPath cp) {129this.certPath = cp;130}131List<X509Certificate> certificates() {132if (certs == null) {133if (certPath == null) {134certs = Collections.emptyList();135} else {136// Reverse the ordering for validation so that the target137// cert is the last certificate138@SuppressWarnings("unchecked")139List<X509Certificate> xc = new ArrayList<>140((List<X509Certificate>)certPath.getCertificates());141Collections.reverse(xc);142certs = xc;143}144}145return certs;146}147List<PKIXCertPathChecker> certPathCheckers() {148if (checkers == null)149checkers = params.getCertPathCheckers();150return checkers;151}152List<CertStore> certStores() {153if (stores == null)154stores = params.getCertStores();155return stores;156}157// The date() param is used when enforcing the validity period158// of certificates and when checking the time period of revocation data.159// The main difference between the date() and timestamp() method is160// that the date() method only uses the timestamp (if specified)161// for certificates in a code signer's chain.162Date date() {163if (!gotDate) {164// Use timestamp if checking signed code that is165// timestamped, otherwise use date parameter.166// Note that TSA server certificates do not use the167// timestamp, which means that an expired TSA certificate168// is considered a validation failure. This policy means169// that signed and timestamped code is valid until the TSA170// certificate expires (assuming all other checks are valid).171if (timestamp != null &&172(variant.equals(Validator.VAR_CODE_SIGNING) ||173variant.equals(Validator.VAR_PLUGIN_CODE_SIGNING))) {174date = timestamp.getTimestamp();175} else {176date = params.getDate();177if (date == null)178date = new Date();179}180gotDate = true;181}182return date;183}184Set<String> initialPolicies() {185if (policies == null)186policies = params.getInitialPolicies();187return policies;188}189CertSelector targetCertConstraints() {190if (!gotConstraints) {191constraints = params.getTargetCertConstraints();192gotConstraints = true;193}194return constraints;195}196Set<TrustAnchor> trustAnchors() {197return anchors;198}199boolean revocationEnabled() {200return params.isRevocationEnabled();201}202boolean policyMappingInhibited() {203return params.isPolicyMappingInhibited();204}205boolean explicitPolicyRequired() {206return params.isExplicitPolicyRequired();207}208boolean policyQualifiersRejected() {209return params.getPolicyQualifiersRejected();210}211String sigProvider() { return params.getSigProvider(); }212boolean anyPolicyInhibited() { return params.isAnyPolicyInhibited(); }213214// in rare cases we need access to the original params, for example215// in order to clone CertPathCheckers before building a new chain216PKIXParameters getPKIXParameters() {217return params;218}219220String variant() {221return variant;222}223// The timestamp() param is passed as the date param when creating an224// AlgorithmChecker. An AlgorithmChecker always uses the timestamp225// if specified in order to enforce the denyAfter constraint.226Date timestamp() {227// return timestamp date if set, otherwise use date parameter228if (timestampDate == null) {229timestampDate = (timestamp != null)230? timestamp.getTimestamp() : date();231}232return timestampDate;233}234}235236static class BuilderParams extends ValidatorParams {237private PKIXBuilderParameters params;238private List<CertStore> stores;239private X500Principal targetSubject;240241BuilderParams(PKIXBuilderParameters params)242throws InvalidAlgorithmParameterException243{244super(params);245checkParams(params);246}247private void checkParams(PKIXBuilderParameters params)248throws InvalidAlgorithmParameterException249{250CertSelector sel = targetCertConstraints();251if (!(sel instanceof X509CertSelector)) {252throw new InvalidAlgorithmParameterException("the "253+ "targetCertConstraints parameter must be an "254+ "X509CertSelector");255}256this.params = params;257this.targetSubject = getTargetSubject(258certStores(), (X509CertSelector)targetCertConstraints());259}260@Override List<CertStore> certStores() {261if (stores == null) {262// reorder CertStores so that local CertStores are tried first263stores = new ArrayList<>(params.getCertStores());264Collections.sort(stores, new CertStoreComparator());265}266return stores;267}268int maxPathLength() { return params.getMaxPathLength(); }269PKIXBuilderParameters params() { return params; }270X500Principal targetSubject() { return targetSubject; }271272/**273* Returns the target subject DN from the first X509Certificate that274* is fetched that matches the specified X509CertSelector.275*/276private static X500Principal getTargetSubject(List<CertStore> stores,277X509CertSelector sel)278throws InvalidAlgorithmParameterException279{280X500Principal subject = sel.getSubject();281if (subject != null) {282return subject;283}284X509Certificate cert = sel.getCertificate();285if (cert != null) {286subject = cert.getSubjectX500Principal();287}288if (subject != null) {289return subject;290}291for (CertStore store : stores) {292try {293Collection<? extends Certificate> certs =294(Collection<? extends Certificate>)295store.getCertificates(sel);296if (!certs.isEmpty()) {297X509Certificate xc =298(X509Certificate)certs.iterator().next();299return xc.getSubjectX500Principal();300}301} catch (CertStoreException e) {302// ignore but log it303if (debug != null) {304debug.println("BuilderParams.getTargetSubjectDN: " +305"non-fatal exception retrieving certs: " + e);306e.printStackTrace();307}308}309}310throw new InvalidAlgorithmParameterException311("Could not determine unique target subject");312}313}314315/**316* A CertStoreException with additional information about the type of317* CertStore that generated the exception.318*/319static class CertStoreTypeException extends CertStoreException {320@java.io.Serial321private static final long serialVersionUID = 7463352639238322556L;322323private final String type;324325CertStoreTypeException(String type, CertStoreException cse) {326super(cse.getMessage(), cse.getCause());327this.type = type;328}329String getType() {330return type;331}332}333334/**335* Comparator that orders CertStores so that local CertStores come before336* remote CertStores.337*/338private static class CertStoreComparator implements Comparator<CertStore> {339@Override340public int compare(CertStore store1, CertStore store2) {341if (store1.getType().equals("Collection") ||342store1.getCertStoreParameters() instanceof343CollectionCertStoreParameters) {344return -1;345} else {346return 1;347}348}349}350}351352353