001package org.apache.commons.ssl.org.bouncycastle.asn1; 002 003import java.io.ByteArrayOutputStream; 004import java.io.IOException; 005 006/** 007 * Class representing the DER-type External 008 */ 009public class DERExternal 010 extends ASN1Primitive 011{ 012 private ASN1ObjectIdentifier directReference; 013 private ASN1Integer indirectReference; 014 private ASN1Primitive dataValueDescriptor; 015 private int encoding; 016 private ASN1Primitive externalContent; 017 018 public DERExternal(ASN1EncodableVector vector) 019 { 020 int offset = 0; 021 022 ASN1Primitive enc = getObjFromVector(vector, offset); 023 if (enc instanceof ASN1ObjectIdentifier) 024 { 025 directReference = (ASN1ObjectIdentifier)enc; 026 offset++; 027 enc = getObjFromVector(vector, offset); 028 } 029 if (enc instanceof ASN1Integer) 030 { 031 indirectReference = (ASN1Integer) enc; 032 offset++; 033 enc = getObjFromVector(vector, offset); 034 } 035 if (!(enc instanceof DERTaggedObject)) 036 { 037 dataValueDescriptor = (ASN1Primitive) enc; 038 offset++; 039 enc = getObjFromVector(vector, offset); 040 } 041 042 if (vector.size() != offset + 1) 043 { 044 throw new IllegalArgumentException("input vector too large"); 045 } 046 047 if (!(enc instanceof DERTaggedObject)) 048 { 049 throw new IllegalArgumentException("No tagged object found in vector. Structure doesn't seem to be of type External"); 050 } 051 DERTaggedObject obj = (DERTaggedObject)enc; 052 setEncoding(obj.getTagNo()); 053 externalContent = obj.getObject(); 054 } 055 056 private ASN1Primitive getObjFromVector(ASN1EncodableVector v, int index) 057 { 058 if (v.size() <= index) 059 { 060 throw new IllegalArgumentException("too few objects in input vector"); 061 } 062 063 return v.get(index).toASN1Primitive(); 064 } 065 /** 066 * Creates a new instance of DERExternal 067 * See X.690 for more informations about the meaning of these parameters 068 * @param directReference The direct reference or <code>null</code> if not set. 069 * @param indirectReference The indirect reference or <code>null</code> if not set. 070 * @param dataValueDescriptor The data value descriptor or <code>null</code> if not set. 071 * @param externalData The external data in its encoded form. 072 */ 073 public DERExternal(ASN1ObjectIdentifier directReference, ASN1Integer indirectReference, ASN1Primitive dataValueDescriptor, DERTaggedObject externalData) 074 { 075 this(directReference, indirectReference, dataValueDescriptor, externalData.getTagNo(), externalData.toASN1Primitive()); 076 } 077 078 /** 079 * Creates a new instance of DERExternal. 080 * See X.690 for more informations about the meaning of these parameters 081 * @param directReference The direct reference or <code>null</code> if not set. 082 * @param indirectReference The indirect reference or <code>null</code> if not set. 083 * @param dataValueDescriptor The data value descriptor or <code>null</code> if not set. 084 * @param encoding The encoding to be used for the external data 085 * @param externalData The external data 086 */ 087 public DERExternal(ASN1ObjectIdentifier directReference, ASN1Integer indirectReference, ASN1Primitive dataValueDescriptor, int encoding, ASN1Primitive externalData) 088 { 089 setDirectReference(directReference); 090 setIndirectReference(indirectReference); 091 setDataValueDescriptor(dataValueDescriptor); 092 setEncoding(encoding); 093 setExternalContent(externalData.toASN1Primitive()); 094 } 095 096 /* (non-Javadoc) 097 * @see java.lang.Object#hashCode() 098 */ 099 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 boolean isConstructed() 119 { 120 return true; 121 } 122 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 */ 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 */ 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 */ 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 */ 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 */ 218 public int getEncoding() 219 { 220 return encoding; 221 } 222 223 /** 224 * Returns the content of this element 225 * @return The content 226 */ 227 public ASN1Primitive getExternalContent() 228 { 229 return externalContent; 230 } 231 232 /** 233 * Returns the indirect reference of this element 234 * @return The reference 235 */ 236 public ASN1Integer getIndirectReference() 237 { 238 return indirectReference; 239 } 240 241 /** 242 * Sets the data value descriptor 243 * @param dataValueDescriptor The descriptor 244 */ 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 */ 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 */ 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 */ 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 */ 290 private void setIndirectReference(ASN1Integer indirectReference) 291 { 292 this.indirectReference = indirectReference; 293 } 294}