Home | History | Annotate | Download | only in asn1
      1 package org.bouncycastle.asn1;
      2 
      3 import java.io.IOException;
      4 import java.util.Enumeration;
      5 
      6 /**
      7  * The DLSet encodes ASN.1 SET value without element ordering,
      8  * and always using definite length form.
      9  * <hr>
     10  * <h2>X.690</h2>
     11  * <h3>8: Basic encoding rules</h3>
     12  * <h4>8.11 Encoding of a set value </h4>
     13  * <b>8.11.1</b> The encoding of a set value shall be constructed
     14  * <p>
     15  * <b>8.11.2</b> The contents octets shall consist of the complete
     16  * encoding of a data value from each of the types listed in the
     17  * ASN.1 definition of the set type, in an order chosen by the sender,
     18  * unless the type was referenced with the keyword
     19  * <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>.
     20  * <p>
     21  * <b>8.11.3</b> The encoding of a data value may, but need not,
     22  * be present for a type which was referenced with the keyword
     23  * <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>.
     24  * <blockquote>
     25  * NOTE &mdash; The order of data values in a set value is not significant,
     26  * and places no constraints on the order during transfer
     27  * </blockquote>
     28  * <h3>9: Canonical encoding rules</h3>
     29  * <h4>9.3 Set components</h4>
     30  * The encodings of the component values of a set value shall
     31  * appear in an order determined by their tags as specified
     32  * in 8.6 of ITU-T Rec. X.680 | ISO/IEC 8824-1.
     33  * Additionally, for the purposes of determining the order in which
     34  * components are encoded when one or more component is an untagged
     35  * choice type, each untagged choice type is ordered as though it
     36  * has a tag equal to that of the smallest tag in that choice type
     37  * or any untagged choice types nested within.
     38  * <h3>10: Distinguished encoding rules</h3>
     39  * <h4>10.3 Set components</h4>
     40  * The encodings of the component values of a set value shall appear
     41  * in an order determined by their tags as specified
     42  * in 8.6 of ITU-T Rec. X.680 | ISO/IEC 8824-1.
     43  * <blockquote>
     44  * NOTE &mdash; Where a component of the set is an untagged choice type,
     45  * the location of that component in the ordering will depend on
     46  * the tag of the choice component being encoded.
     47  * </blockquote>
     48  * <h3>11: Restrictions on BER employed by both CER and DER</h3>
     49  * <h4>11.5 Set and sequence components with default value </h4>
     50  * The encoding of a set value or sequence value shall not include
     51  * an encoding for any component value which is equal to
     52  * its default value.
     53  */
     54 public class DLSet
     55     extends ASN1Set
     56 {
     57     private int bodyLength = -1;
     58 
     59     /**
     60      * create an empty set
     61      */
     62     public DLSet()
     63     {
     64     }
     65 
     66     /**
     67      * @param obj - a single object that makes up the set.
     68      */
     69     public DLSet(
     70         ASN1Encodable obj)
     71     {
     72         super(obj);
     73     }
     74 
     75     /**
     76      * @param v - a vector of objects making up the set.
     77      */
     78     public DLSet(
     79         ASN1EncodableVector v)
     80     {
     81         super(v, false);
     82     }
     83 
     84     /**
     85      * create a set from an array of objects.
     86      */
     87     public DLSet(
     88         ASN1Encodable[] a)
     89     {
     90         super(a, false);
     91     }
     92 
     93     private int getBodyLength()
     94         throws IOException
     95     {
     96         if (bodyLength < 0)
     97         {
     98             int length = 0;
     99 
    100             for (Enumeration e = this.getObjects(); e.hasMoreElements();)
    101             {
    102                 Object obj = e.nextElement();
    103 
    104                 length += ((ASN1Encodable)obj).toASN1Primitive().toDLObject().encodedLength();
    105             }
    106 
    107             bodyLength = length;
    108         }
    109 
    110         return bodyLength;
    111     }
    112 
    113     int encodedLength()
    114         throws IOException
    115     {
    116         int length = getBodyLength();
    117 
    118         return 1 + StreamUtil.calculateBodyLength(length) + length;
    119     }
    120 
    121     /**
    122      * A note on the implementation:
    123      * <p>
    124      * As DL requires the constructed, definite-length model to
    125      * be used for structured types, this varies slightly from the
    126      * ASN.1 descriptions given. Rather than just outputting SET,
    127      * we also have to specify CONSTRUCTED, and the objects length.
    128      */
    129     void encode(
    130         ASN1OutputStream out)
    131         throws IOException
    132     {
    133         ASN1OutputStream dOut = out.getDLSubStream();
    134         int length = getBodyLength();
    135 
    136         out.write(BERTags.SET | BERTags.CONSTRUCTED);
    137         out.writeLength(length);
    138 
    139         for (Enumeration e = this.getObjects(); e.hasMoreElements();)
    140         {
    141             Object obj = e.nextElement();
    142 
    143             dOut.writeObject((ASN1Encodable)obj);
    144         }
    145     }
    146 }