173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root/* 273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Copyright (c) 2002, 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 Root 3073405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport java.security.InvalidAlgorithmParameterException; 3173405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport java.security.cert.*; 3273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 3373405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport javax.security.auth.x500.X500Principal; 3473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 3573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root/** 3673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * A <code>CertStore</code> that retrieves <code>Certificates</code> and 3773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * <code>CRL</code>s from a <code>Collection</code>. 3873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * <p> 3973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * This implementation is functionally equivalent to CollectionCertStore 4073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * with two differences: 4173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * <ol> 4273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * <li>Upon construction, the elements in the specified Collection are 4373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * partially indexed. X509Certificates are indexed by subject, X509CRLs 4473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * by issuer, non-X509 Certificates and CRLs are copied without indexing, 4573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * other objects are ignored. This increases CertStore construction time 4673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * but allows significant speedups for searches which specify the indexed 4773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * attributes, in particular for large Collections (reduction from linear 4873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * time to effectively constant time). Searches for non-indexed queries 4973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * are as fast (or marginally faster) than for the standard 5073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * CollectionCertStore. Certificate subjects and CRL issuers 5173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * were found to be specified in most searches used internally by the 5273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * CertPath provider. Additional attributes could indexed if there are 5373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * queries that justify the effort. 5473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 5573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * <li>Changes to the specified Collection after construction time are 5673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * not detected and ignored. This is because there is no way to efficiently 5773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * detect if a Collection has been modified, a full traversal would be 5873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * required. That would degrade lookup performance to linear time and 5973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * eliminated the benefit of indexing. We may fix this via the introduction 6073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * of new public APIs in the future. 6173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * </ol> 6273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * <p> 6373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Before calling the {@link #engineGetCertificates engineGetCertificates} or 6473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * {@link #engineGetCRLs engineGetCRLs} methods, the 6573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * {@link #CollectionCertStore(CertStoreParameters) 6673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * CollectionCertStore(CertStoreParameters)} constructor is called to 6773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * create the <code>CertStore</code> and establish the 6873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * <code>Collection</code> from which <code>Certificate</code>s and 6973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * <code>CRL</code>s will be retrieved. If the specified 7073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * <code>Collection</code> contains an object that is not a 7173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * <code>Certificate</code> or <code>CRL</code>, that object will be 7273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * ignored. 7373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * <p> 7473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * <b>Concurrent Access</b> 7573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * <p> 7673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * As described in the javadoc for <code>CertStoreSpi</code>, the 7773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * <code>engineGetCertificates</code> and <code>engineGetCRLs</code> methods 7873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * must be thread-safe. That is, multiple threads may concurrently 7973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * invoke these methods on a single <code>CollectionCertStore</code> 8073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * object (or more than one) with no ill effects. 8173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * <p> 8273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * This is achieved by requiring that the <code>Collection</code> passed to 8373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * the {@link #CollectionCertStore(CertStoreParameters) 8473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * CollectionCertStore(CertStoreParameters)} constructor (via the 8573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * <code>CollectionCertStoreParameters</code> object) must have fail-fast 8673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * iterators. Simultaneous modifications to the <code>Collection</code> can thus be 8773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * detected and certificate or CRL retrieval can be retried. The fact that 8873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * <code>Certificate</code>s and <code>CRL</code>s must be thread-safe is also 8973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * essential. 9073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 9173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @see java.security.cert.CertStore 9273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @see CollectionCertStore 9373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 9473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @author Andreas Sterbenz 9573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 9673405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootpublic class IndexedCollectionCertStore extends CertStoreSpi { 9773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 9873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 9973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Map X500Principal(subject) -> X509Certificate | List of X509Certificate 10073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 10173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private Map<X500Principal, Object> certSubjects; 10273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 10373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Map X500Principal(issuer) -> X509CRL | List of X509CRL 10473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 10573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private Map<X500Principal, Object> crlIssuers; 10673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 10773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Sets of non-X509 certificates and CRLs 10873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 10973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private Set<Certificate> otherCertificates; 11073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private Set<CRL> otherCRLs; 11173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 11273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 11373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Creates a <code>CertStore</code> with the specified parameters. 11473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * For this class, the parameters object must be an instance of 11573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * <code>CollectionCertStoreParameters</code>. 11673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 11773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @param params the algorithm parameters 11873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @exception InvalidAlgorithmParameterException if params is not an 11973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * instance of <code>CollectionCertStoreParameters</code> 12073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 12173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root public IndexedCollectionCertStore(CertStoreParameters params) 12273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root throws InvalidAlgorithmParameterException { 12373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root super(params); 12473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (!(params instanceof CollectionCertStoreParameters)) { 12573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root throw new InvalidAlgorithmParameterException( 12673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root "parameters must be CollectionCertStoreParameters"); 12773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 12873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root Collection<?> coll = ((CollectionCertStoreParameters)params).getCollection(); 12973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (coll == null) { 13073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root throw new InvalidAlgorithmParameterException 13173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root ("Collection must not be null"); 13273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 13373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root buildIndex(coll); 13473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 13573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 13673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 13773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Index the specified Collection copying all references to Certificates 13873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * and CRLs. 13973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 14073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private void buildIndex(Collection<?> coll) { 14173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root certSubjects = new HashMap<X500Principal, Object>(); 14273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root crlIssuers = new HashMap<X500Principal, Object>(); 14373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root otherCertificates = null; 14473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root otherCRLs = null; 14573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root for (Object obj : coll) { 14673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (obj instanceof X509Certificate) { 14773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root indexCertificate((X509Certificate)obj); 14873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } else if (obj instanceof X509CRL) { 14973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root indexCRL((X509CRL)obj); 15073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } else if (obj instanceof Certificate) { 15173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (otherCertificates == null) { 15273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root otherCertificates = new HashSet<Certificate>(); 15373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 15473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root otherCertificates.add((Certificate)obj); 15573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } else if (obj instanceof CRL) { 15673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (otherCRLs == null) { 15773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root otherCRLs = new HashSet<CRL>(); 15873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 15973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root otherCRLs.add((CRL)obj); 16073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } else { 16173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // ignore 16273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 16373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 16473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (otherCertificates == null) { 16573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root otherCertificates = Collections.<Certificate>emptySet(); 16673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 16773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (otherCRLs == null) { 16873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root otherCRLs = Collections.<CRL>emptySet(); 16973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 17073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 17173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 17273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 17373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Add an X509Certificate to the index. 17473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 17573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private void indexCertificate(X509Certificate cert) { 17673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root X500Principal subject = cert.getSubjectX500Principal(); 17773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root Object oldEntry = certSubjects.put(subject, cert); 17873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (oldEntry != null) { // assume this is unlikely 17973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (oldEntry instanceof X509Certificate) { 18073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (cert.equals(oldEntry)) { 18173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return; 18273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 18373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root List<X509Certificate> list = new ArrayList<>(2); 18473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root list.add(cert); 18573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root list.add((X509Certificate)oldEntry); 18673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root certSubjects.put(subject, list); 18773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } else { 18873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root @SuppressWarnings("unchecked") // See certSubjects javadoc. 18973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root List<X509Certificate> list = (List<X509Certificate>)oldEntry; 19073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (list.contains(cert) == false) { 19173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root list.add(cert); 19273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 19373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root certSubjects.put(subject, list); 19473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 19573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 19673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 19773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 19873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 19973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Add an X509CRL to the index. 20073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 20173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private void indexCRL(X509CRL crl) { 20273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root X500Principal issuer = crl.getIssuerX500Principal(); 20373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root Object oldEntry = crlIssuers.put(issuer, crl); 20473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (oldEntry != null) { // assume this is unlikely 20573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (oldEntry instanceof X509CRL) { 20673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (crl.equals(oldEntry)) { 20773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return; 20873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 20973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root List<X509CRL> list = new ArrayList<>(2); 21073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root list.add(crl); 21173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root list.add((X509CRL)oldEntry); 21273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root crlIssuers.put(issuer, list); 21373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } else { 21473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // See crlIssuers javadoc. 21573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root @SuppressWarnings("unchecked") 21673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root List<X509CRL> list = (List<X509CRL>)oldEntry; 21773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (list.contains(crl) == false) { 21873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root list.add(crl); 21973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 22073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root crlIssuers.put(issuer, list); 22173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 22273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 22373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 22473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 22573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 22673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Returns a <code>Collection</code> of <code>Certificate</code>s that 22773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * match the specified selector. If no <code>Certificate</code>s 22873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * match the selector, an empty <code>Collection</code> will be returned. 22973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 23073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @param selector a <code>CertSelector</code> used to select which 23173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * <code>Certificate</code>s should be returned. Specify <code>null</code> 23273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * to return all <code>Certificate</code>s. 23373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @return a <code>Collection</code> of <code>Certificate</code>s that 23473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * match the specified selector 23573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @throws CertStoreException if an exception occurs 23673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 23773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root @Override 23873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root public Collection<? extends Certificate> engineGetCertificates(CertSelector selector) 23973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root throws CertStoreException { 24073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 24173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // no selector means match all 24273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (selector == null) { 24373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root Set<Certificate> matches = new HashSet<>(); 24473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root matchX509Certs(new X509CertSelector(), matches); 24573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root matches.addAll(otherCertificates); 24673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return matches; 24773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 24873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 24973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (selector instanceof X509CertSelector == false) { 25073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root Set<Certificate> matches = new HashSet<>(); 25173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root matchX509Certs(selector, matches); 25273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root for (Certificate cert : otherCertificates) { 25373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (selector.match(cert)) { 25473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root matches.add(cert); 25573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 25673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 25773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return matches; 25873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 25973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 26073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (certSubjects.isEmpty()) { 26173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return Collections.<X509Certificate>emptySet(); 26273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 26373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root X509CertSelector x509Selector = (X509CertSelector)selector; 26473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // see if the subject is specified 26573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root X500Principal subject; 26673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root X509Certificate matchCert = x509Selector.getCertificate(); 26773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (matchCert != null) { 26873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root subject = matchCert.getSubjectX500Principal(); 26973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } else { 27073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root subject = x509Selector.getSubject(); 27173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 27273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (subject != null) { 27373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // yes, narrow down candidates to indexed possibilities 27473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root Object entry = certSubjects.get(subject); 27573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (entry == null) { 27673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return Collections.<X509Certificate>emptySet(); 27773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 27873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (entry instanceof X509Certificate) { 27973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root X509Certificate x509Entry = (X509Certificate)entry; 28073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (x509Selector.match(x509Entry)) { 28173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return Collections.singleton(x509Entry); 28273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } else { 28373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return Collections.<X509Certificate>emptySet(); 28473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 28573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } else { 28673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // See certSubjects javadoc. 28773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root @SuppressWarnings("unchecked") 28873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root List<X509Certificate> list = (List<X509Certificate>)entry; 28973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root Set<X509Certificate> matches = new HashSet<>(16); 29073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root for (X509Certificate cert : list) { 29173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (x509Selector.match(cert)) { 29273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root matches.add(cert); 29373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 29473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 29573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return matches; 29673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 29773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 29873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // cannot use index, iterate all 29973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root Set<Certificate> matches = new HashSet<>(16); 30073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root matchX509Certs(x509Selector, matches); 30173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return matches; 30273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 30373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 30473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 30573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Iterate through all the X509Certificates and add matches to the 30673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * collection. 30773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 30873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private void matchX509Certs(CertSelector selector, 30973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root Collection<Certificate> matches) { 31073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 31173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root for (Object obj : certSubjects.values()) { 31273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (obj instanceof X509Certificate) { 31373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root X509Certificate cert = (X509Certificate)obj; 31473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (selector.match(cert)) { 31573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root matches.add(cert); 31673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 31773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } else { 31873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // See certSubjects javadoc. 31973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root @SuppressWarnings("unchecked") 32073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root List<X509Certificate> list = (List<X509Certificate>)obj; 32173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root for (X509Certificate cert : list) { 32273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (selector.match(cert)) { 32373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root matches.add(cert); 32473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 32573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 32673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 32773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 32873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 32973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 33073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 33173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Returns a <code>Collection</code> of <code>CRL</code>s that 33273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * match the specified selector. If no <code>CRL</code>s 33373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * match the selector, an empty <code>Collection</code> will be returned. 33473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 33573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @param selector a <code>CRLSelector</code> used to select which 33673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * <code>CRL</code>s should be returned. Specify <code>null</code> 33773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * to return all <code>CRL</code>s. 33873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @return a <code>Collection</code> of <code>CRL</code>s that 33973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * match the specified selector 34073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @throws CertStoreException if an exception occurs 34173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 34273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root @Override 34373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root public Collection<CRL> engineGetCRLs(CRLSelector selector) 34473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root throws CertStoreException { 34573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 34673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (selector == null) { 34773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root Set<CRL> matches = new HashSet<>(); 34873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root matchX509CRLs(new X509CRLSelector(), matches); 34973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root matches.addAll(otherCRLs); 35073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return matches; 35173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 35273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 35373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (selector instanceof X509CRLSelector == false) { 35473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root Set<CRL> matches = new HashSet<>(); 35573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root matchX509CRLs(selector, matches); 35673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root for (CRL crl : otherCRLs) { 35773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (selector.match(crl)) { 35873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root matches.add(crl); 35973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 36073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 36173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return matches; 36273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 36373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 36473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (crlIssuers.isEmpty()) { 36573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return Collections.<CRL>emptySet(); 36673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 36773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root X509CRLSelector x509Selector = (X509CRLSelector)selector; 36873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // see if the issuer is specified 36973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root Collection<X500Principal> issuers = x509Selector.getIssuers(); 37073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (issuers != null) { 37173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root HashSet<CRL> matches = new HashSet<>(16); 37273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root for (X500Principal issuer : issuers) { 37373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root Object entry = crlIssuers.get(issuer); 37473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (entry == null) { 37573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // empty 37673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } else if (entry instanceof X509CRL) { 37773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root X509CRL crl = (X509CRL)entry; 37873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (x509Selector.match(crl)) { 37973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root matches.add(crl); 38073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 38173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } else { // List 38273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // See crlIssuers javadoc. 38373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root @SuppressWarnings("unchecked") 38473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root List<X509CRL> list = (List<X509CRL>)entry; 38573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root for (X509CRL crl : list) { 38673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (x509Selector.match(crl)) { 38773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root matches.add(crl); 38873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 38973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 39073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 39173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 39273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return matches; 39373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 39473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // cannot use index, iterate all 39573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root Set<CRL> matches = new HashSet<>(16); 39673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root matchX509CRLs(x509Selector, matches); 39773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return matches; 39873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 39973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 40073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 40173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Iterate through all the X509CRLs and add matches to the 40273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * collection. 40373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 40473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private void matchX509CRLs(CRLSelector selector, Collection<CRL> matches) { 40573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root for (Object obj : crlIssuers.values()) { 40673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (obj instanceof X509CRL) { 40773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root X509CRL crl = (X509CRL)obj; 40873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (selector.match(crl)) { 40973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root matches.add(crl); 41073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 41173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } else { 41273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // See crlIssuers javadoc. 41373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root @SuppressWarnings("unchecked") 41473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root List<X509CRL> list = (List<X509CRL>)obj; 41573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root for (X509CRL crl : list) { 41673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (selector.match(crl)) { 41773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root matches.add(crl); 41873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 41973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 42073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 42173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 42273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 42373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 42473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root} 425