/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @author Vladimir N. Molotkov, Stepan M. Mishura * @version $Revision$ */ package org.apache.harmony.security.asn1; import java.io.IOException; import java.io.InputStream; /** * This abstract class is the super class for all ASN.1 types * * @see <a href="http://asn1.elibel.tm.fr/en/standards/index.htm">ASN.1</a> */ public abstract class ASN1Type implements ASN1Constants { /** Integer representation of primitive identifier. */ public final int id; /** Integer representation of constructed identifier. */ public final int constrId; /** * Constructs a primitive, universal ASN.1 type. * * @param tagNumber - ASN.1 tag number * @throws IllegalArgumentException - if tagNumber is invalid */ public ASN1Type(int tagNumber) { this(CLASS_UNIVERSAL, tagNumber); } /** * Constructs an ASN.1 type. * * @param tagClass - tag class. MUST be * CLASS_UNIVERSAL, CLASS_APPLICATION, CLASS_CONTEXTSPECIFIC, CLASS_PRIVATE * @param tagNumber - ASN.1 tag number. * @throws IllegalArgumentException - if tagClass or tagNumber is invalid */ public ASN1Type(int tagClass, int tagNumber) { if (tagNumber < 0) { throw new IllegalArgumentException("tagNumber < 0"); } if (tagClass != CLASS_UNIVERSAL && tagClass != CLASS_APPLICATION && tagClass != CLASS_CONTEXTSPECIFIC && tagClass != CLASS_PRIVATE) { throw new IllegalArgumentException("invalid tagClass"); } if (tagNumber < 31) { // short form this.id = tagClass + tagNumber; } else { // long form throw new IllegalArgumentException("tag long form not implemented"); } this.constrId = this.id + PC_CONSTRUCTED; } public final Object decode(byte[] encoded) throws IOException { return decode(new DerInputStream(encoded)); } public final Object decode(byte[] encoded, int offset, int encodingLen) throws IOException { return decode(new DerInputStream(encoded, offset, encodingLen)); } public final Object decode(InputStream in) throws IOException { return decode(new DerInputStream(in)); } public final void verify(byte[] encoded) throws IOException { DerInputStream decoder = new DerInputStream(encoded); decoder.setVerify(); decode(decoder); } public final void verify(InputStream in) throws IOException { DerInputStream decoder = new DerInputStream(in); decoder.setVerify(); decode(decoder); } public final byte[] encode(Object object) { DerOutputStream out = new DerOutputStream(this, object); return out.encoded; } /** * Decodes ASN.1 type. * * @throws IOException if an I/O error occurs or the end of the stream is reached */ public abstract Object decode(BerInputStream in) throws IOException; /** * Tests provided identifier. * * @param identifier identifier to be verified * @return true if identifier is associated with this ASN.1 type */ public abstract boolean checkTag(int identifier); /** * Creates decoded object. * * Derived classes should override this method to provide creation for a * selected class of objects during decoding. * * The default implementation returns an object created by decoding stream. */ protected Object getDecodedObject(BerInputStream in) throws IOException { return in.content; } /** * Encodes ASN.1 type. */ public abstract void encodeASN(BerOutputStream out); public abstract void encodeContent(BerOutputStream out); public abstract void setEncodingContent(BerOutputStream out); public int getEncodedLength(BerOutputStream out) { //FIXME name //tag length int len = 1; //FIXME tag length = 1. what about long form? //for (; tag > 0; tag = tag >> 8, len++); // length length :-) len++; if (out.length > 127) { len++; for (int cur = out.length >> 8; cur > 0; len++) { cur = cur >> 8; } } len += out.length; return len; } @Override public String toString() { // TODO decide whether this method is necessary return getClass().getName() + "(tag: 0x" + Integer.toHexString(0xff & this.id) + ")"; } }