History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/security/pkcs/PKCS9Attribute.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/security/pkcs/PKCS9Attribute.java+841−0
@@ -0,0 +1,841 @@
1/*
2 * Copyright (c) 1997, 2010, 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.pkcs;
27
28import java.io.IOException;
29import java.io.OutputStream;
30import java.security.cert.CertificateException;
31import java.util.Locale;
32import java.util.Date;
33import java.util.Hashtable;
34import sun.security.x509.CertificateExtensions;
35import sun.security.util.Debug;
36import sun.security.util.DerEncoder;
37import sun.security.util.DerValue;
38import sun.security.util.DerInputStream;
39import sun.security.util.DerOutputStream;
40import sun.security.util.ObjectIdentifier;
41import sun.misc.HexDumpEncoder;
42
43/**
44 * Class supporting any PKCS9 attributes.
45 * Supports DER decoding and access to attribute values, but not
46 * DER encoding or setting of values.
47 *
48 * <a name="classTable"><h3>Type/Class Table</h3></a>
49 * The following table shows the correspondence between
50 * PKCS9 attribute types and value component classes.
51 *
52 * <P>
53 * <TABLE BORDER CELLPADDING=8 ALIGN=CENTER>
54 *
55 * <TR>
56 * <TH>Object Identifier</TH>
57 * <TH>Attribute Name</TH>
58 * <TH>Type</TH>
59 * <TH>Value Class</TH>
60 * </TR>
61 *
62 * <TR>
63 * <TD>1.2.840.113549.1.9.1</TD>
64 * <TD>EmailAddress</TD>
65 * <TD>Multi-valued</TD>
66 * <TD><code>String[]</code></TD>
67 * </TR>
68 *
69 * <TR>
70 * <TD>1.2.840.113549.1.9.2</TD>
71 * <TD>UnstructuredName</TD>
72 * <TD>Multi-valued</TD>
73 * <TD><code>String[]</code></TD>
74 * </TR>
75 *
76 * <TR>
77 * <TD>1.2.840.113549.1.9.3</TD>
78 * <TD>ContentType</TD>
79 * <TD>Single-valued</TD>
80 * <TD><code>ObjectIdentifier</code></TD>
81 * </TR>
82 *
83 * <TR>
84 * <TD>1.2.840.113549.1.9.4</TD>
85 * <TD>MessageDigest</TD>
86 * <TD>Single-valued</TD>
87 * <TD><code>byte[]</code></TD>
88 * </TR>
89 *
90 * <TR>
91 * <TD>1.2.840.113549.1.9.5</TD>
92 * <TD>SigningTime</TD>
93 * <TD>Single-valued</TD>
94 * <TD><code>Date</code></TD>
95 * </TR>
96 *
97 * <TR>
98 * <TD>1.2.840.113549.1.9.6</TD>
99 * <TD>Countersignature</TD>
100 * <TD>Multi-valued</TD>
101 * <TD><code>SignerInfo[]</code></TD>
102 * </TR>
103 *
104 * <TR>
105 * <TD>1.2.840.113549.1.9.7</TD>
106 * <TD>ChallengePassword</TD>
107 * <TD>Single-valued</TD>
108 * <TD><code>String</code></TD>
109 * </TR>
110 *
111 * <TR>
112 * <TD>1.2.840.113549.1.9.8</TD>
113 * <TD>UnstructuredAddress</TD>
114 * <TD>Single-valued</TD>
115 * <TD><code>String</code></TD>
116 * </TR>
117 *
118 * <TR>
119 * <TD>1.2.840.113549.1.9.9</TD>
120 * <TD>ExtendedCertificateAttributes</TD>
121 * <TD>Multi-valued</TD>
122 * <TD>(not supported)</TD>
123 * </TR>
124 *
125 * <TR>
126 * <TD>1.2.840.113549.1.9.10</TD>
127 * <TD>IssuerAndSerialNumber</TD>
128 * <TD>Single-valued</TD>
129 * <TD>(not supported)</TD>
130 * </TR>
131 *
132 * <TR>
133 * <TD>1.2.840.113549.1.9.{11,12}</TD>
134 * <TD>RSA DSI proprietary</TD>
135 * <TD>Single-valued</TD>
136 * <TD>(not supported)</TD>
137 * </TR>
138 *
139 * <TR>
140 * <TD>1.2.840.113549.1.9.13</TD>
141 * <TD>S/MIME unused assignment</TD>
142 * <TD>Single-valued</TD>
143 * <TD>(not supported)</TD>
144 * </TR>
145 *
146 * <TR>
147 * <TD>1.2.840.113549.1.9.14</TD>
148 * <TD>ExtensionRequest</TD>
149 * <TD>Single-valued</TD>
150 * <TD>CertificateExtensions</TD>
151 * </TR>
152 *
153 * <TR>
154 * <TD>1.2.840.113549.1.9.15</TD>
155 * <TD>SMIMECapability</TD>
156 * <TD>Single-valued</TD>
157 * <TD>(not supported)</TD>
158 * </TR>
159 *
160 * <TR>
161 * <TD>1.2.840.113549.1.9.16.2.12</TD>
162 * <TD>SigningCertificate</TD>
163 * <TD>Single-valued</TD>
164 * <TD>SigningCertificateInfo</TD>
165 * </TR>
166 *
167 * <TR>
168 * <TD>1.2.840.113549.1.9.16.2.14</TD>
169 * <TD>SignatureTimestampToken</TD>
170 * <TD>Single-valued</TD>
171 * <TD>byte[]</TD>
172 * </TR>
173 *
174 * </TABLE>
175 *
176 * @author Douglas Hoover
177 */
178public class PKCS9Attribute implements DerEncoder {
179
180 /* Are we debugging ? */
181 private static final Debug debug = Debug.getInstance("jar");
182
183 /**
184 * Array of attribute OIDs defined in PKCS9, by number.
185 */
186 static final ObjectIdentifier[] PKCS9_OIDS = new ObjectIdentifier[18];
187
188 static { // static initializer for PKCS9_OIDS
189 for (int i = 1; i < PKCS9_OIDS.length - 2; i++) {
190 PKCS9_OIDS[i] =
191 ObjectIdentifier.newInternal(new int[]{1,2,840,113549,1,9,i});
192 }
193 // Initialize SigningCertificate and SignatureTimestampToken
194 // separately (because their values are out of sequence)
195 PKCS9_OIDS[PKCS9_OIDS.length - 2] =
196 ObjectIdentifier.newInternal(new int[]{1,2,840,113549,1,9,16,2,12});
197 PKCS9_OIDS[PKCS9_OIDS.length - 1] =
198 ObjectIdentifier.newInternal(new int[]{1,2,840,113549,1,9,16,2,14});
199 }
200
201 // first element [0] not used
202 public static final ObjectIdentifier EMAIL_ADDRESS_OID = PKCS9_OIDS[1];
203 public static final ObjectIdentifier UNSTRUCTURED_NAME_OID = PKCS9_OIDS[2];
204 public static final ObjectIdentifier CONTENT_TYPE_OID = PKCS9_OIDS[3];
205 public static final ObjectIdentifier MESSAGE_DIGEST_OID = PKCS9_OIDS[4];
206 public static final ObjectIdentifier SIGNING_TIME_OID = PKCS9_OIDS[5];
207 public static final ObjectIdentifier COUNTERSIGNATURE_OID = PKCS9_OIDS[6];
208 public static final ObjectIdentifier CHALLENGE_PASSWORD_OID = PKCS9_OIDS[7];
209 public static final ObjectIdentifier UNSTRUCTURED_ADDRESS_OID = PKCS9_OIDS[8];
210 public static final ObjectIdentifier EXTENDED_CERTIFICATE_ATTRIBUTES_OID
211 = PKCS9_OIDS[9];
212 public static final ObjectIdentifier ISSUER_SERIALNUMBER_OID = PKCS9_OIDS[10];
213 // [11], [12] are RSA DSI proprietary
214 // [13] ==> signingDescription, S/MIME, not used anymore
215 public static final ObjectIdentifier EXTENSION_REQUEST_OID = PKCS9_OIDS[14];
216 public static final ObjectIdentifier SMIME_CAPABILITY_OID = PKCS9_OIDS[15];
217 public static final ObjectIdentifier SIGNING_CERTIFICATE_OID = PKCS9_OIDS[16];
218 public static final ObjectIdentifier SIGNATURE_TIMESTAMP_TOKEN_OID =
219 PKCS9_OIDS[17];
220 public static final String EMAIL_ADDRESS_STR = "EmailAddress";
221 public static final String UNSTRUCTURED_NAME_STR = "UnstructuredName";
222 public static final String CONTENT_TYPE_STR = "ContentType";
223 public static final String MESSAGE_DIGEST_STR = "MessageDigest";
224 public static final String SIGNING_TIME_STR = "SigningTime";
225 public static final String COUNTERSIGNATURE_STR = "Countersignature";
226 public static final String CHALLENGE_PASSWORD_STR = "ChallengePassword";
227 public static final String UNSTRUCTURED_ADDRESS_STR = "UnstructuredAddress";
228 public static final String EXTENDED_CERTIFICATE_ATTRIBUTES_STR =
229 "ExtendedCertificateAttributes";
230 public static final String ISSUER_SERIALNUMBER_STR = "IssuerAndSerialNumber";
231 // [11], [12] are RSA DSI proprietary
232 private static final String RSA_PROPRIETARY_STR = "RSAProprietary";
233 // [13] ==> signingDescription, S/MIME, not used anymore
234 private static final String SMIME_SIGNING_DESC_STR = "SMIMESigningDesc";
235 public static final String EXTENSION_REQUEST_STR = "ExtensionRequest";
236 public static final String SMIME_CAPABILITY_STR = "SMIMECapability";
237 public static final String SIGNING_CERTIFICATE_STR = "SigningCertificate";
238 public static final String SIGNATURE_TIMESTAMP_TOKEN_STR =
239 "SignatureTimestampToken";
240
241 /**
242 * Hashtable mapping names and variant names of supported
243 * attributes to their OIDs. This table contains all name forms
244 * that occur in PKCS9, in lower case.
245 */
246 private static final Hashtable<String, ObjectIdentifier> NAME_OID_TABLE =
247 new Hashtable<String, ObjectIdentifier>(18);
248
249 static { // static initializer for PCKS9_NAMES
250 NAME_OID_TABLE.put("emailaddress", PKCS9_OIDS[1]);
251 NAME_OID_TABLE.put("unstructuredname", PKCS9_OIDS[2]);
252 NAME_OID_TABLE.put("contenttype", PKCS9_OIDS[3]);
253 NAME_OID_TABLE.put("messagedigest", PKCS9_OIDS[4]);
254 NAME_OID_TABLE.put("signingtime", PKCS9_OIDS[5]);
255 NAME_OID_TABLE.put("countersignature", PKCS9_OIDS[6]);
256 NAME_OID_TABLE.put("challengepassword", PKCS9_OIDS[7]);
257 NAME_OID_TABLE.put("unstructuredaddress", PKCS9_OIDS[8]);
258 NAME_OID_TABLE.put("extendedcertificateattributes", PKCS9_OIDS[9]);
259 NAME_OID_TABLE.put("issuerandserialnumber", PKCS9_OIDS[10]);
260 NAME_OID_TABLE.put("rsaproprietary", PKCS9_OIDS[11]);
261 NAME_OID_TABLE.put("rsaproprietary", PKCS9_OIDS[12]);
262 NAME_OID_TABLE.put("signingdescription", PKCS9_OIDS[13]);
263 NAME_OID_TABLE.put("extensionrequest", PKCS9_OIDS[14]);
264 NAME_OID_TABLE.put("smimecapability", PKCS9_OIDS[15]);
265 NAME_OID_TABLE.put("signingcertificate", PKCS9_OIDS[16]);
266 NAME_OID_TABLE.put("signaturetimestamptoken", PKCS9_OIDS[17]);
267 };
268
269 /**
270 * Hashtable mapping attribute OIDs defined in PKCS9 to the
271 * corresponding attribute value type.
272 */
273 private static final Hashtable<ObjectIdentifier, String> OID_NAME_TABLE =
274 new Hashtable<ObjectIdentifier, String>(16);
275 static {
276 OID_NAME_TABLE.put(PKCS9_OIDS[1], EMAIL_ADDRESS_STR);
277 OID_NAME_TABLE.put(PKCS9_OIDS[2], UNSTRUCTURED_NAME_STR);
278 OID_NAME_TABLE.put(PKCS9_OIDS[3], CONTENT_TYPE_STR);
279 OID_NAME_TABLE.put(PKCS9_OIDS[4], MESSAGE_DIGEST_STR);
280 OID_NAME_TABLE.put(PKCS9_OIDS[5], SIGNING_TIME_STR);
281 OID_NAME_TABLE.put(PKCS9_OIDS[6], COUNTERSIGNATURE_STR);
282 OID_NAME_TABLE.put(PKCS9_OIDS[7], CHALLENGE_PASSWORD_STR);
283 OID_NAME_TABLE.put(PKCS9_OIDS[8], UNSTRUCTURED_ADDRESS_STR);
284 OID_NAME_TABLE.put(PKCS9_OIDS[9], EXTENDED_CERTIFICATE_ATTRIBUTES_STR);
285 OID_NAME_TABLE.put(PKCS9_OIDS[10], ISSUER_SERIALNUMBER_STR);
286 OID_NAME_TABLE.put(PKCS9_OIDS[11], RSA_PROPRIETARY_STR);
287 OID_NAME_TABLE.put(PKCS9_OIDS[12], RSA_PROPRIETARY_STR);
288 OID_NAME_TABLE.put(PKCS9_OIDS[13], SMIME_SIGNING_DESC_STR);
289 OID_NAME_TABLE.put(PKCS9_OIDS[14], EXTENSION_REQUEST_STR);
290 OID_NAME_TABLE.put(PKCS9_OIDS[15], SMIME_CAPABILITY_STR);
291 OID_NAME_TABLE.put(PKCS9_OIDS[16], SIGNING_CERTIFICATE_STR);
292 OID_NAME_TABLE.put(PKCS9_OIDS[17], SIGNATURE_TIMESTAMP_TOKEN_STR);
293 }
294
295 /**
296 * Acceptable ASN.1 tags for DER encodings of values of PKCS9
297 * attributes, by index in <code>PKCS9_OIDS</code>.
298 * Sets of acceptable tags are represented as arrays.
299 */
300 private static final Byte[][] PKCS9_VALUE_TAGS = {
301 null,
302 {new Byte(DerValue.tag_IA5String)}, // EMailAddress
303 {new Byte(DerValue.tag_IA5String)}, // UnstructuredName
304 {new Byte(DerValue.tag_ObjectId)}, // ContentType
305 {new Byte(DerValue.tag_OctetString)}, // MessageDigest
306 {new Byte(DerValue.tag_UtcTime)}, // SigningTime
307 {new Byte(DerValue.tag_Sequence)}, // Countersignature
308 {new Byte(DerValue.tag_PrintableString),
309 new Byte(DerValue.tag_T61String)}, // ChallengePassword
310 {new Byte(DerValue.tag_PrintableString),
311 new Byte(DerValue.tag_T61String)}, // UnstructuredAddress
312 {new Byte(DerValue.tag_SetOf)}, // ExtendedCertificateAttributes
313 {new Byte(DerValue.tag_Sequence)}, // issuerAndSerialNumber
314 null,
315 null,
316 null,
317 {new Byte(DerValue.tag_Sequence)}, // extensionRequest
318 {new Byte(DerValue.tag_Sequence)}, // SMIMECapability
319 {new Byte(DerValue.tag_Sequence)}, // SigningCertificate
320 {new Byte(DerValue.tag_Sequence)} // SignatureTimestampToken
321 };
322
323 private static final Class[] VALUE_CLASSES = new Class[18];
324
325 static {
326 try {
327 Class str = Class.forName("[Ljava.lang.String;");
328
329 VALUE_CLASSES[0] = null; // not used
330 VALUE_CLASSES[1] = str; // EMailAddress
331 VALUE_CLASSES[2] = str; // UnstructuredName
332 VALUE_CLASSES[3] = // ContentType
333 Class.forName("sun.security.util.ObjectIdentifier");
334 VALUE_CLASSES[4] = Class.forName("[B"); // MessageDigest (byte[])
335 VALUE_CLASSES[5] = Class.forName("java.util.Date"); // SigningTime
336 VALUE_CLASSES[6] = // Countersignature
337 Class.forName("[Lsun.security.pkcs.SignerInfo;");
338 VALUE_CLASSES[7] = // ChallengePassword
339 Class.forName("java.lang.String");
340 VALUE_CLASSES[8] = str; // UnstructuredAddress
341 VALUE_CLASSES[9] = null; // ExtendedCertificateAttributes
342 VALUE_CLASSES[10] = null; // IssuerAndSerialNumber
343 VALUE_CLASSES[11] = null; // not used
344 VALUE_CLASSES[12] = null; // not used
345 VALUE_CLASSES[13] = null; // not used
346 VALUE_CLASSES[14] = // ExtensionRequest
347 Class.forName("sun.security.x509.CertificateExtensions");
348 VALUE_CLASSES[15] = null; // not supported yet
349 VALUE_CLASSES[16] = null; // not supported yet
350 VALUE_CLASSES[17] = Class.forName("[B"); // SignatureTimestampToken
351 } catch (ClassNotFoundException e) {
352 throw new ExceptionInInitializerError(e.toString());
353 }
354 }
355
356 /**
357 * Array indicating which PKCS9 attributes are single-valued,
358 * by index in <code>PKCS9_OIDS</code>.
359 */
360 private static final boolean[] SINGLE_VALUED = {
361 false,
362 false, // EMailAddress
363 false, // UnstructuredName
364 true, // ContentType
365 true, // MessageDigest
366 true, // SigningTime
367 false, // Countersignature
368 true, // ChallengePassword
369 false, // UnstructuredAddress
370 false, // ExtendedCertificateAttributes
371 true, // IssuerAndSerialNumber - not supported yet
372 false, // not used
373 false, // not used
374 false, // not used
375 true, // ExtensionRequest
376 true, // SMIMECapability - not supported yet
377 true, // SigningCertificate
378 true // SignatureTimestampToken
379 };
380
381 /**
382 * The OID of this attribute is <code>PKCS9_OIDS[index]</code>.
383 */
384 private int index;
385
386 /**
387 * Value set of this attribute. Its class is given by
388 * <code>VALUE_CLASSES[index]</code>.
389 */
390 private Object value;
391
392 /**
393 * Construct an attribute object from the attribute's OID and
394 * value. If the attribute is single-valued, provide only one
395 * value. If the attribute is multi-valued, provide an array
396 * containing all the values.
397 * Arrays of length zero are accepted, though probably useless.
398 *
399 * <P> The
400 * <a href=#classTable>table</a> gives the class that <code>value</code>
401 * must have for a given attribute.
402 *
403 */
404 public PKCS9Attribute(ObjectIdentifier oid, Object value)
405 throws IllegalArgumentException {
406 init(oid, value);
407 }
408
409 /**
410 * Construct an attribute object from the attribute's name and
411 * value. If the attribute is single-valued, provide only one
412 * value. If the attribute is multi-valued, provide an array
413 * containing all the values.
414 * Arrays of length zero are accepted, though probably useless.
415 *
416 * <P> The
417 * <a href=#classTable>table</a> gives the class that <code>value</code>
418 * must have for a given attribute. Reasonable variants of these
419 * attributes are accepted; in particular, case does not matter.
420 *
421 * @exception IllegalArgumentException
422 * if the <code>name</code> is not recognized of the
423 * <code>value</code> has the wrong type.
424 */
425 public PKCS9Attribute(String name, Object value)
426 throws IllegalArgumentException {
427 ObjectIdentifier oid = getOID(name);
428
429 if (oid == null)
430 throw new IllegalArgumentException(
431 "Unrecognized attribute name " + name +
432 " constructing PKCS9Attribute.");
433
434 init(oid, value);
435 }
436
437 private void init(ObjectIdentifier oid, Object value)
438 throws IllegalArgumentException {
439
440 index = indexOf(oid, PKCS9_OIDS, 1);
441
442 if (index == -1)
443 throw new IllegalArgumentException(
444 "Unsupported OID " + oid +
445 " constructing PKCS9Attribute.");
446
447 if (!VALUE_CLASSES[index].isInstance(value))
448 throw new IllegalArgumentException(
449 "Wrong value class " +
450 " for attribute " + oid +
451 " constructing PKCS9Attribute; was " +
452 value.getClass().toString() + ", should be " +
453 VALUE_CLASSES[index].toString());
454
455 this.value = value;
456 }
457
458
459 /**
460 * Construct a PKCS9Attribute from its encoding on an input
461 * stream.
462 *
463 * @param val the DerValue representing the DER encoding of the attribute.
464 * @exception IOException on parsing error.
465 */
466 public PKCS9Attribute(DerValue derVal) throws IOException {
467
468 DerInputStream derIn = new DerInputStream(derVal.toByteArray());
469 DerValue[] val = derIn.getSequence(2);
470
471 if (derIn.available() != 0)
472 throw new IOException("Excess data parsing PKCS9Attribute");
473
474 if (val.length != 2)
475 throw new IOException("PKCS9Attribute doesn't have two components");
476
477 // get the oid
478 ObjectIdentifier oid = val[0].getOID();
479 index = indexOf(oid, PKCS9_OIDS, 1);
480 if (index == -1) {
481 if (debug != null) {
482 debug.println("ignoring unsupported signer attribute: " + oid);
483 }
484 throw new ParsingException("Unsupported PKCS9 attribute: " + oid);
485 }
486
487 DerValue[] elems = new DerInputStream(val[1].toByteArray()).getSet(1);
488 // check single valued have only one value
489 if (SINGLE_VALUED[index] && elems.length > 1)
490 throwSingleValuedException();
491
492 // check for illegal element tags
493 Byte tag;
494 for (int i=0; i < elems.length; i++) {
495 tag = new Byte(elems[i].tag);
496
497 if (indexOf(tag, PKCS9_VALUE_TAGS[index], 0) == -1)
498 throwTagException(tag);
499 }
500
501 switch (index) {
502 case 1: // email address
503 case 2: // unstructured name
504 case 8: // unstructured address
505 { // open scope
506 String[] values = new String[elems.length];
507
508 for (int i=0; i < elems.length; i++)
509 values[i] = elems[i].getAsString();
510 value = values;
511 } // close scope
512 break;
513
514 case 3: // content type
515 value = elems[0].getOID();
516 break;
517
518 case 4: // message digest
519 value = elems[0].getOctetString();
520 break;
521
522 case 5: // signing time
523 value = (new DerInputStream(elems[0].toByteArray())).getUTCTime();
524 break;
525
526 case 6: // countersignature
527 { // open scope
528 SignerInfo[] values = new SignerInfo[elems.length];
529 for (int i=0; i < elems.length; i++)
530 values[i] =
531 new SignerInfo(elems[i].toDerInputStream());
532 value = values;
533 } // close scope
534 break;
535
536 case 7: // challenge password
537 value = elems[0].getAsString();
538 break;
539
540 case 9: // extended-certificate attribute -- not supported
541 throw new IOException("PKCS9 extended-certificate " +
542 "attribute not supported.");
543 // break unnecessary
544 case 10: // issuerAndserialNumber attribute -- not supported
545 throw new IOException("PKCS9 IssuerAndSerialNumber" +
546 "attribute not supported.");
547 // break unnecessary
548 case 11: // RSA DSI proprietary
549 case 12: // RSA DSI proprietary
550 throw new IOException("PKCS9 RSA DSI attributes" +
551 "11 and 12, not supported.");
552 // break unnecessary
553 case 13: // S/MIME unused attribute
554 throw new IOException("PKCS9 attribute #13 not supported.");
555 // break unnecessary
556
557 case 14: // ExtensionRequest
558 value = new CertificateExtensions(
559 new DerInputStream(elems[0].toByteArray()));
560 break;
561
562 case 15: // SMIME-capability attribute -- not supported
563 throw new IOException("PKCS9 SMIMECapability " +
564 "attribute not supported.");
565 // break unnecessary
566 case 16: // SigningCertificate attribute
567 value = new SigningCertificateInfo(elems[0].toByteArray());
568 break;
569
570 case 17: // SignatureTimestampToken attribute
571 value = elems[0].toByteArray();
572 break;
573 default: // can't happen
574 }
575 }
576
577 /**
578 * Write the DER encoding of this attribute to an output stream.
579 *
580 * <P> N.B.: This method always encodes values of
581 * ChallengePassword and UnstructuredAddress attributes as ASN.1
582 * <code>PrintableString</code>s, without checking whether they
583 * should be encoded as <code>T61String</code>s.
584 */
585 public void derEncode(OutputStream out) throws IOException {
586 DerOutputStream temp = new DerOutputStream();
587 temp.putOID(getOID());
588 switch (index) {
589 case 1: // email address
590 case 2: // unstructured name
591 { // open scope
592 String[] values = (String[]) value;
593 DerOutputStream[] temps = new
594 DerOutputStream[values.length];
595
596 for (int i=0; i < values.length; i++) {
597 temps[i] = new DerOutputStream();
598 temps[i].putIA5String( values[i]);
599 }
600 temp.putOrderedSetOf(DerValue.tag_Set, temps);
601 } // close scope
602 break;
603
604 case 3: // content type
605 {
606 DerOutputStream temp2 = new DerOutputStream();
607 temp2.putOID((ObjectIdentifier) value);
608 temp.write(DerValue.tag_Set, temp2.toByteArray());
609 }
610 break;
611
612 case 4: // message digest
613 {
614 DerOutputStream temp2 = new DerOutputStream();
615 temp2.putOctetString((byte[]) value);
616 temp.write(DerValue.tag_Set, temp2.toByteArray());
617 }
618 break;
619
620 case 5: // signing time
621 {
622 DerOutputStream temp2 = new DerOutputStream();
623 temp2.putUTCTime((Date) value);
624 temp.write(DerValue.tag_Set, temp2.toByteArray());
625 }
626 break;
627
628 case 6: // countersignature
629 temp.putOrderedSetOf(DerValue.tag_Set, (DerEncoder[]) value);
630 break;
631
632 case 7: // challenge password
633 {
634 DerOutputStream temp2 = new DerOutputStream();
635 temp2.putPrintableString((String) value);
636 temp.write(DerValue.tag_Set, temp2.toByteArray());
637 }
638 break;
639
640 case 8: // unstructured address
641 { // open scope
642 String[] values = (String[]) value;
643 DerOutputStream[] temps = new
644 DerOutputStream[values.length];
645
646 for (int i=0; i < values.length; i++) {
647 temps[i] = new DerOutputStream();
648 temps[i].putPrintableString(values[i]);
649 }
650 temp.putOrderedSetOf(DerValue.tag_Set, temps);
651 } // close scope
652 break;
653
654 case 9: // extended-certificate attribute -- not supported
655 throw new IOException("PKCS9 extended-certificate " +
656 "attribute not supported.");
657 // break unnecessary
658 case 10: // issuerAndserialNumber attribute -- not supported
659 throw new IOException("PKCS9 IssuerAndSerialNumber" +
660 "attribute not supported.");
661 // break unnecessary
662 case 11: // RSA DSI proprietary
663 case 12: // RSA DSI proprietary
664 throw new IOException("PKCS9 RSA DSI attributes" +
665 "11 and 12, not supported.");
666 // break unnecessary
667 case 13: // S/MIME unused attribute
668 throw new IOException("PKCS9 attribute #13 not supported.");
669 // break unnecessary
670
671 case 14: // ExtensionRequest
672 {
673 DerOutputStream temp2 = new DerOutputStream();
674 CertificateExtensions exts = (CertificateExtensions)value;
675 try {
676 exts.encode(temp2, true);
677 } catch (CertificateException ex) {
678 throw new IOException(ex.toString());
679 }
680 temp.write(DerValue.tag_Set, temp2.toByteArray());
681 }
682 break;
683 case 15: // SMIMECapability
684 throw new IOException("PKCS9 attribute #15 not supported.");
685 // break unnecessary
686
687 case 16: // SigningCertificate
688 throw new IOException(
689 "PKCS9 SigningCertificate attribute not supported.");
690 // break unnecessary
691
692 case 17: // SignatureTimestampToken
693 temp.write(DerValue.tag_Set, (byte[])value);
694 break;
695
696 default: // can't happen
697 }
698
699 DerOutputStream derOut = new DerOutputStream();
700 derOut.write(DerValue.tag_Sequence, temp.toByteArray());
701
702 out.write(derOut.toByteArray());
703
704 }
705
706 /**
707 * Get the value of this attribute. If the attribute is
708 * single-valued, return just the one value. If the attribute is
709 * multi-valued, return an array containing all the values.
710 * It is possible for this array to be of length 0.
711 *
712 * <P> The
713 * <a href=#classTable>table</a> gives the class of the value returned,
714 * depending on the type of this attribute.
715 */
716 public Object getValue() {
717 return value;
718 }
719
720 /**
721 * Show whether this attribute is single-valued.
722 */
723 public boolean isSingleValued() {
724 return SINGLE_VALUED[index];
725 }
726
727 /**
728 * Return the OID of this attribute.
729 */
730 public ObjectIdentifier getOID() {
731 return PKCS9_OIDS[index];
732 }
733
734 /**
735 * Return the name of this attribute.
736 */
737 public String getName() {
738 return OID_NAME_TABLE.get(PKCS9_OIDS[index]);
739 }
740
741 /**
742 * Return the OID for a given attribute name or null if we don't recognize
743 * the name.
744 */
745 public static ObjectIdentifier getOID(String name) {
746 return NAME_OID_TABLE.get(name.toLowerCase(Locale.ENGLISH));
747 }
748
749 /**
750 * Return the attribute name for a given OID or null if we don't recognize
751 * the oid.
752 */
753 public static String getName(ObjectIdentifier oid) {
754 return OID_NAME_TABLE.get(oid);
755 }
756
757 /**
758 * Returns a string representation of this attribute.
759 */
760 public String toString() {
761 StringBuffer buf = new StringBuffer(100);
762
763 buf.append("[");
764
765 buf.append(OID_NAME_TABLE.get(PKCS9_OIDS[index]));
766 buf.append(": ");
767
768 if (SINGLE_VALUED[index]) {
769 if (value instanceof byte[]) { // special case for octet string
770 HexDumpEncoder hexDump = new HexDumpEncoder();
771 buf.append(hexDump.encodeBuffer((byte[]) value));
772 } else {
773 buf.append(value.toString());
774 }
775 buf.append("]");
776 return buf.toString();
777 } else { // multi-valued
778 boolean first = true;
779 Object[] values = (Object[]) value;
780
781 for (int j=0; j < values.length; j++) {
782 if (first)
783 first = false;
784 else
785 buf.append(", ");
786
787 buf.append(values[j].toString());
788 }
789 return buf.toString();
790 }
791 }
792
793 /**
794 * Beginning the search at <code>start</code>, find the first
795 * index <code>i</code> such that <code>a[i] = obj</code>.
796 *
797 * @return the index, if found, and -1 otherwise.
798 */
799 static int indexOf(Object obj, Object[] a, int start) {
800 for (int i=start; i < a.length; i++) {
801 if (obj.equals(a[i])) return i;
802 }
803 return -1;
804 }
805
806 /**
807 * Throw an exception when there are multiple values for
808 * a single-valued attribute.
809 */
810 private void throwSingleValuedException() throws IOException {
811 throw new IOException("Single-value attribute " +
812 getOID() + " (" + getName() + ")" +
813 " has multiple values.");
814 }
815
816 /**
817 * Throw an exception when the tag on a value encoding is
818 * wrong for the attribute whose value it is.
819 */
820 private void throwTagException(Byte tag)
821 throws IOException {
822 Byte[] expectedTags = PKCS9_VALUE_TAGS[index];
823 StringBuffer msg = new StringBuffer(100);
824 msg.append("Value of attribute ");
825 msg.append(getOID().toString());
826 msg.append(" (");
827 msg.append(getName());
828 msg.append(") has wrong tag: ");
829 msg.append(tag.toString());
830 msg.append(". Expected tags: ");
831
832 msg.append(expectedTags[0].toString());
833
834 for (int i = 1; i < expectedTags.length; i++) {
835 msg.append(", ");
836 msg.append(expectedTags[i].toString());
837 }
838 msg.append(".");
839 throw new IOException(msg.toString());
840 }
841}