1 /*
   2  * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.security.x509;
  27 
  28 import java.io.BufferedReader;
  29 import java.io.BufferedInputStream;
  30 import java.io.ByteArrayOutputStream;
  31 import java.io.IOException;
  32 import java.io.InputStream;
  33 import java.io.InputStreamReader;
  34 import java.io.OutputStream;
  35 import java.math.BigInteger;
  36 import java.security.*;
  37 import java.security.spec.AlgorithmParameterSpec;
  38 import java.security.cert.*;
  39 import java.security.cert.Certificate;
  40 import java.util.*;
  41 import java.util.concurrent.ConcurrentHashMap;
  42 
  43 import javax.security.auth.x500.X500Principal;
  44 
  45 import sun.security.util.*;
  46 import sun.security.provider.X509Factory;
  47 
  48 /**
  49  * The X509CertImpl class represents an X.509 certificate. These certificates
  50  * are widely used to support authentication and other functionality in
  51  * Internet security systems.  Common applications include Privacy Enhanced
  52  * Mail (PEM), Transport Layer Security (SSL), code signing for trusted
  53  * software distribution, and Secure Electronic Transactions (SET).  There
  54  * is a commercial infrastructure ready to manage large scale deployments
  55  * of X.509 identity certificates.
  56  *
  57  * <P>These certificates are managed and vouched for by <em>Certificate
  58  * Authorities</em> (CAs).  CAs are services which create certificates by
  59  * placing data in the X.509 standard format and then digitally signing
  60  * that data.  Such signatures are quite difficult to forge.  CAs act as
  61  * trusted third parties, making introductions between agents who have no
  62  * direct knowledge of each other.  CA certificates are either signed by
  63  * themselves, or by some other CA such as a "root" CA.
  64  *
  65  * <P>RFC 1422 is very informative, though it does not describe much
  66  * of the recent work being done with X.509 certificates.  That includes
  67  * a 1996 version (X.509v3) and a variety of enhancements being made to
  68  * facilitate an explosion of personal certificates used as "Internet
  69  * Drivers' Licences", or with SET for credit card transactions.
  70  *
  71  * <P>More recent work includes the IETF PKIX Working Group efforts,
  72  * especially RFC2459.
  73  *
  74  * @author Dave Brownell
  75  * @author Amit Kapoor
  76  * @author Hemma Prafullchandra
  77  * @see X509CertInfo
  78  */
  79 public class X509CertImpl extends X509Certificate implements DerEncoder {
  80 
  81     private static final long serialVersionUID = -3457612960190864406L;
  82 
  83     private static final char DOT = '.';
  84     /**
  85      * Public attribute names.
  86      */
  87     public static final String NAME = "x509";
  88     public static final String INFO = X509CertInfo.NAME;
  89     public static final String ALG_ID = "algorithm";
  90     public static final String SIGNATURE = "signature";
  91     public static final String SIGNED_CERT = "signed_cert";
  92 
  93     /**
  94      * The following are defined for ease-of-use. These
  95      * are the most frequently retrieved attributes.
  96      */
  97     // x509.info.subject.dname
  98     public static final String SUBJECT_DN = NAME + DOT + INFO + DOT +
  99                                X509CertInfo.SUBJECT + DOT + X509CertInfo.DN_NAME;
 100     // x509.info.issuer.dname
 101     public static final String ISSUER_DN = NAME + DOT + INFO + DOT +
 102                                X509CertInfo.ISSUER + DOT + X509CertInfo.DN_NAME;
 103     // x509.info.serialNumber.number
 104     public static final String SERIAL_ID = NAME + DOT + INFO + DOT +
 105                                X509CertInfo.SERIAL_NUMBER + DOT +
 106                                CertificateSerialNumber.NUMBER;
 107     // x509.info.key.value
 108     public static final String PUBLIC_KEY = NAME + DOT + INFO + DOT +
 109                                X509CertInfo.KEY + DOT +
 110                                CertificateX509Key.KEY;
 111 
 112     // x509.info.version.value
 113     public static final String VERSION = NAME + DOT + INFO + DOT +
 114                                X509CertInfo.VERSION + DOT +
 115                                CertificateVersion.VERSION;
 116 
 117     // x509.algorithm
 118     public static final String SIG_ALG = NAME + DOT + ALG_ID;
 119 
 120     // x509.signature
 121     public static final String SIG = NAME + DOT + SIGNATURE;
 122 
 123     // when we sign and decode we set this to true
 124     // this is our means to make certificates immutable
 125     private boolean readOnly = false;
 126 
 127     // Certificate data, and its envelope
 128     private byte[]              signedCert = null;
 129     protected X509CertInfo      info = null;
 130     protected AlgorithmId       algId = null;
 131     protected byte[]            signature = null;
 132 
 133     // recognized extension OIDS
 134     private static final String KEY_USAGE_OID = "2.5.29.15";
 135     private static final String EXTENDED_KEY_USAGE_OID = "2.5.29.37";
 136     private static final String BASIC_CONSTRAINT_OID = "2.5.29.19";
 137     private static final String SUBJECT_ALT_NAME_OID = "2.5.29.17";
 138     private static final String ISSUER_ALT_NAME_OID = "2.5.29.18";
 139     private static final String AUTH_INFO_ACCESS_OID = "1.3.6.1.5.5.7.1.1";
 140 
 141     // number of standard key usage bits.
 142     private static final int NUM_STANDARD_KEY_USAGE = 9;
 143 
 144     // SubjectAlterntativeNames cache
 145     private Collection<List<?>> subjectAlternativeNames;
 146 
 147     // IssuerAlternativeNames cache
 148     private Collection<List<?>> issuerAlternativeNames;
 149 
 150     // ExtendedKeyUsage cache
 151     private List<String> extKeyUsage;
 152 
 153     // AuthorityInformationAccess cache
 154     private Set<AccessDescription> authInfoAccess;
 155 
 156     /**
 157      * PublicKey that has previously been used to verify
 158      * the signature of this certificate. Null if the certificate has not
 159      * yet been verified.
 160      */
 161     private PublicKey verifiedPublicKey;
 162     /**
 163      * If verifiedPublicKey is not null, name of the provider used to
 164      * successfully verify the signature of this certificate, or the
 165      * empty String if no provider was explicitly specified.
 166      */
 167     private String verifiedProvider;
 168     /**
 169      * If verifiedPublicKey is not null, result of the verification using
 170      * verifiedPublicKey and verifiedProvider. If true, verification was
 171      * successful, if false, it failed.
 172      */
 173     private boolean verificationResult;
 174 
 175     /**
 176      * Default constructor.
 177      */
 178     public X509CertImpl() { }
 179 
 180     /**
 181      * Unmarshals a certificate from its encoded form, parsing the
 182      * encoded bytes.  This form of constructor is used by agents which
 183      * need to examine and use certificate contents.  That is, this is
 184      * one of the more commonly used constructors.  Note that the buffer
 185      * must include only a certificate, and no "garbage" may be left at
 186      * the end.  If you need to ignore data at the end of a certificate,
 187      * use another constructor.
 188      *
 189      * @param certData the encoded bytes, with no trailing padding.
 190      * @exception CertificateException on parsing and initialization errors.
 191      */
 192     public X509CertImpl(byte[] certData) throws CertificateException {
 193         try {
 194             parse(new DerValue(certData));
 195         } catch (IOException e) {
 196             signedCert = null;
 197             throw new CertificateException("Unable to initialize, " + e, e);
 198         }
 199     }
 200 
 201     /**
 202      * unmarshals an X.509 certificate from an input stream.  If the
 203      * certificate is RFC1421 hex-encoded, then it must begin with
 204      * the line X509Factory.BEGIN_CERT and end with the line
 205      * X509Factory.END_CERT.
 206      *
 207      * @param in an input stream holding at least one certificate that may
 208      *        be either DER-encoded or RFC1421 hex-encoded version of the
 209      *        DER-encoded certificate.
 210      * @exception CertificateException on parsing and initialization errors.
 211      */
 212     public X509CertImpl(InputStream in) throws CertificateException {
 213 
 214         DerValue der = null;
 215 
 216         BufferedInputStream inBuffered = new BufferedInputStream(in);
 217 
 218         // First try reading stream as HEX-encoded DER-encoded bytes,
 219         // since not mistakable for raw DER
 220         try {
 221             inBuffered.mark(Integer.MAX_VALUE);
 222             der = readRFC1421Cert(inBuffered);
 223         } catch (IOException ioe) {
 224             try {
 225                 // Next, try reading stream as raw DER-encoded bytes
 226                 inBuffered.reset();
 227                 der = new DerValue(inBuffered);
 228             } catch (IOException ioe1) {
 229                 throw new CertificateException("Input stream must be " +
 230                                                "either DER-encoded bytes " +
 231                                                "or RFC1421 hex-encoded " +
 232                                                "DER-encoded bytes: " +
 233                                                ioe1.getMessage(), ioe1);
 234             }
 235         }
 236         try {
 237             parse(der);
 238         } catch (IOException ioe) {
 239             signedCert = null;
 240             throw new CertificateException("Unable to parse DER value of " +
 241                                            "certificate, " + ioe, ioe);
 242         }
 243     }
 244 
 245     /**
 246      * read input stream as HEX-encoded DER-encoded bytes
 247      *
 248      * @param in InputStream to read
 249      * @return DerValue corresponding to decoded HEX-encoded bytes
 250      * @throws IOException if stream can not be interpreted as RFC1421
 251      *                     encoded bytes
 252      */
 253     private DerValue readRFC1421Cert(InputStream in) throws IOException {
 254         DerValue der = null;
 255         String line = null;
 256         BufferedReader certBufferedReader =
 257             new BufferedReader(new InputStreamReader(in, "ASCII"));
 258         try {
 259             line = certBufferedReader.readLine();
 260         } catch (IOException ioe1) {
 261             throw new IOException("Unable to read InputStream: " +
 262                                   ioe1.getMessage());
 263         }
 264         if (line.equals(X509Factory.BEGIN_CERT)) {
 265             /* stream appears to be hex-encoded bytes */
 266             ByteArrayOutputStream decstream = new ByteArrayOutputStream();
 267             try {
 268                 while ((line = certBufferedReader.readLine()) != null) {
 269                     if (line.equals(X509Factory.END_CERT)) {
 270                         der = new DerValue(decstream.toByteArray());
 271                         break;
 272                     } else {
 273                         decstream.write(Pem.decode(line));
 274                     }
 275                 }
 276             } catch (IOException ioe2) {
 277                 throw new IOException("Unable to read InputStream: "
 278                                       + ioe2.getMessage());
 279             }
 280         } else {
 281             throw new IOException("InputStream is not RFC1421 hex-encoded " +
 282                                   "DER bytes");
 283         }
 284         return der;
 285     }
 286 
 287     /**
 288      * Construct an initialized X509 Certificate. The certificate is stored
 289      * in raw form and has to be signed to be useful.
 290      *
 291      * @param certInfo the X509CertificateInfo which the Certificate is to be
 292      *             created from.
 293      */
 294     public X509CertImpl(X509CertInfo certInfo) {
 295         this.info = certInfo;
 296     }
 297 
 298     /**
 299      * Unmarshal a certificate from its encoded form, parsing a DER value.
 300      * This form of constructor is used by agents which need to examine
 301      * and use certificate contents.
 302      *
 303      * @param derVal the der value containing the encoded cert.
 304      * @exception CertificateException on parsing and initialization errors.
 305      */
 306     public X509CertImpl(DerValue derVal) throws CertificateException {
 307         try {
 308             parse(derVal);
 309         } catch (IOException e) {
 310             signedCert = null;
 311             throw new CertificateException("Unable to initialize, " + e, e);
 312         }
 313     }
 314 
 315     /**
 316      * Appends the certificate to an output stream.
 317      *
 318      * @param out an input stream to which the certificate is appended.
 319      * @exception CertificateEncodingException on encoding errors.
 320      */
 321     public void encode(OutputStream out)
 322     throws CertificateEncodingException {
 323         if (signedCert == null)
 324             throw new CertificateEncodingException(
 325                           "Null certificate to encode");
 326         try {
 327             out.write(signedCert.clone());
 328         } catch (IOException e) {
 329             throw new CertificateEncodingException(e.toString());
 330         }
 331     }
 332 
 333     /**
 334      * DER encode this object onto an output stream.
 335      * Implements the <code>DerEncoder</code> interface.
 336      *
 337      * @param out the output stream on which to write the DER encoding.
 338      *
 339      * @exception IOException on encoding error.
 340      */
 341     public void derEncode(OutputStream out) throws IOException {
 342         if (signedCert == null)
 343             throw new IOException("Null certificate to encode");
 344         out.write(signedCert.clone());
 345     }
 346 
 347     /**
 348      * Returns the encoded form of this certificate. It is
 349      * assumed that each certificate type would have only a single
 350      * form of encoding; for example, X.509 certificates would
 351      * be encoded as ASN.1 DER.
 352      *
 353      * @exception CertificateEncodingException if an encoding error occurs.
 354      */
 355     public byte[] getEncoded() throws CertificateEncodingException {
 356         return getEncodedInternal().clone();
 357     }
 358 
 359     /**
 360      * Returned the encoding as an uncloned byte array. Callers must
 361      * guarantee that they neither modify it nor expose it to untrusted
 362      * code.
 363      */
 364     public byte[] getEncodedInternal() throws CertificateEncodingException {
 365         if (signedCert == null) {
 366             throw new CertificateEncodingException(
 367                           "Null certificate to encode");
 368         }
 369         return signedCert;
 370     }
 371 
 372     /**
 373      * Throws an exception if the certificate was not signed using the
 374      * verification key provided.  Successfully verifying a certificate
 375      * does <em>not</em> indicate that one should trust the entity which
 376      * it represents.
 377      *
 378      * @param key the public key used for verification.
 379      *
 380      * @exception InvalidKeyException on incorrect key.
 381      * @exception NoSuchAlgorithmException on unsupported signature
 382      * algorithms.
 383      * @exception NoSuchProviderException if there's no default provider.
 384      * @exception SignatureException on signature errors.
 385      * @exception CertificateException on encoding errors.
 386      */
 387     public void verify(PublicKey key)
 388     throws CertificateException, NoSuchAlgorithmException,
 389         InvalidKeyException, NoSuchProviderException, SignatureException {
 390         verify(key, "");
 391     }
 392 
 393     /**
 394      * Throws an exception if the certificate was not signed using the
 395      * verification key provided.  Successfully verifying a certificate
 396      * does <em>not</em> indicate that one should trust the entity which
 397      * it represents.
 398      *
 399      * @param key the public key used for verification.
 400      * @param sigProvider the name of the provider.
 401      *
 402      * @exception NoSuchAlgorithmException on unsupported signature
 403      * algorithms.
 404      * @exception InvalidKeyException on incorrect key.
 405      * @exception NoSuchProviderException on incorrect provider.
 406      * @exception SignatureException on signature errors.
 407      * @exception CertificateException on encoding errors.
 408      */
 409     public synchronized void verify(PublicKey key, String sigProvider)
 410             throws CertificateException, NoSuchAlgorithmException,
 411             InvalidKeyException, NoSuchProviderException, SignatureException {
 412         if (sigProvider == null) {
 413             sigProvider = "";
 414         }
 415         if ((verifiedPublicKey != null) && verifiedPublicKey.equals(key)) {
 416             // this certificate has already been verified using
 417             // this public key. Make sure providers match, too.
 418             if (sigProvider.equals(verifiedProvider)) {
 419                 if (verificationResult) {
 420                     return;
 421                 } else {
 422                     throw new SignatureException("Signature does not match.");
 423                 }
 424             }
 425         }
 426         if (signedCert == null) {
 427             throw new CertificateEncodingException("Uninitialized certificate");
 428         }
 429         // Verify the signature ...
 430         Signature sigVerf = null;
 431         if (sigProvider.isEmpty()) {
 432             sigVerf = Signature.getInstance(algId.getName());
 433         } else {
 434             sigVerf = Signature.getInstance(algId.getName(), sigProvider);
 435         }
 436 
 437         sigVerf.initVerify(key);
 438 
 439         // set parameters after Signature.initSign/initVerify call,
 440         // so the deferred provider selection happens when key is set
 441         try {
 442             SignatureUtil.specialSetParameter(sigVerf, getSigAlgParams());
 443         } catch (ProviderException e) {
 444             throw new CertificateException(e.getMessage(), e.getCause());
 445         } catch (InvalidAlgorithmParameterException e) {
 446             throw new CertificateException(e);
 447         }
 448 
 449         byte[] rawCert = info.getEncodedInfo();
 450         sigVerf.update(rawCert, 0, rawCert.length);
 451 
 452         // verify may throw SignatureException for invalid encodings, etc.
 453         verificationResult = sigVerf.verify(signature);
 454         verifiedPublicKey = key;
 455         verifiedProvider = sigProvider;
 456 
 457         if (verificationResult == false) {
 458             throw new SignatureException("Signature does not match.");
 459         }
 460     }
 461 
 462     /**
 463      * Throws an exception if the certificate was not signed using the
 464      * verification key provided.  This method uses the signature verification
 465      * engine supplied by the specified provider. Note that the specified
 466      * Provider object does not have to be registered in the provider list.
 467      * Successfully verifying a certificate does <em>not</em> indicate that one
 468      * should trust the entity which it represents.
 469      *
 470      * @param key the public key used for verification.
 471      * @param sigProvider the provider.
 472      *
 473      * @exception NoSuchAlgorithmException on unsupported signature
 474      * algorithms.
 475      * @exception InvalidKeyException on incorrect key.
 476      * @exception SignatureException on signature errors.
 477      * @exception CertificateException on encoding errors.
 478      */
 479     public synchronized void verify(PublicKey key, Provider sigProvider)
 480             throws CertificateException, NoSuchAlgorithmException,
 481             InvalidKeyException, SignatureException {
 482         if (signedCert == null) {
 483             throw new CertificateEncodingException("Uninitialized certificate");
 484         }
 485         // Verify the signature ...
 486         Signature sigVerf = null;
 487         if (sigProvider == null) {
 488             sigVerf = Signature.getInstance(algId.getName());
 489         } else {
 490             sigVerf = Signature.getInstance(algId.getName(), sigProvider);
 491         }
 492 
 493         sigVerf.initVerify(key);
 494 
 495         // set parameters after Signature.initSign/initVerify call,
 496         // so the deferred provider selection happens when key is set
 497         try {
 498             SignatureUtil.specialSetParameter(sigVerf, getSigAlgParams());
 499         } catch (ProviderException e) {
 500             throw new CertificateException(e.getMessage(), e.getCause());
 501         } catch (InvalidAlgorithmParameterException e) {
 502             throw new CertificateException(e);
 503         }
 504 
 505         byte[] rawCert = info.getEncodedInfo();
 506         sigVerf.update(rawCert, 0, rawCert.length);
 507 
 508         // verify may throw SignatureException for invalid encodings, etc.
 509         verificationResult = sigVerf.verify(signature);
 510         verifiedPublicKey = key;
 511 
 512         if (verificationResult == false) {
 513             throw new SignatureException("Signature does not match.");
 514         }
 515     }
 516 
 517     /**
 518      * Creates an X.509 certificate, and signs it using the given key
 519      * (associating a signature algorithm and an X.500 name).
 520      * This operation is used to implement the certificate generation
 521      * functionality of a certificate authority.
 522      *
 523      * @param key the private key used for signing.
 524      * @param algorithm the name of the signature algorithm used.
 525      *
 526      * @exception InvalidKeyException on incorrect key.
 527      * @exception NoSuchAlgorithmException on unsupported signature
 528      * algorithms.
 529      * @exception NoSuchProviderException if there's no default provider.
 530      * @exception SignatureException on signature errors.
 531      * @exception CertificateException on encoding errors.
 532      */
 533     public void sign(PrivateKey key, String algorithm)
 534     throws CertificateException, NoSuchAlgorithmException,
 535         InvalidKeyException, NoSuchProviderException, SignatureException {
 536         sign(key, algorithm, null);
 537     }
 538 
 539     /**
 540      * Creates an X.509 certificate, and signs it using the given key
 541      * (associating a signature algorithm and an X.500 name).
 542      * This operation is used to implement the certificate generation
 543      * functionality of a certificate authority.
 544      *
 545      * @param key the private key used for signing.
 546      * @param algorithm the name of the signature algorithm used.
 547      * @param provider the name of the provider.
 548      *
 549      * @exception NoSuchAlgorithmException on unsupported signature
 550      * algorithms.
 551      * @exception InvalidKeyException on incorrect key.
 552      * @exception NoSuchProviderException on incorrect provider.
 553      * @exception SignatureException on signature errors.
 554      * @exception CertificateException on encoding errors.
 555      */
 556     public void sign(PrivateKey key, String algorithm, String provider)
 557     throws CertificateException, NoSuchAlgorithmException,
 558         InvalidKeyException, NoSuchProviderException, SignatureException {
 559         try {
 560             sign(key, null, algorithm, provider);
 561         } catch (InvalidAlgorithmParameterException e) {
 562             // should not happen; re-throw just in case
 563             throw new SignatureException(e);
 564         }
 565     }
 566 
 567     /**
 568      * Creates an X.509 certificate, and signs it using the given key
 569      * (associating a signature algorithm and an X.500 name), signature
 570      * parameters, and security provider. If the given provider name
 571      * is null or empty, the implementation look up will be based on
 572      * provider configurations.
 573      * This operation is used to implement the certificate generation
 574      * functionality of a certificate authority.
 575      *
 576      * @param key the private key used for signing
 577      * @param signingParams the parameters used for signing
 578      * @param algorithm the name of the signature algorithm used
 579      * @param provider the name of the provider, may be null
 580      *
 581      * @exception NoSuchAlgorithmException on unsupported signature
 582      *            algorithms
 583      * @exception InvalidKeyException on incorrect key
 584      * @exception InvalidAlgorithmParameterException on invalid signature
 585      *            parameters
 586      * @exception NoSuchProviderException on incorrect provider
 587      * @exception SignatureException on signature errors
 588      * @exception CertificateException on encoding errors
 589      */
 590     public void sign(PrivateKey key, AlgorithmParameterSpec signingParams,
 591             String algorithm, String provider)
 592             throws CertificateException, NoSuchAlgorithmException,
 593             InvalidKeyException, InvalidAlgorithmParameterException,
 594             NoSuchProviderException, SignatureException {
 595         try {
 596             if (readOnly)
 597                 throw new CertificateEncodingException(
 598                               "cannot over-write existing certificate");
 599             Signature sigEngine = null;
 600             if (provider == null || provider.isEmpty())
 601                 sigEngine = Signature.getInstance(algorithm);
 602             else
 603                 sigEngine = Signature.getInstance(algorithm, provider);
 604 
 605             sigEngine.initSign(key);
 606 
 607             if (signingParams != null) {
 608                 // set parameters after Signature.initSign/initVerify call, so
 609                 // the deferred provider selection happens when the key is set
 610                 sigEngine.setParameter(signingParams);
 611             }
 612 
 613             // in case the name is reset
 614             if (signingParams != null) {
 615                 algId = AlgorithmId.get(sigEngine.getParameters());
 616             } else {
 617                 algId = AlgorithmId.get(algorithm);
 618             }
 619             DerOutputStream out = new DerOutputStream();
 620             DerOutputStream tmp = new DerOutputStream();
 621 
 622             // encode certificate info
 623             info.encode(tmp);
 624             byte[] rawCert = tmp.toByteArray();
 625 
 626             // encode algorithm identifier
 627             algId.encode(tmp);
 628 
 629             // Create and encode the signature itself.
 630             sigEngine.update(rawCert, 0, rawCert.length);
 631             signature = sigEngine.sign();
 632             tmp.putBitString(signature);
 633 
 634             // Wrap the signed data in a SEQUENCE { data, algorithm, sig }
 635             out.write(DerValue.tag_Sequence, tmp);
 636             signedCert = out.toByteArray();
 637             readOnly = true;
 638 
 639         } catch (IOException e) {
 640             throw new CertificateEncodingException(e.toString());
 641       }
 642     }
 643 
 644     /**
 645      * Checks that the certificate is currently valid, i.e. the current
 646      * time is within the specified validity period.
 647      *
 648      * @exception CertificateExpiredException if the certificate has expired.
 649      * @exception CertificateNotYetValidException if the certificate is not
 650      * yet valid.
 651      */
 652     public void checkValidity()
 653     throws CertificateExpiredException, CertificateNotYetValidException {
 654         Date date = new Date();
 655         checkValidity(date);
 656     }
 657 
 658     /**
 659      * Checks that the specified date is within the certificate's
 660      * validity period, or basically if the certificate would be
 661      * valid at the specified date/time.
 662      *
 663      * @param date the Date to check against to see if this certificate
 664      *        is valid at that date/time.
 665      *
 666      * @exception CertificateExpiredException if the certificate has expired
 667      * with respect to the <code>date</code> supplied.
 668      * @exception CertificateNotYetValidException if the certificate is not
 669      * yet valid with respect to the <code>date</code> supplied.
 670      */
 671     public void checkValidity(Date date)
 672     throws CertificateExpiredException, CertificateNotYetValidException {
 673 
 674         CertificateValidity interval = null;
 675         try {
 676             interval = (CertificateValidity)info.get(CertificateValidity.NAME);
 677         } catch (Exception e) {
 678             throw new CertificateNotYetValidException("Incorrect validity period");
 679         }
 680         if (interval == null)
 681             throw new CertificateNotYetValidException("Null validity period");
 682         interval.valid(date);
 683     }
 684 
 685     /**
 686      * Return the requested attribute from the certificate.
 687      *
 688      * Note that the X509CertInfo is not cloned for performance reasons.
 689      * Callers must ensure that they do not modify it. All other
 690      * attributes are cloned.
 691      *
 692      * @param name the name of the attribute.
 693      * @exception CertificateParsingException on invalid attribute identifier.
 694      */
 695     public Object get(String name)
 696     throws CertificateParsingException {
 697         X509AttributeName attr = new X509AttributeName(name);
 698         String id = attr.getPrefix();
 699         if (!(id.equalsIgnoreCase(NAME))) {
 700             throw new CertificateParsingException("Invalid root of "
 701                           + "attribute name, expected [" + NAME +
 702                           "], received " + "[" + id + "]");
 703         }
 704         attr = new X509AttributeName(attr.getSuffix());
 705         id = attr.getPrefix();
 706 
 707         if (id.equalsIgnoreCase(INFO)) {
 708             if (info == null) {
 709                 return null;
 710             }
 711             if (attr.getSuffix() != null) {
 712                 try {
 713                     return info.get(attr.getSuffix());
 714                 } catch (IOException e) {
 715                     throw new CertificateParsingException(e.toString());
 716                 } catch (CertificateException e) {
 717                     throw new CertificateParsingException(e.toString());
 718                 }
 719             } else {
 720                 return info;
 721             }
 722         } else if (id.equalsIgnoreCase(ALG_ID)) {
 723             return(algId);
 724         } else if (id.equalsIgnoreCase(SIGNATURE)) {
 725             if (signature != null)
 726                 return signature.clone();
 727             else
 728                 return null;
 729         } else if (id.equalsIgnoreCase(SIGNED_CERT)) {
 730             if (signedCert != null)
 731                 return signedCert.clone();
 732             else
 733                 return null;
 734         } else {
 735             throw new CertificateParsingException("Attribute name not "
 736                  + "recognized or get() not allowed for the same: " + id);
 737         }
 738     }
 739 
 740     /**
 741      * Set the requested attribute in the certificate.
 742      *
 743      * @param name the name of the attribute.
 744      * @param obj the value of the attribute.
 745      * @exception CertificateException on invalid attribute identifier.
 746      * @exception IOException on encoding error of attribute.
 747      */
 748     public void set(String name, Object obj)
 749     throws CertificateException, IOException {
 750         // check if immutable
 751         if (readOnly)
 752             throw new CertificateException("cannot over-write existing"
 753                                            + " certificate");
 754 
 755         X509AttributeName attr = new X509AttributeName(name);
 756         String id = attr.getPrefix();
 757         if (!(id.equalsIgnoreCase(NAME))) {
 758             throw new CertificateException("Invalid root of attribute name,"
 759                            + " expected [" + NAME + "], received " + id);
 760         }
 761         attr = new X509AttributeName(attr.getSuffix());
 762         id = attr.getPrefix();
 763 
 764         if (id.equalsIgnoreCase(INFO)) {
 765             if (attr.getSuffix() == null) {
 766                 if (!(obj instanceof X509CertInfo)) {
 767                     throw new CertificateException("Attribute value should"
 768                                     + " be of type X509CertInfo.");
 769                 }
 770                 info = (X509CertInfo)obj;
 771                 signedCert = null;  //reset this as certificate data has changed
 772             } else {
 773                 info.set(attr.getSuffix(), obj);
 774                 signedCert = null;  //reset this as certificate data has changed
 775             }
 776         } else {
 777             throw new CertificateException("Attribute name not recognized or " +
 778                               "set() not allowed for the same: " + id);
 779         }
 780     }
 781 
 782     /**
 783      * Delete the requested attribute from the certificate.
 784      *
 785      * @param name the name of the attribute.
 786      * @exception CertificateException on invalid attribute identifier.
 787      * @exception IOException on other errors.
 788      */
 789     public void delete(String name)
 790     throws CertificateException, IOException {
 791         // check if immutable
 792         if (readOnly)
 793             throw new CertificateException("cannot over-write existing"
 794                                            + " certificate");
 795 
 796         X509AttributeName attr = new X509AttributeName(name);
 797         String id = attr.getPrefix();
 798         if (!(id.equalsIgnoreCase(NAME))) {
 799             throw new CertificateException("Invalid root of attribute name,"
 800                                    + " expected ["
 801                                    + NAME + "], received " + id);
 802         }
 803         attr = new X509AttributeName(attr.getSuffix());
 804         id = attr.getPrefix();
 805 
 806         if (id.equalsIgnoreCase(INFO)) {
 807             if (attr.getSuffix() != null) {
 808                 info = null;
 809             } else {
 810                 info.delete(attr.getSuffix());
 811             }
 812         } else if (id.equalsIgnoreCase(ALG_ID)) {
 813             algId = null;
 814         } else if (id.equalsIgnoreCase(SIGNATURE)) {
 815             signature = null;
 816         } else if (id.equalsIgnoreCase(SIGNED_CERT)) {
 817             signedCert = null;
 818         } else {
 819             throw new CertificateException("Attribute name not recognized or " +
 820                               "delete() not allowed for the same: " + id);
 821         }
 822     }
 823 
 824     /**
 825      * Return an enumeration of names of attributes existing within this
 826      * attribute.
 827      */
 828     public Enumeration<String> getElements() {
 829         AttributeNameEnumeration elements = new AttributeNameEnumeration();
 830         elements.addElement(NAME + DOT + INFO);
 831         elements.addElement(NAME + DOT + ALG_ID);
 832         elements.addElement(NAME + DOT + SIGNATURE);
 833         elements.addElement(NAME + DOT + SIGNED_CERT);
 834 
 835         return elements.elements();
 836     }
 837 
 838     /**
 839      * Return the name of this attribute.
 840      */
 841     public String getName() {
 842         return(NAME);
 843     }
 844 
 845     /**
 846      * Returns a printable representation of the certificate.  This does not
 847      * contain all the information available to distinguish this from any
 848      * other certificate.  The certificate must be fully constructed
 849      * before this function may be called.
 850      */
 851     public String toString() {
 852         if (info == null || algId == null || signature == null)
 853             return "";
 854 
 855         HexDumpEncoder encoder = new HexDumpEncoder();
 856         return "[\n" + info + '\n' +
 857             "  Algorithm: [" + algId + "]\n" +
 858             "  Signature:\n" + encoder.encodeBuffer(signature) + "\n]";
 859     }
 860 
 861     // the strongly typed gets, as per java.security.cert.X509Certificate
 862 
 863     /**
 864      * Gets the publickey from this certificate.
 865      *
 866      * @return the publickey.
 867      */
 868     public PublicKey getPublicKey() {
 869         if (info == null)
 870             return null;
 871         try {
 872             PublicKey key = (PublicKey)info.get(CertificateX509Key.NAME
 873                                 + DOT + CertificateX509Key.KEY);
 874             return key;
 875         } catch (Exception e) {
 876             return null;
 877         }
 878     }
 879 
 880     /**
 881      * Gets the version number from the certificate.
 882      *
 883      * @return the version number, i.e. 1, 2 or 3.
 884      */
 885     public int getVersion() {
 886         if (info == null)
 887             return -1;
 888         try {
 889             int vers = ((Integer)info.get(CertificateVersion.NAME
 890                         + DOT + CertificateVersion.VERSION)).intValue();
 891             return vers+1;
 892         } catch (Exception e) {
 893             return -1;
 894         }
 895     }
 896 
 897     /**
 898      * Gets the serial number from the certificate.
 899      *
 900      * @return the serial number.
 901      */
 902     public BigInteger getSerialNumber() {
 903         SerialNumber ser = getSerialNumberObject();
 904 
 905         return ser != null ? ser.getNumber() : null;
 906     }
 907 
 908     /**
 909      * Gets the serial number from the certificate as
 910      * a SerialNumber object.
 911      *
 912      * @return the serial number.
 913      */
 914     public SerialNumber getSerialNumberObject() {
 915         if (info == null)
 916             return null;
 917         try {
 918             SerialNumber ser = (SerialNumber)info.get(
 919                               CertificateSerialNumber.NAME + DOT +
 920                               CertificateSerialNumber.NUMBER);
 921            return ser;
 922         } catch (Exception e) {
 923             return null;
 924         }
 925     }
 926 
 927 
 928     /**
 929      * Gets the subject distinguished name from the certificate.
 930      *
 931      * @return the subject name.
 932      */
 933     public Principal getSubjectDN() {
 934         if (info == null)
 935             return null;
 936         try {
 937             Principal subject = (Principal)info.get(X509CertInfo.SUBJECT + DOT +
 938                                                     X509CertInfo.DN_NAME);
 939             return subject;
 940         } catch (Exception e) {
 941             return null;
 942         }
 943     }
 944 
 945     /**
 946      * Get subject name as X500Principal. Overrides implementation in
 947      * X509Certificate with a slightly more efficient version that is
 948      * also aware of X509CertImpl mutability.
 949      */
 950     public X500Principal getSubjectX500Principal() {
 951         if (info == null) {
 952             return null;
 953         }
 954         try {
 955             X500Principal subject = (X500Principal)info.get(
 956                                             X509CertInfo.SUBJECT + DOT +
 957                                             "x500principal");
 958             return subject;
 959         } catch (Exception e) {
 960             return null;
 961         }
 962     }
 963 
 964     /**
 965      * Gets the issuer distinguished name from the certificate.
 966      *
 967      * @return the issuer name.
 968      */
 969     public Principal getIssuerDN() {
 970         if (info == null)
 971             return null;
 972         try {
 973             Principal issuer = (Principal)info.get(X509CertInfo.ISSUER + DOT +
 974                                                    X509CertInfo.DN_NAME);
 975             return issuer;
 976         } catch (Exception e) {
 977             return null;
 978         }
 979     }
 980 
 981     /**
 982      * Get issuer name as X500Principal. Overrides implementation in
 983      * X509Certificate with a slightly more efficient version that is
 984      * also aware of X509CertImpl mutability.
 985      */
 986     public X500Principal getIssuerX500Principal() {
 987         if (info == null) {
 988             return null;
 989         }
 990         try {
 991             X500Principal issuer = (X500Principal)info.get(
 992                                             X509CertInfo.ISSUER + DOT +
 993                                             "x500principal");
 994             return issuer;
 995         } catch (Exception e) {
 996             return null;
 997         }
 998     }
 999 
1000     /**
1001      * Gets the notBefore date from the validity period of the certificate.
1002      *
1003      * @return the start date of the validity period.
1004      */
1005     public Date getNotBefore() {
1006         if (info == null)
1007             return null;
1008         try {
1009             Date d = (Date) info.get(CertificateValidity.NAME + DOT +
1010                                         CertificateValidity.NOT_BEFORE);
1011             return d;
1012         } catch (Exception e) {
1013             return null;
1014         }
1015     }
1016 
1017     /**
1018      * Gets the notAfter date from the validity period of the certificate.
1019      *
1020      * @return the end date of the validity period.
1021      */
1022     public Date getNotAfter() {
1023         if (info == null)
1024             return null;
1025         try {
1026             Date d = (Date) info.get(CertificateValidity.NAME + DOT +
1027                                      CertificateValidity.NOT_AFTER);
1028             return d;
1029         } catch (Exception e) {
1030             return null;
1031         }
1032     }
1033 
1034     /**
1035      * Gets the DER encoded certificate informations, the
1036      * <code>tbsCertificate</code> from this certificate.
1037      * This can be used to verify the signature independently.
1038      *
1039      * @return the DER encoded certificate information.
1040      * @exception CertificateEncodingException if an encoding error occurs.
1041      */
1042     public byte[] getTBSCertificate() throws CertificateEncodingException {
1043         if (info != null) {
1044             return info.getEncodedInfo();
1045         } else
1046             throw new CertificateEncodingException("Uninitialized certificate");
1047     }
1048 
1049     /**
1050      * Gets the raw Signature bits from the certificate.
1051      *
1052      * @return the signature.
1053      */
1054     public byte[] getSignature() {
1055         if (signature == null)
1056             return null;
1057         return signature.clone();
1058     }
1059 
1060     /**
1061      * Gets the signature algorithm name for the certificate
1062      * signature algorithm.
1063      * For example, the string "SHA-1/DSA" or "DSS".
1064      *
1065      * @return the signature algorithm name.
1066      */
1067     public String getSigAlgName() {
1068         if (algId == null)
1069             return null;
1070         return (algId.getName());
1071     }
1072 
1073     /**
1074      * Gets the signature algorithm OID string from the certificate.
1075      * For example, the string "1.2.840.10040.4.3"
1076      *
1077      * @return the signature algorithm oid string.
1078      */
1079     public String getSigAlgOID() {
1080         if (algId == null)
1081             return null;
1082         ObjectIdentifier oid = algId.getOID();
1083         return (oid.toString());
1084     }
1085 
1086     /**
1087      * Gets the DER encoded signature algorithm parameters from this
1088      * certificate's signature algorithm.
1089      *
1090      * @return the DER encoded signature algorithm parameters, or
1091      *         null if no parameters are present.
1092      */
1093     public byte[] getSigAlgParams() {
1094         if (algId == null)
1095             return null;
1096         try {
1097             return algId.getEncodedParams();
1098         } catch (IOException e) {
1099             return null;
1100         }
1101     }
1102 
1103     /**
1104      * Gets the Issuer Unique Identity from the certificate.
1105      *
1106      * @return the Issuer Unique Identity.
1107      */
1108     public boolean[] getIssuerUniqueID() {
1109         if (info == null)
1110             return null;
1111         try {
1112             UniqueIdentity id = (UniqueIdentity)info.get(
1113                                  X509CertInfo.ISSUER_ID);
1114             if (id == null)
1115                 return null;
1116             else
1117                 return (id.getId());
1118         } catch (Exception e) {
1119             return null;
1120         }
1121     }
1122 
1123     /**
1124      * Gets the Subject Unique Identity from the certificate.
1125      *
1126      * @return the Subject Unique Identity.
1127      */
1128     public boolean[] getSubjectUniqueID() {
1129         if (info == null)
1130             return null;
1131         try {
1132             UniqueIdentity id = (UniqueIdentity)info.get(
1133                                  X509CertInfo.SUBJECT_ID);
1134             if (id == null)
1135                 return null;
1136             else
1137                 return (id.getId());
1138         } catch (Exception e) {
1139             return null;
1140         }
1141     }
1142 
1143     public KeyIdentifier getAuthKeyId() {
1144         AuthorityKeyIdentifierExtension aki
1145             = getAuthorityKeyIdentifierExtension();
1146         if (aki != null) {
1147             try {
1148                 return (KeyIdentifier)aki.get(
1149                     AuthorityKeyIdentifierExtension.KEY_ID);
1150             } catch (IOException ioe) {} // not possible
1151         }
1152         return null;
1153     }
1154 
1155     /**
1156      * Returns the subject's key identifier, or null
1157      */
1158     public KeyIdentifier getSubjectKeyId() {
1159         SubjectKeyIdentifierExtension ski = getSubjectKeyIdentifierExtension();
1160         if (ski != null) {
1161             try {
1162                 return ski.get(SubjectKeyIdentifierExtension.KEY_ID);
1163             } catch (IOException ioe) {} // not possible
1164         }
1165         return null;
1166     }
1167 
1168     /**
1169      * Get AuthorityKeyIdentifier extension
1170      * @return AuthorityKeyIdentifier object or null (if no such object
1171      * in certificate)
1172      */
1173     public AuthorityKeyIdentifierExtension getAuthorityKeyIdentifierExtension()
1174     {
1175         return (AuthorityKeyIdentifierExtension)
1176             getExtension(PKIXExtensions.AuthorityKey_Id);
1177     }
1178 
1179     /**
1180      * Get BasicConstraints extension
1181      * @return BasicConstraints object or null (if no such object in
1182      * certificate)
1183      */
1184     public BasicConstraintsExtension getBasicConstraintsExtension() {
1185         return (BasicConstraintsExtension)
1186             getExtension(PKIXExtensions.BasicConstraints_Id);
1187     }
1188 
1189     /**
1190      * Get CertificatePoliciesExtension
1191      * @return CertificatePoliciesExtension or null (if no such object in
1192      * certificate)
1193      */
1194     public CertificatePoliciesExtension getCertificatePoliciesExtension() {
1195         return (CertificatePoliciesExtension)
1196             getExtension(PKIXExtensions.CertificatePolicies_Id);
1197     }
1198 
1199     /**
1200      * Get ExtendedKeyUsage extension
1201      * @return ExtendedKeyUsage extension object or null (if no such object
1202      * in certificate)
1203      */
1204     public ExtendedKeyUsageExtension getExtendedKeyUsageExtension() {
1205         return (ExtendedKeyUsageExtension)
1206             getExtension(PKIXExtensions.ExtendedKeyUsage_Id);
1207     }
1208 
1209     /**
1210      * Get IssuerAlternativeName extension
1211      * @return IssuerAlternativeName object or null (if no such object in
1212      * certificate)
1213      */
1214     public IssuerAlternativeNameExtension getIssuerAlternativeNameExtension() {
1215         return (IssuerAlternativeNameExtension)
1216             getExtension(PKIXExtensions.IssuerAlternativeName_Id);
1217     }
1218 
1219     /**
1220      * Get NameConstraints extension
1221      * @return NameConstraints object or null (if no such object in certificate)
1222      */
1223     public NameConstraintsExtension getNameConstraintsExtension() {
1224         return (NameConstraintsExtension)
1225             getExtension(PKIXExtensions.NameConstraints_Id);
1226     }
1227 
1228     /**
1229      * Get PolicyConstraints extension
1230      * @return PolicyConstraints object or null (if no such object in
1231      * certificate)
1232      */
1233     public PolicyConstraintsExtension getPolicyConstraintsExtension() {
1234         return (PolicyConstraintsExtension)
1235             getExtension(PKIXExtensions.PolicyConstraints_Id);
1236     }
1237 
1238     /**
1239      * Get PolicyMappingsExtension extension
1240      * @return PolicyMappingsExtension object or null (if no such object
1241      * in certificate)
1242      */
1243     public PolicyMappingsExtension getPolicyMappingsExtension() {
1244         return (PolicyMappingsExtension)
1245             getExtension(PKIXExtensions.PolicyMappings_Id);
1246     }
1247 
1248     /**
1249      * Get PrivateKeyUsage extension
1250      * @return PrivateKeyUsage object or null (if no such object in certificate)
1251      */
1252     public PrivateKeyUsageExtension getPrivateKeyUsageExtension() {
1253         return (PrivateKeyUsageExtension)
1254             getExtension(PKIXExtensions.PrivateKeyUsage_Id);
1255     }
1256 
1257     /**
1258      * Get SubjectAlternativeName extension
1259      * @return SubjectAlternativeName object or null (if no such object in
1260      * certificate)
1261      */
1262     public SubjectAlternativeNameExtension getSubjectAlternativeNameExtension()
1263     {
1264         return (SubjectAlternativeNameExtension)
1265             getExtension(PKIXExtensions.SubjectAlternativeName_Id);
1266     }
1267 
1268     /**
1269      * Get SubjectKeyIdentifier extension
1270      * @return SubjectKeyIdentifier object or null (if no such object in
1271      * certificate)
1272      */
1273     public SubjectKeyIdentifierExtension getSubjectKeyIdentifierExtension() {
1274         return (SubjectKeyIdentifierExtension)
1275             getExtension(PKIXExtensions.SubjectKey_Id);
1276     }
1277 
1278     /**
1279      * Get CRLDistributionPoints extension
1280      * @return CRLDistributionPoints object or null (if no such object in
1281      * certificate)
1282      */
1283     public CRLDistributionPointsExtension getCRLDistributionPointsExtension() {
1284         return (CRLDistributionPointsExtension)
1285             getExtension(PKIXExtensions.CRLDistributionPoints_Id);
1286     }
1287 
1288     /**
1289      * Return true if a critical extension is found that is
1290      * not supported, otherwise return false.
1291      */
1292     public boolean hasUnsupportedCriticalExtension() {
1293         if (info == null)
1294             return false;
1295         try {
1296             CertificateExtensions exts = (CertificateExtensions)info.get(
1297                                          CertificateExtensions.NAME);
1298             if (exts == null)
1299                 return false;
1300             return exts.hasUnsupportedCriticalExtension();
1301         } catch (Exception e) {
1302             return false;
1303         }
1304     }
1305 
1306     /**
1307      * Gets a Set of the extension(s) marked CRITICAL in the
1308      * certificate. In the returned set, each extension is
1309      * represented by its OID string.
1310      *
1311      * @return a set of the extension oid strings in the
1312      * certificate that are marked critical.
1313      */
1314     public Set<String> getCriticalExtensionOIDs() {
1315         if (info == null) {
1316             return null;
1317         }
1318         try {
1319             CertificateExtensions exts = (CertificateExtensions)info.get(
1320                                          CertificateExtensions.NAME);
1321             if (exts == null) {
1322                 return null;
1323             }
1324             Set<String> extSet = new TreeSet<>();
1325             for (Extension ex : exts.getAllExtensions()) {
1326                 if (ex.isCritical()) {
1327                     extSet.add(ex.getExtensionId().toString());
1328                 }
1329             }
1330             return extSet;
1331         } catch (Exception e) {
1332             return null;
1333         }
1334     }
1335 
1336     /**
1337      * Gets a Set of the extension(s) marked NON-CRITICAL in the
1338      * certificate. In the returned set, each extension is
1339      * represented by its OID string.
1340      *
1341      * @return a set of the extension oid strings in the
1342      * certificate that are NOT marked critical.
1343      */
1344     public Set<String> getNonCriticalExtensionOIDs() {
1345         if (info == null) {
1346             return null;
1347         }
1348         try {
1349             CertificateExtensions exts = (CertificateExtensions)info.get(
1350                                          CertificateExtensions.NAME);
1351             if (exts == null) {
1352                 return null;
1353             }
1354             Set<String> extSet = new TreeSet<>();
1355             for (Extension ex : exts.getAllExtensions()) {
1356                 if (!ex.isCritical()) {
1357                     extSet.add(ex.getExtensionId().toString());
1358                 }
1359             }
1360             extSet.addAll(exts.getUnparseableExtensions().keySet());
1361             return extSet;
1362         } catch (Exception e) {
1363             return null;
1364         }
1365     }
1366 
1367     /**
1368      * Gets the extension identified by the given ObjectIdentifier
1369      *
1370      * @param oid the Object Identifier value for the extension.
1371      * @return Extension or null if certificate does not contain this
1372      *         extension
1373      */
1374     public Extension getExtension(ObjectIdentifier oid) {
1375         if (info == null) {
1376             return null;
1377         }
1378         try {
1379             CertificateExtensions extensions;
1380             try {
1381                 extensions = (CertificateExtensions)info.get(CertificateExtensions.NAME);
1382             } catch (CertificateException ce) {
1383                 return null;
1384             }
1385             if (extensions == null) {
1386                 return null;
1387             } else {
1388                 Extension ex = extensions.getExtension(oid.toString());
1389                 if (ex != null) {
1390                     return ex;
1391                 }
1392                 for (Extension ex2: extensions.getAllExtensions()) {
1393                     if (ex2.getExtensionId().equals(oid)) {
1394                         //XXXX May want to consider cloning this
1395                         return ex2;
1396                     }
1397                 }
1398                 /* no such extension in this certificate */
1399                 return null;
1400             }
1401         } catch (IOException ioe) {
1402             return null;
1403         }
1404     }
1405 
1406     public Extension getUnparseableExtension(ObjectIdentifier oid) {
1407         if (info == null) {
1408             return null;
1409         }
1410         try {
1411             CertificateExtensions extensions;
1412             try {
1413                 extensions = (CertificateExtensions)info.get(CertificateExtensions.NAME);
1414             } catch (CertificateException ce) {
1415                 return null;
1416             }
1417             if (extensions == null) {
1418                 return null;
1419             } else {
1420                 return extensions.getUnparseableExtensions().get(oid.toString());
1421             }
1422         } catch (IOException ioe) {
1423             return null;
1424         }
1425     }
1426 
1427     /**
1428      * Gets the DER encoded extension identified by the given
1429      * oid String.
1430      *
1431      * @param oid the Object Identifier value for the extension.
1432      */
1433     public byte[] getExtensionValue(String oid) {
1434         try {
1435             ObjectIdentifier findOID = new ObjectIdentifier(oid);
1436             String extAlias = OIDMap.getName(findOID);
1437             Extension certExt = null;
1438             CertificateExtensions exts = (CertificateExtensions)info.get(
1439                                      CertificateExtensions.NAME);
1440 
1441             if (extAlias == null) { // may be unknown
1442                 // get the extensions, search thru' for this oid
1443                 if (exts == null) {
1444                     return null;
1445                 }
1446 
1447                 for (Extension ex : exts.getAllExtensions()) {
1448                     ObjectIdentifier inCertOID = ex.getExtensionId();
1449                     if (inCertOID.equals(findOID)) {
1450                         certExt = ex;
1451                         break;
1452                     }
1453                 }
1454             } else { // there's sub-class that can handle this extension
1455                 try {
1456                     certExt = (Extension)this.get(extAlias);
1457                 } catch (CertificateException e) {
1458                     // get() throws an Exception instead of returning null, ignore
1459                 }
1460             }
1461             if (certExt == null) {
1462                 if (exts != null) {
1463                     certExt = exts.getUnparseableExtensions().get(oid);
1464                 }
1465                 if (certExt == null) {
1466                     return null;
1467                 }
1468             }
1469             byte[] extData = certExt.getExtensionValue();
1470             if (extData == null) {
1471                 return null;
1472             }
1473             DerOutputStream out = new DerOutputStream();
1474             out.putOctetString(extData);
1475             return out.toByteArray();
1476         } catch (Exception e) {
1477             return null;
1478         }
1479     }
1480 
1481     /**
1482      * Get a boolean array representing the bits of the KeyUsage extension,
1483      * (oid = 2.5.29.15).
1484      * @return the bit values of this extension as an array of booleans.
1485      */
1486     public boolean[] getKeyUsage() {
1487         try {
1488             String extAlias = OIDMap.getName(PKIXExtensions.KeyUsage_Id);
1489             if (extAlias == null)
1490                 return null;
1491 
1492             KeyUsageExtension certExt = (KeyUsageExtension)this.get(extAlias);
1493             if (certExt == null)
1494                 return null;
1495 
1496             boolean[] ret = certExt.getBits();
1497             if (ret.length < NUM_STANDARD_KEY_USAGE) {
1498                 boolean[] usageBits = new boolean[NUM_STANDARD_KEY_USAGE];
1499                 System.arraycopy(ret, 0, usageBits, 0, ret.length);
1500                 ret = usageBits;
1501             }
1502             return ret;
1503         } catch (Exception e) {
1504             return null;
1505         }
1506     }
1507 
1508     /**
1509      * This method are the overridden implementation of
1510      * getExtendedKeyUsage method in X509Certificate in the Sun
1511      * provider. It is better performance-wise since it returns cached
1512      * values.
1513      */
1514     public synchronized List<String> getExtendedKeyUsage()
1515         throws CertificateParsingException {
1516         if (readOnly && extKeyUsage != null) {
1517             return extKeyUsage;
1518         } else {
1519             ExtendedKeyUsageExtension ext = getExtendedKeyUsageExtension();
1520             if (ext == null) {
1521                 return null;
1522             }
1523             extKeyUsage =
1524                 Collections.unmodifiableList(ext.getExtendedKeyUsage());
1525             return extKeyUsage;
1526         }
1527     }
1528 
1529     /**
1530      * This static method is the default implementation of the
1531      * getExtendedKeyUsage method in X509Certificate. A
1532      * X509Certificate provider generally should overwrite this to
1533      * provide among other things caching for better performance.
1534      */
1535     public static List<String> getExtendedKeyUsage(X509Certificate cert)
1536         throws CertificateParsingException {
1537         try {
1538             byte[] ext = cert.getExtensionValue(EXTENDED_KEY_USAGE_OID);
1539             if (ext == null)
1540                 return null;
1541             DerValue val = new DerValue(ext);
1542             byte[] data = val.getOctetString();
1543 
1544             ExtendedKeyUsageExtension ekuExt =
1545                 new ExtendedKeyUsageExtension(Boolean.FALSE, data);
1546             return Collections.unmodifiableList(ekuExt.getExtendedKeyUsage());
1547         } catch (IOException ioe) {
1548             throw new CertificateParsingException(ioe);
1549         }
1550     }
1551 
1552     /**
1553      * Get the certificate constraints path length from
1554      * the critical BasicConstraints extension, (oid = 2.5.29.19).
1555      * @return the length of the constraint.
1556      */
1557     public int getBasicConstraints() {
1558         try {
1559             String extAlias = OIDMap.getName(PKIXExtensions.BasicConstraints_Id);
1560             if (extAlias == null)
1561                 return -1;
1562             BasicConstraintsExtension certExt =
1563                         (BasicConstraintsExtension)this.get(extAlias);
1564             if (certExt == null)
1565                 return -1;
1566 
1567             if (((Boolean)certExt.get(BasicConstraintsExtension.IS_CA)
1568                  ).booleanValue() == true)
1569                 return ((Integer)certExt.get(
1570                         BasicConstraintsExtension.PATH_LEN)).intValue();
1571             else
1572                 return -1;
1573         } catch (Exception e) {
1574             return -1;
1575         }
1576     }
1577 
1578     /**
1579      * Converts a GeneralNames structure into an immutable Collection of
1580      * alternative names (subject or issuer) in the form required by
1581      * {@link #getSubjectAlternativeNames} or
1582      * {@link #getIssuerAlternativeNames}.
1583      *
1584      * @param names the GeneralNames to be converted
1585      * @return an immutable Collection of alternative names
1586      */
1587     private static Collection<List<?>> makeAltNames(GeneralNames names) {
1588         if (names.isEmpty()) {
1589             return Collections.<List<?>>emptySet();
1590         }
1591         List<List<?>> newNames = new ArrayList<>();
1592         for (GeneralName gname : names.names()) {
1593             GeneralNameInterface name = gname.getName();
1594             List<Object> nameEntry = new ArrayList<>(2);
1595             nameEntry.add(Integer.valueOf(name.getType()));
1596             switch (name.getType()) {
1597             case GeneralNameInterface.NAME_RFC822:
1598                 nameEntry.add(((RFC822Name) name).getName());
1599                 break;
1600             case GeneralNameInterface.NAME_DNS:
1601                 nameEntry.add(((DNSName) name).getName());
1602                 break;
1603             case GeneralNameInterface.NAME_DIRECTORY:
1604                 nameEntry.add(((X500Name) name).getRFC2253Name());
1605                 break;
1606             case GeneralNameInterface.NAME_URI:
1607                 nameEntry.add(((URIName) name).getName());
1608                 break;
1609             case GeneralNameInterface.NAME_IP:
1610                 try {
1611                     nameEntry.add(((IPAddressName) name).getName());
1612                 } catch (IOException ioe) {
1613                     // IPAddressName in cert is bogus
1614                     throw new RuntimeException("IPAddress cannot be parsed",
1615                         ioe);
1616                 }
1617                 break;
1618             case GeneralNameInterface.NAME_OID:
1619                 nameEntry.add(((OIDName) name).getOID().toString());
1620                 break;
1621             default:
1622                 // add DER encoded form
1623                 DerOutputStream derOut = new DerOutputStream();
1624                 try {
1625                     name.encode(derOut);
1626                 } catch (IOException ioe) {
1627                     // should not occur since name has already been decoded
1628                     // from cert (this would indicate a bug in our code)
1629                     throw new RuntimeException("name cannot be encoded", ioe);
1630                 }
1631                 nameEntry.add(derOut.toByteArray());
1632                 break;
1633             }
1634             newNames.add(Collections.unmodifiableList(nameEntry));
1635         }
1636         return Collections.unmodifiableCollection(newNames);
1637     }
1638 
1639     /**
1640      * Checks a Collection of altNames and clones any name entries of type
1641      * byte [].
1642      */ // only partially generified due to javac bug
1643     private static Collection<List<?>> cloneAltNames(Collection<List<?>> altNames) {
1644         boolean mustClone = false;
1645         for (List<?> nameEntry : altNames) {
1646             if (nameEntry.get(1) instanceof byte[]) {
1647                 // must clone names
1648                 mustClone = true;
1649             }
1650         }
1651         if (mustClone) {
1652             List<List<?>> namesCopy = new ArrayList<>();
1653             for (List<?> nameEntry : altNames) {
1654                 Object nameObject = nameEntry.get(1);
1655                 if (nameObject instanceof byte[]) {
1656                     List<Object> nameEntryCopy =
1657                                         new ArrayList<>(nameEntry);
1658                     nameEntryCopy.set(1, ((byte[])nameObject).clone());
1659                     namesCopy.add(Collections.unmodifiableList(nameEntryCopy));
1660                 } else {
1661                     namesCopy.add(nameEntry);
1662                 }
1663             }
1664             return Collections.unmodifiableCollection(namesCopy);
1665         } else {
1666             return altNames;
1667         }
1668     }
1669 
1670     /**
1671      * This method are the overridden implementation of
1672      * getSubjectAlternativeNames method in X509Certificate in the Sun
1673      * provider. It is better performance-wise since it returns cached
1674      * values.
1675      */
1676     public synchronized Collection<List<?>> getSubjectAlternativeNames()
1677         throws CertificateParsingException {
1678         // return cached value if we can
1679         if (readOnly && subjectAlternativeNames != null)  {
1680             return cloneAltNames(subjectAlternativeNames);
1681         }
1682         SubjectAlternativeNameExtension subjectAltNameExt =
1683             getSubjectAlternativeNameExtension();
1684         if (subjectAltNameExt == null) {
1685             return null;
1686         }
1687         GeneralNames names;
1688         try {
1689             names = subjectAltNameExt.get(
1690                     SubjectAlternativeNameExtension.SUBJECT_NAME);
1691         } catch (IOException ioe) {
1692             // should not occur
1693             return Collections.<List<?>>emptySet();
1694         }
1695         subjectAlternativeNames = makeAltNames(names);
1696         return subjectAlternativeNames;
1697     }
1698 
1699     /**
1700      * This static method is the default implementation of the
1701      * getSubjectAlternaitveNames method in X509Certificate. A
1702      * X509Certificate provider generally should overwrite this to
1703      * provide among other things caching for better performance.
1704      */
1705     public static Collection<List<?>> getSubjectAlternativeNames(X509Certificate cert)
1706         throws CertificateParsingException {
1707         try {
1708             byte[] ext = cert.getExtensionValue(SUBJECT_ALT_NAME_OID);
1709             if (ext == null) {
1710                 return null;
1711             }
1712             DerValue val = new DerValue(ext);
1713             byte[] data = val.getOctetString();
1714 
1715             SubjectAlternativeNameExtension subjectAltNameExt =
1716                 new SubjectAlternativeNameExtension(Boolean.FALSE,
1717                                                     data);
1718 
1719             GeneralNames names;
1720             try {
1721                 names = subjectAltNameExt.get(
1722                         SubjectAlternativeNameExtension.SUBJECT_NAME);
1723             }  catch (IOException ioe) {
1724                 // should not occur
1725                 return Collections.<List<?>>emptySet();
1726             }
1727             return makeAltNames(names);
1728         } catch (IOException ioe) {
1729             throw new CertificateParsingException(ioe);
1730         }
1731     }
1732 
1733     /**
1734      * This method are the overridden implementation of
1735      * getIssuerAlternativeNames method in X509Certificate in the Sun
1736      * provider. It is better performance-wise since it returns cached
1737      * values.
1738      */
1739     public synchronized Collection<List<?>> getIssuerAlternativeNames()
1740         throws CertificateParsingException {
1741         // return cached value if we can
1742         if (readOnly && issuerAlternativeNames != null) {
1743             return cloneAltNames(issuerAlternativeNames);
1744         }
1745         IssuerAlternativeNameExtension issuerAltNameExt =
1746             getIssuerAlternativeNameExtension();
1747         if (issuerAltNameExt == null) {
1748             return null;
1749         }
1750         GeneralNames names;
1751         try {
1752             names = issuerAltNameExt.get(
1753                     IssuerAlternativeNameExtension.ISSUER_NAME);
1754         } catch (IOException ioe) {
1755             // should not occur
1756             return Collections.<List<?>>emptySet();
1757         }
1758         issuerAlternativeNames = makeAltNames(names);
1759         return issuerAlternativeNames;
1760     }
1761 
1762     /**
1763      * This static method is the default implementation of the
1764      * getIssuerAlternaitveNames method in X509Certificate. A
1765      * X509Certificate provider generally should overwrite this to
1766      * provide among other things caching for better performance.
1767      */
1768     public static Collection<List<?>> getIssuerAlternativeNames(X509Certificate cert)
1769         throws CertificateParsingException {
1770         try {
1771             byte[] ext = cert.getExtensionValue(ISSUER_ALT_NAME_OID);
1772             if (ext == null) {
1773                 return null;
1774             }
1775 
1776             DerValue val = new DerValue(ext);
1777             byte[] data = val.getOctetString();
1778 
1779             IssuerAlternativeNameExtension issuerAltNameExt =
1780                 new IssuerAlternativeNameExtension(Boolean.FALSE,
1781                                                     data);
1782             GeneralNames names;
1783             try {
1784                 names = issuerAltNameExt.get(
1785                         IssuerAlternativeNameExtension.ISSUER_NAME);
1786             }  catch (IOException ioe) {
1787                 // should not occur
1788                 return Collections.<List<?>>emptySet();
1789             }
1790             return makeAltNames(names);
1791         } catch (IOException ioe) {
1792             throw new CertificateParsingException(ioe);
1793         }
1794     }
1795 
1796     public AuthorityInfoAccessExtension getAuthorityInfoAccessExtension() {
1797         return (AuthorityInfoAccessExtension)
1798             getExtension(PKIXExtensions.AuthInfoAccess_Id);
1799     }
1800 
1801     /************************************************************/
1802 
1803     /*
1804      * Cert is a SIGNED ASN.1 macro, a three elment sequence:
1805      *
1806      *  - Data to be signed (ToBeSigned) -- the "raw" cert
1807      *  - Signature algorithm (SigAlgId)
1808      *  - The signature bits
1809      *
1810      * This routine unmarshals the certificate, saving the signature
1811      * parts away for later verification.
1812      */
1813     private void parse(DerValue val)
1814     throws CertificateException, IOException {
1815         // check if can over write the certificate
1816         if (readOnly)
1817             throw new CertificateParsingException(
1818                       "cannot over-write existing certificate");
1819 
1820         if (val.data == null || val.tag != DerValue.tag_Sequence)
1821             throw new CertificateParsingException(
1822                       "invalid DER-encoded certificate data");
1823 
1824         signedCert = val.toByteArray();
1825         DerValue[] seq = new DerValue[3];
1826 
1827         seq[0] = val.data.getDerValue();
1828         seq[1] = val.data.getDerValue();
1829         seq[2] = val.data.getDerValue();
1830 
1831         if (val.data.available() != 0) {
1832             throw new CertificateParsingException("signed overrun, bytes = "
1833                                      + val.data.available());
1834         }
1835         if (seq[0].tag != DerValue.tag_Sequence) {
1836             throw new CertificateParsingException("signed fields invalid");
1837         }
1838 
1839         algId = AlgorithmId.parse(seq[1]);
1840         signature = seq[2].getBitString();
1841 
1842         if (seq[1].data.available() != 0) {
1843             throw new CertificateParsingException("algid field overrun");
1844         }
1845         if (seq[2].data.available() != 0)
1846             throw new CertificateParsingException("signed fields overrun");
1847 
1848         // The CertificateInfo
1849         info = new X509CertInfo(seq[0]);
1850 
1851         // the "inner" and "outer" signature algorithms must match
1852         AlgorithmId infoSigAlg = (AlgorithmId)info.get(
1853                                               CertificateAlgorithmId.NAME
1854                                               + DOT +
1855                                               CertificateAlgorithmId.ALGORITHM);
1856         if (! algId.equals(infoSigAlg))
1857             throw new CertificateException("Signature algorithm mismatch");
1858         readOnly = true;
1859     }
1860 
1861     /**
1862      * Extract the subject or issuer X500Principal from an X509Certificate.
1863      * Parses the encoded form of the cert to preserve the principal's
1864      * ASN.1 encoding.
1865      */
1866     private static X500Principal getX500Principal(X509Certificate cert,
1867             boolean getIssuer) throws Exception {
1868         byte[] encoded = cert.getEncoded();
1869         DerInputStream derIn = new DerInputStream(encoded);
1870         DerValue tbsCert = derIn.getSequence(3)[0];
1871         DerInputStream tbsIn = tbsCert.data;
1872         DerValue tmp;
1873         tmp = tbsIn.getDerValue();
1874         // skip version number if present
1875         if (tmp.isContextSpecific((byte)0)) {
1876           tmp = tbsIn.getDerValue();
1877         }
1878         // tmp always contains serial number now
1879         tmp = tbsIn.getDerValue();              // skip signature
1880         tmp = tbsIn.getDerValue();              // issuer
1881         if (getIssuer == false) {
1882             tmp = tbsIn.getDerValue();          // skip validity
1883             tmp = tbsIn.getDerValue();          // subject
1884         }
1885         byte[] principalBytes = tmp.toByteArray();
1886         return new X500Principal(principalBytes);
1887     }
1888 
1889     /**
1890      * Extract the subject X500Principal from an X509Certificate.
1891      * Called from java.security.cert.X509Certificate.getSubjectX500Principal().
1892      */
1893     public static X500Principal getSubjectX500Principal(X509Certificate cert) {
1894         try {
1895             return getX500Principal(cert, false);
1896         } catch (Exception e) {
1897             throw new RuntimeException("Could not parse subject", e);
1898         }
1899     }
1900 
1901     /**
1902      * Extract the issuer X500Principal from an X509Certificate.
1903      * Called from java.security.cert.X509Certificate.getIssuerX500Principal().
1904      */
1905     public static X500Principal getIssuerX500Principal(X509Certificate cert) {
1906         try {
1907             return getX500Principal(cert, true);
1908         } catch (Exception e) {
1909             throw new RuntimeException("Could not parse issuer", e);
1910         }
1911     }
1912 
1913     /**
1914      * Returned the encoding of the given certificate for internal use.
1915      * Callers must guarantee that they neither modify it nor expose it
1916      * to untrusted code. Uses getEncodedInternal() if the certificate
1917      * is instance of X509CertImpl, getEncoded() otherwise.
1918      */
1919     public static byte[] getEncodedInternal(Certificate cert)
1920             throws CertificateEncodingException {
1921         if (cert instanceof X509CertImpl) {
1922             return ((X509CertImpl)cert).getEncodedInternal();
1923         } else {
1924             return cert.getEncoded();
1925         }
1926     }
1927 
1928     /**
1929      * Utility method to convert an arbitrary instance of X509Certificate
1930      * to a X509CertImpl. Does a cast if possible, otherwise reparses
1931      * the encoding.
1932      */
1933     public static X509CertImpl toImpl(X509Certificate cert)
1934             throws CertificateException {
1935         if (cert instanceof X509CertImpl) {
1936             return (X509CertImpl)cert;
1937         } else {
1938             return X509Factory.intern(cert);
1939         }
1940     }
1941 
1942     /**
1943      * Utility method to test if a certificate is self-issued. This is
1944      * the case iff the subject and issuer X500Principals are equal.
1945      */
1946     public static boolean isSelfIssued(X509Certificate cert) {
1947         X500Principal subject = cert.getSubjectX500Principal();
1948         X500Principal issuer = cert.getIssuerX500Principal();
1949         return subject.equals(issuer);
1950     }
1951 
1952     /**
1953      * Utility method to test if a certificate is self-signed. This is
1954      * the case iff the subject and issuer X500Principals are equal
1955      * AND the certificate's subject public key can be used to verify
1956      * the certificate. In case of exception, returns false.
1957      */
1958     public static boolean isSelfSigned(X509Certificate cert,
1959         String sigProvider) {
1960         if (isSelfIssued(cert)) {
1961             try {
1962                 if (sigProvider == null) {
1963                     cert.verify(cert.getPublicKey());
1964                 } else {
1965                     cert.verify(cert.getPublicKey(), sigProvider);
1966                 }
1967                 return true;
1968             } catch (Exception e) {
1969                 // In case of exception, return false
1970             }
1971         }
1972         return false;
1973     }
1974 
1975     private ConcurrentHashMap<String,String> fingerprints =
1976             new ConcurrentHashMap<>(2);
1977 
1978     public String getFingerprint(String algorithm) {
1979         return fingerprints.computeIfAbsent(algorithm,
1980             x -> getFingerprint(x, this));
1981     }
1982 
1983     /**
1984      * Gets the requested finger print of the certificate. The result
1985      * only contains 0-9 and A-F. No small case, no colon.
1986      */
1987     public static String getFingerprint(String algorithm,
1988             X509Certificate cert) {
1989         try {
1990             byte[] encCertInfo = cert.getEncoded();
1991             MessageDigest md = MessageDigest.getInstance(algorithm);
1992             byte[] digest = md.digest(encCertInfo);
1993             StringBuilder sb = new StringBuilder(digest.length * 2);
1994             for (int i = 0; i < digest.length; i++) {
1995                 byte2hex(digest[i], sb);
1996             }
1997             return sb.toString();
1998         } catch (NoSuchAlgorithmException | CertificateEncodingException e) {
1999             // ignored
2000         }
2001         return "";
2002     }
2003 
2004     /**
2005      * Converts a byte to hex digit and writes to the supplied builder
2006      */
2007     private static void byte2hex(byte b, StringBuilder buf) {
2008         char[] hexChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
2009                 '9', 'A', 'B', 'C', 'D', 'E', 'F' };
2010         int high = ((b & 0xf0) >> 4);
2011         int low = (b & 0x0f);
2012         buf.append(hexChars[high])
2013             .append(hexChars[low]);
2014     }
2015 }