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