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