1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * this work for additional information regarding copyright ownership. 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (the "License"); you may not use this file except in compliance with 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the License. You may obtain a copy of the License at 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project* @author Vladimir N. Molotkov, Stepan M. Mishura 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project* @version $Revision$ 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project*/ 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage org.apache.harmony.security.asn1; 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.IOException; 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.math.BigInteger; 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.Arrays; 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.Iterator; 28e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughesimport java.util.Map; 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.TreeMap; 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.apache.harmony.security.internal.nls.Messages; 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This abstract class represents ASN.1 Choice type. 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * To implement custom ASN.1 choice type an application class 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * must provide implementation for the following methods: 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * getIndex() 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * getObjectToEncode() 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * There are two ways to implement custom ASN.1 choice type: 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * with application class that represents ASN.1 custom choice type or without. 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The key point is how a value of choice type is stored by application classes. 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For example, let's consider the following ASN.1 notations 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (see http://www.ietf.org/rfc/rfc3280.txt) 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Time ::= CHOICE { 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * utcTime UTCTime, 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * generalTime GeneralizedTime 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * } 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Validity ::= SEQUENCE { 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * notBefore Time, 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * notAfter Time 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * } 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1)First approach: 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * No application class to represent ASN.1 Time notation 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The Time notation is a choice of different time formats: UTC and Generalized. 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Both of them are mapped to java.util.Date object, so an application 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class that represents ASN.1 Validity notation may keep values 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * as Date objects. 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * So a custom ASN.1 Time choice type should map its notation to Date object. 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class Time { 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * // custom ASN.1 choice class: maps Time to is notation 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * public static final ASN1Choice asn1 = new ASN1Choice(new ASN1Type[] { 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ASN1GeneralizedTime.asn1, ASN1UTCTime.asn1 }) { 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * public int getIndex(java.lang.Object object) { 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * return 0; // always encode as ASN1GeneralizedTime 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * } 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * public Object getObjectToEncode(Object object) { 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * // A value to be encoded value is a Date object 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * // pass it to custom time class 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * return object; 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * } 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * }; 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * } 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class Validity { 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * private Date notBefore; // choice as Date 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * private Date notAfter; // choice as Date 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ... // constructors and other methods go here 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * // custom ASN.1 sequence class: maps Validity class to is notation 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * public static final ASN1Sequence ASN1 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * = new ASN1Sequence(new ASN1Type[] {Time.asn1, Time.asn1 }) { 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * protected Object getObject(Object[] values) { 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * // ASN.1 Time choice passed Data object - use it 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * return new Validity((Date) values[0], (Date) values[1]); 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * } 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * protected void getValues(Object object, Object[] values) { 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Validity validity = (Validity) object; 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * // pass Date objects to ASN.1 Time choice 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * values[0] = validity.notBefore; 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * values[1] = validity.notAfter; 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * } 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * } 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * } 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 2)Second approach: 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * There is an application class to represent ASN.1 Time notation 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If it is a matter what time format should be used to decode/encode 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Date objects a class to represent ASN.1 Time notation must be created. 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For example, 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class Time { 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * private Date utcTime; 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * private Date gTime; 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ... // constructors and other methods go here 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * // custom ASN.1 choice class: maps Time to is notation 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * public static final ASN1Choice asn1 = new ASN1Choice(new ASN1Type[] { 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ASN1GeneralizedTime.asn1, ASN1UTCTime.asn1 }) { 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * public Object getDecodedObject(BerInputStream in) { 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * // create Time object to pass as decoded value 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Time time = new Time(); 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if (in.choiceIndex==0) { 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * // we decoded GeneralizedTime 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * // store decoded Date value in corresponding field 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * time.gTime = in.content; 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * // return it 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * return time; 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * } else { 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * // we decoded UTCTime 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * // store decoded Date value in corresponding field 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * time.utcTime = in.content; 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * // return it 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * return time; 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * } 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * } 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * public int getIndex(java.lang.Object object) { 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Time time = (Time)object; 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if(time.utcTime!=null){ 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * // encode Date as UTCTime 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * return 1; 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * } else { 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * // otherwise encode Date as GeneralizedTime 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * return 0; 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * } 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * } 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * public Object getObjectToEncode(Object object) { 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Time time = (Time)object; 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if(time.utcTime!=null){ 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * // encode Date as UTCTime 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * return 1; 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * } else { 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * // otherwise encode Date as GeneralizedTime 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * return 0; 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * } 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * } 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * }; 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * } 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * So now Validity class must keep all values in Time object 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and its custom ASN.1 sequence class must handle this class of objects 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class Validity { 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * private Time notBefore; // now it is a Time!!! 185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * private Time notAfter; // now it is a Time!!! 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ... // constructors and other methods go here 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * // custom ASN.1 sequence class: maps Validity class to is notation 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * public static final ASN1Sequence ASN1 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * = new ASN1Sequence(new ASN1Type[] {Time.asn1, Time.asn1 }) { 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * protected Object getObject(Object[] values) { 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * // We've gotten Time objects here !!! 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * return new Validity((Time) values[0], (Time) values[1]); 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * } 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * protected void getValues(Object object, Object[] values) { 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Validity validity = (Validity) object; 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * // pass Time objects to ASN.1 Time choice 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * values[0] = validity.notBefore; 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * values[1] = validity.notAfter; 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * } 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * } 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * } 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @see <a href="http://asn1.elibel.tm.fr/en/standards/index.htm">ASN.1</a> 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic abstract class ASN1Choice extends ASN1Type { 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public final ASN1Type[] type; 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // identifiers table: [2][number of distinct identifiers] 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // identifiers[0]: stores identifiers (includes nested choices) 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // identifiers[1]: stores identifiers' indexes in array of types 220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final int[][] identifiers; 221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Constructs ASN.1 choice type. 224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param type - 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an array of one or more ASN.1 type alternatives. 227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws IllegalArgumentException - 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * type parameter is invalid 229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public ASN1Choice(ASN1Type[] type) { 231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project super(TAG_CHOICE); // has not tag number 232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (type.length == 0) { 234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IllegalArgumentException(Messages.getString("security.10E", //$NON-NLS-1$ 235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project getClass().getName())); 236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // create map of all identifiers 239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project TreeMap map = new TreeMap(); 240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int index = 0; index < type.length; index++) { 241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ASN1Type t = type[index]; 243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (t instanceof ASN1Any) { 245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // ASN.1 ANY is not allowed, 246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // even it is a single component (not good for nested choices) 247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IllegalArgumentException(Messages.getString("security.10F", //$NON-NLS-1$ 248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project getClass().getName())); // FIXME name 249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (t instanceof ASN1Choice) { 250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // add all choice's identifiers 252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int[][] choiceToAdd = ((ASN1Choice) t).identifiers; 253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int j = 0; j < choiceToAdd[0].length; j++) { 254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project addIdentifier(map, choiceToAdd[0][j], index); 255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project continue; 257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // add primitive identifier 260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (t.checkTag(t.id)) { 261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project addIdentifier(map, t.id, index); 262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // add constructed identifier 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (t.checkTag(t.constrId)) { 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project addIdentifier(map, t.constrId, index); 267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // fill identifiers array 271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int size = map.size(); 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project identifiers = new int[2][size]; 273e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes Iterator it = map.entrySet().iterator(); 274e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes 275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < size; i++) { 276e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes Map.Entry entry = (Map.Entry) it.next(); 277e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes BigInteger identifier = (BigInteger) entry.getKey(); 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project identifiers[0][i] = identifier.intValue(); 280e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes identifiers[1][i] = ((BigInteger) entry.getValue()).intValue(); 281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.type = type; 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void addIdentifier(TreeMap map, int identifier, int index){ 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (map.put(BigInteger.valueOf(identifier), BigInteger.valueOf(index)) != null) { 288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IllegalArgumentException(Messages.getString("security.10F", //$NON-NLS-1$ 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project getClass().getName())); // FIXME name 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // DECODE 296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Tests whether one of choice alternatives has the same identifier or not. 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param identifier - 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ASN.1 identifier to be verified 304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return - true if one of choice alternatives has the same identifier, 305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * otherwise false; 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public final boolean checkTag(int identifier) { 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return Arrays.binarySearch(identifiers[0], identifier) >= 0; 309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public Object decode(BerInputStream in) throws IOException { 312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int index = Arrays.binarySearch(identifiers[0], in.tag); 314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (index < 0) { 315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new ASN1Exception(Messages.getString("security.110", //$NON-NLS-1$ 316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project getClass().getName()));// FIXME message 317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project index = identifiers[1][index]; 320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project in.content = type[index].decode(in); 322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // set index for getDecodedObject method 324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project in.choiceIndex = index; 325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (in.isVerify) { 327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return null; 328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return getDecodedObject(in); 330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // ENCODE 335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void encodeASN(BerOutputStream out) { 339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project encodeContent(out); 340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public final void encodeContent(BerOutputStream out) { 343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.encodeChoice(this); 344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO Put method description here 348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param object - an object to be encoded 350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return 351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public abstract int getIndex(Object object); 353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public abstract Object getObjectToEncode(Object object); 355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public final void setEncodingContent(BerOutputStream out) { 357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.getChoiceLength(this); 358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 360