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 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 Project 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Decodes ASN.1 types encoded with DER (X.690) 30f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see <a href="http://asn1.elibel.tm.fr/en/standards/index.htm">ASN.1</a> 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic final class DerInputStream extends BerInputStream { 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 355c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson /** mask for verifying unused bits for ASN.1 bitstring */ 365c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson private static final byte[] UNUSED_BITS_MASK = new byte[] { 0x01, 0x03, 375c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson 0x07, 0x0F, 0x1F, 0x3F, 0x7F }; 385c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public DerInputStream(byte[] encoded) throws IOException { 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(encoded, 0, encoded.length); 41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 435c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson public DerInputStream(byte[] encoded, int offset, int encodingLen) throws IOException { 44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(encoded, offset, encodingLen); 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public DerInputStream(InputStream in) throws IOException { 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(in); 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 515c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson public int next() throws IOException { 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int tag = super.next(); 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (length == INDEFINIT_LENGTH) { 55897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes throw new ASN1Exception("DER: only definite length encoding MUST be used"); 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // FIXME add check: length encoding uses minimum number of octets 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return tag; 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void readBitString() throws IOException { 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (tag == ASN1Constants.TAG_C_BITSTRING) { 655c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson throw new ASN1Exception("ASN.1 bitstring: constructed identifier at [" + tagOffset 665c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson + "]. Not valid for DER."); 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.readBitString(); 70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project //check: unused bits values - MUST be 0 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (length > 1 73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project && buffer[contentOffset] != 0 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project && (buffer[offset - 1] & UNUSED_BITS_MASK[buffer[contentOffset] - 1]) != 0) { 755c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson throw new ASN1Exception("ASN.1 bitstring: wrong content at [" + contentOffset 765c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson + "]. DER requires zero unused bits in final octet."); 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void readBoolean() throws IOException { 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.readBoolean(); 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // check encoded content 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (buffer[contentOffset] != 0 && buffer[contentOffset] != (byte) 0xFF) { 855c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson throw new ASN1Exception("ASN.1 boolean: wrong content at [" + contentOffset 865c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson + "]. DER allows only 0x00 or 0xFF values"); 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void readOctetString() throws IOException { 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (tag == ASN1Constants.TAG_C_OCTETSTRING) { 925c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson throw new ASN1Exception("ASN.1 octetstring: constructed identifier at [" + tagOffset 935c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson + "]. Not valid for DER."); 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.readOctetString(); 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void readSequence(ASN1Sequence sequence) throws IOException { 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // According to ASN.1 DER spec. sequence MUST not include 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // any encoding which value is equal to its default value 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Verification of this assertion is not implemented 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.readSequence(sequence); 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void readSetOf(ASN1SetOf setOf) throws IOException { 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // According to ASN.1 DER spec. set of MUST appear in 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // ascending order (short component are padded for comparison) 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Verification of this assertion is not implemented 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // 115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.readSetOf(setOf); 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void readString(ASN1StringType type) throws IOException { 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (tag == type.constrId) { 1205c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson throw new ASN1Exception("ASN.1 string: constructed identifier at [" + tagOffset 1215c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson + "]. Not valid for DER."); 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.readString(type); 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void readUTCTime() throws IOException { 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (tag == ASN1Constants.TAG_C_UTCTIME) { 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // It is a string type and it can be encoded as primitive or constructed. 1295c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson throw new ASN1Exception("ASN.1 UTCTime: constructed identifier at [" + tagOffset 1305c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson + "]. Not valid for DER."); 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // check format: DER uses YYMMDDHHMMSS'Z' only 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (length != ASN1UTCTime.UTC_HMS) { 1355c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson throw new ASN1Exception("ASN.1 UTCTime: wrong format for DER, identifier at [" 1365c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson + tagOffset + "]"); 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.readUTCTime(); 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void readGeneralizedTime() throws IOException { 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (tag == ASN1Constants.TAG_C_GENERALIZEDTIME) { 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // It is a string type and it can be encoded as primitive or constructed. 1455c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson throw new ASN1Exception("ASN.1 GeneralizedTime: constructed identifier at [" 1465c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson + tagOffset + "]. Not valid for DER."); 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.readGeneralizedTime(); 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 152