001package org.apache.commons.ssl.org.bouncycastle.asn1; 002 003import java.io.IOException; 004import java.util.Enumeration; 005 006/** 007 * The DLSet encodes ASN.1 SET value without element ordering, 008 * and always using definite length form. 009 * <hr> 010 * <h2>X.690</h2> 011 * <h3>8: Basic encoding rules</h3> 012 * <h4>8.11 Encoding of a set value </h4> 013 * <b>8.11.1</b> The encoding of a set value shall be constructed 014 * <p> 015 * <b>8.11.2</b> The contents octets shall consist of the complete 016 * encoding of a data value from each of the types listed in the 017 * ASN.1 definition of the set type, in an order chosen by the sender, 018 * unless the type was referenced with the keyword 019 * <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>. 020 * <p> 021 * <b>8.11.3</b> The encoding of a data value may, but need not, 022 * be present for a type which was referenced with the keyword 023 * <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>. 024 * <blockquote> 025 * NOTE — The order of data values in a set value is not significant, 026 * and places no constraints on the order during transfer 027 * </blockquote> 028 * <h3>9: Canonical encoding rules</h3> 029 * <h4>9.3 Set components</h4> 030 * The encodings of the component values of a set value shall 031 * appear in an order determined by their tags as specified 032 * in 8.6 of ITU-T Rec. X.680 | ISO/IEC 8824-1. 033 * Additionally, for the purposes of determining the order in which 034 * components are encoded when one or more component is an untagged 035 * choice type, each untagged choice type is ordered as though it 036 * has a tag equal to that of the smallest tag in that choice type 037 * or any untagged choice types nested within. 038 * <h3>10: Distinguished encoding rules</h3> 039 * <h4>10.3 Set components</h4> 040 * The encodings of the component values of a set value shall appear 041 * in an order determined by their tags as specified 042 * in 8.6 of ITU-T Rec. X.680 | ISO/IEC 8824-1. 043 * <blockquote> 044 * NOTE — Where a component of the set is an untagged choice type, 045 * the location of that component in the ordering will depend on 046 * the tag of the choice component being encoded. 047 * </blockquote> 048 * <h3>11: Restrictions on BER employed by both CER and DER</h3> 049 * <h4>11.5 Set and sequence components with default value </h4> 050 * The encoding of a set value or sequence value shall not include 051 * an encoding for any component value which is equal to 052 * its default value. 053 */ 054public class DLSet 055 extends ASN1Set 056{ 057 private int bodyLength = -1; 058 059 /** 060 * create an empty set 061 */ 062 public DLSet() 063 { 064 } 065 066 /** 067 * @param obj - a single object that makes up the set. 068 */ 069 public DLSet( 070 ASN1Encodable obj) 071 { 072 super(obj); 073 } 074 075 /** 076 * @param v - a vector of objects making up the set. 077 */ 078 public DLSet( 079 ASN1EncodableVector v) 080 { 081 super(v, false); 082 } 083 084 /** 085 * create a set from an array of objects. 086 */ 087 public DLSet( 088 ASN1Encodable[] a) 089 { 090 super(a, false); 091 } 092 093 private int getBodyLength() 094 throws IOException 095 { 096 if (bodyLength < 0) 097 { 098 int length = 0; 099 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}