Home | History | Annotate | Download | only in jsse
      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 TrustAnchor findByIssuerAndSignature(X509Certificate cert) {
     78         X500Principal issuer = cert.getIssuerX500Principal();
     79         synchronized (subjectToTrustAnchors) {
     80             List<TrustAnchor> anchors = subjectToTrustAnchors.get(issuer);
     81             if (anchors == null) {
     82                 return null;
     83             }
     84 
     85             for (TrustAnchor anchor : anchors) {
     86                 PublicKey publicKey;
     87                 try {
     88                     X509Certificate caCert = anchor.getTrustedCert();
     89                     if (caCert != null) {
     90                         publicKey = caCert.getPublicKey();
     91                     } else {
     92                         publicKey = anchor.getCAPublicKey();
     93                     }
     94                     cert.verify(publicKey);
     95                     return anchor;
     96                 } catch (Exception ignored) {
     97                 }
     98             }
     99         }
    100         return null;
    101     }
    102 
    103     public TrustAnchor findBySubjectAndPublicKey(X509Certificate cert) {
    104         X500Principal subject = cert.getSubjectX500Principal();
    105         synchronized (subjectToTrustAnchors) {
    106             List<TrustAnchor> anchors = subjectToTrustAnchors.get(subject);
    107             if (anchors == null) {
    108                 return null;
    109             }
    110             return findBySubjectAndPublicKey(cert, anchors);
    111         }
    112     }
    113 
    114     private static TrustAnchor findBySubjectAndPublicKey(X509Certificate cert,
    115                                                          Collection<TrustAnchor> anchors) {
    116         PublicKey certPublicKey = cert.getPublicKey();
    117         for (TrustAnchor anchor : anchors) {
    118             PublicKey caPublicKey;
    119             try {
    120                 X509Certificate caCert = anchor.getTrustedCert();
    121                 if (caCert != null) {
    122                     caPublicKey = caCert.getPublicKey();
    123                 } else {
    124                     caPublicKey = anchor.getCAPublicKey();
    125                 }
    126                 if (caPublicKey.equals(certPublicKey)) {
    127                     return anchor;
    128                 }
    129             } catch (Exception e) {
    130                 // can happen with unsupported public key types
    131             }
    132         }
    133         return null;
    134     }
    135 }
    136