TrustedCertificateIndex.java revision c77290eaef032e5e8952d65e0456b091b6b50804
11f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project/* 21f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project * Copyright (C) 2009 The Android Open Source Project 31f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project * 41f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 51f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project * you may not use this file except in compliance with the License. 61f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project * You may obtain a copy of the License at 71f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project * 81f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 91f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project * 101f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 111f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 121f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project * See the License for the specific language governing permissions and 141f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project * limitations under the License. 151f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project */ 161f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project 171f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Projectpackage org.apache.harmony.xnet.provider.jsse; 186014527c350895383b99ba91d3d009a32b1d22a6Dianne Hackborn 196014527c350895383b99ba91d3d009a32b1d22a6Dianne Hackbornimport java.security.PublicKey; 206014527c350895383b99ba91d3d009a32b1d22a6Dianne Hackbornimport java.security.cert.CertPathValidatorException; 21cc6828c676c0bfabbcbefa27f4be9183352f5feeRomain Guyimport java.security.cert.TrustAnchor; 22491293ef234d093adccf442d76cbd0db12632692svetoslavganovimport java.security.cert.X509Certificate; 23491293ef234d093adccf442d76cbd0db12632692svetoslavganovimport java.util.ArrayList; 24491293ef234d093adccf442d76cbd0db12632692svetoslavganovimport java.util.Collection; 25491293ef234d093adccf442d76cbd0db12632692svetoslavganovimport java.util.HashMap; 264bf7bcf89b459132e743ebbd8df895dc5e129989Dianne Hackbornimport java.util.List; 2746e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brownimport java.util.Map; 28491293ef234d093adccf442d76cbd0db12632692svetoslavganovimport java.util.Set; 29dc8a7f69d7df5f1ca29763995a0d55acf7936fc6Dianne Hackbornimport javax.security.auth.x500.X500Principal; 305d27977f9da482627ceb19317a2cd70467aff046Adam Powell 311f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project/** 32696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell * Indexes {@code TrustAnchor} instances so they can be found in O(1) 33640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell * time instead of O(N). 341f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project */ 351f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Projectpublic final class TrustedCertificateIndex { 36696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell 37640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell private final Map<X500Principal, List<TrustAnchor>> subjectToTrustAnchors 38640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell = new HashMap<X500Principal, List<TrustAnchor>>(); 395d27977f9da482627ceb19317a2cd70467aff046Adam Powell 4089e0645b4157961e8c465eb9c819f965fdb453d8Adam Powell public TrustedCertificateIndex() {} 411f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project 421f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project public TrustedCertificateIndex(Set<TrustAnchor> anchors) { 431f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project index(anchors); 44269248d112e35fe8e9f0d5d11c96dcb2ac1118b0Adam Powell } 451f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project 461f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project private void index(Set<TrustAnchor> anchors) { 471f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project for (TrustAnchor anchor : anchors) { 481f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project index(anchor); 491f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project } 501f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project } 511f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project 521f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project public TrustAnchor index(X509Certificate cert) { 531f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project TrustAnchor anchor = new TrustAnchor(cert, null); 541f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project index(anchor); 551f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project return anchor; 561f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project } 576014527c350895383b99ba91d3d009a32b1d22a6Dianne Hackborn 581f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project public void index(TrustAnchor anchor) { 591f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project X500Principal subject; 601f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project X509Certificate cert = anchor.getTrustedCert(); 6185446e95afa480cee2247bb96795fccc8cf812afAdam Powell if (cert != null) { 626e34636749217654f43221885afb7a29bb5ca96aAdam Powell subject = cert.getSubjectX500Principal(); 631f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project } else { 641e4b9f3936d6f357e89360293e05a0e16d5fa440Dianne Hackborn subject = anchor.getCA(); 651f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project } 661f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project 671f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project synchronized (subjectToTrustAnchors) { 681f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project List<TrustAnchor> anchors = subjectToTrustAnchors.get(subject); 691f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project if (anchors == null) { 701f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project anchors = new ArrayList<TrustAnchor>(1); 71dc8a7f69d7df5f1ca29763995a0d55acf7936fc6Dianne Hackborn subjectToTrustAnchors.put(subject, anchors); 721f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project } 731f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project anchors.add(anchor); 741f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project } 758e552630e72a17d7340f1bebccbc6fd6faef82fbAdam Powell } 761f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project 771f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project public TrustAnchor findByIssuerAndSignature(X509Certificate cert) { 78491293ef234d093adccf442d76cbd0db12632692svetoslavganov X500Principal issuer = cert.getIssuerX500Principal(); 79491293ef234d093adccf442d76cbd0db12632692svetoslavganov synchronized (subjectToTrustAnchors) { 801f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project List<TrustAnchor> anchors = subjectToTrustAnchors.get(issuer); 811f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project if (anchors == null) { 821f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project return null; 831f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project } 8485446e95afa480cee2247bb96795fccc8cf812afAdam Powell 851f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project for (TrustAnchor anchor : anchors) { 861f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project PublicKey publicKey; 871f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project try { 881f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project X509Certificate caCert = anchor.getTrustedCert(); 891f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project if (caCert != null) { 901f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project publicKey = caCert.getPublicKey(); 911f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project } else { 921f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project publicKey = anchor.getCAPublicKey(); 931f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project } 941f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project cert.verify(publicKey); 95491293ef234d093adccf442d76cbd0db12632692svetoslavganov return anchor; 961f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project } catch (Exception ignored) { 971f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project } 981f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project } 991f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project } 1001f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project return null; 1011f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project } 1021f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project 1031f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project public TrustAnchor findBySubjectAndPublicKey(X509Certificate cert) { 1046014527c350895383b99ba91d3d009a32b1d22a6Dianne Hackborn X500Principal subject = cert.getSubjectX500Principal(); 1056014527c350895383b99ba91d3d009a32b1d22a6Dianne Hackborn synchronized (subjectToTrustAnchors) { 1066014527c350895383b99ba91d3d009a32b1d22a6Dianne Hackborn List<TrustAnchor> anchors = subjectToTrustAnchors.get(subject); 1076014527c350895383b99ba91d3d009a32b1d22a6Dianne Hackborn if (anchors == null) { 1081f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project return null; 1091f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project } 1101f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project return findBySubjectAndPublicKey(cert, anchors); 1111f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project } 1121f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project } 1131f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project 1141f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project private static TrustAnchor findBySubjectAndPublicKey(X509Certificate cert, 1151f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project Collection<TrustAnchor> anchors) { 116d76b67c340d1564abf8d14d976fdaf83bf2b3320Dianne Hackborn PublicKey certPublicKey = cert.getPublicKey(); 117dc8a7f69d7df5f1ca29763995a0d55acf7936fc6Dianne Hackborn for (TrustAnchor anchor : anchors) { 1181e4b9f3936d6f357e89360293e05a0e16d5fa440Dianne Hackborn PublicKey caPublicKey; 119a95e4cb62f3642cb190d032dbf7dc40d9ecc6973Dianne Hackborn try { 1201f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project X509Certificate caCert = anchor.getTrustedCert(); 1211f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project if (caCert != null) { 1221f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project caPublicKey = caCert.getPublicKey(); 1231f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project } else { 1241f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project caPublicKey = anchor.getCAPublicKey(); 12533b974393b6fadcefc896ec4a0f9b66724f61e9fAdam Powell } 12633b974393b6fadcefc896ec4a0f9b66724f61e9fAdam Powell if (caPublicKey.equals(certPublicKey)) { 127696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell return anchor; 128696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell } 1291f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project } catch (Exception e) { 1301f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project // can happen with unsupported public key types 1311f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project } 1321f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project } 1331f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project return null; 1341f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project } 1351f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project} 1361f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project