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 17package org.conscrypt; 18 19import java.security.PublicKey; 20import java.security.cert.TrustAnchor; 21import java.security.cert.X509Certificate; 22import java.util.ArrayList; 23import java.util.Collection; 24import java.util.HashMap; 25import java.util.List; 26import java.util.Map; 27import java.util.Set; 28import javax.security.auth.x500.X500Principal; 29 30/** 31 * Indexes {@code TrustAnchor} instances so they can be found in O(1) 32 * time instead of O(N). 33 */ 34public final class TrustedCertificateIndex { 35 36 private final Map<X500Principal, List<TrustAnchor>> subjectToTrustAnchors 37 = new HashMap<X500Principal, List<TrustAnchor>>(); 38 39 public TrustedCertificateIndex() {} 40 41 public TrustedCertificateIndex(Set<TrustAnchor> anchors) { 42 index(anchors); 43 } 44 45 private void index(Set<TrustAnchor> anchors) { 46 for (TrustAnchor anchor : anchors) { 47 index(anchor); 48 } 49 } 50 51 public TrustAnchor index(X509Certificate cert) { 52 TrustAnchor anchor = new TrustAnchor(cert, null); 53 index(anchor); 54 return anchor; 55 } 56 57 public void index(TrustAnchor anchor) { 58 X500Principal subject; 59 X509Certificate cert = anchor.getTrustedCert(); 60 if (cert != null) { 61 subject = cert.getSubjectX500Principal(); 62 } else { 63 subject = anchor.getCA(); 64 } 65 66 synchronized (subjectToTrustAnchors) { 67 List<TrustAnchor> anchors = subjectToTrustAnchors.get(subject); 68 if (anchors == null) { 69 anchors = new ArrayList<TrustAnchor>(1); 70 subjectToTrustAnchors.put(subject, anchors); 71 } 72 anchors.add(anchor); 73 } 74 } 75 76 public void reset() { 77 synchronized (subjectToTrustAnchors) { 78 subjectToTrustAnchors.clear(); 79 } 80 } 81 82 public void reset(Set<TrustAnchor> anchors) { 83 synchronized (subjectToTrustAnchors) { 84 reset(); 85 index(anchors); 86 } 87 } 88 89 public TrustAnchor findByIssuerAndSignature(X509Certificate cert) { 90 X500Principal issuer = cert.getIssuerX500Principal(); 91 synchronized (subjectToTrustAnchors) { 92 List<TrustAnchor> anchors = subjectToTrustAnchors.get(issuer); 93 if (anchors == null) { 94 return null; 95 } 96 97 for (TrustAnchor anchor : anchors) { 98 PublicKey publicKey; 99 try { 100 X509Certificate caCert = anchor.getTrustedCert(); 101 if (caCert != null) { 102 publicKey = caCert.getPublicKey(); 103 } else { 104 publicKey = anchor.getCAPublicKey(); 105 } 106 cert.verify(publicKey); 107 return anchor; 108 } catch (Exception ignored) { 109 } 110 } 111 } 112 return null; 113 } 114 115 public TrustAnchor findBySubjectAndPublicKey(X509Certificate cert) { 116 X500Principal subject = cert.getSubjectX500Principal(); 117 synchronized (subjectToTrustAnchors) { 118 List<TrustAnchor> anchors = subjectToTrustAnchors.get(subject); 119 if (anchors == null) { 120 return null; 121 } 122 return findBySubjectAndPublicKey(cert, anchors); 123 } 124 } 125 126 private static TrustAnchor findBySubjectAndPublicKey(X509Certificate cert, 127 Collection<TrustAnchor> anchors) { 128 PublicKey certPublicKey = cert.getPublicKey(); 129 for (TrustAnchor anchor : anchors) { 130 PublicKey caPublicKey; 131 try { 132 X509Certificate caCert = anchor.getTrustedCert(); 133 if (caCert != null) { 134 caPublicKey = caCert.getPublicKey(); 135 } else { 136 caPublicKey = anchor.getCAPublicKey(); 137 } 138 if (caPublicKey.equals(certPublicKey)) { 139 return anchor; 140 } 141 } catch (Exception e) { 142 // can happen with unsupported public key types 143 } 144 } 145 return null; 146 } 147} 148