0N/A/*
2362N/A * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage sun.security.pkcs;
0N/A
0N/Aimport java.io.IOException;
0N/Aimport java.io.OutputStream;
0N/Aimport java.util.Hashtable;
0N/Aimport sun.security.util.DerEncoder;
0N/Aimport sun.security.util.DerValue;
0N/Aimport sun.security.util.DerInputStream;
0N/Aimport sun.security.util.DerOutputStream;
0N/Aimport sun.security.util.ObjectIdentifier;
0N/A
0N/A/**
0N/A * A set of attributes of class PKCS9Attribute.
0N/A *
0N/A * @author Douglas Hoover
0N/A */
0N/Apublic class PKCS9Attributes {
0N/A /**
0N/A * Attributes in this set indexed by OID.
0N/A */
0N/A private final Hashtable<ObjectIdentifier, PKCS9Attribute> attributes =
0N/A new Hashtable<ObjectIdentifier, PKCS9Attribute>(3);
0N/A
0N/A /**
0N/A * The keys of this hashtable are the OIDs of permitted attributes.
0N/A */
0N/A private final Hashtable<ObjectIdentifier, ObjectIdentifier> permittedAttributes;
0N/A
0N/A /**
0N/A * The DER encoding of this attribute set. The tag byte must be
0N/A * DerValue.tag_SetOf.
0N/A */
0N/A private final byte[] derEncoding;
0N/A
0N/A /*
0N/A * Contols how attributes, which are not recognized by the PKCS9Attribute
0N/A * class, are handled during parsing.
0N/A */
0N/A private boolean ignoreUnsupportedAttributes = false;
0N/A
0N/A /**
0N/A * Construct a set of PKCS9 Attributes from its
0N/A * DER encoding on a DerInputStream, accepting only attributes
0N/A * with OIDs on the given
0N/A * list. If the array is null, accept all attributes supported by
0N/A * class PKCS9Attribute.
0N/A *
0N/A * @param permittedAttributes
0N/A * Array of attribute OIDs that will be accepted.
0N/A * @param in
0N/A * the contents of the DER encoding of the attribute set.
0N/A *
0N/A * @exception IOException
0N/A * on i/o error, encoding syntax error, unacceptable or
0N/A * unsupported attribute, or duplicate attribute.
0N/A *
0N/A * @see PKCS9Attribute
0N/A */
0N/A public PKCS9Attributes(ObjectIdentifier[] permittedAttributes,
0N/A DerInputStream in) throws IOException {
0N/A if (permittedAttributes != null) {
0N/A this.permittedAttributes =
0N/A new Hashtable<ObjectIdentifier, ObjectIdentifier>(
0N/A permittedAttributes.length);
0N/A
0N/A for (int i = 0; i < permittedAttributes.length; i++)
0N/A this.permittedAttributes.put(permittedAttributes[i],
0N/A permittedAttributes[i]);
0N/A } else {
0N/A this.permittedAttributes = null;
0N/A }
0N/A
0N/A // derEncoding initialized in <code>decode()</code>
0N/A derEncoding = decode(in);
0N/A }
0N/A
0N/A /**
0N/A * Construct a set of PKCS9 Attributes from the contents of its
0N/A * DER encoding on a DerInputStream. Accept all attributes
0N/A * supported by class PKCS9Attribute and reject any unsupported
0N/A * attributes.
0N/A *
0N/A * @param in the contents of the DER encoding of the attribute set.
0N/A * @exception IOException
0N/A * on i/o error, encoding syntax error, or unsupported or
0N/A * duplicate attribute.
0N/A *
0N/A * @see PKCS9Attribute
0N/A */
0N/A public PKCS9Attributes(DerInputStream in) throws IOException {
0N/A this(in, false);
0N/A }
0N/A
0N/A /**
0N/A * Construct a set of PKCS9 Attributes from the contents of its
0N/A * DER encoding on a DerInputStream. Accept all attributes
0N/A * supported by class PKCS9Attribute and ignore any unsupported
0N/A * attributes, if directed.
0N/A *
0N/A * @param in the contents of the DER encoding of the attribute set.
0N/A * @param ignoreUnsupportedAttributes If true then any attributes
0N/A * not supported by the PKCS9Attribute class are ignored. Otherwise
0N/A * unsupported attributes cause an exception to be thrown.
0N/A * @exception IOException
0N/A * on i/o error, encoding syntax error, or unsupported or
0N/A * duplicate attribute.
0N/A *
0N/A * @see PKCS9Attribute
0N/A */
0N/A public PKCS9Attributes(DerInputStream in,
0N/A boolean ignoreUnsupportedAttributes) throws IOException {
0N/A
0N/A this.ignoreUnsupportedAttributes = ignoreUnsupportedAttributes;
0N/A // derEncoding initialized in <code>decode()</code>
0N/A derEncoding = decode(in);
0N/A permittedAttributes = null;
0N/A }
0N/A
0N/A /**
0N/A * Construct a set of PKCS9 Attributes from the given array of
0N/A * PKCS9 attributes.
0N/A * DER encoding on a DerInputStream. All attributes in
0N/A * <code>attribs</code> must be
0N/A * supported by class PKCS9Attribute.
0N/A *
0N/A * @exception IOException
0N/A * on i/o error, encoding syntax error, or unsupported or
0N/A * duplicate attribute.
0N/A *
0N/A * @see PKCS9Attribute
0N/A */
0N/A public PKCS9Attributes(PKCS9Attribute[] attribs)
0N/A throws IllegalArgumentException, IOException {
0N/A ObjectIdentifier oid;
0N/A for (int i=0; i < attribs.length; i++) {
0N/A oid = attribs[i].getOID();
0N/A if (attributes.containsKey(oid))
0N/A throw new IllegalArgumentException(
0N/A "PKCSAttribute " + attribs[i].getOID() +
0N/A " duplicated while constructing " +
0N/A "PKCS9Attributes.");
0N/A
0N/A attributes.put(oid, attribs[i]);
0N/A }
0N/A derEncoding = generateDerEncoding();
0N/A permittedAttributes = null;
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Decode this set of PKCS9 attributes from the contents of its
0N/A * DER encoding. Ignores unsupported attributes when directed.
0N/A *
0N/A * @param in
0N/A * the contents of the DER encoding of the attribute set.
0N/A *
0N/A * @exception IOException
0N/A * on i/o error, encoding syntax error, unacceptable or
0N/A * unsupported attribute, or duplicate attribute.
0N/A */
0N/A private byte[] decode(DerInputStream in) throws IOException {
0N/A
0N/A DerValue val = in.getDerValue();
0N/A
0N/A // save the DER encoding with its proper tag byte.
0N/A byte[] derEncoding = val.toByteArray();
0N/A derEncoding[0] = DerValue.tag_SetOf;
0N/A
0N/A DerInputStream derIn = new DerInputStream(derEncoding);
0N/A DerValue[] derVals = derIn.getSet(3,true);
0N/A
0N/A PKCS9Attribute attrib;
0N/A ObjectIdentifier oid;
0N/A boolean reuseEncoding = true;
0N/A
0N/A for (int i=0; i < derVals.length; i++) {
0N/A
0N/A try {
0N/A attrib = new PKCS9Attribute(derVals[i]);
0N/A
0N/A } catch (ParsingException e) {
0N/A if (ignoreUnsupportedAttributes) {
0N/A reuseEncoding = false; // cannot reuse supplied DER encoding
0N/A continue; // skip
0N/A } else {
0N/A throw e;
0N/A }
0N/A }
0N/A oid = attrib.getOID();
0N/A
0N/A if (attributes.get(oid) != null)
0N/A throw new IOException("Duplicate PKCS9 attribute: " + oid);
0N/A
0N/A if (permittedAttributes != null &&
0N/A !permittedAttributes.containsKey(oid))
0N/A throw new IOException("Attribute " + oid +
0N/A " not permitted in this attribute set");
0N/A
0N/A attributes.put(oid, attrib);
0N/A }
0N/A return reuseEncoding ? derEncoding : generateDerEncoding();
0N/A }
0N/A
0N/A /**
0N/A * Put the DER encoding of this PKCS9 attribute set on an
0N/A * DerOutputStream, tagged with the given implicit tag.
0N/A *
0N/A * @param tag the implicit tag to use in the DER encoding.
0N/A * @param out the output stream on which to put the DER encoding.
0N/A *
0N/A * @exception IOException on output error.
0N/A */
0N/A public void encode(byte tag, OutputStream out) throws IOException {
0N/A out.write(tag);
0N/A out.write(derEncoding, 1, derEncoding.length -1);
0N/A }
0N/A
0N/A private byte[] generateDerEncoding() throws IOException {
0N/A DerOutputStream out = new DerOutputStream();
0N/A Object[] attribVals = attributes.values().toArray();
0N/A
0N/A out.putOrderedSetOf(DerValue.tag_SetOf,
0N/A castToDerEncoder(attribVals));
0N/A return out.toByteArray();
0N/A }
0N/A
0N/A /**
0N/A * Return the DER encoding of this attribute set, tagged with
0N/A * DerValue.tag_SetOf.
0N/A */
0N/A public byte[] getDerEncoding() throws IOException {
0N/A return derEncoding.clone();
0N/A
0N/A }
0N/A
0N/A /**
0N/A * Get an attribute from this set.
0N/A */
0N/A public PKCS9Attribute getAttribute(ObjectIdentifier oid) {
0N/A return attributes.get(oid);
0N/A }
0N/A
0N/A /**
0N/A * Get an attribute from this set.
0N/A */
0N/A public PKCS9Attribute getAttribute(String name) {
0N/A return attributes.get(PKCS9Attribute.getOID(name));
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Get an array of all attributes in this set, in order of OID.
0N/A */
0N/A public PKCS9Attribute[] getAttributes() {
0N/A PKCS9Attribute[] attribs = new PKCS9Attribute[attributes.size()];
0N/A ObjectIdentifier oid;
0N/A
0N/A int j = 0;
0N/A for (int i=1; i < PKCS9Attribute.PKCS9_OIDS.length &&
0N/A j < attribs.length; i++) {
0N/A attribs[j] = getAttribute(PKCS9Attribute.PKCS9_OIDS[i]);
0N/A
0N/A if (attribs[j] != null)
0N/A j++;
0N/A }
0N/A return attribs;
0N/A }
0N/A
0N/A /**
0N/A * Get an attribute value by OID.
0N/A */
0N/A public Object getAttributeValue(ObjectIdentifier oid)
0N/A throws IOException {
0N/A try {
0N/A Object value = getAttribute(oid).getValue();
0N/A return value;
0N/A } catch (NullPointerException ex) {
0N/A throw new IOException("No value found for attribute " + oid);
0N/A }
0N/A
0N/A }
0N/A
0N/A /**
0N/A * Get an attribute value by type name.
0N/A */
0N/A public Object getAttributeValue(String name) throws IOException {
0N/A ObjectIdentifier oid = PKCS9Attribute.getOID(name);
0N/A
0N/A if (oid == null)
0N/A throw new IOException("Attribute name " + name +
0N/A " not recognized or not supported.");
0N/A
0N/A return getAttributeValue(oid);
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Returns the PKCS9 block in a printable string form.
0N/A */
0N/A public String toString() {
0N/A StringBuffer buf = new StringBuffer(200);
0N/A buf.append("PKCS9 Attributes: [\n\t");
0N/A
0N/A ObjectIdentifier oid;
0N/A PKCS9Attribute value;
0N/A
0N/A boolean first = true;
0N/A for (int i = 1; i < PKCS9Attribute.PKCS9_OIDS.length; i++) {
0N/A value = getAttribute(PKCS9Attribute.PKCS9_OIDS[i]);
0N/A
0N/A if (value == null) continue;
0N/A
0N/A // we have a value; print it
0N/A if (first)
0N/A first = false;
0N/A else
0N/A buf.append(";\n\t");
0N/A
0N/A buf.append(value.toString());
0N/A }
0N/A
0N/A buf.append("\n\t] (end PKCS9 Attributes)");
0N/A
0N/A return buf.toString();
0N/A }
0N/A
0N/A /**
0N/A * Cast an object array whose components are
0N/A * <code>DerEncoder</code>s to <code>DerEncoder[]</code>.
0N/A */
0N/A static DerEncoder[] castToDerEncoder(Object[] objs) {
0N/A
0N/A DerEncoder[] encoders = new DerEncoder[objs.length];
0N/A
0N/A for (int i=0; i < encoders.length; i++)
0N/A encoders[i] = (DerEncoder) objs[i];
0N/A
0N/A return encoders;
0N/A }
0N/A}