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