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