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 sun.security.util.Debug; 2973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 3073405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport java.util.Collections; 3173405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport java.util.List; 3273405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport java.util.Set; 3373405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport java.security.cert.CertPath; 3473405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport java.security.cert.CertPathValidatorException; 3573405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport java.security.cert.PKIXCertPathChecker; 3673405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport java.security.cert.PKIXReason; 3773405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport java.security.cert.X509Certificate; 3873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 3973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root/** 4073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * This class is initialized with a list of <code>PKIXCertPathChecker</code>s 4173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * and is used to verify the certificates in a <code>CertPath</code> by 4273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * feeding each certificate to each <code>PKIXCertPathChecker</code>. 4373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 4473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @since 1.4 4573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @author Yassir Elley 4673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 4773405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootclass PKIXMasterCertPathValidator { 4873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 4973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private static final Debug debug = Debug.getInstance("certpath"); 5073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 5173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 5273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Validates a certification path consisting exclusively of 5373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * <code>X509Certificate</code>s using the specified 5473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * <code>PKIXCertPathChecker</code>s. It is assumed that the 5573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * <code>PKIXCertPathChecker</code>s 5673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * have been initialized with any input parameters they may need. 5773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 5873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @param cpOriginal the original X509 CertPath passed in by the user 5973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @param reversedCertList the reversed X509 CertPath (as a List) 6073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @param certPathCheckers the PKIXCertPathCheckers 6173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @throws CertPathValidatorException if cert path does not validate 6273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 6373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root static void validate(CertPath cpOriginal, 6473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root List<X509Certificate> reversedCertList, 6573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root List<PKIXCertPathChecker> certPathCheckers) 6673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root throws CertPathValidatorException 6773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root { 6873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // we actually process reversedCertList, but we keep cpOriginal because 6973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // we need to return the original certPath when we throw an exception. 7073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // we will also need to modify the index appropriately when we 7173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // throw an exception. 7273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 7373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root int cpSize = reversedCertList.size(); 7473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 7573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (debug != null) { 7673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root debug.println("--------------------------------------------------" 7773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root + "------------"); 7873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root debug.println("Executing PKIX certification path validation " 7973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root + "algorithm."); 8073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 8173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 8273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root for (int i = 0; i < cpSize; i++) { 8373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 8473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /* The basic loop algorithm is that we get the 8573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * current certificate, we verify the current certificate using 8673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * information from the previous certificate and from the state, 8773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * and we modify the state for the next loop by setting the 8873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * current certificate of this loop to be the previous certificate 8973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * of the next loop. The state is initialized during first loop. 9073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 9173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (debug != null) 9273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root debug.println("Checking cert" + (i+1) + " ..."); 9373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 9473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root X509Certificate currCert = reversedCertList.get(i); 9573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root Set<String> unresCritExts = currCert.getCriticalExtensionOIDs(); 9673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (unresCritExts == null) { 9773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root unresCritExts = Collections.<String>emptySet(); 9873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 9973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 10073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (debug != null && !unresCritExts.isEmpty()) { 10173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root debug.println("Set of critical extensions:"); 10273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root for (String oid : unresCritExts) { 10373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root debug.println(oid); 10473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 10573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 10673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 10773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root for (int j = 0; j < certPathCheckers.size(); j++) { 10873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 10973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root PKIXCertPathChecker currChecker = certPathCheckers.get(j); 11073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (debug != null) { 11173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root debug.println("-Using checker" + (j + 1) + " ... [" + 11273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root currChecker.getClass().getName() + "]"); 11373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 11473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 11573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (i == 0) 11673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root currChecker.init(false); 11773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 11873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root try { 11973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root currChecker.check(currCert, unresCritExts); 12073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 12173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (debug != null) { 12273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root debug.println("-checker" + (j + 1) + 12373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root " validation succeeded"); 12473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 12573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 12673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } catch (CertPathValidatorException cpve) { 12773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root throw new CertPathValidatorException(cpve.getMessage(), 12873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root cpve.getCause(), cpOriginal, cpSize - (i + 1), 12973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root cpve.getReason()); 13073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 13173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 13273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 13373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (!unresCritExts.isEmpty()) { 13473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root throw new CertPathValidatorException("unrecognized " + 13573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root "critical extension(s)", null, cpOriginal, cpSize-(i+1), 13673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root PKIXReason.UNRECOGNIZED_CRIT_EXT); 13773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 13873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 13973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (debug != null) 14073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root debug.println("\ncert" + (i+1) + " validation succeeded.\n"); 14173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 14273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 14373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (debug != null) { 14473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root debug.println("Cert path validation succeeded. (PKIX validation " 14573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root + "algorithm)"); 14673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root debug.println("-------------------------------------------------" 14773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root + "-------------"); 14873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 14973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 15073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root} 151