Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/validator/EndEntityChecker.java
38831 views
/*1* Copyright (c) 2002, 2019, 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*/2425package sun.security.validator;2627import java.util.*;2829import java.security.cert.*;3031import sun.security.x509.NetscapeCertTypeExtension;3233/**34* Class to check if an end entity cert is suitable for use in some35* context.<p>36*37* This class is used internally by the validator. Currently, seven variants38* are supported defined as VAR_XXX constants in the Validator class:39* <ul>40* <li>Generic. No additional requirements, all certificates are ok.41*42* <li>TLS server. Requires that a String parameter is passed to43* validate that specifies the name of the TLS key exchange algorithm44* in use. See the JSSE X509TrustManager spec for details.45*46* <li>TLS client.47*48* <li>Code signing.49*50* <li>JCE code signing. Some early JCE code signing certs issued to51* providers had incorrect extensions. In this mode the checks52* are relaxed compared to standard code signing checks in order to53* allow these certificates to pass.54*55* <li>Plugin code signing. WebStart and Plugin require their own variant56* which is equivalent to VAR_CODE_SIGNING with additional checks for57* compatibility/special cases. See also PKIXValidator.58*59* <li>TSA Server (see RFC 3161, section 2.3).60*61* </ul>62*63* @author Andreas Sterbenz64*/65class EndEntityChecker {6667// extended key usage OIDs for TLS server, TLS client, code signing68// and any usage6970private final static String OID_EXTENDED_KEY_USAGE =71SimpleValidator.OID_EXTENDED_KEY_USAGE;7273private final static String OID_EKU_TLS_SERVER = "1.3.6.1.5.5.7.3.1";7475private final static String OID_EKU_TLS_CLIENT = "1.3.6.1.5.5.7.3.2";7677private final static String OID_EKU_CODE_SIGNING = "1.3.6.1.5.5.7.3.3";7879private final static String OID_EKU_TIME_STAMPING = "1.3.6.1.5.5.7.3.8";8081private final static String OID_EKU_ANY_USAGE = "2.5.29.37.0";8283// the Netscape Server-Gated-Cryptography EKU extension OID84private final static String OID_EKU_NS_SGC = "2.16.840.1.113730.4.1";8586// the Microsoft Server-Gated-Cryptography EKU extension OID87private final static String OID_EKU_MS_SGC = "1.3.6.1.4.1.311.10.3.3";8889// the recognized extension OIDs90private final static String OID_SUBJECT_ALT_NAME = "2.5.29.17";9192private final static String NSCT_SSL_CLIENT =93NetscapeCertTypeExtension.SSL_CLIENT;9495private final static String NSCT_SSL_SERVER =96NetscapeCertTypeExtension.SSL_SERVER;9798private final static String NSCT_CODE_SIGNING =99NetscapeCertTypeExtension.OBJECT_SIGNING;100101// bit numbers in the key usage extension102private final static int KU_SIGNATURE = 0;103private final static int KU_KEY_ENCIPHERMENT = 2;104private final static int KU_KEY_AGREEMENT = 4;105106// TLS key exchange algorithms requiring digitalSignature key usage107private final static Collection<String> KU_SERVER_SIGNATURE =108Arrays.asList("DHE_DSS", "DHE_RSA", "ECDHE_ECDSA", "ECDHE_RSA",109"RSA_EXPORT", "UNKNOWN");110111// TLS key exchange algorithms requiring keyEncipherment key usage112private final static Collection<String> KU_SERVER_ENCRYPTION =113Arrays.asList("RSA");114115// TLS key exchange algorithms requiring keyAgreement key usage116private final static Collection<String> KU_SERVER_KEY_AGREEMENT =117Arrays.asList("DH_DSS", "DH_RSA", "ECDH_ECDSA", "ECDH_RSA");118119// variant of this end entity cert checker120private final String variant;121122// type of the validator this checker belongs to123private final String type;124125private EndEntityChecker(String type, String variant) {126this.type = type;127this.variant = variant;128}129130static EndEntityChecker getInstance(String type, String variant) {131return new EndEntityChecker(type, variant);132}133134void check(X509Certificate[] chain, Object parameter,135boolean checkUnresolvedCritExts)136throws CertificateException {137if (variant.equals(Validator.VAR_GENERIC)) {138return; // no checks139}140141Set<String> exts = getCriticalExtensions(chain[0]);142if (variant.equals(Validator.VAR_TLS_SERVER)) {143checkTLSServer(chain[0], (String)parameter, exts);144} else if (variant.equals(Validator.VAR_TLS_CLIENT)) {145checkTLSClient(chain[0], exts);146} else if (variant.equals(Validator.VAR_CODE_SIGNING)) {147checkCodeSigning(chain[0], exts);148} else if (variant.equals(Validator.VAR_JCE_SIGNING)) {149checkCodeSigning(chain[0], exts);150} else if (variant.equals(Validator.VAR_PLUGIN_CODE_SIGNING)) {151checkCodeSigning(chain[0], exts);152} else if (variant.equals(Validator.VAR_TSA_SERVER)) {153checkTSAServer(chain[0], exts);154} else {155throw new CertificateException("Unknown variant: " + variant);156}157158// if neither VAR_GENERIC variant nor unknown variant159if (checkUnresolvedCritExts) {160checkRemainingExtensions(exts);161}162163// check if certificate should be distrusted according to policies164// set in the jdk.security.caDistrustPolicies security property165for (CADistrustPolicy policy : CADistrustPolicy.POLICIES) {166policy.checkDistrust(variant, chain);167}168}169170/**171* Utility method returning the Set of critical extensions for172* certificate cert (never null).173*/174private Set<String> getCriticalExtensions(X509Certificate cert) {175Set<String> exts = cert.getCriticalExtensionOIDs();176if (exts == null) {177exts = Collections.emptySet();178}179return exts;180}181182/**183* Utility method checking if there are any unresolved critical extensions.184* @throws CertificateException if so.185*/186private void checkRemainingExtensions(Set<String> exts)187throws CertificateException {188// basic constraints irrelevant in EE certs189exts.remove(SimpleValidator.OID_BASIC_CONSTRAINTS);190191// If the subject field contains an empty sequence, the subjectAltName192// extension MUST be marked critical.193// We do not check the validity of the critical extension, just mark194// it recognizable here.195exts.remove(OID_SUBJECT_ALT_NAME);196197if (!exts.isEmpty()) {198throw new CertificateException("Certificate contains unsupported "199+ "critical extensions: " + exts);200}201}202203/**204* Utility method checking if the extended key usage extension in205* certificate cert allows use for expectedEKU.206*/207private boolean checkEKU(X509Certificate cert, Set<String> exts,208String expectedEKU) throws CertificateException {209List<String> eku = cert.getExtendedKeyUsage();210if (eku == null) {211return true;212}213return eku.contains(expectedEKU) || eku.contains(OID_EKU_ANY_USAGE);214}215216/**217* Utility method checking if bit 'bit' is set in this certificates218* key usage extension.219* @throws CertificateException if not220*/221private boolean checkKeyUsage(X509Certificate cert, int bit)222throws CertificateException {223boolean[] keyUsage = cert.getKeyUsage();224if (keyUsage == null) {225return true;226}227return (keyUsage.length > bit) && keyUsage[bit];228}229230/**231* Check whether this certificate can be used for TLS client232* authentication.233* @throws CertificateException if not.234*/235private void checkTLSClient(X509Certificate cert, Set<String> exts)236throws CertificateException {237if (checkKeyUsage(cert, KU_SIGNATURE) == false) {238throw new ValidatorException239("KeyUsage does not allow digital signatures",240ValidatorException.T_EE_EXTENSIONS, cert);241}242243if (checkEKU(cert, exts, OID_EKU_TLS_CLIENT) == false) {244throw new ValidatorException("Extended key usage does not "245+ "permit use for TLS client authentication",246ValidatorException.T_EE_EXTENSIONS, cert);247}248249if (!SimpleValidator.getNetscapeCertTypeBit(cert, NSCT_SSL_CLIENT)) {250throw new ValidatorException251("Netscape cert type does not permit use for SSL client",252ValidatorException.T_EE_EXTENSIONS, cert);253}254255// remove extensions we checked256exts.remove(SimpleValidator.OID_KEY_USAGE);257exts.remove(SimpleValidator.OID_EXTENDED_KEY_USAGE);258exts.remove(SimpleValidator.OID_NETSCAPE_CERT_TYPE);259}260261/**262* Check whether this certificate can be used for TLS server authentication263* using the specified authentication type parameter. See X509TrustManager264* specification for details.265* @throws CertificateException if not.266*/267private void checkTLSServer(X509Certificate cert, String parameter,268Set<String> exts) throws CertificateException {269if (KU_SERVER_ENCRYPTION.contains(parameter)) {270if (checkKeyUsage(cert, KU_KEY_ENCIPHERMENT) == false) {271throw new ValidatorException272("KeyUsage does not allow key encipherment",273ValidatorException.T_EE_EXTENSIONS, cert);274}275} else if (KU_SERVER_SIGNATURE.contains(parameter)) {276if (checkKeyUsage(cert, KU_SIGNATURE) == false) {277throw new ValidatorException278("KeyUsage does not allow digital signatures",279ValidatorException.T_EE_EXTENSIONS, cert);280}281} else if (KU_SERVER_KEY_AGREEMENT.contains(parameter)) {282if (checkKeyUsage(cert, KU_KEY_AGREEMENT) == false) {283throw new ValidatorException284("KeyUsage does not allow key agreement",285ValidatorException.T_EE_EXTENSIONS, cert);286}287} else {288throw new CertificateException("Unknown authType: " + parameter);289}290291if (checkEKU(cert, exts, OID_EKU_TLS_SERVER) == false) {292// check for equivalent but now obsolete Server-Gated-Cryptography293// (aka Step-Up, 128 bit) EKU OIDs294if ((checkEKU(cert, exts, OID_EKU_MS_SGC) == false) &&295(checkEKU(cert, exts, OID_EKU_NS_SGC) == false)) {296throw new ValidatorException297("Extended key usage does not permit use for TLS "298+ "server authentication",299ValidatorException.T_EE_EXTENSIONS, cert);300}301}302303if (!SimpleValidator.getNetscapeCertTypeBit(cert, NSCT_SSL_SERVER)) {304throw new ValidatorException305("Netscape cert type does not permit use for SSL server",306ValidatorException.T_EE_EXTENSIONS, cert);307}308309// remove extensions we checked310exts.remove(SimpleValidator.OID_KEY_USAGE);311exts.remove(SimpleValidator.OID_EXTENDED_KEY_USAGE);312exts.remove(SimpleValidator.OID_NETSCAPE_CERT_TYPE);313}314315/**316* Check whether this certificate can be used for code signing.317* @throws CertificateException if not.318*/319private void checkCodeSigning(X509Certificate cert, Set<String> exts)320throws CertificateException {321if (checkKeyUsage(cert, KU_SIGNATURE) == false) {322throw new ValidatorException323("KeyUsage does not allow digital signatures",324ValidatorException.T_EE_EXTENSIONS, cert);325}326327if (checkEKU(cert, exts, OID_EKU_CODE_SIGNING) == false) {328throw new ValidatorException329("Extended key usage does not permit use for code signing",330ValidatorException.T_EE_EXTENSIONS, cert);331}332333// do not check Netscape cert type for JCE code signing checks334// (some certs were issued with incorrect extensions)335if (variant.equals(Validator.VAR_JCE_SIGNING) == false) {336if (!SimpleValidator.getNetscapeCertTypeBit(cert, NSCT_CODE_SIGNING)) {337throw new ValidatorException338("Netscape cert type does not permit use for code signing",339ValidatorException.T_EE_EXTENSIONS, cert);340}341exts.remove(SimpleValidator.OID_NETSCAPE_CERT_TYPE);342}343344// remove extensions we checked345exts.remove(SimpleValidator.OID_KEY_USAGE);346exts.remove(SimpleValidator.OID_EXTENDED_KEY_USAGE);347}348349/**350* Check whether this certificate can be used by a time stamping authority351* server (see RFC 3161, section 2.3).352* @throws CertificateException if not.353*/354private void checkTSAServer(X509Certificate cert, Set<String> exts)355throws CertificateException {356if (checkKeyUsage(cert, KU_SIGNATURE) == false) {357throw new ValidatorException358("KeyUsage does not allow digital signatures",359ValidatorException.T_EE_EXTENSIONS, cert);360}361362if (cert.getExtendedKeyUsage() == null) {363throw new ValidatorException364("Certificate does not contain an extended key usage " +365"extension required for a TSA server",366ValidatorException.T_EE_EXTENSIONS, cert);367}368369if (checkEKU(cert, exts, OID_EKU_TIME_STAMPING) == false) {370throw new ValidatorException371("Extended key usage does not permit use for TSA server",372ValidatorException.T_EE_EXTENSIONS, cert);373}374375// remove extensions we checked376exts.remove(SimpleValidator.OID_KEY_USAGE);377exts.remove(SimpleValidator.OID_EXTENDED_KEY_USAGE);378}379}380381382