1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.location.cts.asn1.base;
18 
19 import com.google.common.collect.ImmutableList;
20 
21 import java.nio.ByteBuffer;
22 import java.util.Collection;
23 import java.util.NoSuchElementException;
24 
25 /**
26  * Implements ASN.1 functionality.
27  *
28  */
29 public abstract class Asn1Sequence extends Asn1Object {
30   private static final Collection<Asn1Tag> possibleFirstTags =
31       ImmutableList.of(Asn1Tag.SEQUENCE);
32 
isExtensible()33   protected abstract boolean isExtensible();
34 
containsExtensionValues()35   protected abstract boolean containsExtensionValues();
36 
getComponents()37   protected abstract Iterable<? extends SequenceComponent> getComponents();
38 
getExtensionComponents()39   protected abstract Iterable<? extends SequenceComponent> getExtensionComponents();
40 
getPossibleFirstTags()41   public static Collection<Asn1Tag> getPossibleFirstTags() {
42     return possibleFirstTags;
43   }
44 
getDefaultTag()45   @Override Asn1Tag getDefaultTag() {
46     return Asn1Tag.SEQUENCE;
47   }
48 
isConstructed()49   @Override boolean isConstructed() {
50     return true;
51   }
52 
53   @Override
getBerValueLength()54   public int getBerValueLength() {
55     int length = 0;
56     for (SequenceComponent component : getComponents()) {
57       if (component.isExplicitlySet()) {
58         Asn1Tag tag = component.getTag();
59         Asn1Object value = component.getComponentValue();
60         if (tag == null) {
61           length += value.getBerLength();
62         } else {
63           int valueLen = component.isImplicitTagging()
64               ? value.getBerValueLength() : value.getBerLength();
65           length += tag.getTaggedLength(valueLen);
66         }
67       }
68     }
69     return length;
70   }
71 
72   @Override
encodeBerValue(ByteBuffer buf)73   public void encodeBerValue(ByteBuffer buf) {
74     for (SequenceComponent component : getComponents()) {
75       if (component.isExplicitlySet()) {
76         Asn1Object obj = component.getComponentValue();
77         Asn1Tag componentTag = component.getTag();
78         if (componentTag == null) {
79           obj.encodeBer(buf);
80         } else {
81           if (component.isImplicitTagging()) {
82             componentTag.writeTagAndLength(buf, obj.isConstructed(), obj.getBerValueLength());
83             obj.encodeBerValue(buf);
84           } else {
85             componentTag.writeTagAndLength(buf, true, obj.getBerLength());
86             obj.encodeBer(buf);
87           }
88         }
89       } else if (!component.isOptional() && !component.hasDefaultValue()) {
90         throw new IllegalStateException("Mandatory component "
91             + component.getClass().getName()
92             + " not set.");
93       }
94     }
95   }
96 
97   @Override
decodeBerValue(ByteBuffer buf)98   public void decodeBerValue(ByteBuffer buf) {
99     Iterable<? extends SequenceComponent> components = getComponents();
100 
101     while (buf.hasRemaining()) {
102       int bufStartPos = buf.position();
103       int bufEndPos = buf.limit();
104       Asn1Tag tag = Asn1Tag.readTag(buf);
105       SequenceComponent component = getComponent(components, tag);
106       if (component.isExplicitlySet()) {
107         throw new IllegalArgumentException("Encountered duplicate field");
108       }
109       component.setToNewInstance();
110       int valueLength = Asn1Tag.readLength(buf);
111       buf.limit(buf.position() + valueLength);
112       if (component.getTag() != null) {
113         if (component.isImplicitTagging()) {
114           component.getComponentValue().decodeBerValue(buf);
115         } else {
116           component.getComponentValue().decodeBer(buf);
117         }
118       } else {
119         buf.position(bufStartPos); // rewind to before tag
120         component.getComponentValue().decodeBer(buf);
121       }
122       buf.limit(bufEndPos); // set the limit back to the real end position
123     }
124 
125     checkMandatoryFieldsPresent(components);
126   }
127 
128   /**
129    * Throws {@link IllegalArgumentException} if all mandatory fields not set on this sequence.
130    */
checkMandatoryFieldsPresent(Iterable<? extends SequenceComponent> components)131   private void checkMandatoryFieldsPresent(Iterable<? extends SequenceComponent> components) {
132     for (SequenceComponent component : components) {
133       if (!component.isOptional() && !component.isExplicitlySet()) {
134         throw new IllegalArgumentException("Mandatory field not present");
135       }
136     }
137   }
138 
139   /**
140    * Returns the child component that can start with the specified tag.
141    * @throws NoSuchElementException if no child component can start with the tag
142    */
getComponent(Iterable<? extends SequenceComponent> components, Asn1Tag tag)143   private SequenceComponent getComponent(Iterable<? extends SequenceComponent> components,
144       Asn1Tag tag) {
145     for (SequenceComponent component : components) {
146       if (component.getPossibleFirstTags().contains(tag)) {
147         return component;
148       }
149     }
150     throw new NoSuchElementException("SEQUENCE=" + this + ", tag=" + tag);
151   }
152 
encodePerImpl(boolean aligned)153   private Iterable<BitStream> encodePerImpl(boolean aligned) {
154     ImmutableList.Builder<BitStream> listBuilder = ImmutableList.builder();
155     BitStream prefix = new BitStream();
156 
157     if (isExtensible()) {
158       prefix.appendBit(containsExtensionValues());
159     }
160 
161     Iterable<? extends SequenceComponent> components = getComponents();
162     int bitFieldSize = calculateBitFieldSize(components);
163     if (bitFieldSize >= PerAlignedUtils.SIXTYFOUR_K) {
164       throw new UnsupportedOperationException("unimplemented");
165     }
166     for (SequenceComponent component : components) {
167       if (component.isOptional() || component.hasDefaultValue()) {
168         prefix.appendBit(component.isExplicitlySet());
169       } else if (!component.isExplicitlySet()) {
170         throw new IllegalStateException("Mandatory component "
171                                         + component.getClass().getName()
172                                         + " not set.");
173       }
174     }
175     listBuilder.add(prefix);
176 
177     for (SequenceComponent component : components) {
178       if (component.isExplicitlySet()) {
179         Asn1Object value = component.getComponentValue();
180         Iterable<BitStream> encodedValue = null;
181         if (aligned) {
182           encodedValue = value.encodePerAligned();
183         } else {
184           encodedValue = value.encodePerUnaligned();
185         }
186         listBuilder.addAll(encodedValue);
187       }
188     }
189 
190     if (isExtensible() && containsExtensionValues()) {
191       Iterable<? extends SequenceComponent> extensionComponents =
192           getExtensionComponents();
193       BitStream extensions = new BitStream();
194       int extensionBitFieldSize = 0;
195       /*
196        * Adding a bit marker per extension addition as ITU spec, however some
197        * H323 implementations seem to only add markers up to the last set
198        * extension.
199        */
200       for (SequenceComponent component : extensionComponents) {
201         if (!component.isOptional() && !component.isExplicitlySet()) {
202           throw new IllegalStateException("Mandatory extension component "
203                                           + component.getClass().getName()
204                                           + " not set.");
205         }
206         extensions.appendBit(component.isExplicitlySet());
207         extensionBitFieldSize++;
208       }
209       if (extensionBitFieldSize <= 64) {
210         //encode length to x.691-0207 10.9.3.4 (i.e. length -1)
211         BitStream lengthDeterminant = new BitStream();
212         lengthDeterminant.appendBit(false);
213         lengthDeterminant.appendLowBits(6, (byte) (extensionBitFieldSize - 1));
214         listBuilder.add(lengthDeterminant);
215       } else {
216         BitStream marker = new BitStream();
217         marker.appendBit(true);
218         listBuilder.add(marker);
219         BitStream lengthDeterminant = null;
220         if (aligned) {
221           lengthDeterminant =
222               PerAlignedUtils.encodeSemiConstrainedLength(extensionBitFieldSize);
223           lengthDeterminant.setBeginByteAligned();
224         } else {
225           lengthDeterminant =
226               PerUnalignedUtils.encodeSemiConstrainedLength(extensionBitFieldSize);
227         }
228         listBuilder.add(lengthDeterminant);
229       }
230       listBuilder.add(extensions);
231       for (SequenceComponent component : extensionComponents) {
232         if (component.isExplicitlySet()) {
233           Iterable<BitStream> extensionValues = null;
234           if (aligned) {
235             extensionValues = PerAlignedUtils.
236                 encodeOpenTypeField(component.getComponentValue());
237           } else {
238             extensionValues = PerUnalignedUtils.encodeOpenTypeField(component.getComponentValue());
239           }
240           listBuilder.addAll(extensionValues);
241         }
242       }
243     }
244     return listBuilder.build();
245   }
246 
encodePerUnaligned()247   @Override public Iterable<BitStream> encodePerUnaligned() {
248     return encodePerImpl(false);
249   }
250 
251   @Override
encodePerAligned()252   public Iterable<BitStream> encodePerAligned() {
253     return encodePerImpl(true);
254   }
255 
calculateBitFieldSize( Iterable<? extends SequenceComponent> components)256   private int calculateBitFieldSize(
257       Iterable<? extends SequenceComponent> components) {
258     int bitFieldSize = 0;
259     for (SequenceComponent component : components) {
260       if (component.isOptional() || component.hasDefaultValue()) {
261         bitFieldSize++;
262       }
263     }
264     return bitFieldSize;
265   }
266 
decodePerImpl(BitStreamReader reader, boolean aligned)267   private void decodePerImpl(BitStreamReader reader, boolean aligned) {
268     boolean hasExtensionValuesToDecode = false;
269     if (isExtensible()) {
270       hasExtensionValuesToDecode = reader.readBit();
271     }
272 
273     Iterable<? extends SequenceComponent> components = getComponents();
274     int bitFieldSize = calculateBitFieldSize(components);
275     if (bitFieldSize >= PerAlignedUtils.SIXTYFOUR_K) {
276       throw new UnsupportedOperationException("unimplemented");
277     }
278     for (SequenceComponent component : components) {
279       if (component.isOptional() || component.hasDefaultValue()) {
280         if (reader.readBit()) {
281           component.setToNewInstance();
282         }
283       } else {
284         component.setToNewInstance();
285       }
286     }
287 
288     for (SequenceComponent component : components) {
289       if (component.isExplicitlySet()) {
290         if (aligned) {
291           component.getComponentValue().decodePerAligned(reader);
292         } else {
293           component.getComponentValue().decodePerUnaligned(reader);
294         }
295       }
296     }
297 
298     if (hasExtensionValuesToDecode) {
299       Iterable<? extends SequenceComponent> extensionComponents =
300           getExtensionComponents();
301       int extensionBitFieldSize;
302       if (reader.readBit()) {
303         if (aligned) {
304           reader.spoolToByteBoundary();
305           extensionBitFieldSize =
306               PerAlignedUtils.decodeSemiConstrainedLength(reader);
307         } else {
308           extensionBitFieldSize =
309               PerUnalignedUtils.decodeSemiConstrainedLength(reader);
310         }
311       } else {
312         extensionBitFieldSize = 1 + reader.readLowBits(6);
313       }
314       for (SequenceComponent component : extensionComponents) {
315         if (extensionBitFieldSize > 0) {
316           --extensionBitFieldSize;
317           if (reader.readBit()) {
318             component.setToNewInstance();
319           }
320         }
321       }
322       int unknownExtensionCount = 0;
323       for (; extensionBitFieldSize > 0; --extensionBitFieldSize) {
324         if (reader.readBit()) {
325           ++unknownExtensionCount;
326         }
327       }
328       for (SequenceComponent component : extensionComponents) {
329         if (component.isExplicitlySet()) {
330           if (aligned) {
331             byte[] encodedComponent =
332                 PerAlignedUtils.decodeSemiConstrainedLengthOfBytes(reader);
333             component.getComponentValue().decodePerAligned(new BitStreamReader(encodedComponent));
334           } else {
335             byte[] encodedComponent =
336                 PerUnalignedUtils.decodeSemiConstrainedLengthOfBytes(reader);
337             component.getComponentValue().decodePerUnaligned(new BitStreamReader(encodedComponent));
338           }
339         }
340       }
341       for (; unknownExtensionCount > 0; --unknownExtensionCount) {
342         if (aligned) {
343           byte[] unknownEncodedExtension =
344               PerAlignedUtils.decodeSemiConstrainedLengthOfBytes(reader);
345         } else {
346           byte[] unknownEncodedExtension =
347               PerUnalignedUtils.decodeSemiConstrainedLengthOfBytes(reader);
348         }
349       }
350     }
351   }
352 
decodePerUnaligned(BitStreamReader reader)353   @Override public void decodePerUnaligned(BitStreamReader reader) {
354     decodePerImpl(reader, false);
355   }
356 
decodePerAligned(BitStreamReader reader)357   @Override public void decodePerAligned(BitStreamReader reader) {
358     decodePerImpl(reader, true);
359   }
360 }
361 
362