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