Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
      3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      4  *
      5  * This code is free software; you can redistribute it and/or modify it
      6  * under the terms of the GNU General Public License version 2 only, as
      7  * published by the Free Software Foundation.  Oracle designates this
      8  * particular file as subject to the "Classpath" exception as provided
      9  * by Oracle in the LICENSE file that accompanied this code.
     10  *
     11  * This code is distributed in the hope that it will be useful, but WITHOUT
     12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     14  * version 2 for more details (a copy is included in the LICENSE file that
     15  * accompanied this code).
     16  *
     17  * You should have received a copy of the GNU General Public License version
     18  * 2 along with this work; if not, write to the Free Software Foundation,
     19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     20  *
     21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     22  * or visit www.oracle.com if you need additional information or have any
     23  * questions.
     24  */
     25 
     26 package sun.security.util;
     27 
     28 import java.io.*;
     29 import java.math.BigInteger;
     30 import java.util.Date;
     31 import sun.misc.IOUtils;
     32 
     33 /**
     34  * Represents a single DER-encoded value.  DER encoding rules are a subset
     35  * of the "Basic" Encoding Rules (BER), but they only support a single way
     36  * ("Definite" encoding) to encode any given value.
     37  *
     38  * <P>All DER-encoded data are triples <em>{type, length, data}</em>.  This
     39  * class represents such tagged values as they have been read (or constructed),
     40  * and provides structured access to the encoded data.
     41  *
     42  * <P>At this time, this class supports only a subset of the types of DER
     43  * data encodings which are defined.  That subset is sufficient for parsing
     44  * most X.509 certificates, and working with selected additional formats
     45  * (such as PKCS #10 certificate requests, and some kinds of PKCS #7 data).
     46  *
     47  * A note with respect to T61/Teletex strings: From RFC 1617, section 4.1.3
     48  * and RFC 3280, section 4.1.2.4., we assume that this kind of string will
     49  * contain ISO-8859-1 characters only.
     50  *
     51  *
     52  * @author David Brownell
     53  * @author Amit Kapoor
     54  * @author Hemma Prafullchandra
     55  */
     56 public class DerValue {
     57     /** The tag class types */
     58     public static final byte TAG_UNIVERSAL = (byte)0x000;
     59     public static final byte TAG_APPLICATION = (byte)0x040;
     60     public static final byte TAG_CONTEXT = (byte)0x080;
     61     public static final byte TAG_PRIVATE = (byte)0x0c0;
     62 
     63     /** The DER tag of the value; one of the tag_ constants. */
     64     public byte                 tag;
     65 
     66     protected DerInputBuffer    buffer;
     67 
     68     /**
     69      * The DER-encoded data of the value, never null
     70      */
     71     public final DerInputStream data;
     72 
     73     private int                 length;
     74 
     75     // BEGIN Android-added: Original encoded form needed for APKs parsing/validation
     76     /**
     77      * The original encoded form of the whole value (tag, length, and value)
     78      * or null if the form was not provided or was not retained during parsing.
     79      */
     80     private byte[]              originalEncodedForm;
     81     // END Android-added: Original encoded form needed for APKs parsing/validation
     82 
     83     /*
     84      * The type starts at the first byte of the encoding, and
     85      * is one of these tag_* values.  That may be all the type
     86      * data that is needed.
     87      */
     88 
     89     /*
     90      * These tags are the "universal" tags ... they mean the same
     91      * in all contexts.  (Mask with 0x1f -- five bits.)
     92      */
     93 
     94     /** Tag value indicating an ASN.1 "BOOLEAN" value. */
     95     public final static byte    tag_Boolean = 0x01;
     96 
     97     /** Tag value indicating an ASN.1 "INTEGER" value. */
     98     public final static byte    tag_Integer = 0x02;
     99 
    100     /** Tag value indicating an ASN.1 "BIT STRING" value. */
    101     public final static byte    tag_BitString = 0x03;
    102 
    103     /** Tag value indicating an ASN.1 "OCTET STRING" value. */
    104     public final static byte    tag_OctetString = 0x04;
    105 
    106     /** Tag value indicating an ASN.1 "NULL" value. */
    107     public final static byte    tag_Null = 0x05;
    108 
    109     /** Tag value indicating an ASN.1 "OBJECT IDENTIFIER" value. */
    110     public final static byte    tag_ObjectId = 0x06;
    111 
    112     /** Tag value including an ASN.1 "ENUMERATED" value */
    113     public final static byte    tag_Enumerated = 0x0A;
    114 
    115     /** Tag value indicating an ASN.1 "UTF8String" value. */
    116     public final static byte    tag_UTF8String = 0x0C;
    117 
    118     /** Tag value including a "printable" string */
    119     public final static byte    tag_PrintableString = 0x13;
    120 
    121     /** Tag value including a "teletype" string */
    122     public final static byte    tag_T61String = 0x14;
    123 
    124     /** Tag value including an ASCII string */
    125     public final static byte    tag_IA5String = 0x16;
    126 
    127     /** Tag value indicating an ASN.1 "UTCTime" value. */
    128     public final static byte    tag_UtcTime = 0x17;
    129 
    130     /** Tag value indicating an ASN.1 "GeneralizedTime" value. */
    131     public final static byte    tag_GeneralizedTime = 0x18;
    132 
    133     /** Tag value indicating an ASN.1 "GenerallString" value. */
    134     public final static byte    tag_GeneralString = 0x1B;
    135 
    136     /** Tag value indicating an ASN.1 "UniversalString" value. */
    137     public final static byte    tag_UniversalString = 0x1C;
    138 
    139     /** Tag value indicating an ASN.1 "BMPString" value. */
    140     public final static byte    tag_BMPString = 0x1E;
    141 
    142     // CONSTRUCTED seq/set
    143 
    144     /**
    145      * Tag value indicating an ASN.1
    146      * "SEQUENCE" (zero to N elements, order is significant).
    147      */
    148     public final static byte    tag_Sequence = 0x30;
    149 
    150     /**
    151      * Tag value indicating an ASN.1
    152      * "SEQUENCE OF" (one to N elements, order is significant).
    153      */
    154     public final static byte    tag_SequenceOf = 0x30;
    155 
    156     /**
    157      * Tag value indicating an ASN.1
    158      * "SET" (zero to N members, order does not matter).
    159      */
    160     public final static byte    tag_Set = 0x31;
    161 
    162     /**
    163      * Tag value indicating an ASN.1
    164      * "SET OF" (one to N members, order does not matter).
    165      */
    166     public final static byte    tag_SetOf = 0x31;
    167 
    168     /*
    169      * These values are the high order bits for the other kinds of tags.
    170      */
    171 
    172     /**
    173      * Returns true if the tag class is UNIVERSAL.
    174      */
    175     public boolean isUniversal()      { return ((tag & 0x0c0) == 0x000); }
    176 
    177     /**
    178      * Returns true if the tag class is APPLICATION.
    179      */
    180     public boolean isApplication()    { return ((tag & 0x0c0) == 0x040); }
    181 
    182     /**
    183      * Returns true iff the CONTEXT SPECIFIC bit is set in the type tag.
    184      * This is associated with the ASN.1 "DEFINED BY" syntax.
    185      */
    186     public boolean isContextSpecific() { return ((tag & 0x0c0) == 0x080); }
    187 
    188     /**
    189      * Returns true iff the CONTEXT SPECIFIC TAG matches the passed tag.
    190      */
    191     public boolean isContextSpecific(byte cntxtTag) {
    192         if (!isContextSpecific()) {
    193             return false;
    194         }
    195         return ((tag & 0x01f) == cntxtTag);
    196     }
    197 
    198     boolean isPrivate()        { return ((tag & 0x0c0) == 0x0c0); }
    199 
    200     /** Returns true iff the CONSTRUCTED bit is set in the type tag. */
    201     public boolean isConstructed()    { return ((tag & 0x020) == 0x020); }
    202 
    203     /**
    204      * Returns true iff the CONSTRUCTED TAG matches the passed tag.
    205      */
    206     public boolean isConstructed(byte constructedTag) {
    207         if (!isConstructed()) {
    208             return false;
    209         }
    210         return ((tag & 0x01f) == constructedTag);
    211     }
    212 
    213     /**
    214      * Creates a PrintableString or UTF8string DER value from a string
    215      */
    216     public DerValue(String value) throws IOException {
    217         boolean isPrintableString = true;
    218         for (int i = 0; i < value.length(); i++) {
    219             if (!isPrintableStringChar(value.charAt(i))) {
    220                 isPrintableString = false;
    221                 break;
    222             }
    223         }
    224 
    225         data = init(isPrintableString ? tag_PrintableString : tag_UTF8String, value);
    226     }
    227 
    228     /**
    229      * Creates a string type DER value from a String object
    230      * @param stringTag the tag for the DER value to create
    231      * @param value the String object to use for the DER value
    232      */
    233     public DerValue(byte stringTag, String value) throws IOException {
    234         data = init(stringTag, value);
    235     }
    236 
    237     /**
    238      * Creates a DerValue from a tag and some DER-encoded data.
    239      *
    240      * @param tag the DER type tag
    241      * @param data the DER-encoded data
    242      */
    243     public DerValue(byte tag, byte[] data) {
    244         this.tag = tag;
    245         buffer = new DerInputBuffer(data.clone());
    246         length = data.length;
    247         this.data = new DerInputStream(buffer);
    248         this.data.mark(Integer.MAX_VALUE);
    249     }
    250 
    251     /*
    252      * package private
    253      */
    254     // BEGIN Android-changed: Original encoded form needed for APKs parsing/validation
    255     DerValue(DerInputBuffer in, boolean originalEncodedFormRetained)
    256             throws IOException {
    257         // XXX must also parse BER-encoded constructed
    258         // values such as sequences, sets...
    259 
    260         int startPosInInput = in.getPos();
    261         tag = (byte)in.read();
    262         byte lenByte = (byte)in.read();
    263         length = DerInputStream.getLength(lenByte, in);
    264         if (length == -1) {  // indefinite length encoding found
    265             DerInputBuffer inbuf = in.dup();
    266             int readLen = inbuf.available();
    267             int offset = 2;     // for tag and length bytes
    268             byte[] indefData = new byte[readLen + offset];
    269             indefData[0] = tag;
    270             indefData[1] = lenByte;
    271             DataInputStream dis = new DataInputStream(inbuf);
    272             dis.readFully(indefData, offset, readLen);
    273             dis.close();
    274             DerIndefLenConverter derIn = new DerIndefLenConverter();
    275             inbuf = new DerInputBuffer(derIn.convert(indefData));
    276             if (tag != inbuf.read())
    277                 throw new IOException
    278                         ("Indefinite length encoding not supported");
    279             length = DerInputStream.getLength(inbuf);
    280             buffer = inbuf.dup();
    281             buffer.truncate(length);
    282             data = new DerInputStream(buffer);
    283             // indefinite form is encoded by sending a length field with a
    284             // length of 0. - i.e. [1000|0000].
    285             // the object is ended by sending two zero bytes.
    286             in.skip(length + offset);
    287         } else {
    288 
    289             buffer = in.dup();
    290             buffer.truncate(length);
    291             data = new DerInputStream(buffer);
    292 
    293             in.skip(length);
    294         }
    295 
    296         if (originalEncodedFormRetained) {
    297             int consumed = in.getPos() - startPosInInput;
    298             originalEncodedForm = in.getSlice(startPosInInput, consumed);
    299         }
    300     // END Android-changed: Original encoded form needed for APKs parsing/validation
    301     }
    302 
    303     /**
    304      * Get an ASN.1/DER encoded datum from a buffer.  The
    305      * entire buffer must hold exactly one datum, including
    306      * its tag and length.
    307      *
    308      * @param buf buffer holding a single DER-encoded datum.
    309      */
    310     public DerValue(byte[] buf) throws IOException {
    311         data = init(true, new ByteArrayInputStream(buf));
    312     }
    313 
    314     /**
    315      * Get an ASN.1/DER encoded datum from part of a buffer.
    316      * That part of the buffer must hold exactly one datum, including
    317      * its tag and length.
    318      *
    319      * @param buf the buffer
    320      * @param offset start point of the single DER-encoded dataum
    321      * @param length how many bytes are in the encoded datum
    322      */
    323     public DerValue(byte[] buf, int offset, int len) throws IOException {
    324         data = init(true, new ByteArrayInputStream(buf, offset, len));
    325     }
    326 
    327     /**
    328      * Get an ASN1/DER encoded datum from an input stream.  The
    329      * stream may have additional data following the encoded datum.
    330      * In case of indefinite length encoded datum, the input stream
    331      * must hold only one datum.
    332      *
    333      * @param in the input stream holding a single DER datum,
    334      *  which may be followed by additional data
    335      */
    336     public DerValue(InputStream in) throws IOException {
    337         data = init(false, in);
    338     }
    339 
    340     private DerInputStream init(byte stringTag, String value) throws IOException {
    341         String enc = null;
    342 
    343         tag = stringTag;
    344 
    345         switch (stringTag) {
    346         case tag_PrintableString:
    347         case tag_IA5String:
    348         case tag_GeneralString:
    349             enc = "ASCII";
    350             break;
    351         case tag_T61String:
    352             enc = "ISO-8859-1";
    353             break;
    354         case tag_BMPString:
    355             enc = "UnicodeBigUnmarked";
    356             break;
    357         case tag_UTF8String:
    358             enc = "UTF8";
    359             break;
    360             // TBD: Need encoder for UniversalString before it can
    361             // be handled.
    362         default:
    363             throw new IllegalArgumentException("Unsupported DER string type");
    364         }
    365 
    366         byte[] buf = value.getBytes(enc);
    367         length = buf.length;
    368         buffer = new DerInputBuffer(buf);
    369         DerInputStream result = new DerInputStream(buffer);
    370         result.mark(Integer.MAX_VALUE);
    371         return result;
    372     }
    373 
    374     /*
    375      * helper routine
    376      */
    377     private DerInputStream init(boolean fullyBuffered, InputStream in)
    378             throws IOException {
    379 
    380         tag = (byte)in.read();
    381         byte lenByte = (byte)in.read();
    382         length = DerInputStream.getLength(lenByte, in);
    383         if (length == -1) { // indefinite length encoding found
    384             int readLen = in.available();
    385             int offset = 2;     // for tag and length bytes
    386             byte[] indefData = new byte[readLen + offset];
    387             indefData[0] = tag;
    388             indefData[1] = lenByte;
    389             DataInputStream dis = new DataInputStream(in);
    390             dis.readFully(indefData, offset, readLen);
    391             dis.close();
    392             DerIndefLenConverter derIn = new DerIndefLenConverter();
    393             in = new ByteArrayInputStream(derIn.convert(indefData));
    394             if (tag != in.read())
    395                 throw new IOException
    396                         ("Indefinite length encoding not supported");
    397             length = DerInputStream.getLength(in);
    398         }
    399 
    400         if (fullyBuffered && in.available() != length)
    401             throw new IOException("extra data given to DerValue constructor");
    402 
    403         byte[] bytes = IOUtils.readFully(in, length, true);
    404 
    405         buffer = new DerInputBuffer(bytes);
    406         return new DerInputStream(buffer);
    407     }
    408 
    409     /**
    410      * Encode an ASN1/DER encoded datum onto a DER output stream.
    411      */
    412     public void encode(DerOutputStream out)
    413     throws IOException {
    414         out.write(tag);
    415         out.putLength(length);
    416         // XXX yeech, excess copies ... DerInputBuffer.write(OutStream)
    417         if (length > 0) {
    418             byte[] value = new byte[length];
    419             // always synchronized on data
    420             synchronized (data) {
    421                 buffer.reset();
    422                 if (buffer.read(value) != length) {
    423                     throw new IOException("short DER value read (encode)");
    424                 }
    425                 out.write(value);
    426             }
    427         }
    428     }
    429 
    430     public final DerInputStream getData() {
    431         return data;
    432     }
    433 
    434     public final byte getTag() {
    435         return tag;
    436     }
    437 
    438     /**
    439      * Returns an ASN.1 BOOLEAN
    440      *
    441      * @return the boolean held in this DER value
    442      */
    443     public boolean getBoolean() throws IOException {
    444         if (tag != tag_Boolean) {
    445             throw new IOException("DerValue.getBoolean, not a BOOLEAN " + tag);
    446         }
    447         if (length != 1) {
    448             throw new IOException("DerValue.getBoolean, invalid length "
    449                                         + length);
    450         }
    451         if (buffer.read() != 0) {
    452             return true;
    453         }
    454         return false;
    455     }
    456 
    457     /**
    458      * Returns an ASN.1 OBJECT IDENTIFIER.
    459      *
    460      * @return the OID held in this DER value
    461      */
    462     public ObjectIdentifier getOID() throws IOException {
    463         if (tag != tag_ObjectId)
    464             throw new IOException("DerValue.getOID, not an OID " + tag);
    465         return new ObjectIdentifier(buffer);
    466     }
    467 
    468     private byte[] append(byte[] a, byte[] b) {
    469         if (a == null)
    470             return b;
    471 
    472         byte[] ret = new byte[a.length + b.length];
    473         System.arraycopy(a, 0, ret, 0, a.length);
    474         System.arraycopy(b, 0, ret, a.length, b.length);
    475 
    476         return ret;
    477     }
    478 
    479     /**
    480      * Returns an ASN.1 OCTET STRING
    481      *
    482      * @return the octet string held in this DER value
    483      */
    484     public byte[] getOctetString() throws IOException {
    485         byte[] bytes;
    486 
    487         if (tag != tag_OctetString && !isConstructed(tag_OctetString)) {
    488             throw new IOException(
    489                 "DerValue.getOctetString, not an Octet String: " + tag);
    490         }
    491         bytes = new byte[length];
    492         // Note: do not tempt to call buffer.read(bytes) at all. There's a
    493         // known bug that it returns -1 instead of 0.
    494         if (length == 0) {
    495             return bytes;
    496         }
    497         if (buffer.read(bytes) != length)
    498             throw new IOException("short read on DerValue buffer");
    499         if (isConstructed()) {
    500             DerInputStream in = new DerInputStream(bytes);
    501             bytes = null;
    502             while (in.available() != 0) {
    503                 bytes = append(bytes, in.getOctetString());
    504             }
    505         }
    506         return bytes;
    507     }
    508 
    509     /**
    510      * Returns an ASN.1 INTEGER value as an integer.
    511      *
    512      * @return the integer held in this DER value.
    513      */
    514     public int getInteger() throws IOException {
    515         if (tag != tag_Integer) {
    516             throw new IOException("DerValue.getInteger, not an int " + tag);
    517         }
    518         return buffer.getInteger(data.available());
    519     }
    520 
    521     /**
    522      * Returns an ASN.1 INTEGER value as a BigInteger.
    523      *
    524      * @return the integer held in this DER value as a BigInteger.
    525      */
    526     public BigInteger getBigInteger() throws IOException {
    527         if (tag != tag_Integer)
    528             throw new IOException("DerValue.getBigInteger, not an int " + tag);
    529         return buffer.getBigInteger(data.available(), false);
    530     }
    531 
    532     /**
    533      * Returns an ASN.1 INTEGER value as a positive BigInteger.
    534      * This is just to deal with implementations that incorrectly encode
    535      * some values as negative.
    536      *
    537      * @return the integer held in this DER value as a BigInteger.
    538      */
    539     public BigInteger getPositiveBigInteger() throws IOException {
    540         if (tag != tag_Integer)
    541             throw new IOException("DerValue.getBigInteger, not an int " + tag);
    542         return buffer.getBigInteger(data.available(), true);
    543     }
    544 
    545     /**
    546      * Returns an ASN.1 ENUMERATED value.
    547      *
    548      * @return the integer held in this DER value.
    549      */
    550     public int getEnumerated() throws IOException {
    551         if (tag != tag_Enumerated) {
    552             throw new IOException("DerValue.getEnumerated, incorrect tag: "
    553                                   + tag);
    554         }
    555         return buffer.getInteger(data.available());
    556     }
    557 
    558     /**
    559      * Returns an ASN.1 BIT STRING value.  The bit string must be byte-aligned.
    560      *
    561      * @return the bit string held in this value
    562      */
    563     public byte[] getBitString() throws IOException {
    564         if (tag != tag_BitString)
    565             throw new IOException(
    566                 "DerValue.getBitString, not a bit string " + tag);
    567 
    568         return buffer.getBitString();
    569     }
    570 
    571     /**
    572      * Returns an ASN.1 BIT STRING value that need not be byte-aligned.
    573      *
    574      * @return a BitArray representing the bit string held in this value
    575      */
    576     public BitArray getUnalignedBitString() throws IOException {
    577         if (tag != tag_BitString)
    578             throw new IOException(
    579                 "DerValue.getBitString, not a bit string " + tag);
    580 
    581         return buffer.getUnalignedBitString();
    582     }
    583 
    584     /**
    585      * Returns the name component as a Java string, regardless of its
    586      * encoding restrictions (ASCII, T61, Printable, IA5, BMP, UTF8).
    587      */
    588     // TBD: Need encoder for UniversalString before it can be handled.
    589     public String getAsString() throws IOException {
    590         if (tag == tag_UTF8String)
    591             return getUTF8String();
    592         else if (tag == tag_PrintableString)
    593             return getPrintableString();
    594         else if (tag == tag_T61String)
    595             return getT61String();
    596         else if (tag == tag_IA5String)
    597             return getIA5String();
    598         /*
    599           else if (tag == tag_UniversalString)
    600           return getUniversalString();
    601         */
    602         else if (tag == tag_BMPString)
    603             return getBMPString();
    604         else if (tag == tag_GeneralString)
    605             return getGeneralString();
    606         else
    607             return null;
    608     }
    609 
    610     /**
    611      * Returns an ASN.1 BIT STRING value, with the tag assumed implicit
    612      * based on the parameter.  The bit string must be byte-aligned.
    613      *
    614      * @params tagImplicit if true, the tag is assumed implicit.
    615      * @return the bit string held in this value
    616      */
    617     public byte[] getBitString(boolean tagImplicit) throws IOException {
    618         if (!tagImplicit) {
    619             if (tag != tag_BitString)
    620                 throw new IOException("DerValue.getBitString, not a bit string "
    621                                        + tag);
    622             }
    623         return buffer.getBitString();
    624     }
    625 
    626     /**
    627      * Returns an ASN.1 BIT STRING value, with the tag assumed implicit
    628      * based on the parameter.  The bit string need not be byte-aligned.
    629      *
    630      * @params tagImplicit if true, the tag is assumed implicit.
    631      * @return the bit string held in this value
    632      */
    633     public BitArray getUnalignedBitString(boolean tagImplicit)
    634     throws IOException {
    635         if (!tagImplicit) {
    636             if (tag != tag_BitString)
    637                 throw new IOException("DerValue.getBitString, not a bit string "
    638                                        + tag);
    639             }
    640         return buffer.getUnalignedBitString();
    641     }
    642 
    643     /**
    644      * Helper routine to return all the bytes contained in the
    645      * DerInputStream associated with this object.
    646      */
    647     public byte[] getDataBytes() throws IOException {
    648         byte[] retVal = new byte[length];
    649         synchronized (data) {
    650             data.reset();
    651             data.getBytes(retVal);
    652         }
    653         return retVal;
    654     }
    655 
    656     /**
    657      * Returns an ASN.1 STRING value
    658      *
    659      * @return the printable string held in this value
    660      */
    661     public String getPrintableString()
    662     throws IOException {
    663         if (tag != tag_PrintableString)
    664             throw new IOException(
    665                 "DerValue.getPrintableString, not a string " + tag);
    666 
    667         return new String(getDataBytes(), "ASCII");
    668     }
    669 
    670     /**
    671      * Returns an ASN.1 T61 (Teletype) STRING value
    672      *
    673      * @return the teletype string held in this value
    674      */
    675     public String getT61String() throws IOException {
    676         if (tag != tag_T61String)
    677             throw new IOException(
    678                 "DerValue.getT61String, not T61 " + tag);
    679 
    680         return new String(getDataBytes(), "ISO-8859-1");
    681     }
    682 
    683     /**
    684      * Returns an ASN.1 IA5 (ASCII) STRING value
    685      *
    686      * @return the ASCII string held in this value
    687      */
    688     public String getIA5String() throws IOException {
    689         if (tag != tag_IA5String)
    690             throw new IOException(
    691                 "DerValue.getIA5String, not IA5 " + tag);
    692 
    693         return new String(getDataBytes(), "ASCII");
    694     }
    695 
    696     /**
    697      * Returns the ASN.1 BMP (Unicode) STRING value as a Java string.
    698      *
    699      * @return a string corresponding to the encoded BMPString held in
    700      * this value
    701      */
    702     public String getBMPString() throws IOException {
    703         if (tag != tag_BMPString)
    704             throw new IOException(
    705                 "DerValue.getBMPString, not BMP " + tag);
    706 
    707         // BMPString is the same as Unicode in big endian, unmarked
    708         // format.
    709         return new String(getDataBytes(), "UnicodeBigUnmarked");
    710     }
    711 
    712     /**
    713      * Returns the ASN.1 UTF-8 STRING value as a Java String.
    714      *
    715      * @return a string corresponding to the encoded UTF8String held in
    716      * this value
    717      */
    718     public String getUTF8String() throws IOException {
    719         if (tag != tag_UTF8String)
    720             throw new IOException(
    721                 "DerValue.getUTF8String, not UTF-8 " + tag);
    722 
    723         return new String(getDataBytes(), "UTF8");
    724     }
    725 
    726     /**
    727      * Returns the ASN.1 GENERAL STRING value as a Java String.
    728      *
    729      * @return a string corresponding to the encoded GeneralString held in
    730      * this value
    731      */
    732     public String getGeneralString() throws IOException {
    733         if (tag != tag_GeneralString)
    734             throw new IOException(
    735                 "DerValue.getGeneralString, not GeneralString " + tag);
    736 
    737         return new String(getDataBytes(), "ASCII");
    738     }
    739 
    740     /**
    741      * Returns a Date if the DerValue is UtcTime.
    742      *
    743      * @return the Date held in this DER value
    744      */
    745     public Date getUTCTime() throws IOException {
    746         if (tag != tag_UtcTime) {
    747             throw new IOException("DerValue.getUTCTime, not a UtcTime: " + tag);
    748         }
    749         return buffer.getUTCTime(data.available());
    750     }
    751 
    752     /**
    753      * Returns a Date if the DerValue is GeneralizedTime.
    754      *
    755      * @return the Date held in this DER value
    756      */
    757     public Date getGeneralizedTime() throws IOException {
    758         if (tag != tag_GeneralizedTime) {
    759             throw new IOException(
    760                 "DerValue.getGeneralizedTime, not a GeneralizedTime: " + tag);
    761         }
    762         return buffer.getGeneralizedTime(data.available());
    763     }
    764 
    765     /**
    766      * Returns true iff the other object is a DER value which
    767      * is bitwise equal to this one.
    768      *
    769      * @param other the object being compared with this one
    770      */
    771     public boolean equals(Object other) {
    772         if (other instanceof DerValue)
    773             return equals((DerValue)other);
    774         else
    775             return false;
    776     }
    777 
    778     /**
    779      * Bitwise equality comparison.  DER encoded values have a single
    780      * encoding, so that bitwise equality of the encoded values is an
    781      * efficient way to establish equivalence of the unencoded values.
    782      *
    783      * @param other the object being compared with this one
    784      */
    785     public boolean equals(DerValue other) {
    786         if (this == other) {
    787             return true;
    788         }
    789         if (tag != other.tag) {
    790             return false;
    791         }
    792         if (data == other.data) {
    793             return true;
    794         }
    795 
    796         // make sure the order of lock is always consistent to avoid a deadlock
    797         return (System.identityHashCode(this.data)
    798                 > System.identityHashCode(other.data)) ?
    799                 doEquals(this, other):
    800                 doEquals(other, this);
    801     }
    802 
    803     /**
    804      * Helper for public method equals()
    805      */
    806     private static boolean doEquals(DerValue d1, DerValue d2) {
    807         synchronized (d1.data) {
    808             synchronized (d2.data) {
    809                 d1.data.reset();
    810                 d2.data.reset();
    811                 return d1.buffer.equals(d2.buffer);
    812             }
    813         }
    814     }
    815 
    816     /**
    817      * Returns a printable representation of the value.
    818      *
    819      * @return printable representation of the value
    820      */
    821     public String toString() {
    822         try {
    823 
    824             String str = getAsString();
    825             if (str != null)
    826                 return "\"" + str + "\"";
    827             if (tag == tag_Null)
    828                 return "[DerValue, null]";
    829             if (tag == tag_ObjectId)
    830                 return "OID." + getOID();
    831 
    832             // integers
    833             else
    834                 return "[DerValue, tag = " + tag
    835                         + ", length = " + length + "]";
    836         } catch (IOException e) {
    837             throw new IllegalArgumentException("misformatted DER value");
    838         }
    839     }
    840 
    841     // BEGIN Android-added: Original encoded form needed for APKs parsing/validation
    842     /**
    843      * Returns the original encoded form or {@code null} if the form was not
    844      * retained or is not available.
    845      */
    846     public byte[] getOriginalEncodedForm() {
    847         return (originalEncodedForm != null)
    848                 ? originalEncodedForm.clone() : null;
    849     }
    850     // END Android-added: Original encoded form needed for APKs parsing/validation
    851 
    852     /**
    853      * Returns a DER-encoded value, such that if it's passed to the
    854      * DerValue constructor, a value equivalent to "this" is returned.
    855      *
    856      * @return DER-encoded value, including tag and length.
    857      */
    858     public byte[] toByteArray() throws IOException {
    859         DerOutputStream out = new DerOutputStream();
    860 
    861         encode(out);
    862         data.reset();
    863         return out.toByteArray();
    864     }
    865 
    866     /**
    867      * For "set" and "sequence" types, this function may be used
    868      * to return a DER stream of the members of the set or sequence.
    869      * This operation is not supported for primitive types such as
    870      * integers or bit strings.
    871      */
    872     public DerInputStream toDerInputStream() throws IOException {
    873         if (tag == tag_Sequence || tag == tag_Set)
    874             return new DerInputStream(buffer);
    875         throw new IOException("toDerInputStream rejects tag type " + tag);
    876     }
    877 
    878     /**
    879      * Get the length of the encoded value.
    880      */
    881     public int length() {
    882         return length;
    883     }
    884 
    885     /**
    886      * Determine if a character is one of the permissible characters for
    887      * PrintableString:
    888      * A-Z, a-z, 0-9, space, apostrophe (39), left and right parentheses,
    889      * plus sign, comma, hyphen, period, slash, colon, equals sign,
    890      * and question mark.
    891      *
    892      * Characters that are *not* allowed in PrintableString include
    893      * exclamation point, quotation mark, number sign, dollar sign,
    894      * percent sign, ampersand, asterisk, semicolon, less than sign,
    895      * greater than sign, at sign, left and right square brackets,
    896      * backslash, circumflex (94), underscore, back quote (96),
    897      * left and right curly brackets, vertical line, tilde,
    898      * and the control codes (0-31 and 127).
    899      *
    900      * This list is based on X.680 (the ASN.1 spec).
    901      */
    902     public static boolean isPrintableStringChar(char ch) {
    903         if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
    904             (ch >= '0' && ch <= '9')) {
    905             return true;
    906         } else {
    907             switch (ch) {
    908                 case ' ':       /* space */
    909                 case '\'':      /* apostrophe */
    910                 case '(':       /* left paren */
    911                 case ')':       /* right paren */
    912                 case '+':       /* plus */
    913                 case ',':       /* comma */
    914                 case '-':       /* hyphen */
    915                 case '.':       /* period */
    916                 case '/':       /* slash */
    917                 case ':':       /* colon */
    918                 case '=':       /* equals */
    919                 case '?':       /* question mark */
    920                     return true;
    921                 default:
    922                     return false;
    923             }
    924         }
    925     }
    926 
    927     /**
    928      * Create the tag of the attribute.
    929      *
    930      * @params class the tag class type, one of UNIVERSAL, CONTEXT,
    931      *               APPLICATION or PRIVATE
    932      * @params form if true, the value is constructed, otherwise it
    933      * is primitive.
    934      * @params val the tag value
    935      */
    936     public static byte createTag(byte tagClass, boolean form, byte val) {
    937         byte tag = (byte)(tagClass | val);
    938         if (form) {
    939             tag |= (byte)0x20;
    940         }
    941         return (tag);
    942     }
    943 
    944     /**
    945      * Set the tag of the attribute. Commonly used to reset the
    946      * tag value used for IMPLICIT encodings.
    947      *
    948      * @params tag the tag value
    949      */
    950     public void resetTag(byte tag) {
    951         this.tag = tag;
    952     }
    953 
    954     /**
    955      * Returns a hashcode for this DerValue.
    956      *
    957      * @return a hashcode for this DerValue.
    958      */
    959     public int hashCode() {
    960         return toString().hashCode();
    961     }
    962 }
    963