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 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