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