001: /*
002: * @(#)PKCS9Attributes.java 1.15 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package sun.security.pkcs;
029:
030: import java.io.IOException;
031: import java.io.OutputStream;
032: import java.util.Hashtable;
033: import sun.security.util.DerEncoder;
034: import sun.security.util.DerValue;
035: import sun.security.util.DerInputStream;
036: import sun.security.util.DerOutputStream;
037: import sun.security.util.ObjectIdentifier;
038:
039: /**
040: * A set of attributes of class PKCS9Attribute.
041: *
042: * @version 1.8 02/02/00
043: * @author Douglas Hoover
044: */
045: public class PKCS9Attributes {
046: /**
047: * Attributes in this set indexed by OID.
048: */
049: private final Hashtable attributes = new Hashtable(3);
050:
051: /**
052: * The keys of this hashtable are the OIDs of permitted attributes.
053: */
054: private final Hashtable permittedAttributes;
055:
056: /**
057: * The DER encoding of this attribute set. The tag byte must be
058: * DerValue.tag_SetOf.
059: */
060: private final byte[] derEncoding;
061:
062: /**
063: * Construct a set of PKCS9 Attributes from its
064: * DER encoding on a DerInputStream, accepting only attributes
065: * with OIDs on the given
066: * list. If the array is null, accept all attributes supported by
067: * class PKCS9Attribute.
068: *
069: * @param permittedAttributes
070: * Array of attribute OIDs that will be accepted.
071: * @param buf
072: * the contents of the DER encoding of the attribute set.
073: *
074: * @exception IOException
075: * on i/o error, encoding syntax error, unacceptable or
076: * unsupported attribute, or duplicate attribute.
077: *
078: * @see PKCS9Attribute
079: */
080: public PKCS9Attributes(ObjectIdentifier[] permittedAttributes,
081: DerInputStream in) throws IOException {
082: if (permittedAttributes != null) {
083: this .permittedAttributes = new Hashtable(
084: permittedAttributes.length);
085:
086: for (int i = 0; i < permittedAttributes.length; i++)
087: this .permittedAttributes.put(permittedAttributes[i],
088: permittedAttributes[i]);
089: } else {
090: this .permittedAttributes = null;
091: }
092:
093: // derEncoding initialized in <code>decode()</code>
094: derEncoding = decode(in);
095: }
096:
097: /**
098: * Construct a set of PKCS9 Attributes from its contents of its
099: * DER encoding on a DerInputStream. Accept all attributes
100: * supported by class PKCS9Attribute.
101: *
102: * @exception IOException
103: * on i/o error, encoding syntax error, or unsupported or
104: * duplicate attribute.
105: *
106: * @see PKCS9Attribute
107: */
108: public PKCS9Attributes(DerInputStream in) throws IOException {
109: // anything goes
110: // derEncoding initialized in <code>decode()</code>
111: derEncoding = decode(in);
112: permittedAttributes = null;
113: }
114:
115: /**
116: * Construct a set of PKCS9 Attributes from the given array of
117: * PKCS9 attributes.
118: * DER encoding on a DerInputStream. All attributes in
119: * <code>attribs</code> must be
120: * supported by class PKCS9Attribute.
121: *
122: * @exception IOException
123: * on i/o error, encoding syntax error, or unsupported or
124: * duplicate attribute.
125: *
126: * @see PKCS9Attribute
127: */
128: public PKCS9Attributes(PKCS9Attribute[] attribs)
129: throws IllegalArgumentException, IOException {
130: ObjectIdentifier oid;
131: for (int i = 0; i < attribs.length; i++) {
132: oid = attribs[i].getOID();
133: if (attributes.containsKey(oid))
134: throw new IllegalArgumentException("PKCSAttribute "
135: + attribs[i].getOID()
136: + " duplicated while constructing "
137: + "PKCS9Attributes.");
138:
139: attributes.put(oid, attribs[i]);
140: }
141: derEncoding = generateDerEncoding();
142: permittedAttributes = null;
143: }
144:
145: /**
146: * Decode this set of PKCS9 attribute set from the contents of its
147: * DER encoding.
148: *
149: * @param buf
150: * the contents of the DER encoding of the attribute set.
151: *
152: * @exception IOException
153: * on i/o error, encoding syntax error, unacceptable or
154: * unsupported attribute, or duplicate attribute.
155: */
156: private byte[] decode(DerInputStream in) throws IOException {
157:
158: DerValue val = in.getDerValue();
159:
160: // save the DER encoding with its proper tag byte.
161: byte[] derEncoding = val.toByteArray();
162: derEncoding[0] = DerValue.tag_SetOf;
163:
164: DerInputStream derIn = new DerInputStream(derEncoding);
165: DerValue[] derVals = derIn.getSet(3, true);
166:
167: PKCS9Attribute attrib;
168: ObjectIdentifier oid;
169: int index;
170:
171: for (int i = 0; i < derVals.length; i++) {
172: attrib = new PKCS9Attribute(derVals[i]);
173: oid = attrib.getOID();
174:
175: if (attributes.get(oid) != null)
176: throw new IOException("Duplicate PKCS9 attribute: "
177: + oid);
178:
179: if (permittedAttributes != null
180: && !permittedAttributes.containsKey(oid))
181: throw new IOException("Attribute " + oid
182: + " not permitted in this attribute set");
183:
184: attributes.put(oid, attrib);
185: }
186: return derEncoding;
187: }
188:
189: /**
190: * Put the DER encoding of this PKCS9 attribute set on an
191: * DerOutputStream, tagged with the given implicit tag.
192: *
193: * @param tag the implicit tag to use in the DER encoding.
194: * @param out the output stream on which to put the DER encoding.
195: *
196: * @exception IOException on output error.
197: */
198: public void encode(byte tag, OutputStream out) throws IOException {
199: out.write(tag);
200: out.write(derEncoding, 1, derEncoding.length - 1);
201: }
202:
203: private byte[] generateDerEncoding() throws IOException {
204: DerOutputStream out = new DerOutputStream();
205: Object[] attribVals = attributes.values().toArray();
206:
207: out.putOrderedSetOf(DerValue.tag_SetOf,
208: castToDerEncoder(attribVals));
209: return out.toByteArray();
210: }
211:
212: /**
213: * Return the DER encoding of this attribute set, tagged with
214: * DerValue.tag_SetOf.
215: */
216: public byte[] getDerEncoding() throws IOException {
217: return (byte[]) derEncoding.clone();
218:
219: }
220:
221: /**
222: * Get an attribute from this set.
223: */
224: public PKCS9Attribute getAttribute(ObjectIdentifier oid) {
225: return (PKCS9Attribute) attributes.get(oid);
226: }
227:
228: /**
229: * Get an attribute from this set.
230: */
231: public PKCS9Attribute getAttribute(String name) {
232: return (PKCS9Attribute) attributes.get(PKCS9Attribute
233: .getOID(name));
234: }
235:
236: /**
237: * Get an array of all attributes in this set, in order of OID.
238: */
239: public PKCS9Attribute[] getAttributes() {
240: PKCS9Attribute[] attribs = new PKCS9Attribute[attributes.size()];
241: ObjectIdentifier oid;
242:
243: int j = 0;
244: for (int i = 1; i < PKCS9Attribute.PKCS9_OIDS.length
245: && j < attribs.length; i++) {
246: attribs[j] = getAttribute(PKCS9Attribute.PKCS9_OIDS[i]);
247:
248: if (attribs[j] != null)
249: j++;
250: }
251: return attribs;
252: }
253:
254: /**
255: * Get an attribute value by OID.
256: */
257: public Object getAttributeValue(ObjectIdentifier oid)
258: throws IOException {
259: try {
260: Object value = getAttribute(oid).getValue();
261: return value;
262: } catch (NullPointerException ex) {
263: throw new IOException("No value found for attribute " + oid);
264: }
265:
266: }
267:
268: /**
269: * Get an attribute value by type name.
270: */
271: public Object getAttributeValue(String name) throws IOException {
272: ObjectIdentifier oid = PKCS9Attribute.getOID(name);
273:
274: if (oid == null)
275: throw new IOException("Attribute name " + name
276: + " not recognized or not supported.");
277:
278: return getAttributeValue(oid);
279: }
280:
281: /**
282: * Returns the PKCS9 block in a printable string form.
283: */
284: public String toString() {
285: StringBuffer buf = new StringBuffer(200);
286: buf.append("PKCS9 Attributes: [\n\t");
287:
288: ObjectIdentifier oid;
289: PKCS9Attribute value;
290:
291: boolean first = true;
292: for (int i = 1; i < PKCS9Attribute.PKCS9_OIDS.length; i++) {
293: value = getAttribute(PKCS9Attribute.PKCS9_OIDS[i]);
294:
295: if (value == null)
296: continue;
297:
298: // we have a value; print it
299: if (first)
300: first = false;
301: else
302: buf.append(";\n\t");
303:
304: buf.append(value.toString());
305: }
306:
307: buf.append("\n\t] (end PKCS9 Attributes)");
308:
309: return buf.toString();
310: }
311:
312: /**
313: * Cast an object array whose components are
314: * <code>DerEncoder</code>s to <code>DerEncoder[]</code>.
315: */
316: static DerEncoder[] castToDerEncoder(Object[] objs) {
317:
318: DerEncoder[] encoders = new DerEncoder[objs.length];
319:
320: for (int i = 0; i < encoders.length; i++)
321: encoders[i] = (DerEncoder) objs[i];
322:
323: return encoders;
324: }
325: }
|