BerInputStream.java revision f33eae7e84eb6d3b0f4e86b59605bb3de73009f3
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 Projectimport java.io.InputStream; 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.ArrayList; 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.internal.nls.Messages; 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Decodes ASN.1 types encoded with BER (X.690) 34f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see <a href="http://asn1.elibel.tm.fr/en/standards/index.htm">ASN.1</a> 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class BerInputStream { 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Associated <code>InputStream</code> 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected InputStream in; 44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 46f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * Internal buffer for storing encoded array 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected byte[] buffer; 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The position in the buffer. 52f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Next read must place data into the buffer from this offset 54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected int offset = 0; 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // The buffer increment size. 58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Must be reasonable big to reallocate memory not to often. 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Primary is used for decoding indefinite length encoding 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int BUF_INCREASE_SIZE = 1024 * 16; 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 63f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * Indicates indefinite length of the current type 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected static final int INDEFINIT_LENGTH = -1; 66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Creates stream for decoding. 69f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param encoded - bytes array to be decoded 71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException - if an error occurs 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public BerInputStream(byte[] encoded) throws IOException { 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this(encoded, 0, encoded.length); 75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Creates stream for decoding. 79f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param encoded - 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * bytes array to be decoded 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param offset - 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the encoding offset 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param expectedLength - 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * expected length of full encoding, this includes identifier, 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * length an content octets 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException - 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if an error occurs 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public BerInputStream(byte[] encoded, int offset, int expectedLength) 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throws IOException { 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.buffer = encoded; 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.offset = offset; 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project next(); 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // compare expected and decoded length 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (length != INDEFINIT_LENGTH 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project && (offset + expectedLength) != (this.offset + this.length)) { 101f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.111")); 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Creates stream for decoding. 107f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Allocates initial buffer of default size 109f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param is associated <code>InputStream</code> 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public BerInputStream(InputStream in) throws IOException { 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this(in, BUF_INCREASE_SIZE); 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Creates stream for decoding. 118f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 119f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * Allocates initial buffer of <code>initialSize</code> size 120f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param initialSize the internal buffer initial size 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param is associated <code>InputStream</code> 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public BerInputStream(InputStream in, int initialSize) throws IOException { 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.in = in; 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buffer = new byte[initialSize]; 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project next(); 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (length != INDEFINIT_LENGTH) { 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // input stream has definite length encoding 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // check allocated length to avoid further reallocations 1342f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes if (buffer.length < (length + offset)) { 1352f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes byte[] newBuffer = new byte[length + offset]; 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project System.arraycopy(buffer, 0, newBuffer, 0, offset); 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buffer = newBuffer; 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project isIndefinedLength = true; 141f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.112")); 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Resets this stream to initial state. 147f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param encoded - a new bytes array to be decoded 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException - if an error occurs 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final void reset(byte[] encoded) throws IOException { 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buffer = encoded; 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project next(); 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Current decoded tag 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int tag; 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Current decoded length 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected int length; 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Current decoded content 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public Object content; 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Current decoded tag offset 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected int tagOffset; 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Current decoded content offset 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected int contentOffset; 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Decodes next encoded type. 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Initializes tag, length, tagOffset and contentOffset variables 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return next decoded tag 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException - if error occured 188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int next() throws IOException { 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tagOffset = offset; 192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // read tag 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tag = read(); 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // read length 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project length = read(); 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (length != 0x80) { // definite form 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // long or short length form 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if ((length & 0x80) != 0) { // long form 201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int numOctets = length & 0x7F; 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (numOctets > 5) { 204f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.113", 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tagOffset)); //FIXME message 206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // collect this value length 209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project length = read(); 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (int i = 1; i < numOctets; i++) { 211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int ch = read(); 212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project length = (length << 8) + ch;//read(); 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (length > 0xFFFFFF) { 216f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.113", 217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tagOffset)); //FIXME message 218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { //indefinite form 221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project length = INDEFINIT_LENGTH; 222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project contentOffset = offset; 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return tag; 226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns the length of the encoding 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public static int getLength(byte[] encoding) { 232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int length = encoding[1] & 0xFF; 233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int numOctets = 0; 234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if ((length & 0x80) != 0) { // long form 235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project numOctets = length & 0x7F; 236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // collect this value length 238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project length = encoding[2] & 0xFF; 239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (int i = 3; i < numOctets + 2; i++) { 240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project length = (length << 8) + (encoding[i] & 0xFF); 241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // tag length long_form content 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return 1 + 1 + numOctets + length; 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Decodes ASN.1 bitstring type 249f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException - if error occured 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void readBitString() throws IOException { 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (tag == ASN1Constants.TAG_BITSTRING) { 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (length == 0) { 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new ASN1Exception( 258f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes Messages.getString("security.114", tagOffset)); 259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project readContent(); 262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // content: check unused bits 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (buffer[contentOffset] > 7) { 265f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.115", 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project contentOffset)); 267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (length == 1 && buffer[contentOffset] != 0) { 270f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.116", 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project contentOffset)); 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (tag == ASN1Constants.TAG_C_BITSTRING) { 275f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.117")); 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new ASN1Exception( 278f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes Messages.getString("security.118", tagOffset, 279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Integer.toHexString(tag))); 280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Decodes ASN.1 Enumerated type 285f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException - if error occured 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void readEnumerated() throws IOException { 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (tag != ASN1Constants.TAG_ENUM) { 291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new ASN1Exception( 292f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes Messages.getString("security.119", tagOffset, 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Integer.toHexString(tag))); 294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // 297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // all checks are the same as for ASN.1 integer type 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // check encoded length 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (length == 0) { 302fd6bb3510c2f94d636f3572dcf5f7f4dcd1a2726Elliott Hughes throw new ASN1Exception(Messages.getString("security.11A", tagOffset)); 303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project readContent(); 306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // check encoded content 308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (length > 1) { 309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int bits = buffer[contentOffset] & 0xFF; 311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (buffer[contentOffset + 1] < 0) { 312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project bits += 0x100; 313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (bits == 0 || bits == 0x1FF) { 316f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.11B", contentOffset)); 317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Decodes ASN.1 boolean type 323f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException - if error occured 325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void readBoolean() throws IOException { 327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (tag != ASN1Constants.TAG_BOOLEAN) { 329f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.11C", 330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tagOffset, Integer.toHexString(tag))); 331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // check encoded length 334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (length != 1) { 335fd6bb3510c2f94d636f3572dcf5f7f4dcd1a2726Elliott Hughes throw new ASN1Exception(Messages.getString("security.11D", tagOffset)); 336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project readContent(); 339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The last choice index 343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int choiceIndex; 345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Keeps last decoded: year, month, day, hour, minute, second, millisecond 348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int[] times; 350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Decodes ASN.1 GeneralizedTime type 353f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException - if error occured 355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void readGeneralizedTime() throws IOException { 357f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (tag == ASN1Constants.TAG_GENERALIZEDTIME) { 359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // FIXME: any other optimizations? 361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project readContent(); 362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // FIXME store string somewhere to allow a custom time type perform 363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // additional checks 364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // check syntax: the last char MUST be Z 366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (buffer[offset - 1] != 'Z') { 367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // FIXME support only format that is acceptable for DER 368f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.11E")); 369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // check syntax: MUST be YYYYMMDDHHMMSS[(./,)DDD]'Z' 372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (length != 15 && (length < 17 || length > 19)) // invalid 373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // length 374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project { 375f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.11F", 376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project contentOffset)); 377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // check content: milliseconds 380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (length > 16) { 381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte char14 = buffer[contentOffset + 14]; 382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (char14 != '.' && char14 != ',') { 383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new ASN1Exception( 384f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes Messages.getString("security.11F", 385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project contentOffset)); 386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (times == null) { 390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project times = new int[7]; 391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project times[0] = strToInt(contentOffset, 4); // year 393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project times[1] = strToInt(contentOffset + 4, 2); // month 394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project times[2] = strToInt(contentOffset + 6, 2); // day 395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project times[3] = strToInt(contentOffset + 8, 2); // hour 396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project times[4] = strToInt(contentOffset + 10, 2); // minute 397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project times[5] = strToInt(contentOffset + 12, 2); // second 398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (length > 16) { 400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // FIXME optimize me 401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project times[6] = strToInt(contentOffset + 15, length - 16); 402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (length == 17) { 404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project times[6] = times[6] * 100; 405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (length == 18) { 406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project times[6] = times[6] * 10; 407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // FIXME check all values for valid numbers!!! 411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (tag == ASN1Constants.TAG_C_GENERALIZEDTIME) { 412f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.120")); 413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 415f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.121", 416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tagOffset, Integer.toHexString(tag))); 417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Decodes ASN.1 UTCTime type 422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException - if an I/O error occurs or the end of the stream is reached 424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void readUTCTime() throws IOException { 426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (tag == ASN1Constants.TAG_UTCTIME) { 428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project switch (length) { 430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case ASN1UTCTime.UTC_HM: 431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case ASN1UTCTime.UTC_HMS: 432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case ASN1UTCTime.UTC_LOCAL_HM: 434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case ASN1UTCTime.UTC_LOCAL_HMS: 435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // FIXME only coordinated universal time formats are supported 436f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.122")); 437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project default: 438f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.123", 439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tagOffset)); 440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // FIXME: any other optimizations? 443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project readContent(); 444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // FIXME store string somewhere to allow a custom time type perform 446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // additional checks 447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // check syntax: the last char MUST be Z 449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (buffer[offset - 1] != 'Z') { 450f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception("ASN.1 UTCTime wrongly encoded at [" 451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project + contentOffset + ']'); 452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (times == null) { 455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project times = new int[7]; 456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project times[0] = strToInt(contentOffset, 2); // year 459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (times[0] > 49) { 460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project times[0] += 1900; 461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project times[0] += 2000; 463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project times[1] = strToInt(contentOffset + 2, 2); // month 466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project times[2] = strToInt(contentOffset + 4, 2); // day 467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project times[3] = strToInt(contentOffset + 6, 2); // hour 468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project times[4] = strToInt(contentOffset + 8, 2); // minute 469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (length == ASN1UTCTime.UTC_HMS) { 471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project times[5] = strToInt(contentOffset + 10, 2); // second 472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // FIXME check all time values for valid numbers!!! 475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (tag == ASN1Constants.TAG_C_UTCTIME) { 476f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.124")); 477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 478f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.125", 479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tagOffset, Integer.toHexString(tag))); 480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project //TODO comment me 484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private int strToInt(int off, int count) throws ASN1Exception { 485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project //FIXME works only with buffer 487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int c; 489adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int result = 0; 490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (int i = off, end = off + count; i < end; i++) { 491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project c = buffer[i] - 48; 492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (c < 0 || c > 9) { 493f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.126")); 494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project result = result * 10 + c; 496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return result; 498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Decodes ASN.1 Integer type 502f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 503adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException - if error occured 504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 505adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void readInteger() throws IOException { 506adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 507adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (tag != ASN1Constants.TAG_INTEGER) { 508f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.127", 509adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tagOffset, Integer.toHexString(tag))); 510adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 511adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 512adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // check encoded length 513adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (length < 1) { 514f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.128", 515f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes tagOffset)); 516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 518adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project readContent(); 519adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 520adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // check encoded content 521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (length > 1) { 522adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte firstByte = buffer[offset - length]; 524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte secondByte = (byte) (buffer[offset - length + 1] & 0x80); 525adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 526adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (firstByte == 0 && secondByte == 0 || firstByte == (byte) 0xFF 527adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project && secondByte == (byte) 0x80) { 528f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.129", 529adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project (offset - length))); 530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 531adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 532adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 534adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 535adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Decodes ASN.1 Octetstring type 536adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 537adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException - if error occured 538adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 539adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void readOctetString() throws IOException { 540adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 541adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (tag == ASN1Constants.TAG_OCTETSTRING) { 542adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project readContent(); 543adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (tag == ASN1Constants.TAG_C_OCTETSTRING) { 544f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.12A")); 545adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 546adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new ASN1Exception( 547f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes Messages.getString("security.12B", tagOffset, 548adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Integer.toHexString(tag))); 549adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 550adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 551adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 552adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project //FIXME comment me 553adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int oidElement; 554adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 555adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 556adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Decodes ASN.1 ObjectIdentifier type 557adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 558adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException - if error occured 559adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void readOID() throws IOException { 561adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 562adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (tag != ASN1Constants.TAG_OID) { 563f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.12C", 564adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tagOffset, Integer.toHexString(tag))); 565adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 566adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 567adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // check encoded length 568adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (length < 1) { 569f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.12D", tagOffset)); 570adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 571adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 572adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project readContent(); 573adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 574adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // check content: last encoded byte (8th bit MUST be zero) 575adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if ((buffer[offset - 1] & 0x80) != 0) { 576f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.12E", (offset - 1))); 577adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 578adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 579adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project oidElement = 1; 580adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (int i = 0; i < length; i++, ++oidElement) { 581f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 582adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // According to ASN.1 BER spec: 583adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // leading octet of subidentifier MUST not be 0x80 584adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // This assertion is not verified 585adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // 586adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project //if (buffer[contentOffset + i] == (byte)0x80) { 587adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // throw new ASN1Exception( 588adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // "Wrong content for ASN.1 object identifier at [" 589adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // + contentOffset 590adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // + "]. Subidentifier MUST be encoded in minimum number of octets"); 591adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project //} 592f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 593adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while ((buffer[contentOffset + i] & 0x80) == 0x80) { 594adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project i++; 595adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 596adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 597adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 598adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 599adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 600adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Decodes ASN.1 Sequence type 601adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 602adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param sequence - ASN.1 sequence to be decoded 603adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException - if error occured 604adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 605adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void readSequence(ASN1Sequence sequence) throws IOException { 606adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 607adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (tag != ASN1Constants.TAG_C_SEQUENCE) { 608adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new ASN1Exception( 609f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes Messages.getString("security.12F", tagOffset, 610adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Integer.toHexString(tag))); 611adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 612adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 613adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int begOffset = offset; 614adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int endOffset = begOffset + length; 615adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 616adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ASN1Type[] type = sequence.type; 617adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 618adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int i = 0; 619adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 620adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (isVerify) { 621adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 622adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (; (offset < endOffset) && (i < type.length); i++) { 623adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 624adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project next(); 625adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (!type[i].checkTag(tag)) { 626f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes // check whether it is optional component or not 627adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!sequence.OPTIONAL[i] || (i == type.length - 1)) { 628f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.130", 629adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tagOffset)); 630adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 631adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project i++; 632adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 633adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 634adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project type[i].decode(this); 635adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 636adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 637adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // check the rest of components 638adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (; i < type.length; i++) { 639adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!sequence.OPTIONAL[i]) { 640f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.131", 641adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tagOffset)); 642adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 643adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 644adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 645adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 646adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 647adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int seqTagOffset = tagOffset; //store tag offset 648adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 649adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Object[] values = new Object[type.length]; 650adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (; (offset < endOffset) && (i < type.length); i++) { 651adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 652adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project next(); 653adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (!type[i].checkTag(tag)) { 654f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes // check whether it is optional component or not 655adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!sequence.OPTIONAL[i] || (i == type.length - 1)) { 656f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.132", 657adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tagOffset)); 658adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 659adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 660adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // sets default value 661adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (sequence.DEFAULT[i] != null) { 662adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project values[i] = sequence.DEFAULT[i]; 663adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 664adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project i++; 665adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 666adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project values[i] = type[i].decode(this); 667adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 668adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 669adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // check the rest of components 670adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (; i < type.length; i++) { 671adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!sequence.OPTIONAL[i]) { 672f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.133", 673adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tagOffset)); 674adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 675adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (sequence.DEFAULT[i] != null) { 676adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project values[i] = sequence.DEFAULT[i]; 677adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 678adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 679adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project content = values; 680adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 681adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tagOffset = seqTagOffset; //retrieve tag offset 682adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 683adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 684adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (offset != endOffset) { 685f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.134", begOffset)); 686adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 687adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 688adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 689adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 690adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Decodes ASN.1 SequenceOf type 691adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 692adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param sequenceOf - ASN.1 sequence to be decoded 693adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException - if error occured 694adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 695adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void readSequenceOf(ASN1SequenceOf sequenceOf) throws IOException { 696f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 697adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (tag != ASN1Constants.TAG_C_SEQUENCEOF) { 698f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.135", tagOffset, 699adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Integer.toHexString(tag))); 700adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 701adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 702adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project decodeValueCollection(sequenceOf); 703adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 704adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 705adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 706adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Decodes ASN.1 Set type 707adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 708adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param set - ASN.1 set to be decoded 709adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException - if error occured 710adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 711adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void readSet(ASN1Set set) throws IOException { 712f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 713adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (tag != ASN1Constants.TAG_C_SET) { 714f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.136", 715adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tagOffset, Integer.toHexString(tag))); 716adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 717adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 718f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.137")); 719adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 720adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 721adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 722adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Decodes ASN.1 SetOf type 723adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 724adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param set - ASN.1 set to be decoded 725adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException - if error occured 726adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 727adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void readSetOf(ASN1SetOf setOf) throws IOException { 728f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 729adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (tag != ASN1Constants.TAG_C_SETOF) { 730f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.138", 731adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tagOffset, Integer.toHexString(tag))); 732adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 733adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 734adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project decodeValueCollection(setOf); 735adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 736adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 737adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final void decodeValueCollection(ASN1ValueCollection collection) 738adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throws IOException { 739adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 740adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int begOffset = offset; 741adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int endOffset = begOffset + length; 742adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 743adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ASN1Type type = collection.type; 744adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 745adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (isVerify) { 746adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (endOffset > offset) { 747adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project next(); 748adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project type.decode(this); 749adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 750adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 751adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 752adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int seqTagOffset = tagOffset; //store tag offset 753adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 754adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ArrayList values = new ArrayList(); 755adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (endOffset > offset) { 756adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project next(); 757adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project values.add(type.decode(this)); 758adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 759adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 760adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project content = values; 761adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 762adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tagOffset = seqTagOffset; //retrieve tag offset 763adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 764adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 765adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (offset != endOffset) { 766f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.134", begOffset)); 767adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 768adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 769adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 770adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 771adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Decodes ASN.1 String type 772adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 773adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException - if an I/O error occurs or the end of the stream is reached 774adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 775adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void readString(ASN1StringType type) throws IOException { 776adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 777adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project //FIXME check string content 778adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (tag == type.id) { 779adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project readContent(); 780adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (tag == type.constrId) { 781f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.139")); 782adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 783adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new ASN1Exception( 784f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes Messages.getString("security.13A", tagOffset, 785adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Integer.toHexString(tag))); 786adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 787adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 788adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 789adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 790adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns encoded array. 791f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 792f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * MUST be invoked after decoding corresponding ASN.1 notation 793adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 794adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public byte[] getEncoded() { 795adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] encoded = new byte[offset - tagOffset]; 796adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project System.arraycopy(buffer, tagOffset, encoded, 0, encoded.length); 797adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return encoded; 798adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 799adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 800adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 801adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns internal buffer used for decoding 802adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 803adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return - buffer 804adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 805adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final byte[] getBuffer() { 806adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return buffer; 807adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 808adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 809adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 810adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns length of the current content for decoding 811adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 812adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return - length of content 813adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 814adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final int getLength() { 815adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return length; 816adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 817adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 818adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 819adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns the current offset 820adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 821adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return - offset 822adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 823adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final int getOffset() { 824adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return offset; 825adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 826adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 827adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 828adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns end offset for the current encoded type 829adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 830adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return - offset 831adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 832adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final int getEndOffset() { 833adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return offset + length; 834adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 835adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 836adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 837adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns start offset for the current encoded type 838adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 839adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return - offset 840adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 841adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final int getTagOffset() { 842adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return tagOffset; 843adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 844adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 845adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final int getContentOffset() { 846adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return contentOffset; 847adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 848adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 849adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 850adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Indicates verify or store mode. 851f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 852adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * In store mode a decoded content is stored in a newly allocated 853adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * appropriate object. The <code>content</code> variable holds 854adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * a reference to the last created object. 855f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 856adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * In verify mode a decoded content is not stored. 857adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 858adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // FIXME it is used only for one case 859adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // decoding PCKS#8 Private Key Info notation 860adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // remove this option because it does decoding more complex 861adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected boolean isVerify; 862adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 863adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 864adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Sets verify mode. 865adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 866adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final void setVerify() { 867adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project isVerify = true; 868adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 869adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 870adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 871adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Indicates defined or indefined reading mode for associated InputStream. 872f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 873adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This mode is defined by reading a length 874adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * for a first ASN.1 type from InputStream. 875adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 876adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected boolean isIndefinedLength; 877adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 878adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 879adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Reads the next encoded byte from the encoded input stream. 880adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 881adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the next encoded byte 882adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException - if error occured 883adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 884adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected int read() throws IOException { 885adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 886adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (offset == buffer.length) { 887f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.13B")); 888adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 889adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 890adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (in == null) { 891adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return buffer[offset++] & 0xFF; 892adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 893adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int octet = in.read(); 894adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (octet == -1) { 895f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.13B")); 896adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 897f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 898adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buffer[offset++] = (byte) octet; 899f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 900adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return octet; 901adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 902adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 903adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 904adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 905adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Reads the next encoded content from the encoded input stream. 906adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The method MUST be used for reading a primitive encoded content. 907adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 908adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException - if error occured 909adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 910adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void readContent() throws IOException { 911adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (offset + length > buffer.length) { 912f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new ASN1Exception(Messages.getString("security.13B")); 913adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 914adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 915adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (in == null) { 916adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project offset += length; 917adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 9182f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes int bytesRead = in.read(buffer, offset, length); 9192f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes 9202f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes if (bytesRead != length) { 9212f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes // if input stream didn't return all data at once 9222f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes // try to read it in several blocks 9232f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes int c = bytesRead; 9242f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes do { 9252f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes if (c < 1 || bytesRead > length) { 9262f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes throw new ASN1Exception(Messages 927f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes .getString("security.13C")); 9282f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes } 9292f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes c = in.read(buffer, offset + bytesRead, length - bytesRead); 9302f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes bytesRead += c; 9312f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes } while (bytesRead != length); 932adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 9332f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes 934adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project offset += length; 935adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 936adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 937adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 938adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // // reallocates internal buffer for indefined reading mode 939adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // private void reallocateBuffer(int n) { 940adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // int newSize; 941adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // for (newSize = buffer.length * 2; newSize < buffer.length + n; newSize = newSize * 2) 942adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // ; 943adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // byte[] newBuffer = new byte[newSize]; 944adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // System.arraycopy(buffer, 0, newBuffer, 0, buffer.length); 945adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // buffer = newBuffer; 946adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // } 947adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 948adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 949adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Reallocates the buffer in order to make it 950adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * exactly the size of data it contains 951adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 952adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void compactBuffer() { 953adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (offset != buffer.length) { 954adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] newBuffer = new byte[offset]; 955adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // restore buffer content 956adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project System.arraycopy(buffer, 0, newBuffer, 0, offset); 957adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // set new buffer 958adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buffer = newBuffer; 959adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 960adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 961adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 962adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // 963adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // 964adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // 965adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // 966adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // 967adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 968adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private Object[][] pool; 969adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 970adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void put(Object key, Object entry) { 971adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 972adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (pool == null) { 973adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project pool = new Object[2][10]; 974adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 975adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 976adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int i = 0; 977adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (; i < pool[0].length && pool[0][i] != null; i++) { 978adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (pool[0][i] == key) { 979adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project pool[1][i] = entry; 980adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 981adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 982adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 983adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 984adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (i == pool[0].length) { 985adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Object[][] newPool = new Object[pool[0].length * 2][2]; 986adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project System.arraycopy(pool[0], 0, newPool[0], 0, pool[0].length); 987adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project System.arraycopy(pool[1], 0, newPool[1], 0, pool[0].length); 988adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project pool = newPool; 989adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 990adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project pool[0][i] = key; 991adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project pool[1][i] = entry; 992adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 993adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 994adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 995adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public Object get(Object key) { 996adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 997adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (pool == null) { 998adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 999adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1000adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1001adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (int i = 0; i < pool[0].length; i++) { 1002adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (pool[0][i] == key) { 1003adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return pool[1][i]; 1004adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1005adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1006adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 1007adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1008adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 1009