Home | History | Annotate | Download | only in asn1
      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 
     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 
     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      */
     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      */
     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      */
     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     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 }
    295