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 ASN1Primitive 11 { 12 private ASN1ObjectIdentifier directReference; 13 private ASN1Integer indirectReference; 14 private ASN1Primitive dataValueDescriptor; 15 private int encoding; 16 private ASN1Primitive externalContent; 17 DERExternal(ASN1EncodableVector vector)18 public DERExternal(ASN1EncodableVector vector) 19 { 20 int offset = 0; 21 22 ASN1Primitive enc = getObjFromVector(vector, offset); 23 if (enc instanceof ASN1ObjectIdentifier) 24 { 25 directReference = (ASN1ObjectIdentifier)enc; 26 offset++; 27 enc = getObjFromVector(vector, offset); 28 } 29 if (enc instanceof ASN1Integer) 30 { 31 indirectReference = (ASN1Integer) enc; 32 offset++; 33 enc = getObjFromVector(vector, offset); 34 } 35 if (!(enc instanceof DERTaggedObject)) 36 { 37 dataValueDescriptor = (ASN1Primitive) 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 getObjFromVector(ASN1EncodableVector v, int index)56 private ASN1Primitive 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).toASN1Primitive(); 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 */ DERExternal(ASN1ObjectIdentifier directReference, ASN1Integer indirectReference, ASN1Primitive dataValueDescriptor, DERTaggedObject externalData)73 public DERExternal(ASN1ObjectIdentifier directReference, ASN1Integer indirectReference, ASN1Primitive dataValueDescriptor, DERTaggedObject externalData) 74 { 75 this(directReference, indirectReference, dataValueDescriptor, externalData.getTagNo(), externalData.toASN1Primitive()); 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 */ DERExternal(ASN1ObjectIdentifier directReference, ASN1Integer indirectReference, ASN1Primitive dataValueDescriptor, int encoding, ASN1Primitive externalData)87 public DERExternal(ASN1ObjectIdentifier directReference, ASN1Integer indirectReference, ASN1Primitive dataValueDescriptor, int encoding, ASN1Primitive externalData) 88 { 89 setDirectReference(directReference); 90 setIndirectReference(indirectReference); 91 setDataValueDescriptor(dataValueDescriptor); 92 setEncoding(encoding); 93 setExternalContent(externalData.toASN1Primitive()); 94 } 95 96 /* (non-Javadoc) 97 * @see java.lang.Object#hashCode() 98 */ hashCode()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 isConstructed()118 boolean isConstructed() 119 { 120 return true; 121 } 122 encodedLength()123 int encodedLength() 124 throws IOException 125 { 126 return this.getEncoded().length; 127 } 128 129 /* (non-Javadoc) 130 * @see org.bouncycastle.asn1.ASN1Primitive#encode(org.bouncycastle.asn1.DEROutputStream) 131 */ encode(ASN1OutputStream out)132 void encode(ASN1OutputStream out) 133 throws IOException 134 { 135 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 136 if (directReference != null) 137 { 138 baos.write(directReference.getEncoded(ASN1Encoding.DER)); 139 } 140 if (indirectReference != null) 141 { 142 baos.write(indirectReference.getEncoded(ASN1Encoding.DER)); 143 } 144 if (dataValueDescriptor != null) 145 { 146 baos.write(dataValueDescriptor.getEncoded(ASN1Encoding.DER)); 147 } 148 DERTaggedObject obj = new DERTaggedObject(true, encoding, externalContent); 149 baos.write(obj.getEncoded(ASN1Encoding.DER)); 150 out.writeEncoded(BERTags.CONSTRUCTED, BERTags.EXTERNAL, baos.toByteArray()); 151 } 152 153 /* (non-Javadoc) 154 * @see org.bouncycastle.asn1.ASN1Primitive#asn1Equals(org.bouncycastle.asn1.ASN1Primitive) 155 */ asn1Equals(ASN1Primitive o)156 boolean asn1Equals(ASN1Primitive o) 157 { 158 if (!(o instanceof DERExternal)) 159 { 160 return false; 161 } 162 if (this == o) 163 { 164 return true; 165 } 166 DERExternal other = (DERExternal)o; 167 if (directReference != null) 168 { 169 if (other.directReference == null || !other.directReference.equals(directReference)) 170 { 171 return false; 172 } 173 } 174 if (indirectReference != null) 175 { 176 if (other.indirectReference == null || !other.indirectReference.equals(indirectReference)) 177 { 178 return false; 179 } 180 } 181 if (dataValueDescriptor != null) 182 { 183 if (other.dataValueDescriptor == null || !other.dataValueDescriptor.equals(dataValueDescriptor)) 184 { 185 return false; 186 } 187 } 188 return externalContent.equals(other.externalContent); 189 } 190 191 /** 192 * Returns the data value descriptor 193 * @return The descriptor 194 */ getDataValueDescriptor()195 public ASN1Primitive getDataValueDescriptor() 196 { 197 return dataValueDescriptor; 198 } 199 200 /** 201 * Returns the direct reference of the external element 202 * @return The reference 203 */ getDirectReference()204 public ASN1ObjectIdentifier getDirectReference() 205 { 206 return directReference; 207 } 208 209 /** 210 * Returns the encoding of the content. Valid values are 211 * <ul> 212 * <li><code>0</code> single-ASN1-type</li> 213 * <li><code>1</code> OCTET STRING</li> 214 * <li><code>2</code> BIT STRING</li> 215 * </ul> 216 * @return The encoding 217 */ getEncoding()218 public int getEncoding() 219 { 220 return encoding; 221 } 222 223 /** 224 * Returns the content of this element 225 * @return The content 226 */ getExternalContent()227 public ASN1Primitive getExternalContent() 228 { 229 return externalContent; 230 } 231 232 /** 233 * Returns the indirect reference of this element 234 * @return The reference 235 */ getIndirectReference()236 public ASN1Integer getIndirectReference() 237 { 238 return indirectReference; 239 } 240 241 /** 242 * Sets the data value descriptor 243 * @param dataValueDescriptor The descriptor 244 */ setDataValueDescriptor(ASN1Primitive dataValueDescriptor)245 private void setDataValueDescriptor(ASN1Primitive dataValueDescriptor) 246 { 247 this.dataValueDescriptor = dataValueDescriptor; 248 } 249 250 /** 251 * Sets the direct reference of the external element 252 * @param directReferemce The reference 253 */ setDirectReference(ASN1ObjectIdentifier directReferemce)254 private void setDirectReference(ASN1ObjectIdentifier directReferemce) 255 { 256 this.directReference = directReferemce; 257 } 258 259 /** 260 * Sets the encoding of the content. Valid values are 261 * <ul> 262 * <li><code>0</code> single-ASN1-type</li> 263 * <li><code>1</code> OCTET STRING</li> 264 * <li><code>2</code> BIT STRING</li> 265 * </ul> 266 * @param encoding The encoding 267 */ setEncoding(int encoding)268 private void setEncoding(int encoding) 269 { 270 if (encoding < 0 || encoding > 2) 271 { 272 throw new IllegalArgumentException("invalid encoding value: " + encoding); 273 } 274 this.encoding = encoding; 275 } 276 277 /** 278 * Sets the content of this element 279 * @param externalContent The content 280 */ setExternalContent(ASN1Primitive externalContent)281 private void setExternalContent(ASN1Primitive externalContent) 282 { 283 this.externalContent = externalContent; 284 } 285 286 /** 287 * Sets the indirect reference of this element 288 * @param indirectReference The reference 289 */ setIndirectReference(ASN1Integer indirectReference)290 private void setIndirectReference(ASN1Integer indirectReference) 291 { 292 this.indirectReference = indirectReference; 293 } 294 } 295