1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package org.apache.harmony.xnet.provider.jsse; 18 19 import java.security.PublicKey; 20 import java.security.cert.CertPathValidatorException; 21 import java.security.cert.TrustAnchor; 22 import java.security.cert.X509Certificate; 23 import java.util.ArrayList; 24 import java.util.Collection; 25 import java.util.HashMap; 26 import java.util.List; 27 import java.util.Map; 28 import java.util.Set; 29 import javax.security.auth.x500.X500Principal; 30 31 /** 32 * Indexes {@code TrustAnchor} instances so they can be found in O(1) 33 * time instead of O(N). 34 */ 35 public final class TrustedCertificateIndex { 36 37 private final Map<X500Principal, List<TrustAnchor>> subjectToTrustAnchors 38 = new HashMap<X500Principal, List<TrustAnchor>>(); 39 40 public TrustedCertificateIndex() {} 41 42 public TrustedCertificateIndex(Set<TrustAnchor> anchors) { 43 index(anchors); 44 } 45 46 private void index(Set<TrustAnchor> anchors) { 47 for (TrustAnchor anchor : anchors) { 48 index(anchor); 49 } 50 } 51 52 public TrustAnchor index(X509Certificate cert) { 53 TrustAnchor anchor = new TrustAnchor(cert, null); 54 index(anchor); 55 return anchor; 56 } 57 58 public void index(TrustAnchor anchor) { 59 X500Principal subject; 60 X509Certificate cert = anchor.getTrustedCert(); 61 if (cert != null) { 62 subject = cert.getSubjectX500Principal(); 63 } else { 64 subject = anchor.getCA(); 65 } 66 67 synchronized (subjectToTrustAnchors) { 68 List<TrustAnchor> anchors = subjectToTrustAnchors.get(subject); 69 if (anchors == null) { 70 anchors = new ArrayList<TrustAnchor>(1); 71 subjectToTrustAnchors.put(subject, anchors); 72 } 73 anchors.add(anchor); 74 } 75 } 76 77 public void reset() { 78 synchronized (subjectToTrustAnchors) { 79 subjectToTrustAnchors.clear(); 80 } 81 } 82 83 public void reset(Set<TrustAnchor> anchors) { 84 synchronized (subjectToTrustAnchors) { 85 reset(); 86 index(anchors); 87 } 88 } 89 90 public TrustAnchor findByIssuerAndSignature(X509Certificate cert) { 91 X500Principal issuer = cert.getIssuerX500Principal(); 92 synchronized (subjectToTrustAnchors) { 93 List<TrustAnchor> anchors = subjectToTrustAnchors.get(issuer); 94 if (anchors == null) { 95 return null; 96 } 97 98 for (TrustAnchor anchor : anchors) { 99 PublicKey publicKey; 100 try { 101 X509Certificate caCert = anchor.getTrustedCert(); 102 if (caCert != null) { 103 publicKey = caCert.getPublicKey(); 104 } else { 105 publicKey = anchor.getCAPublicKey(); 106 } 107 cert.verify(publicKey); 108 return anchor; 109 } catch (Exception ignored) { 110 } 111 } 112 } 113 return null; 114 } 115 116 public TrustAnchor findBySubjectAndPublicKey(X509Certificate cert) { 117 X500Principal subject = cert.getSubjectX500Principal(); 118 synchronized (subjectToTrustAnchors) { 119 List<TrustAnchor> anchors = subjectToTrustAnchors.get(subject); 120 if (anchors == null) { 121 return null; 122 } 123 return findBySubjectAndPublicKey(cert, anchors); 124 } 125 } 126 127 private static TrustAnchor findBySubjectAndPublicKey(X509Certificate cert, 128 Collection<TrustAnchor> anchors) { 129 PublicKey certPublicKey = cert.getPublicKey(); 130 for (TrustAnchor anchor : anchors) { 131 PublicKey caPublicKey; 132 try { 133 X509Certificate caCert = anchor.getTrustedCert(); 134 if (caCert != null) { 135 caPublicKey = caCert.getPublicKey(); 136 } else { 137 caPublicKey = anchor.getCAPublicKey(); 138 } 139 if (caPublicKey.equals(certPublicKey)) { 140 return anchor; 141 } 142 } catch (Exception e) { 143 // can happen with unsupported public key types 144 } 145 } 146 return null; 147 } 148 } 149