1 package org.bouncycastle.asn1; 2 3 import java.io.IOException; 4 import java.math.BigInteger; 5 6 import org.bouncycastle.util.Arrays; 7 8 /** 9 * Class representing the ASN.1 ENUMERATED type. 10 */ 11 public class ASN1Enumerated 12 extends ASN1Primitive 13 { 14 private final byte[] bytes; 15 16 /** 17 * return an enumerated from the passed in object 18 * 19 * @param obj an ASN1Enumerated or an object that can be converted into one. 20 * @exception IllegalArgumentException if the object cannot be converted. 21 * @return an ASN1Enumerated instance, or null. 22 */ getInstance( Object obj)23 public static ASN1Enumerated getInstance( 24 Object obj) 25 { 26 if (obj == null || obj instanceof ASN1Enumerated) 27 { 28 return (ASN1Enumerated)obj; 29 } 30 31 if (obj instanceof byte[]) 32 { 33 try 34 { 35 return (ASN1Enumerated)fromByteArray((byte[])obj); 36 } 37 catch (Exception e) 38 { 39 throw new IllegalArgumentException("encoding error in getInstance: " + e.toString()); 40 } 41 } 42 43 throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); 44 } 45 46 /** 47 * return an Enumerated from a tagged object. 48 * 49 * @param obj the tagged object holding the object we want 50 * @param explicit true if the object is meant to be explicitly 51 * tagged false otherwise. 52 * @exception IllegalArgumentException if the tagged object cannot 53 * be converted. 54 * @return an ASN1Enumerated instance, or null. 55 */ getInstance( ASN1TaggedObject obj, boolean explicit)56 public static ASN1Enumerated getInstance( 57 ASN1TaggedObject obj, 58 boolean explicit) 59 { 60 ASN1Primitive o = obj.getObject(); 61 62 if (explicit || o instanceof ASN1Enumerated) 63 { 64 return getInstance(o); 65 } 66 else 67 { 68 return fromOctetString(((ASN1OctetString)o).getOctets()); 69 } 70 } 71 72 /** 73 * Constructor from int. 74 * 75 * @param value the value of this enumerated. 76 */ ASN1Enumerated( int value)77 public ASN1Enumerated( 78 int value) 79 { 80 bytes = BigInteger.valueOf(value).toByteArray(); 81 } 82 83 /** 84 * Constructor from BigInteger 85 * 86 * @param value the value of this enumerated. 87 */ ASN1Enumerated( BigInteger value)88 public ASN1Enumerated( 89 BigInteger value) 90 { 91 bytes = value.toByteArray(); 92 } 93 94 /** 95 * Constructor from encoded BigInteger. 96 * 97 * @param bytes the value of this enumerated as an encoded BigInteger (signed). 98 */ ASN1Enumerated( byte[] bytes)99 public ASN1Enumerated( 100 byte[] bytes) 101 { 102 if (bytes.length > 1) 103 { 104 if (bytes[0] == 0 && (bytes[1] & 0x80) == 0) 105 { 106 throw new IllegalArgumentException("malformed enumerated"); 107 } 108 if (bytes[0] == (byte)0xff && (bytes[1] & 0x80) != 0) 109 { 110 throw new IllegalArgumentException("malformed enumerated"); 111 } 112 } 113 this.bytes = Arrays.clone(bytes); 114 } 115 getValue()116 public BigInteger getValue() 117 { 118 return new BigInteger(bytes); 119 } 120 isConstructed()121 boolean isConstructed() 122 { 123 return false; 124 } 125 encodedLength()126 int encodedLength() 127 { 128 return 1 + StreamUtil.calculateBodyLength(bytes.length) + bytes.length; 129 } 130 encode( ASN1OutputStream out)131 void encode( 132 ASN1OutputStream out) 133 throws IOException 134 { 135 out.writeEncoded(BERTags.ENUMERATED, bytes); 136 } 137 asn1Equals( ASN1Primitive o)138 boolean asn1Equals( 139 ASN1Primitive o) 140 { 141 if (!(o instanceof ASN1Enumerated)) 142 { 143 return false; 144 } 145 146 ASN1Enumerated other = (ASN1Enumerated)o; 147 148 return Arrays.areEqual(this.bytes, other.bytes); 149 } 150 hashCode()151 public int hashCode() 152 { 153 return Arrays.hashCode(bytes); 154 } 155 156 private static ASN1Enumerated[] cache = new ASN1Enumerated[12]; 157 fromOctetString(byte[] enc)158 static ASN1Enumerated fromOctetString(byte[] enc) 159 { 160 if (enc.length > 1) 161 { 162 return new ASN1Enumerated(enc); 163 } 164 165 if (enc.length == 0) 166 { 167 throw new IllegalArgumentException("ENUMERATED has zero length"); 168 } 169 int value = enc[0] & 0xff; 170 171 if (value >= cache.length) 172 { 173 return new ASN1Enumerated(Arrays.clone(enc)); 174 } 175 176 ASN1Enumerated possibleMatch = cache[value]; 177 178 if (possibleMatch == null) 179 { 180 possibleMatch = cache[value] = new ASN1Enumerated(Arrays.clone(enc)); 181 } 182 183 return possibleMatch; 184 } 185 } 186