1 /* GENERATED SOURCE. DO NOT MODIFY. */ 2 /* 3 * Copyright (C) 2009 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package com.android.org.conscrypt; 19 20 import java.security.PublicKey; 21 import java.security.cert.TrustAnchor; 22 import java.security.cert.X509Certificate; 23 import java.util.ArrayList; 24 import java.util.Arrays; 25 import java.util.Collection; 26 import java.util.Collections; 27 import java.util.HashMap; 28 import java.util.HashSet; 29 import java.util.List; 30 import java.util.Map; 31 import java.util.Set; 32 import javax.security.auth.x500.X500Principal; 33 34 /** 35 * Indexes {@code TrustAnchor} instances so they can be found in O(1) 36 * time instead of O(N). 37 * @hide This class is not part of the Android public SDK API 38 */ 39 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) 40 @Internal 41 public final class TrustedCertificateIndex { 42 private final Map<X500Principal, List<TrustAnchor>> subjectToTrustAnchors 43 = new HashMap<X500Principal, List<TrustAnchor>>(); 44 45 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) TrustedCertificateIndex()46 public TrustedCertificateIndex() {} 47 TrustedCertificateIndex(Set<TrustAnchor> anchors)48 public TrustedCertificateIndex(Set<TrustAnchor> anchors) { 49 index(anchors); 50 } 51 index(Set<TrustAnchor> anchors)52 private void index(Set<TrustAnchor> anchors) { 53 for (TrustAnchor anchor : anchors) { 54 index(anchor); 55 } 56 } 57 58 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) index(X509Certificate cert)59 public TrustAnchor index(X509Certificate cert) { 60 TrustAnchor anchor = new TrustAnchor(cert, null); 61 index(anchor); 62 return anchor; 63 } 64 index(TrustAnchor anchor)65 public void index(TrustAnchor anchor) { 66 X500Principal subject; 67 X509Certificate cert = anchor.getTrustedCert(); 68 if (cert != null) { 69 subject = cert.getSubjectX500Principal(); 70 } else { 71 subject = anchor.getCA(); 72 } 73 74 synchronized (subjectToTrustAnchors) { 75 List<TrustAnchor> anchors = subjectToTrustAnchors.get(subject); 76 if (anchors == null) { 77 anchors = new ArrayList<TrustAnchor>(1); 78 subjectToTrustAnchors.put(subject, anchors); 79 } else { 80 // Avoid indexing the same certificate multiple times 81 if (cert != null) { 82 for (TrustAnchor entry : anchors) { 83 if (cert.equals(entry.getTrustedCert())) { 84 return; 85 } 86 } 87 } 88 } 89 anchors.add(anchor); 90 } 91 } 92 reset()93 public void reset() { 94 synchronized (subjectToTrustAnchors) { 95 subjectToTrustAnchors.clear(); 96 } 97 } 98 reset(Set<TrustAnchor> anchors)99 public void reset(Set<TrustAnchor> anchors) { 100 synchronized (subjectToTrustAnchors) { 101 reset(); 102 index(anchors); 103 } 104 } 105 106 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) findByIssuerAndSignature(X509Certificate cert)107 public TrustAnchor findByIssuerAndSignature(X509Certificate cert) { 108 X500Principal issuer = cert.getIssuerX500Principal(); 109 synchronized (subjectToTrustAnchors) { 110 List<TrustAnchor> anchors = subjectToTrustAnchors.get(issuer); 111 if (anchors == null) { 112 return null; 113 } 114 115 for (TrustAnchor anchor : anchors) { 116 PublicKey publicKey; 117 try { 118 X509Certificate caCert = anchor.getTrustedCert(); 119 if (caCert != null) { 120 publicKey = caCert.getPublicKey(); 121 } else { 122 publicKey = anchor.getCAPublicKey(); 123 } 124 cert.verify(publicKey); 125 return anchor; 126 } catch (Exception ignored) { 127 // Ignored 128 } 129 } 130 } 131 return null; 132 } 133 134 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) findBySubjectAndPublicKey(X509Certificate cert)135 public TrustAnchor findBySubjectAndPublicKey(X509Certificate cert) { 136 X500Principal subject = cert.getSubjectX500Principal(); 137 synchronized (subjectToTrustAnchors) { 138 List<TrustAnchor> anchors = subjectToTrustAnchors.get(subject); 139 if (anchors == null) { 140 return null; 141 } 142 return findBySubjectAndPublicKey(cert, anchors); 143 } 144 } 145 findBySubjectAndPublicKey(X509Certificate cert, Collection<TrustAnchor> anchors)146 private static TrustAnchor findBySubjectAndPublicKey(X509Certificate cert, 147 Collection<TrustAnchor> anchors) { 148 PublicKey certPublicKey = cert.getPublicKey(); 149 for (TrustAnchor anchor : anchors) { 150 PublicKey caPublicKey; 151 try { 152 X509Certificate caCert = anchor.getTrustedCert(); 153 if (caCert != null) { 154 caPublicKey = caCert.getPublicKey(); 155 } else { 156 caPublicKey = anchor.getCAPublicKey(); 157 } 158 if (caPublicKey.equals(certPublicKey)) { 159 return anchor; 160 } else { 161 // PublicKey.equals is not required to compare keys across providers. Fall back 162 // to checking using the encoded form. 163 if ("X.509".equals(caPublicKey.getFormat()) 164 && "X.509".equals(certPublicKey.getFormat())) { 165 byte[] caPublicKeyEncoded = caPublicKey.getEncoded(); 166 byte[] certPublicKeyEncoded = certPublicKey.getEncoded(); 167 if (certPublicKeyEncoded != null 168 && caPublicKeyEncoded != null 169 && Arrays.equals(caPublicKeyEncoded, certPublicKeyEncoded)) { 170 return anchor; 171 } 172 } 173 } 174 } catch (Exception e) { 175 // can happen with unsupported public key types 176 } 177 } 178 return null; 179 } 180 181 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) findAllByIssuerAndSignature(X509Certificate cert)182 public Set<TrustAnchor> findAllByIssuerAndSignature(X509Certificate cert) { 183 X500Principal issuer = cert.getIssuerX500Principal(); 184 synchronized (subjectToTrustAnchors) { 185 List<TrustAnchor> anchors = subjectToTrustAnchors.get(issuer); 186 if (anchors == null) { 187 return Collections.<TrustAnchor>emptySet(); 188 } 189 190 Set<TrustAnchor> result = new HashSet<TrustAnchor>(); 191 for (TrustAnchor anchor : anchors) { 192 try { 193 PublicKey publicKey; 194 X509Certificate caCert = anchor.getTrustedCert(); 195 if (caCert != null) { 196 publicKey = caCert.getPublicKey(); 197 } else { 198 publicKey = anchor.getCAPublicKey(); 199 } 200 if (publicKey == null) { 201 continue; 202 } 203 cert.verify(publicKey); 204 result.add(anchor); 205 } catch (Exception ignored) { 206 // Ignored 207 } 208 } 209 return result; 210 } 211 } 212 } 213