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