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