2
|
1 |
/*
|
|
2 |
* Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
|
|
3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
4 |
*
|
|
5 |
* This code is free software; you can redistribute it and/or modify it
|
|
6 |
* under the terms of the GNU General Public License version 2 only, as
|
|
7 |
* published by the Free Software Foundation. Sun designates this
|
|
8 |
* particular file as subject to the "Classpath" exception as provided
|
|
9 |
* by Sun in the LICENSE file that accompanied this code.
|
|
10 |
*
|
|
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that
|
|
15 |
* accompanied this code).
|
|
16 |
*
|
|
17 |
* You should have received a copy of the GNU General Public License version
|
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
20 |
*
|
|
21 |
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
|
22 |
* CA 95054 USA or visit www.sun.com if you need additional information or
|
|
23 |
* have any questions.
|
|
24 |
*/
|
|
25 |
|
|
26 |
package sun.security.util;
|
|
27 |
|
|
28 |
import java.io.*;
|
|
29 |
|
|
30 |
|
|
31 |
/**
|
|
32 |
* Represent an ISO Object Identifier.
|
|
33 |
*
|
|
34 |
* <P>Object Identifiers are arbitrary length hierarchical identifiers.
|
|
35 |
* The individual components are numbers, and they define paths from the
|
|
36 |
* root of an ISO-managed identifier space. You will sometimes see a
|
|
37 |
* string name used instead of (or in addition to) the numerical id.
|
|
38 |
* These are synonyms for the numerical IDs, but are not widely used
|
|
39 |
* since most sites do not know all the requisite strings, while all
|
|
40 |
* sites can parse the numeric forms.
|
|
41 |
*
|
|
42 |
* <P>So for example, JavaSoft has the sole authority to assign the
|
|
43 |
* meaning to identifiers below the 1.3.6.1.4.1.42.2.17 node in the
|
|
44 |
* hierarchy, and other organizations can easily acquire the ability
|
|
45 |
* to assign such unique identifiers.
|
|
46 |
*
|
|
47 |
*
|
|
48 |
* @author David Brownell
|
|
49 |
* @author Amit Kapoor
|
|
50 |
* @author Hemma Prafullchandra
|
|
51 |
*/
|
|
52 |
final public
|
|
53 |
class ObjectIdentifier implements Serializable
|
|
54 |
{
|
|
55 |
/** use serialVersionUID from JDK 1.1. for interoperability */
|
|
56 |
private static final long serialVersionUID = 8697030238860181294L;
|
|
57 |
private static final int maxFirstComponent = 2;
|
|
58 |
private static final int maxSecondComponent = 39;
|
|
59 |
|
|
60 |
/**
|
|
61 |
* Constructs an object identifier from a string. This string
|
|
62 |
* should be of the form 1.23.34.45.56 etc.
|
|
63 |
*/
|
|
64 |
public ObjectIdentifier (String oid) throws IOException
|
|
65 |
{
|
|
66 |
int ch = '.';
|
|
67 |
int start = 0;
|
|
68 |
int end = 0;
|
|
69 |
|
|
70 |
// Calculate length of oid
|
|
71 |
componentLen = 0;
|
|
72 |
while ((end = oid.indexOf(ch,start)) != -1) {
|
|
73 |
start = end + 1;
|
|
74 |
componentLen += 1;
|
|
75 |
}
|
|
76 |
componentLen += 1;
|
|
77 |
components = new int[componentLen];
|
|
78 |
|
|
79 |
start = 0;
|
|
80 |
int i = 0;
|
|
81 |
String comp = null;
|
|
82 |
try {
|
|
83 |
while ((end = oid.indexOf(ch,start)) != -1) {
|
|
84 |
comp = oid.substring(start,end);
|
|
85 |
components[i++] = Integer.valueOf(comp).intValue();
|
|
86 |
start = end + 1;
|
|
87 |
}
|
|
88 |
comp = oid.substring(start);
|
|
89 |
components[i] = Integer.valueOf(comp).intValue();
|
|
90 |
} catch (Exception e) {
|
|
91 |
throw new IOException("ObjectIdentifier() -- Invalid format: "
|
|
92 |
+ e.toString(), e);
|
|
93 |
}
|
|
94 |
checkValidOid(components, componentLen);
|
|
95 |
this.stringForm = oid;
|
|
96 |
}
|
|
97 |
|
|
98 |
/**
|
|
99 |
* Check if the values make a legal OID. There must be at least 2
|
|
100 |
* components and they must be all non-negative. The first component
|
|
101 |
* should be 0,1 or 2. When the first component is 0 or 1, the
|
|
102 |
* second component should be less than or equal to 39
|
|
103 |
*
|
|
104 |
* @param values the components that will make the OID
|
|
105 |
* @param len the number of components to check. Note that the allocation
|
|
106 |
* size of <code>values</code> may be longer than <code>len</code>.
|
|
107 |
* In this case, only the first <code>len</code> items are checked.
|
|
108 |
* @exception IOException if this is not a legal OID
|
|
109 |
*/
|
|
110 |
private void checkValidOid(int[] values, int len) throws IOException {
|
|
111 |
if (values == null || len < 2) {
|
|
112 |
throw new IOException("ObjectIdentifier() -- " +
|
|
113 |
"Must be at least two oid components ");
|
|
114 |
}
|
|
115 |
|
|
116 |
for (int i=0; i<len; i++) {
|
|
117 |
if (values[i] < 0) {
|
|
118 |
throw new IOException("ObjectIdentifier() -- " +
|
|
119 |
"oid component #" + (i+1) + " must be non-negative ");
|
|
120 |
}
|
|
121 |
}
|
|
122 |
|
|
123 |
if (values[0] > maxFirstComponent) {
|
|
124 |
throw new IOException("ObjectIdentifier() -- " +
|
|
125 |
"First oid component is invalid ");
|
|
126 |
}
|
|
127 |
|
|
128 |
if (values[0] < 2 && values[1] > maxSecondComponent) {
|
|
129 |
throw new IOException("ObjectIdentifier() -- " +
|
|
130 |
"Second oid component is invalid ");
|
|
131 |
}
|
|
132 |
}
|
|
133 |
/**
|
|
134 |
* Constructs an object ID from an array of integers. This
|
|
135 |
* is used to construct constant object IDs.
|
|
136 |
*/
|
|
137 |
public ObjectIdentifier (int values []) throws IOException
|
|
138 |
{
|
|
139 |
checkValidOid(values, values.length);
|
|
140 |
components = values.clone();
|
|
141 |
componentLen = values.length;
|
|
142 |
}
|
|
143 |
|
|
144 |
/**
|
|
145 |
* Constructs an object ID from an ASN.1 encoded input stream.
|
|
146 |
* The encoding of the ID in the stream uses "DER", a BER/1 subset.
|
|
147 |
* In this case, that means a triple { typeId, length, data }.
|
|
148 |
*
|
|
149 |
* <P><STRONG>NOTE:</STRONG> When an exception is thrown, the
|
|
150 |
* input stream has not been returned to its "initial" state.
|
|
151 |
*
|
|
152 |
* @param in DER-encoded data holding an object ID
|
|
153 |
* @exception IOException indicates a decoding error
|
|
154 |
*/
|
|
155 |
public ObjectIdentifier (DerInputStream in)
|
|
156 |
throws IOException
|
|
157 |
{
|
|
158 |
byte type_id;
|
|
159 |
int bufferEnd;
|
|
160 |
|
|
161 |
/*
|
|
162 |
* Object IDs are a "universal" type, and their tag needs only
|
|
163 |
* one byte of encoding. Verify that the tag of this datum
|
|
164 |
* is that of an object ID.
|
|
165 |
*
|
|
166 |
* Then get and check the length of the ID's encoding. We set
|
|
167 |
* up so that we can use in.available() to check for the end of
|
|
168 |
* this value in the data stream.
|
|
169 |
*/
|
|
170 |
type_id = (byte) in.getByte ();
|
|
171 |
if (type_id != DerValue.tag_ObjectId)
|
|
172 |
throw new IOException (
|
|
173 |
"ObjectIdentifier() -- data isn't an object ID"
|
|
174 |
+ " (tag = " + type_id + ")"
|
|
175 |
);
|
|
176 |
|
|
177 |
bufferEnd = in.available () - in.getLength () - 1;
|
|
178 |
if (bufferEnd < 0)
|
|
179 |
throw new IOException (
|
|
180 |
"ObjectIdentifier() -- not enough data");
|
|
181 |
|
|
182 |
initFromEncoding (in, bufferEnd);
|
|
183 |
}
|
|
184 |
|
|
185 |
/*
|
|
186 |
* Build the OID from the rest of a DER input buffer; the tag
|
|
187 |
* and length have been removed/verified
|
|
188 |
*/
|
|
189 |
ObjectIdentifier (DerInputBuffer buf) throws IOException
|
|
190 |
{
|
|
191 |
initFromEncoding (new DerInputStream (buf), 0);
|
|
192 |
}
|
|
193 |
|
|
194 |
/**
|
|
195 |
* Private constructor for use by newInternal(). Dummy argument
|
|
196 |
* to avoid clash with the public constructor.
|
|
197 |
*/
|
|
198 |
private ObjectIdentifier(int[] components, boolean dummy) {
|
|
199 |
this.components = components;
|
|
200 |
this.componentLen = components.length;
|
|
201 |
}
|
|
202 |
|
|
203 |
/**
|
|
204 |
* Create a new ObjectIdentifier for internal use. The values are
|
|
205 |
* neither checked nor cloned.
|
|
206 |
*/
|
|
207 |
public static ObjectIdentifier newInternal(int[] values) {
|
|
208 |
return new ObjectIdentifier(values, true);
|
|
209 |
}
|
|
210 |
|
|
211 |
/*
|
|
212 |
* Helper function -- get the OID from a stream, after tag and
|
|
213 |
* length are verified.
|
|
214 |
*/
|
|
215 |
private void initFromEncoding (DerInputStream in, int bufferEnd)
|
|
216 |
throws IOException
|
|
217 |
{
|
|
218 |
|
|
219 |
/*
|
|
220 |
* Now get the components ("sub IDs") one at a time. We fill a
|
|
221 |
* temporary buffer, resizing it as needed.
|
|
222 |
*/
|
|
223 |
int component;
|
|
224 |
boolean first_subid = true;
|
|
225 |
|
|
226 |
for (components = new int [allocationQuantum], componentLen = 0;
|
|
227 |
in.available () > bufferEnd;
|
|
228 |
) {
|
|
229 |
component = getComponent (in);
|
|
230 |
if (component < 0) {
|
|
231 |
throw new IOException(
|
|
232 |
"ObjectIdentifier() -- " +
|
|
233 |
"component values must be nonnegative");
|
|
234 |
}
|
|
235 |
if (first_subid) {
|
|
236 |
int X, Y;
|
|
237 |
|
|
238 |
/*
|
|
239 |
* NOTE: the allocation quantum is large enough that we know
|
|
240 |
* we don't have to reallocate here!
|
|
241 |
*/
|
|
242 |
if (component < 40)
|
|
243 |
X = 0;
|
|
244 |
else if (component < 80)
|
|
245 |
X = 1;
|
|
246 |
else
|
|
247 |
X = 2;
|
|
248 |
Y = component - ( X * 40);
|
|
249 |
components [0] = X;
|
|
250 |
components [1] = Y;
|
|
251 |
componentLen = 2;
|
|
252 |
|
|
253 |
first_subid = false;
|
|
254 |
|
|
255 |
} else {
|
|
256 |
|
|
257 |
/*
|
|
258 |
* Other components are encoded less exotically. The only
|
|
259 |
* potential trouble is the need to grow the array.
|
|
260 |
*/
|
|
261 |
if (componentLen >= components.length) {
|
|
262 |
int tmp_components [];
|
|
263 |
|
|
264 |
tmp_components = new int [components.length
|
|
265 |
+ allocationQuantum];
|
|
266 |
System.arraycopy (components, 0, tmp_components, 0,
|
|
267 |
components.length);
|
|
268 |
components = tmp_components;
|
|
269 |
}
|
|
270 |
components [componentLen++] = component;
|
|
271 |
}
|
|
272 |
}
|
|
273 |
|
|
274 |
checkValidOid(components, componentLen);
|
|
275 |
|
|
276 |
/*
|
|
277 |
* Final sanity check -- if we didn't use exactly the number of bytes
|
|
278 |
* specified, something's quite wrong.
|
|
279 |
*/
|
|
280 |
if (in.available () != bufferEnd) {
|
|
281 |
throw new IOException (
|
|
282 |
"ObjectIdentifier() -- malformed input data");
|
|
283 |
}
|
|
284 |
}
|
|
285 |
|
|
286 |
|
|
287 |
/*
|
|
288 |
* n.b. the only public interface is DerOutputStream.putOID()
|
|
289 |
*/
|
|
290 |
void encode (DerOutputStream out) throws IOException
|
|
291 |
{
|
|
292 |
DerOutputStream bytes = new DerOutputStream ();
|
|
293 |
int i;
|
|
294 |
|
|
295 |
// According to ISO X.660, when the 1st component is 0 or 1, the 2nd
|
|
296 |
// component is restricted to be less than or equal to 39, thus make
|
|
297 |
// it small enough to be encoded into one single byte.
|
|
298 |
if (components[0] < 2) {
|
|
299 |
bytes.write ((components [0] * 40) + components [1]);
|
|
300 |
} else {
|
|
301 |
putComponent(bytes, (components [0] * 40) + components [1]);
|
|
302 |
}
|
|
303 |
for (i = 2; i < componentLen; i++)
|
|
304 |
putComponent (bytes, components [i]);
|
|
305 |
|
|
306 |
/*
|
|
307 |
* Now that we've constructed the component, encode
|
|
308 |
* it in the stream we were given.
|
|
309 |
*/
|
|
310 |
out.write (DerValue.tag_ObjectId, bytes);
|
|
311 |
}
|
|
312 |
|
|
313 |
/*
|
|
314 |
* Tricky OID component parsing technique ... note that one bit
|
|
315 |
* per octet is lost, this returns at most 28 bits of component.
|
|
316 |
* Also, notice this parses in big-endian format.
|
|
317 |
*/
|
|
318 |
private static int getComponent (DerInputStream in)
|
|
319 |
throws IOException
|
|
320 |
{
|
|
321 |
int retval, i, tmp;
|
|
322 |
|
|
323 |
for (i = 0, retval = 0; i < 4; i++) {
|
|
324 |
retval <<= 7;
|
|
325 |
tmp = in.getByte ();
|
|
326 |
retval |= (tmp & 0x07f);
|
|
327 |
if ((tmp & 0x080) == 0)
|
|
328 |
return retval;
|
|
329 |
}
|
|
330 |
|
|
331 |
throw new IOException ("ObjectIdentifier() -- component value too big");
|
|
332 |
}
|
|
333 |
|
|
334 |
/*
|
|
335 |
* Reverse of the above routine. Notice it needs to emit in
|
|
336 |
* big-endian form, so it buffers the output until it's ready.
|
|
337 |
* (Minimum length encoding is a DER requirement.)
|
|
338 |
*/
|
|
339 |
private static void putComponent (DerOutputStream out, int val)
|
|
340 |
throws IOException
|
|
341 |
{
|
|
342 |
int i;
|
|
343 |
// TODO: val must be <128*128*128*128 here, otherwise, 4 bytes is not
|
|
344 |
// enough to hold it. Will address this later.
|
|
345 |
byte buf [] = new byte [4] ;
|
|
346 |
|
|
347 |
for (i = 0; i < 4; i++) {
|
|
348 |
buf [i] = (byte) (val & 0x07f);
|
|
349 |
val >>>= 7;
|
|
350 |
if (val == 0)
|
|
351 |
break;
|
|
352 |
}
|
|
353 |
for ( ; i > 0; --i)
|
|
354 |
out.write (buf [i] | 0x080);
|
|
355 |
out.write (buf [0]);
|
|
356 |
}
|
|
357 |
|
|
358 |
// XXX this API should probably facilitate the JDK sort utility
|
|
359 |
|
|
360 |
/**
|
|
361 |
* Compares this identifier with another, for sorting purposes.
|
|
362 |
* An identifier does not precede itself.
|
|
363 |
*
|
|
364 |
* @param other identifer that may precede this one.
|
|
365 |
* @return true iff <em>other</em> precedes this one
|
|
366 |
* in a particular sorting order.
|
|
367 |
*/
|
|
368 |
public boolean precedes (ObjectIdentifier other)
|
|
369 |
{
|
|
370 |
int i;
|
|
371 |
|
|
372 |
// shorter IDs go first
|
|
373 |
if (other == this || componentLen < other.componentLen)
|
|
374 |
return false;
|
|
375 |
if (other.componentLen < componentLen)
|
|
376 |
return true;
|
|
377 |
|
|
378 |
// for each component, the lesser component goes first
|
|
379 |
for (i = 0; i < componentLen; i++) {
|
|
380 |
if (other.components [i] < components [i])
|
|
381 |
return true;
|
|
382 |
}
|
|
383 |
|
|
384 |
// identical IDs don't precede each other
|
|
385 |
return false;
|
|
386 |
}
|
|
387 |
|
|
388 |
/**
|
|
389 |
* @deprecated Use equals((Object)oid)
|
|
390 |
*/
|
|
391 |
@Deprecated
|
|
392 |
public boolean equals(ObjectIdentifier other) {
|
|
393 |
return equals((Object)other);
|
|
394 |
}
|
|
395 |
|
|
396 |
/**
|
|
397 |
* Compares this identifier with another, for equality.
|
|
398 |
*
|
|
399 |
* @return true iff the names are identical.
|
|
400 |
*/
|
|
401 |
public boolean equals(Object obj) {
|
|
402 |
if (this == obj) {
|
|
403 |
return true;
|
|
404 |
}
|
|
405 |
if (obj instanceof ObjectIdentifier == false) {
|
|
406 |
return false;
|
|
407 |
}
|
|
408 |
ObjectIdentifier other = (ObjectIdentifier)obj;
|
|
409 |
if (componentLen != other.componentLen) {
|
|
410 |
return false;
|
|
411 |
}
|
|
412 |
for (int i = 0; i < componentLen; i++) {
|
|
413 |
if (components[i] != other.components[i]) {
|
|
414 |
return false;
|
|
415 |
}
|
|
416 |
}
|
|
417 |
return true;
|
|
418 |
}
|
|
419 |
|
|
420 |
public int hashCode() {
|
|
421 |
int h = componentLen;
|
|
422 |
for (int i = 0; i < componentLen; i++) {
|
|
423 |
h += components[i] * 37;
|
|
424 |
}
|
|
425 |
return h;
|
|
426 |
}
|
|
427 |
|
|
428 |
/**
|
|
429 |
* Returns a string form of the object ID. The format is the
|
|
430 |
* conventional "dot" notation for such IDs, without any
|
|
431 |
* user-friendly descriptive strings, since those strings
|
|
432 |
* will not be understood everywhere.
|
|
433 |
*/
|
|
434 |
public String toString() {
|
|
435 |
String s = stringForm;
|
|
436 |
if (s == null) {
|
|
437 |
StringBuffer sb = new StringBuffer(componentLen * 4);
|
|
438 |
for (int i = 0; i < componentLen; i++) {
|
|
439 |
if (i != 0) {
|
|
440 |
sb.append('.');
|
|
441 |
}
|
|
442 |
sb.append(components[i]);
|
|
443 |
}
|
|
444 |
s = sb.toString();
|
|
445 |
stringForm = s;
|
|
446 |
}
|
|
447 |
return s;
|
|
448 |
}
|
|
449 |
|
|
450 |
/*
|
|
451 |
* To simplify, we assume no individual component of an object ID is
|
|
452 |
* larger than 32 bits. Then we represent the path from the root as
|
|
453 |
* an array that's (usually) only filled at the beginning.
|
|
454 |
*/
|
|
455 |
private int components []; // path from root
|
|
456 |
private int componentLen; // how much is used.
|
|
457 |
|
|
458 |
private transient volatile String stringForm;
|
|
459 |
|
|
460 |
private static final int allocationQuantum = 5; // >= 2
|
|
461 |
}
|