Home | History | Annotate | Download | only in asn1
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 /**
     19 * @author Vladimir N. Molotkov, Stepan M. Mishura
     20 * @version $Revision$
     21 */
     22 
     23 package org.apache.harmony.security.asn1;
     24 
     25 import java.io.IOException;
     26 import java.io.InputStream;
     27 
     28 
     29 /**
     30  * This abstract class is the super class for all ASN.1 types
     31  *
     32  * @see <a href="http://asn1.elibel.tm.fr/en/standards/index.htm">ASN.1</a>
     33  */
     34 public abstract class ASN1Type implements ASN1Constants {
     35 
     36     /** Integer representation of primitive identifier. */
     37     public final int id;
     38 
     39     /** Integer representation of constructed identifier. */
     40     public final int constrId;
     41 
     42     /**
     43      * Constructs a primitive, universal ASN.1 type.
     44      *
     45      * @param tagNumber - ASN.1 tag number
     46      * @throws IllegalArgumentException - if tagNumber is invalid
     47      */
     48     public ASN1Type(int tagNumber) {
     49         this(CLASS_UNIVERSAL, tagNumber);
     50     }
     51 
     52     /**
     53      * Constructs an ASN.1 type.
     54      *
     55      * @param tagClass - tag class. MUST be
     56      *     CLASS_UNIVERSAL, CLASS_APPLICATION, CLASS_CONTEXTSPECIFIC, CLASS_PRIVATE
     57      * @param tagNumber - ASN.1 tag number.
     58      * @throws IllegalArgumentException - if tagClass or tagNumber is invalid
     59      */
     60     public ASN1Type(int tagClass, int tagNumber) {
     61         if (tagNumber < 0) {
     62             throw new IllegalArgumentException("tagNumber < 0");
     63         }
     64 
     65         if (tagClass != CLASS_UNIVERSAL && tagClass != CLASS_APPLICATION
     66                 && tagClass != CLASS_CONTEXTSPECIFIC
     67                 && tagClass != CLASS_PRIVATE) {
     68             throw new IllegalArgumentException("invalid tagClass");
     69         }
     70 
     71         if (tagNumber < 31) {
     72             // short form
     73             this.id = tagClass + tagNumber;
     74         } else {
     75             // long form
     76             throw new IllegalArgumentException("tag long form not implemented");
     77         }
     78         this.constrId = this.id + PC_CONSTRUCTED;
     79     }
     80 
     81     public final Object decode(byte[] encoded) throws IOException {
     82         return decode(new DerInputStream(encoded));
     83     }
     84 
     85     public final Object decode(byte[] encoded, int offset, int encodingLen)
     86             throws IOException {
     87         return decode(new DerInputStream(encoded, offset, encodingLen));
     88     }
     89 
     90     public final Object decode(InputStream in) throws IOException {
     91         return decode(new DerInputStream(in));
     92     }
     93 
     94     public final void verify(byte[] encoded) throws IOException {
     95         DerInputStream decoder = new DerInputStream(encoded);
     96         decoder.setVerify();
     97         decode(decoder);
     98     }
     99 
    100     public final void verify(InputStream in) throws IOException {
    101         DerInputStream decoder = new DerInputStream(in);
    102         decoder.setVerify();
    103         decode(decoder);
    104     }
    105 
    106     public final byte[] encode(Object object) {
    107         DerOutputStream out = new DerOutputStream(this, object);
    108         return out.encoded;
    109     }
    110 
    111     /**
    112      * Decodes ASN.1 type.
    113      *
    114      * @throws IOException if an I/O error occurs or the end of the stream is reached
    115      */
    116     public abstract Object decode(BerInputStream in) throws IOException;
    117 
    118     /**
    119      * Tests provided identifier.
    120      *
    121      * @param identifier identifier to be verified
    122      * @return true if identifier is associated with this ASN.1 type
    123      */
    124     public abstract boolean checkTag(int identifier);
    125 
    126     /**
    127      * Creates decoded object.
    128      *
    129      * Derived classes should override this method to provide creation for a
    130      * selected class of objects during decoding.
    131      *
    132      * The default implementation returns an object created by decoding stream.
    133      */
    134     protected Object getDecodedObject(BerInputStream in) throws IOException {
    135         return in.content;
    136     }
    137 
    138     /**
    139      * Encodes ASN.1 type.
    140      */
    141     public abstract void encodeASN(BerOutputStream out);
    142 
    143     public abstract void encodeContent(BerOutputStream out);
    144 
    145     public abstract void setEncodingContent(BerOutputStream out);
    146 
    147     public int getEncodedLength(BerOutputStream out) { //FIXME name
    148         //tag length
    149         int len = 1; //FIXME tag length = 1. what about long form?
    150         //for (; tag > 0; tag = tag >> 8, len++);
    151 
    152         // length length :-)
    153         len++;
    154         if (out.length > 127) {
    155 
    156             len++;
    157             for (int cur = out.length >> 8; cur > 0; len++) {
    158                 cur = cur >> 8;
    159             }
    160         }
    161         len += out.length;
    162 
    163         return len;
    164     }
    165 
    166     @Override public String toString() {
    167         // TODO decide whether this method is necessary
    168         return getClass().getName() + "(tag: 0x" + Integer.toHexString(0xff & this.id) + ")";
    169     }
    170 }
    171