1 package org.bouncycastle.asn1; 2 3 import java.io.ByteArrayOutputStream; 4 import java.io.IOException; 5 6 /** 7 * Class representing the DER-type External 8 */ 9 public class DERExternal 10 extends ASN1Object 11 { 12 private DERObjectIdentifier directReference; 13 private DERInteger indirectReference; 14 private ASN1Object dataValueDescriptor; 15 private int encoding; 16 private DERObject externalContent; 17 18 public DERExternal(ASN1EncodableVector vector) 19 { 20 int offset = 0; 21 22 DERObject enc = getObjFromVector(vector, offset); 23 if (enc instanceof DERObjectIdentifier) 24 { 25 directReference = (DERObjectIdentifier)enc; 26 offset++; 27 enc = getObjFromVector(vector, offset); 28 } 29 if (enc instanceof DERInteger) 30 { 31 indirectReference = (DERInteger) enc; 32 offset++; 33 enc = getObjFromVector(vector, offset); 34 } 35 if (!(enc instanceof DERTaggedObject)) 36 { 37 dataValueDescriptor = (ASN1Object) enc; 38 offset++; 39 enc = getObjFromVector(vector, offset); 40 } 41 42 if (vector.size() != offset + 1) 43 { 44 throw new IllegalArgumentException("input vector too large"); 45 } 46 47 if (!(enc instanceof DERTaggedObject)) 48 { 49 throw new IllegalArgumentException("No tagged object found in vector. Structure doesn't seem to be of type External"); 50 } 51 DERTaggedObject obj = (DERTaggedObject)enc; 52 setEncoding(obj.getTagNo()); 53 externalContent = obj.getObject(); 54 } 55 56 private DERObject getObjFromVector(ASN1EncodableVector v, int index) 57 { 58 if (v.size() <= index) 59 { 60 throw new IllegalArgumentException("too few objects in input vector"); 61 } 62 63 return v.get(index).getDERObject(); 64 } 65 /** 66 * Creates a new instance of DERExternal 67 * See X.690 for more informations about the meaning of these parameters 68 * @param directReference The direct reference or <code>null</code> if not set. 69 * @param indirectReference The indirect reference or <code>null</code> if not set. 70 * @param dataValueDescriptor The data value descriptor or <code>null</code> if not set. 71 * @param externalData The external data in its encoded form. 72 */ 73 public DERExternal(DERObjectIdentifier directReference, DERInteger indirectReference, ASN1Object dataValueDescriptor, DERTaggedObject externalData) 74 { 75 this(directReference, indirectReference, dataValueDescriptor, externalData.getTagNo(), externalData.getDERObject()); 76 } 77 78 /** 79 * Creates a new instance of DERExternal. 80 * See X.690 for more informations about the meaning of these parameters 81 * @param directReference The direct reference or <code>null</code> if not set. 82 * @param indirectReference The indirect reference or <code>null</code> if not set. 83 * @param dataValueDescriptor The data value descriptor or <code>null</code> if not set. 84 * @param encoding The encoding to be used for the external data 85 * @param externalData The external data 86 */ 87 public DERExternal(DERObjectIdentifier directReference, DERInteger indirectReference, ASN1Object dataValueDescriptor, int encoding, DERObject externalData) 88 { 89 setDirectReference(directReference); 90 setIndirectReference(indirectReference); 91 setDataValueDescriptor(dataValueDescriptor); 92 setEncoding(encoding); 93 setExternalContent(externalData.getDERObject()); 94 } 95 96 /* (non-Javadoc) 97 * @see java.lang.Object#hashCode() 98 */ 99 public int hashCode() 100 { 101 int ret = 0; 102 if (directReference != null) 103 { 104 ret = directReference.hashCode(); 105 } 106 if (indirectReference != null) 107 { 108 ret ^= indirectReference.hashCode(); 109 } 110 if (dataValueDescriptor != null) 111 { 112 ret ^= dataValueDescriptor.hashCode(); 113 } 114 ret ^= externalContent.hashCode(); 115 return ret; 116 } 117 118 /* (non-Javadoc) 119 * @see org.bouncycastle.asn1.DERObject#encode(org.bouncycastle.asn1.DEROutputStream) 120 */ 121 void encode(DEROutputStream out) 122 throws IOException 123 { 124 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 125 if (directReference != null) 126 { 127 baos.write(directReference.getDEREncoded()); 128 } 129 if (indirectReference != null) 130 { 131 baos.write(indirectReference.getDEREncoded()); 132 } 133 if (dataValueDescriptor != null) 134 { 135 baos.write(dataValueDescriptor.getDEREncoded()); 136 } 137 DERTaggedObject obj = new DERTaggedObject(encoding, externalContent); 138 baos.write(obj.getDEREncoded()); 139 out.writeEncoded(DERTags.CONSTRUCTED, DERTags.EXTERNAL, baos.toByteArray()); 140 } 141 142 /* (non-Javadoc) 143 * @see org.bouncycastle.asn1.ASN1Object#asn1Equals(org.bouncycastle.asn1.DERObject) 144 */ 145 boolean asn1Equals(DERObject o) 146 { 147 if (!(o instanceof DERExternal)) 148 { 149 return false; 150 } 151 if (this == o) 152 { 153 return true; 154 } 155 DERExternal other = (DERExternal)o; 156 if (directReference != null) 157 { 158 if (other.directReference == null || !other.directReference.equals(directReference)) 159 { 160 return false; 161 } 162 } 163 if (indirectReference != null) 164 { 165 if (other.indirectReference == null || !other.indirectReference.equals(indirectReference)) 166 { 167 return false; 168 } 169 } 170 if (dataValueDescriptor != null) 171 { 172 if (other.dataValueDescriptor == null || !other.dataValueDescriptor.equals(dataValueDescriptor)) 173 { 174 return false; 175 } 176 } 177 return externalContent.equals(other.externalContent); 178 } 179 180 /** 181 * Returns the data value descriptor 182 * @return The descriptor 183 */ 184 public ASN1Object getDataValueDescriptor() 185 { 186 return dataValueDescriptor; 187 } 188 189 /** 190 * Returns the direct reference of the external element 191 * @return The reference 192 */ 193 public DERObjectIdentifier getDirectReference() 194 { 195 return directReference; 196 } 197 198 /** 199 * Returns the encoding of the content. Valid values are 200 * <ul> 201 * <li><code>0</code> single-ASN1-type</li> 202 * <li><code>1</code> OCTET STRING</li> 203 * <li><code>2</code> BIT STRING</li> 204 * </ul> 205 * @return The encoding 206 */ 207 public int getEncoding() 208 { 209 return encoding; 210 } 211 212 /** 213 * Returns the content of this element 214 * @return The content 215 */ 216 public DERObject getExternalContent() 217 { 218 return externalContent; 219 } 220 221 /** 222 * Returns the indirect reference of this element 223 * @return The reference 224 */ 225 public DERInteger getIndirectReference() 226 { 227 return indirectReference; 228 } 229 230 /** 231 * Sets the data value descriptor 232 * @param dataValueDescriptor The descriptor 233 */ 234 private void setDataValueDescriptor(ASN1Object dataValueDescriptor) 235 { 236 this.dataValueDescriptor = dataValueDescriptor; 237 } 238 239 /** 240 * Sets the direct reference of the external element 241 * @param directReferemce The reference 242 */ 243 private void setDirectReference(DERObjectIdentifier directReferemce) 244 { 245 this.directReference = directReferemce; 246 } 247 248 /** 249 * Sets the encoding of the content. Valid values are 250 * <ul> 251 * <li><code>0</code> single-ASN1-type</li> 252 * <li><code>1</code> OCTET STRING</li> 253 * <li><code>2</code> BIT STRING</li> 254 * </ul> 255 * @param encoding The encoding 256 */ 257 private void setEncoding(int encoding) 258 { 259 if (encoding < 0 || encoding > 2) 260 { 261 throw new IllegalArgumentException("invalid encoding value: " + encoding); 262 } 263 this.encoding = encoding; 264 } 265 266 /** 267 * Sets the content of this element 268 * @param externalContent The content 269 */ 270 private void setExternalContent(DERObject externalContent) 271 { 272 this.externalContent = externalContent; 273 } 274 275 /** 276 * Sets the indirect reference of this element 277 * @param indirectReference The reference 278 */ 279 private void setIndirectReference(DERInteger indirectReference) 280 { 281 this.indirectReference = indirectReference; 282 } 283 } 284