• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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