Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/pkcs/PKCS9Attributes.java
38830 views
/*1* Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.pkcs;2627import java.io.IOException;28import java.io.OutputStream;29import java.util.Hashtable;30import sun.security.util.DerEncoder;31import sun.security.util.DerValue;32import sun.security.util.DerInputStream;33import sun.security.util.DerOutputStream;34import sun.security.util.ObjectIdentifier;3536/**37* A set of attributes of class PKCS9Attribute.38*39* @author Douglas Hoover40*/41public class PKCS9Attributes {42/**43* Attributes in this set indexed by OID.44*/45private final Hashtable<ObjectIdentifier, PKCS9Attribute> attributes =46new Hashtable<ObjectIdentifier, PKCS9Attribute>(3);4748/**49* The keys of this hashtable are the OIDs of permitted attributes.50*/51private final Hashtable<ObjectIdentifier, ObjectIdentifier> permittedAttributes;5253/**54* The DER encoding of this attribute set. The tag byte must be55* DerValue.tag_SetOf.56*/57private final byte[] derEncoding;5859/*60* Contols how attributes, which are not recognized by the PKCS9Attribute61* class, are handled during parsing.62*/63private boolean ignoreUnsupportedAttributes = false;6465/**66* Construct a set of PKCS9 Attributes from its67* DER encoding on a DerInputStream, accepting only attributes68* with OIDs on the given69* list. If the array is null, accept all attributes supported by70* class PKCS9Attribute.71*72* @param permittedAttributes73* Array of attribute OIDs that will be accepted.74* @param in75* the contents of the DER encoding of the attribute set.76*77* @exception IOException78* on i/o error, encoding syntax error, unacceptable or79* unsupported attribute, or duplicate attribute.80*81* @see PKCS9Attribute82*/83public PKCS9Attributes(ObjectIdentifier[] permittedAttributes,84DerInputStream in) throws IOException {85if (permittedAttributes != null) {86this.permittedAttributes =87new Hashtable<ObjectIdentifier, ObjectIdentifier>(88permittedAttributes.length);8990for (int i = 0; i < permittedAttributes.length; i++)91this.permittedAttributes.put(permittedAttributes[i],92permittedAttributes[i]);93} else {94this.permittedAttributes = null;95}9697// derEncoding initialized in <code>decode()</code>98derEncoding = decode(in);99}100101/**102* Construct a set of PKCS9 Attributes from the contents of its103* DER encoding on a DerInputStream. Accept all attributes104* supported by class PKCS9Attribute and reject any unsupported105* attributes.106*107* @param in the contents of the DER encoding of the attribute set.108* @exception IOException109* on i/o error, encoding syntax error, or unsupported or110* duplicate attribute.111*112* @see PKCS9Attribute113*/114public PKCS9Attributes(DerInputStream in) throws IOException {115this(in, false);116}117118/**119* Construct a set of PKCS9 Attributes from the contents of its120* DER encoding on a DerInputStream. Accept all attributes121* supported by class PKCS9Attribute and ignore any unsupported122* attributes, if directed.123*124* @param in the contents of the DER encoding of the attribute set.125* @param ignoreUnsupportedAttributes If true then any attributes126* not supported by the PKCS9Attribute class are ignored. Otherwise127* unsupported attributes cause an exception to be thrown.128* @exception IOException129* on i/o error, encoding syntax error, or unsupported or130* duplicate attribute.131*132* @see PKCS9Attribute133*/134public PKCS9Attributes(DerInputStream in,135boolean ignoreUnsupportedAttributes) throws IOException {136137this.ignoreUnsupportedAttributes = ignoreUnsupportedAttributes;138// derEncoding initialized in <code>decode()</code>139derEncoding = decode(in);140permittedAttributes = null;141}142143/**144* Construct a set of PKCS9 Attributes from the given array of145* PKCS9 attributes.146* DER encoding on a DerInputStream. All attributes in147* <code>attribs</code> must be148* supported by class PKCS9Attribute.149*150* @exception IOException151* on i/o error, encoding syntax error, or unsupported or152* duplicate attribute.153*154* @see PKCS9Attribute155*/156public PKCS9Attributes(PKCS9Attribute[] attribs)157throws IllegalArgumentException, IOException {158ObjectIdentifier oid;159for (int i=0; i < attribs.length; i++) {160oid = attribs[i].getOID();161if (attributes.containsKey(oid))162throw new IllegalArgumentException(163"PKCSAttribute " + attribs[i].getOID() +164" duplicated while constructing " +165"PKCS9Attributes.");166167attributes.put(oid, attribs[i]);168}169derEncoding = generateDerEncoding();170permittedAttributes = null;171}172173174/**175* Decode this set of PKCS9 attributes from the contents of its176* DER encoding. Ignores unsupported attributes when directed.177*178* @param in179* the contents of the DER encoding of the attribute set.180*181* @exception IOException182* on i/o error, encoding syntax error, unacceptable or183* unsupported attribute, or duplicate attribute.184*/185private byte[] decode(DerInputStream in) throws IOException {186187DerValue val = in.getDerValue();188189// save the DER encoding with its proper tag byte.190byte[] derEncoding = val.toByteArray();191derEncoding[0] = DerValue.tag_SetOf;192193DerInputStream derIn = new DerInputStream(derEncoding);194DerValue[] derVals = derIn.getSet(3,true);195196PKCS9Attribute attrib;197ObjectIdentifier oid;198boolean reuseEncoding = true;199200for (int i=0; i < derVals.length; i++) {201202try {203attrib = new PKCS9Attribute(derVals[i]);204205} catch (ParsingException e) {206if (ignoreUnsupportedAttributes) {207reuseEncoding = false; // cannot reuse supplied DER encoding208continue; // skip209} else {210throw e;211}212}213oid = attrib.getOID();214215if (attributes.get(oid) != null)216throw new IOException("Duplicate PKCS9 attribute: " + oid);217218if (permittedAttributes != null &&219!permittedAttributes.containsKey(oid))220throw new IOException("Attribute " + oid +221" not permitted in this attribute set");222223attributes.put(oid, attrib);224}225return reuseEncoding ? derEncoding : generateDerEncoding();226}227228/**229* Put the DER encoding of this PKCS9 attribute set on an230* DerOutputStream, tagged with the given implicit tag.231*232* @param tag the implicit tag to use in the DER encoding.233* @param out the output stream on which to put the DER encoding.234*235* @exception IOException on output error.236*/237public void encode(byte tag, OutputStream out) throws IOException {238out.write(tag);239out.write(derEncoding, 1, derEncoding.length -1);240}241242private byte[] generateDerEncoding() throws IOException {243DerOutputStream out = new DerOutputStream();244Object[] attribVals = attributes.values().toArray();245246out.putOrderedSetOf(DerValue.tag_SetOf,247castToDerEncoder(attribVals));248return out.toByteArray();249}250251/**252* Return the DER encoding of this attribute set, tagged with253* DerValue.tag_SetOf.254*/255public byte[] getDerEncoding() throws IOException {256return derEncoding.clone();257258}259260/**261* Get an attribute from this set.262*/263public PKCS9Attribute getAttribute(ObjectIdentifier oid) {264return attributes.get(oid);265}266267/**268* Get an attribute from this set.269*/270public PKCS9Attribute getAttribute(String name) {271return attributes.get(PKCS9Attribute.getOID(name));272}273274275/**276* Get an array of all attributes in this set, in order of OID.277*/278public PKCS9Attribute[] getAttributes() {279PKCS9Attribute[] attribs = new PKCS9Attribute[attributes.size()];280ObjectIdentifier oid;281282int j = 0;283for (int i=1; i < PKCS9Attribute.PKCS9_OIDS.length &&284j < attribs.length; i++) {285attribs[j] = getAttribute(PKCS9Attribute.PKCS9_OIDS[i]);286287if (attribs[j] != null)288j++;289}290return attribs;291}292293/**294* Get an attribute value by OID.295*/296public Object getAttributeValue(ObjectIdentifier oid)297throws IOException {298try {299Object value = getAttribute(oid).getValue();300return value;301} catch (NullPointerException ex) {302throw new IOException("No value found for attribute " + oid);303}304305}306307/**308* Get an attribute value by type name.309*/310public Object getAttributeValue(String name) throws IOException {311ObjectIdentifier oid = PKCS9Attribute.getOID(name);312313if (oid == null)314throw new IOException("Attribute name " + name +315" not recognized or not supported.");316317return getAttributeValue(oid);318}319320321/**322* Returns the PKCS9 block in a printable string form.323*/324public String toString() {325StringBuffer buf = new StringBuffer(200);326buf.append("PKCS9 Attributes: [\n\t");327328ObjectIdentifier oid;329PKCS9Attribute value;330331boolean first = true;332for (int i = 1; i < PKCS9Attribute.PKCS9_OIDS.length; i++) {333value = getAttribute(PKCS9Attribute.PKCS9_OIDS[i]);334335if (value == null) continue;336337// we have a value; print it338if (first)339first = false;340else341buf.append(";\n\t");342343buf.append(value.toString());344}345346buf.append("\n\t] (end PKCS9 Attributes)");347348return buf.toString();349}350351/**352* Cast an object array whose components are353* <code>DerEncoder</code>s to <code>DerEncoder[]</code>.354*/355static DerEncoder[] castToDerEncoder(Object[] objs) {356357DerEncoder[] encoders = new DerEncoder[objs.length];358359for (int i=0; i < encoders.length; i++)360encoders[i] = (DerEncoder) objs[i];361362return encoders;363}364}365366367