1/*
2 * Copyright (c) 2007, 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
26package sun.security.x509;
27
28import java.io.IOException;
29import java.io.OutputStream;
30import java.util.Date;
31import java.util.Enumeration;
32
33import sun.security.util.*;
34
35/**
36 * From RFC 3280:
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 */
60public 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
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     */
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     */
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     */
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     */
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     */
141    public Object 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     */
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     */
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     */
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     */
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     */
206    public String getName() {
207        return NAME;
208    }
209
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