Extensions.java revision e1142c149e244797ce73b0e7fad40816e447a817
1package org.bouncycastle.asn1.x509;
2
3import java.util.Enumeration;
4import java.util.Hashtable;
5import java.util.Vector;
6
7import org.bouncycastle.asn1.ASN1Boolean;
8import org.bouncycastle.asn1.ASN1Encodable;
9import org.bouncycastle.asn1.ASN1EncodableVector;
10import org.bouncycastle.asn1.ASN1Object;
11import org.bouncycastle.asn1.ASN1ObjectIdentifier;
12import org.bouncycastle.asn1.ASN1OctetString;
13import org.bouncycastle.asn1.ASN1Primitive;
14import org.bouncycastle.asn1.ASN1Sequence;
15import org.bouncycastle.asn1.ASN1TaggedObject;
16import org.bouncycastle.asn1.DERSequence;
17
18public class Extensions
19    extends ASN1Object
20{
21    private Hashtable               extensions = new Hashtable();
22    private Vector                  ordering = new Vector();
23
24    public static Extensions getInstance(
25        ASN1TaggedObject obj,
26        boolean          explicit)
27    {
28        return getInstance(ASN1Sequence.getInstance(obj, explicit));
29    }
30
31    public static Extensions getInstance(
32        Object  obj)
33    {
34        if (obj instanceof Extensions)
35        {
36            return (Extensions)obj;
37        }
38        else if (obj != null)
39        {
40            return new Extensions(ASN1Sequence.getInstance(obj));
41        }
42
43        return null;
44    }
45
46    /**
47     * Constructor from ASN1Sequence.
48     *
49     * the extensions are a list of constructed sequences, either with (OID, OctetString) or (OID, Boolean, OctetString)
50     */
51    private Extensions(
52        ASN1Sequence seq)
53    {
54        Enumeration e = seq.getObjects();
55
56        while (e.hasMoreElements())
57        {
58            ASN1Sequence            s = ASN1Sequence.getInstance(e.nextElement());
59
60            if (s.size() == 3)
61            {
62                extensions.put(s.getObjectAt(0), new Extension(ASN1ObjectIdentifier.getInstance(s.getObjectAt(0)), ASN1Boolean.getInstance(s.getObjectAt(1)), ASN1OctetString.getInstance(s.getObjectAt(2))));
63            }
64            else if (s.size() == 2)
65            {
66                extensions.put(s.getObjectAt(0), new Extension(ASN1ObjectIdentifier.getInstance(s.getObjectAt(0)), false, ASN1OctetString.getInstance(s.getObjectAt(1))));
67            }
68            else
69            {
70                throw new IllegalArgumentException("Bad sequence size: " + s.size());
71            }
72
73            ordering.addElement(s.getObjectAt(0));
74        }
75    }
76
77    /**
78     * Base Constructor
79     *
80     * @param extension a single extension.
81     */
82    public Extensions(
83        Extension extension)
84    {
85        this.ordering.addElement(extension.getExtnId());
86        this.extensions.put(extension.getExtnId(), extension);
87    }
88
89    /**
90     * Base Constructor
91     *
92     * @param extensions an array of extensions.
93     */
94    public Extensions(
95        Extension[] extensions)
96    {
97        for (int i = 0; i != extensions.length; i++)
98        {
99            Extension ext = extensions[i];
100
101            this.ordering.addElement(ext.getExtnId());
102            this.extensions.put(ext.getExtnId(), ext);
103        }
104    }
105
106    /**
107     * return an Enumeration of the extension field's object ids.
108     */
109    public Enumeration oids()
110    {
111        return ordering.elements();
112    }
113
114    /**
115     * return the extension represented by the object identifier
116     * passed in.
117     *
118     * @return the extension if it's present, null otherwise.
119     */
120    public Extension getExtension(
121        ASN1ObjectIdentifier oid)
122    {
123        return (Extension)extensions.get(oid);
124    }
125
126    /**
127     * return the parsed value of the extension represented by the object identifier
128     * passed in.
129     *
130     * @return the parsed value of the extension if it's present, null otherwise.
131     */
132    public ASN1Encodable getExtensionParsedValue(ASN1ObjectIdentifier oid)
133    {
134        Extension ext = this.getExtension(oid);
135
136        if (ext != null)
137        {
138            return ext.getParsedValue();
139        }
140
141        return null;
142    }
143
144    /**
145     * <pre>
146     *     Extensions        ::=   SEQUENCE SIZE (1..MAX) OF Extension
147     *
148     *     Extension         ::=   SEQUENCE {
149     *        extnId            EXTENSION.&amp;id ({ExtensionSet}),
150     *        critical          BOOLEAN DEFAULT FALSE,
151     *        extnValue         OCTET STRING }
152     * </pre>
153     */
154    public ASN1Primitive toASN1Primitive()
155    {
156        ASN1EncodableVector vec = new ASN1EncodableVector();
157        Enumeration             e = ordering.elements();
158
159        while (e.hasMoreElements())
160        {
161            ASN1ObjectIdentifier     oid = (ASN1ObjectIdentifier)e.nextElement();
162            Extension ext = (Extension)extensions.get(oid);
163            ASN1EncodableVector v = new ASN1EncodableVector();
164
165            v.add(oid);
166
167            if (ext.isCritical())
168            {
169                v.add(ASN1Boolean.getInstance(true));
170            }
171
172            v.add(ext.getExtnValue());
173
174            vec.add(new DERSequence(v));
175        }
176
177        return new DERSequence(vec);
178    }
179
180    public boolean equivalent(
181        Extensions other)
182    {
183        if (extensions.size() != other.extensions.size())
184        {
185            return false;
186        }
187
188        Enumeration     e1 = extensions.keys();
189
190        while (e1.hasMoreElements())
191        {
192            Object  key = e1.nextElement();
193
194            if (!extensions.get(key).equals(other.extensions.get(key)))
195            {
196                return false;
197            }
198        }
199
200        return true;
201    }
202
203    public ASN1ObjectIdentifier[] getExtensionOIDs()
204    {
205        return toOidArray(ordering);
206    }
207
208    public ASN1ObjectIdentifier[] getNonCriticalExtensionOIDs()
209    {
210        return getExtensionOIDs(false);
211    }
212
213    public ASN1ObjectIdentifier[] getCriticalExtensionOIDs()
214    {
215        return getExtensionOIDs(true);
216    }
217
218    private ASN1ObjectIdentifier[] getExtensionOIDs(boolean isCritical)
219    {
220        Vector oidVec = new Vector();
221
222        for (int i = 0; i != ordering.size(); i++)
223        {
224            Object oid = ordering.elementAt(i);
225
226            if (((Extension)extensions.get(oid)).isCritical() == isCritical)
227            {
228                oidVec.addElement(oid);
229            }
230        }
231
232        return toOidArray(oidVec);
233    }
234
235    private ASN1ObjectIdentifier[] toOidArray(Vector oidVec)
236    {
237        ASN1ObjectIdentifier[] oids = new ASN1ObjectIdentifier[oidVec.size()];
238
239        for (int i = 0; i != oids.length; i++)
240        {
241            oids[i] = (ASN1ObjectIdentifier)oidVec.elementAt(i);
242        }
243        return oids;
244    }
245}
246