151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/* 273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. 351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it 651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as 751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation. Oracle designates this 851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided 951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code. 1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT 1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that 1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code). 1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version 1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation, 1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any 2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions. 2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage sun.security.provider.certpath; 2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.IOException; 2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.GeneralSecurityException; 2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.PublicKey; 3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.cert.CertificateEncodingException; 3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.cert.CertificateException; 3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.cert.X509Certificate; 3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.interfaces.DSAPublicKey; 3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport javax.security.auth.x500.X500Principal; 3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.security.util.DerOutputStream; 3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.security.util.DerValue; 3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.security.util.Cache; 4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.security.x509.X509CertImpl; 4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.security.provider.X509Factory; 4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/** 4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This class represents an X.509 Certificate Pair object, which is primarily 4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * used to hold a pair of cross certificates issued between Certification 4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Authorities. The ASN.1 structure is listed below. The forward certificate 4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of the CertificatePair contains a certificate issued to this CA by another 4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * CA. The reverse certificate of the CertificatePair contains a certificate 4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * issued by this CA to another CA. When both the forward and the reverse 5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * certificates are present in the CertificatePair, the issuer name in one 5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * certificate shall match the subject name in the other and vice versa, and 5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the subject public key in one certificate shall be capable of verifying the 5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * digital signature on the other certificate and vice versa. If a subject 5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * public key in one certificate does not contain required key algorithm 5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * parameters, then the signature check involving that key is not done.<p> 5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The ASN.1 syntax for this object is: 5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <pre> 5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * CertificatePair ::= SEQUENCE { 6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * forward [0] Certificate OPTIONAL, 6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * reverse [1] Certificate OPTIONAL 6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * -- at least one of the pair shall be present -- } 6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </pre><p> 6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This structure uses EXPLICIT tagging. References: Annex A of 6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * X.509(2000), X.509(1997). 6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author Sean Mullan 6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.4 7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic class X509CertificatePair { 7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* ASN.1 explicit tags */ 7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final byte TAG_FORWARD = 0; 7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final byte TAG_REVERSE = 1; 7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private X509Certificate forward; 7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private X509Certificate reverse; 8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private byte[] encoded; 8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 8273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private static final Cache<Object, X509CertificatePair> cache 8373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root = Cache.newSoftMemoryCache(750); 8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Creates an empty instance of X509CertificatePair. 8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public X509CertificatePair() {} 8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Creates an instance of X509CertificatePair. At least one of 9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the pair must be non-null. 9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param forward The forward component of the certificate pair 9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * which represents a certificate issued to this CA by other CAs. 9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param reverse The reverse component of the certificate pair 9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * which represents a certificate issued by this CA to other CAs. 9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws CertificateException If an exception occurs. 9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public X509CertificatePair(X509Certificate forward, X509Certificate reverse) 10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws CertificateException { 10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (forward == null && reverse == null) { 10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new CertificateException("at least one of certificate pair " 10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski + "must be non-null"); 10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.forward = forward; 10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.reverse = reverse; 10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski checkPair(); 11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Create a new X509CertificatePair from its encoding. 11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * For internal use only, external code should use generateCertificatePair. 11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 11873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private X509CertificatePair(byte[] encoded) throws CertificateException { 11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski parse(new DerValue(encoded)); 12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.encoded = encoded; 12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (IOException ex) { 12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new CertificateException(ex.toString()); 12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski checkPair(); 12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Clear the cache for debugging. 13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static synchronized void clearCache() { 13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cache.clear(); 13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Create a X509CertificatePair from its encoding. Uses cache lookup 13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * if possible. 13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static synchronized X509CertificatePair generateCertificatePair 14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski (byte[] encoded) throws CertificateException { 14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Object key = new Cache.EqualByteArray(encoded); 14273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root X509CertificatePair pair = cache.get(key); 14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pair != null) { 14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return pair; 14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pair = new X509CertificatePair(encoded); 14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski key = new Cache.EqualByteArray(pair.encoded); 14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cache.put(key, pair); 14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return pair; 15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Sets the forward component of the certificate pair. 15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void setForward(X509Certificate cert) throws CertificateException { 15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski checkPair(); 15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski forward = cert; 15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Sets the reverse component of the certificate pair. 16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void setReverse(X509Certificate cert) throws CertificateException { 16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski checkPair(); 16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski reverse = cert; 16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the forward component of the certificate pair. 17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return The forward certificate, or null if not set. 17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public X509Certificate getForward() { 17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return forward; 17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the reverse component of the certificate pair. 17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return The reverse certificate, or null if not set. 18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public X509Certificate getReverse() { 18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return reverse; 18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return the DER encoded form of the certificate pair. 18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return The encoded form of the certificate pair. 19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws CerticateEncodingException If an encoding exception occurs. 19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public byte[] getEncoded() throws CertificateEncodingException { 19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (encoded == null) { 19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerOutputStream tmp = new DerOutputStream(); 19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski emit(tmp); 19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encoded = tmp.toByteArray(); 19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (IOException ex) { 20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new CertificateEncodingException(ex.toString()); 20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return encoded; 20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return a printable representation of the certificate pair. 20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return A String describing the contents of the pair. 20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 21073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root @Override 21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String toString() { 21273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root StringBuilder sb = new StringBuilder(); 21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append("X.509 Certificate Pair: [\n"); 21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (forward != null) 21573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root sb.append(" Forward: ").append(forward).append("\n"); 21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (reverse != null) 21773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root sb.append(" Reverse: ").append(reverse).append("\n"); 21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append("]"); 21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return sb.toString(); 22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* Parse the encoded bytes */ 22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void parse(DerValue val) 22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException, CertificateException 22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (val.tag != DerValue.tag_Sequence) { 22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException 22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ("Sequence tag missing for X509CertificatePair"); 22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (val.data != null && val.data.available() != 0) { 23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerValue opt = val.data.getDerValue(); 23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski short tag = (byte) (opt.tag & 0x01f); 23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski switch (tag) { 23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case TAG_FORWARD: 23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (opt.isContextSpecific() && opt.isConstructed()) { 23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (forward != null) { 23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Duplicate forward " 23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski + "certificate in X509CertificatePair"); 24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski opt = opt.data.getDerValue(); 24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski forward = X509Factory.intern 24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski (new X509CertImpl(opt.toByteArray())); 24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case TAG_REVERSE: 24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (opt.isContextSpecific() && opt.isConstructed()) { 24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (reverse != null) { 24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Duplicate reverse " 25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski + "certificate in X509CertificatePair"); 25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski opt = opt.data.getDerValue(); 25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski reverse = X509Factory.intern 25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski (new X509CertImpl(opt.toByteArray())); 25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski default: 25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Invalid encoding of " 25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski + "X509CertificatePair"); 26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (forward == null && reverse == null) { 26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new CertificateException("at least one of certificate pair " 26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski + "must be non-null"); 26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* Translate to encoded bytes */ 26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void emit(DerOutputStream out) 27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException, CertificateEncodingException 27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerOutputStream tagged = new DerOutputStream(); 27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (forward != null) { 27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerOutputStream tmp = new DerOutputStream(); 27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tmp.putDerValue(new DerValue(forward.getEncoded())); 27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tagged.write(DerValue.createTag(DerValue.TAG_CONTEXT, 27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski true, TAG_FORWARD), tmp); 27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (reverse != null) { 28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerOutputStream tmp = new DerOutputStream(); 28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tmp.putDerValue(new DerValue(reverse.getEncoded())); 28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tagged.write(DerValue.createTag(DerValue.TAG_CONTEXT, 28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski true, TAG_REVERSE), tmp); 28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski out.write(DerValue.tag_Sequence, tagged); 28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Check for a valid certificate pair 29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void checkPair() throws CertificateException { 29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* if either of pair is missing, return w/o error */ 29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (forward == null || reverse == null) { 29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return; 29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If both elements of the pair are present, check that they 30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * are a valid pair. 30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski X500Principal fwSubject = forward.getSubjectX500Principal(); 30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski X500Principal fwIssuer = forward.getIssuerX500Principal(); 30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski X500Principal rvSubject = reverse.getSubjectX500Principal(); 30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski X500Principal rvIssuer = reverse.getIssuerX500Principal(); 30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!fwIssuer.equals(rvSubject) || !rvIssuer.equals(fwSubject)) { 30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new CertificateException("subject and issuer names in " 31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski + "forward and reverse certificates do not match"); 31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* check signatures unless key parameters are missing */ 31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski PublicKey pk = reverse.getPublicKey(); 31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!(pk instanceof DSAPublicKey) || 31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ((DSAPublicKey)pk).getParams() != null) { 31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski forward.verify(pk); 31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pk = forward.getPublicKey(); 32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!(pk instanceof DSAPublicKey) || 32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ((DSAPublicKey)pk).getParams() != null) { 32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski reverse.verify(pk); 32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (GeneralSecurityException e) { 32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new CertificateException("invalid signature: " 32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski + e.getMessage()); 32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski} 331