Home | History | Annotate | Download | only in x509
      1 /*
      2  * Copyright (c) 1997, 2011, 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.IOException;
     29 import java.io.OutputStream;
     30 import java.security.cert.CertificateException;
     31 import java.security.cert.CertificateParsingException;
     32 import java.security.cert.CertificateExpiredException;
     33 import java.security.cert.CertificateNotYetValidException;
     34 import java.util.Date;
     35 import java.util.Enumeration;
     36 import java.util.Objects;
     37 
     38 import sun.security.util.*;
     39 
     40 /**
     41  * This class defines the Private Key Usage Extension.
     42  *
     43  * <p>The Private Key Usage Period extension allows the certificate issuer
     44  * to specify a different validity period for the private key than the
     45  * certificate. This extension is intended for use with digital
     46  * signature keys.  This extension consists of two optional components
     47  * notBefore and notAfter.  The private key associated with the
     48  * certificate should not be used to sign objects before or after the
     49  * times specified by the two components, respectively.
     50  *
     51  * <pre>
     52  * PrivateKeyUsagePeriod ::= SEQUENCE {
     53  *     notBefore  [0]  GeneralizedTime OPTIONAL,
     54  *     notAfter   [1]  GeneralizedTime OPTIONAL }
     55  * </pre>
     56  *
     57  * @author Amit Kapoor
     58  * @author Hemma Prafullchandra
     59  * @see Extension
     60  * @see CertAttrSet
     61  */
     62 public class PrivateKeyUsageExtension extends Extension
     63 implements CertAttrSet<String> {
     64     /**
     65      * Identifier for this attribute, to be used with the
     66      * get, set, delete methods of Certificate, x509 type.
     67      */
     68     public static final String IDENT = "x509.info.extensions.PrivateKeyUsage";
     69     /**
     70      * Sub attributes name for this CertAttrSet.
     71      */
     72     public static final String NAME = "PrivateKeyUsage";
     73     public static final String NOT_BEFORE = "not_before";
     74     public static final String NOT_AFTER = "not_after";
     75 
     76     // Private data members
     77     private static final byte TAG_BEFORE = 0;
     78     private static final byte TAG_AFTER = 1;
     79 
     80     private Date        notBefore = null;
     81     private Date        notAfter = null;
     82 
     83     // Encode this extension value.
     84     private void encodeThis() throws IOException {
     85         if (notBefore == null && notAfter == null) {
     86             this.extensionValue = null;
     87             return;
     88         }
     89         DerOutputStream seq = new DerOutputStream();
     90 
     91         DerOutputStream tagged = new DerOutputStream();
     92         if (notBefore != null) {
     93             DerOutputStream tmp = new DerOutputStream();
     94             tmp.putGeneralizedTime(notBefore);
     95             tagged.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT,
     96                                  false, TAG_BEFORE), tmp);
     97         }
     98         if (notAfter != null) {
     99             DerOutputStream tmp = new DerOutputStream();
    100             tmp.putGeneralizedTime(notAfter);
    101             tagged.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT,
    102                                  false, TAG_AFTER), tmp);
    103         }
    104         seq.write(DerValue.tag_Sequence, tagged);
    105         this.extensionValue = seq.toByteArray();
    106     }
    107 
    108     /**
    109      * The default constructor for PrivateKeyUsageExtension.
    110      *
    111      * @param notBefore the date/time before which the private key
    112      *         should not be used.
    113      * @param notAfter the date/time after which the private key
    114      *         should not be used.
    115      */
    116     public PrivateKeyUsageExtension(Date notBefore, Date notAfter)
    117     throws IOException {
    118         this.notBefore = notBefore;
    119         this.notAfter = notAfter;
    120 
    121         this.extensionId = PKIXExtensions.PrivateKeyUsage_Id;
    122         this.critical = false;
    123         encodeThis();
    124     }
    125 
    126     /**
    127      * Create the extension from the passed DER encoded value.
    128      *
    129      * @param critical true if the extension is to be treated as critical.
    130      * @param value an array of DER encoded bytes of the actual value.
    131      * @exception ClassCastException if value is not an array of bytes
    132      * @exception CertificateException on certificate parsing errors.
    133      * @exception IOException on error.
    134      */
    135     public PrivateKeyUsageExtension(Boolean critical, Object value)
    136     throws CertificateException, IOException {
    137         this.extensionId = PKIXExtensions.PrivateKeyUsage_Id;
    138         this.critical = critical.booleanValue();
    139 
    140         this.extensionValue = (byte[]) value;
    141         DerInputStream str = new DerInputStream(this.extensionValue);
    142         DerValue[] seq = str.getSequence(2);
    143 
    144         // NB. this is always encoded with the IMPLICIT tag
    145         // The checks only make sense if we assume implicit tagging,
    146         // with explicit tagging the form is always constructed.
    147         for (int i = 0; i < seq.length; i++) {
    148             DerValue opt = seq[i];
    149 
    150             if (opt.isContextSpecific(TAG_BEFORE) &&
    151                 !opt.isConstructed()) {
    152                 if (notBefore != null) {
    153                     throw new CertificateParsingException(
    154                         "Duplicate notBefore in PrivateKeyUsage.");
    155                 }
    156                 opt.resetTag(DerValue.tag_GeneralizedTime);
    157                 str = new DerInputStream(opt.toByteArray());
    158                 notBefore = str.getGeneralizedTime();
    159 
    160             } else if (opt.isContextSpecific(TAG_AFTER) &&
    161                        !opt.isConstructed()) {
    162                 if (notAfter != null) {
    163                     throw new CertificateParsingException(
    164                         "Duplicate notAfter in PrivateKeyUsage.");
    165                 }
    166                 opt.resetTag(DerValue.tag_GeneralizedTime);
    167                 str = new DerInputStream(opt.toByteArray());
    168                 notAfter = str.getGeneralizedTime();
    169             } else
    170                 throw new IOException("Invalid encoding of " +
    171                                       "PrivateKeyUsageExtension");
    172         }
    173     }
    174 
    175     /**
    176      * Return the printable string.
    177      */
    178     public String toString() {
    179         return(super.toString() +
    180                 "PrivateKeyUsage: [\n" +
    181                 ((notBefore == null) ? "" : "From: " + notBefore.toString() + ", ")
    182                 + ((notAfter == null) ? "" : "To: " + notAfter.toString())
    183                 + "]\n");
    184     }
    185 
    186     /**
    187      * Verify that that the current time is within the validity period.
    188      *
    189      * @exception CertificateExpiredException if the certificate has expired.
    190      * @exception CertificateNotYetValidException if the certificate is not
    191      * yet valid.
    192      */
    193     public void valid()
    194     throws CertificateNotYetValidException, CertificateExpiredException {
    195         Date now = new Date();
    196         valid(now);
    197     }
    198 
    199     /**
    200      * Verify that that the passed time is within the validity period.
    201      *
    202      * @exception CertificateExpiredException if the certificate has expired
    203      * with respect to the <code>Date</code> supplied.
    204      * @exception CertificateNotYetValidException if the certificate is not
    205      * yet valid with respect to the <code>Date</code> supplied.
    206      *
    207      */
    208     public void valid(Date now)
    209     throws CertificateNotYetValidException, CertificateExpiredException {
    210         Objects.requireNonNull(now);
    211         /*
    212          * we use the internal Dates rather than the passed in Date
    213          * because someone could override the Date methods after()
    214          * and before() to do something entirely different.
    215          */
    216         if (notBefore != null && notBefore.after(now)) {
    217             throw new CertificateNotYetValidException("NotBefore: " +
    218                                                       notBefore.toString());
    219         }
    220         if (notAfter != null && notAfter.before(now)) {
    221             throw new CertificateExpiredException("NotAfter: " +
    222                                                   notAfter.toString());
    223         }
    224     }
    225 
    226     /**
    227      * Write the extension to the OutputStream.
    228      *
    229      * @param out the OutputStream to write the extension to.
    230      * @exception IOException on encoding errors.
    231      */
    232     public void encode(OutputStream out) throws IOException {
    233         DerOutputStream tmp = new DerOutputStream();
    234         if (extensionValue == null) {
    235             extensionId = PKIXExtensions.PrivateKeyUsage_Id;
    236             critical = false;
    237             encodeThis();
    238         }
    239         super.encode(tmp);
    240         out.write(tmp.toByteArray());
    241     }
    242 
    243     /**
    244      * Set the attribute value.
    245      * @exception CertificateException on attribute handling errors.
    246      */
    247     public void set(String name, Object obj)
    248     throws CertificateException, IOException {
    249         if (!(obj instanceof Date)) {
    250             throw new CertificateException("Attribute must be of type Date.");
    251         }
    252         if (name.equalsIgnoreCase(NOT_BEFORE)) {
    253             notBefore = (Date)obj;
    254         } else if (name.equalsIgnoreCase(NOT_AFTER)) {
    255             notAfter = (Date)obj;
    256         } else {
    257           throw new CertificateException("Attribute name not recognized by"
    258                            + " CertAttrSet:PrivateKeyUsage.");
    259         }
    260         encodeThis();
    261     }
    262 
    263     /**
    264      * Get the attribute value.
    265      * @exception CertificateException on attribute handling errors.
    266      */
    267     public Date get(String name) throws CertificateException {
    268       if (name.equalsIgnoreCase(NOT_BEFORE)) {
    269           return (new Date(notBefore.getTime()));
    270       } else if (name.equalsIgnoreCase(NOT_AFTER)) {
    271           return (new Date(notAfter.getTime()));
    272       } else {
    273           throw new CertificateException("Attribute name not recognized by"
    274                            + " CertAttrSet:PrivateKeyUsage.");
    275       }
    276   }
    277 
    278     /**
    279      * Delete the attribute value.
    280      * @exception CertificateException on attribute handling errors.
    281      */
    282     public void delete(String name) throws CertificateException, IOException {
    283         if (name.equalsIgnoreCase(NOT_BEFORE)) {
    284             notBefore = null;
    285         } else if (name.equalsIgnoreCase(NOT_AFTER)) {
    286             notAfter = null;
    287         } else {
    288           throw new CertificateException("Attribute name not recognized by"
    289                            + " CertAttrSet:PrivateKeyUsage.");
    290         }
    291         encodeThis();
    292     }
    293 
    294     /**
    295      * Return an enumeration of names of attributes existing within this
    296      * attribute.
    297      */
    298     public Enumeration<String> getElements() {
    299         AttributeNameEnumeration elements = new AttributeNameEnumeration();
    300         elements.addElement(NOT_BEFORE);
    301         elements.addElement(NOT_AFTER);
    302 
    303         return(elements.elements());
    304     }
    305 
    306     /**
    307      * Return the name of this attribute.
    308      */
    309     public String getName() {
    310       return(NAME);
    311     }
    312 }
    313