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