1 /*
2  * Copyright (c) 2007, 2014, 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.util.Date;
31 import java.util.Enumeration;
32 
33 import sun.security.util.*;
34 
35 /**
36  * From RFC 5280:
37  * <p>
38  * The invalidity date is a non-critical CRL entry extension that
39  * provides the date on which it is known or suspected that the private
40  * key was compromised or that the certificate otherwise became invalid.
41  * This date may be earlier than the revocation date in the CRL entry,
42  * which is the date at which the CA processed the revocation.  When a
43  * revocation is first posted by a CRL issuer in a CRL, the invalidity
44  * date may precede the date of issue of earlier CRLs, but the
45  * revocation date SHOULD NOT precede the date of issue of earlier CRLs.
46  * Whenever this information is available, CRL issuers are strongly
47  * encouraged to share it with CRL users.
48  * <p>
49  * The GeneralizedTime values included in this field MUST be expressed
50  * in Greenwich Mean Time (Zulu), and MUST be specified and interpreted
51  * as defined in section 4.1.2.5.2.
52  * <pre>
53  * id-ce-invalidityDate OBJECT IDENTIFIER ::= { id-ce 24 }
54  *
55  * invalidityDate ::=  GeneralizedTime
56  * </pre>
57  *
58  * @author Sean Mullan
59  */
60 public class InvalidityDateExtension extends Extension
61     implements CertAttrSet<String> {
62 
63     /**
64      * Attribute name and Reason codes
65      */
66     public static final String NAME = "InvalidityDate";
67     public static final String DATE = "date";
68 
69     private Date date;
70 
encodeThis()71     private void encodeThis() throws IOException {
72         if (date == null) {
73             this.extensionValue = null;
74             return;
75         }
76         DerOutputStream dos = new DerOutputStream();
77         dos.putGeneralizedTime(date);
78         this.extensionValue = dos.toByteArray();
79     }
80 
81     /**
82      * Create a InvalidityDateExtension with the passed in date.
83      * Criticality automatically set to false.
84      *
85      * @param date the invalidity date
86      */
InvalidityDateExtension(Date date)87     public InvalidityDateExtension(Date date) throws IOException {
88         this(false, date);
89     }
90 
91     /**
92      * Create a InvalidityDateExtension with the passed in date.
93      *
94      * @param critical true if the extension is to be treated as critical.
95      * @param date the invalidity date
96      */
InvalidityDateExtension(boolean critical, Date date)97     public InvalidityDateExtension(boolean critical, Date date)
98     throws IOException {
99         this.extensionId = PKIXExtensions.InvalidityDate_Id;
100         this.critical = critical;
101         this.date = date;
102         encodeThis();
103     }
104 
105     /**
106      * Create the extension from the passed DER encoded value of the same.
107      *
108      * @param critical true if the extension is to be treated as critical.
109      * @param value an array of DER encoded bytes of the actual value.
110      * @exception ClassCastException if value is not an array of bytes
111      * @exception IOException on error.
112      */
InvalidityDateExtension(Boolean critical, Object value)113     public InvalidityDateExtension(Boolean critical, Object value)
114     throws IOException {
115         this.extensionId = PKIXExtensions.InvalidityDate_Id;
116         this.critical = critical.booleanValue();
117         this.extensionValue = (byte[]) value;
118         DerValue val = new DerValue(this.extensionValue);
119         this.date = val.getGeneralizedTime();
120     }
121 
122     /**
123      * Set the attribute value.
124      */
set(String name, Object obj)125     public void set(String name, Object obj) throws IOException {
126         if (!(obj instanceof Date)) {
127             throw new IOException("Attribute must be of type Date.");
128         }
129         if (name.equalsIgnoreCase(DATE)) {
130             date = (Date) obj;
131         } else {
132             throw new IOException
133                 ("Name not supported by InvalidityDateExtension");
134         }
135         encodeThis();
136     }
137 
138     /**
139      * Get the attribute value.
140      */
get(String name)141     public Date get(String name) throws IOException {
142         if (name.equalsIgnoreCase(DATE)) {
143             if (date == null) {
144                 return null;
145             } else {
146                 return (new Date(date.getTime()));    // clone
147             }
148         } else {
149             throw new IOException
150                 ("Name not supported by InvalidityDateExtension");
151         }
152     }
153 
154     /**
155      * Delete the attribute value.
156      */
delete(String name)157     public void delete(String name) throws IOException {
158         if (name.equalsIgnoreCase(DATE)) {
159             date = null;
160         } else {
161             throw new IOException
162                 ("Name not supported by InvalidityDateExtension");
163         }
164         encodeThis();
165     }
166 
167     /**
168      * Returns a printable representation of the Invalidity Date.
169      */
toString()170     public String toString() {
171         return super.toString() + "    Invalidity Date: " + String.valueOf(date);
172     }
173 
174     /**
175      * Write the extension to the DerOutputStream.
176      *
177      * @param out the DerOutputStream to write the extension to
178      * @exception IOException on encoding errors
179      */
encode(OutputStream out)180     public void encode(OutputStream out) throws IOException {
181         DerOutputStream  tmp = new DerOutputStream();
182 
183         if (this.extensionValue == null) {
184             this.extensionId = PKIXExtensions.InvalidityDate_Id;
185             this.critical = false;
186             encodeThis();
187         }
188         super.encode(tmp);
189         out.write(tmp.toByteArray());
190     }
191 
192     /**
193      * Return an enumeration of names of attributes existing within this
194      * attribute.
195      */
getElements()196     public Enumeration<String> getElements() {
197         AttributeNameEnumeration elements = new AttributeNameEnumeration();
198         elements.addElement(DATE);
199 
200         return elements.elements();
201     }
202 
203     /**
204      * Return the name of this attribute.
205      */
getName()206     public String getName() {
207         return NAME;
208     }
209 
toImpl(java.security.cert.Extension ext)210     public static InvalidityDateExtension toImpl(java.security.cert.Extension ext)
211         throws IOException {
212         if (ext instanceof InvalidityDateExtension) {
213             return (InvalidityDateExtension) ext;
214         } else {
215             return new InvalidityDateExtension
216                 (Boolean.valueOf(ext.isCritical()), ext.getValue());
217         }
218     }
219 }
220