1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership. 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License. You may obtain a copy of the License at 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project* @author Vladimir N. Molotkov, Stepan M. Mishura 20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project* @version $Revision$ 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project*/ 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage org.apache.harmony.security.asn1; 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException; 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Implicitly tagged ASN.1 type. 30f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see <a href="http://asn1.elibel.tm.fr/en/standards/index.htm">ASN.1</a> 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 335c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilsonpublic final class ASN1Implicit extends ASN1Type { 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 355c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson /** primitive type of tagging */ 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int TAGGING_PRIMITIVE = 0; 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 385c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson /** constructed type of tagging */ 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int TAGGING_CONSTRUCTED = 1; 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 415c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson /** string type of tagging */ 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int TAGGING_STRING = 2; 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 445c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson /** tagged ASN.1 type */ 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final ASN1Type type; 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 475c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson /** 485c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson * type of tagging. There are three of them 495c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson * 1) primitive: only primitive identifier is valid 505c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson * 2) constructed: only constructed identifier is valid 515c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson * 3) string: both identifiers are valid 525c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson */ 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final int taggingType; 54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructs implicitly tagged ASN.1 type 57f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * with context-specific tag class and specified tag number. 58f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param tagNumber - ASN.1 tag number 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param type - ASN.1 type to be tagged 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException - if tagNumber or type is invalid 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public ASN1Implicit(int tagNumber, ASN1Type type) { 645c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson super(CLASS_CONTEXTSPECIFIC, tagNumber); 65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if ((type instanceof ASN1Choice) || (type instanceof ASN1Any)) { 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // According to X.680: 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // 'The IMPLICIT alternative shall not be used if the type 69f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes // defined by "Type" is an untagged choice type or an 70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // untagged open type' 71897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes throw new IllegalArgumentException("Implicit tagging can not be used for ASN.1 ANY or CHOICE type"); 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.type = type; 75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (type.checkTag(type.id)) { 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (type.checkTag(type.constrId)) { 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // the base encoding can be primitive ot constructed 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // use both encodings 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project taggingType = TAGGING_STRING; 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // if the base encoding is primitive use primitive encoding 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project taggingType = TAGGING_PRIMITIVE; 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // if the base encoding is constructed use constructed encoding 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project taggingType = TAGGING_CONSTRUCTED; 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final boolean checkTag(int identifier) { 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project switch (taggingType) { 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case TAGGING_PRIMITIVE: 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return id == identifier; 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case TAGGING_CONSTRUCTED: 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return constrId == identifier; 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project default: // TAGGING_STRING 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return id == identifier || constrId == identifier; 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public Object decode(BerInputStream in) throws IOException { 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!checkTag(in.tag)) { 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // FIXME need look for tagging type 105897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes throw new ASN1Exception("ASN.1 implicitly tagged type expected at " + 106897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes "[" + in.tagOffset + "]. Expected tag: " + Integer.toHexString(id) + ", " + 107897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes "but got " + Integer.toHexString(in.tag)); 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1105c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson // substitute identifier for further decoding 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (id == in.tag) { 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project in.tag = type.id; 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project in.tag = type.constrId; 115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project in.content = type.decode(in); 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (in.isVerify) { 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return getDecodedObject(in); 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void encodeASN(BerOutputStream out) { 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project //FIXME need another way for specifying identifier to be encoded 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (taggingType == TAGGING_CONSTRUCTED) { 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project out.encodeTag(constrId); 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project out.encodeTag(id); 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project encodeContent(out); 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void encodeContent(BerOutputStream out) { 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project type.encodeContent(out); 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void setEncodingContent(BerOutputStream out) { 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project type.setEncodingContent(out); 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 142