173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root/* 273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. 373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * This code is free software; you can redistribute it and/or modify it 673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * under the terms of the GNU General Public License version 2 only, as 773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * published by the Free Software Foundation. Oracle designates this 873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * particular file as subject to the "Classpath" exception as provided 973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * by Oracle in the LICENSE file that accompanied this code. 1073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 1173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * This code is distributed in the hope that it will be useful, but WITHOUT 1273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * version 2 for more details (a copy is included in the LICENSE file that 1573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * accompanied this code). 1673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 1773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * You should have received a copy of the GNU General Public License version 1873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 2 along with this work; if not, write to the Free Software Foundation, 1973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 2173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * or visit www.oracle.com if you need additional information or have any 2373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * questions. 2473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 2573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 2673405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootpackage sun.security.provider.certpath; 2773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 2873405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport java.util.*; 2973405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport java.security.cert.*; 3073405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport java.security.cert.PKIXReason; 3173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 3273405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport sun.security.util.Debug; 3373405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport static sun.security.x509.PKIXExtensions.*; 3473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 3573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root/** 3673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * KeyChecker is a <code>PKIXCertPathChecker</code> that checks that the 3773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * keyCertSign bit is set in the keyUsage extension in an intermediate CA 3873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * certificate. It also checks whether the final certificate in a 3973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * certification path meets the specified target constraints specified as 4073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * a CertSelector in the PKIXParameters passed to the CertPathValidator. 4173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 4273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @since 1.4 4373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @author Yassir Elley 4473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 4573405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootclass KeyChecker extends PKIXCertPathChecker { 4673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 4773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private static final Debug debug = Debug.getInstance("certpath"); 4873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private final int certPathLen; 4973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private final CertSelector targetConstraints; 5073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private int remainingCerts; 5173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 5273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private Set<String> supportedExts; 5373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 5473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 5573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Creates a KeyChecker. 5673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 5773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @param certPathLen allowable cert path length 5873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @param targetCertSel a CertSelector object specifying the constraints 5973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * on the target certificate 6073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 6173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root KeyChecker(int certPathLen, CertSelector targetCertSel) { 6273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root this.certPathLen = certPathLen; 6373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root this.targetConstraints = targetCertSel; 6473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 6573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 6673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 6773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Initializes the internal state of the checker from parameters 6873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * specified in the constructor 6973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 7073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root @Override 7173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root public void init(boolean forward) throws CertPathValidatorException { 7273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (!forward) { 7373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root remainingCerts = certPathLen; 7473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } else { 7573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root throw new CertPathValidatorException 7673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root ("forward checking not supported"); 7773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 7873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 7973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 8073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root @Override 8173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root public boolean isForwardCheckingSupported() { 8273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return false; 8373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 8473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 8573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root @Override 8673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root public Set<String> getSupportedExtensions() { 8773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (supportedExts == null) { 8873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root supportedExts = new HashSet<String>(3); 8973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root supportedExts.add(KeyUsage_Id.toString()); 9073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root supportedExts.add(ExtendedKeyUsage_Id.toString()); 9173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root supportedExts.add(SubjectAlternativeName_Id.toString()); 9273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root supportedExts = Collections.unmodifiableSet(supportedExts); 9373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 9473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return supportedExts; 9573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 9673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 9773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 9873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Checks that keyUsage and target constraints are satisfied by 9973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * the specified certificate. 10073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 10173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @param cert the Certificate 10273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @param unresolvedCritExts the unresolved critical extensions 10373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @throws CertPathValidatorException if certificate does not verify 10473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 10573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root @Override 10673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root public void check(Certificate cert, Collection<String> unresCritExts) 10773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root throws CertPathValidatorException 10873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root { 10973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root X509Certificate currCert = (X509Certificate)cert; 11073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 11173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root remainingCerts--; 11273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 11373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // if final certificate, check that target constraints are satisfied 11473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (remainingCerts == 0) { 11573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (targetConstraints != null && 11673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root targetConstraints.match(currCert) == false) { 11773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root throw new CertPathValidatorException("target certificate " + 11873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root "constraints check failed"); 11973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 12073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } else { 12173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // otherwise, verify that keyCertSign bit is set in CA certificate 12273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root verifyCAKeyUsage(currCert); 12373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 12473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 12573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // remove the extensions that we have checked 12673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (unresCritExts != null && !unresCritExts.isEmpty()) { 12773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root unresCritExts.remove(KeyUsage_Id.toString()); 12873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root unresCritExts.remove(ExtendedKeyUsage_Id.toString()); 12973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root unresCritExts.remove(SubjectAlternativeName_Id.toString()); 13073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 13173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 13273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 13373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // the index of keyCertSign in the boolean KeyUsage array 13473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private static final int KEY_CERT_SIGN = 5; 13573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 13673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Verifies the key usage extension in a CA cert. 13773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * The key usage extension, if present, must assert the keyCertSign bit. 13873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * The extended key usage extension is not checked (see CR 4776794 for 13973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * more information). 14073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 14173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root static void verifyCAKeyUsage(X509Certificate cert) 14273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root throws CertPathValidatorException { 14373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root String msg = "CA key usage"; 14473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (debug != null) { 14573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root debug.println("KeyChecker.verifyCAKeyUsage() ---checking " + msg 14673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root + "..."); 14773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 14873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 14973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root boolean[] keyUsageBits = cert.getKeyUsage(); 15073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 15173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // getKeyUsage returns null if the KeyUsage extension is not present 15273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // in the certificate - in which case there is nothing to check 15373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (keyUsageBits == null) { 15473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return; 15573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 15673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 15773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // throw an exception if the keyCertSign bit is not set 15873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (!keyUsageBits[KEY_CERT_SIGN]) { 15973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root throw new CertPathValidatorException 16073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root (msg + " check failed: keyCertSign bit is not set", null, 16173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root null, -1, PKIXReason.INVALID_KEY_USAGE); 16273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 16373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 16473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (debug != null) { 16573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root debug.println("KeyChecker.verifyCAKeyUsage() " + msg 16673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root + " verified."); 16773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 16873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 16973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root} 170