001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /**
019: * @author Vladimir N. Molotkov, Stepan M. Mishura
020: * @version $Revision$
021: */package org.apache.harmony.security.asn1;
022:
023: import java.io.IOException;
024: import java.io.InputStream;
025:
026: import org.apache.harmony.security.internal.nls.Messages;
027:
028: /**
029: * This abstract class is the super class for all ASN.1 types
030: *
031: * @see http://asn1.elibel.tm.fr/en/standards/index.htm
032: */
033:
034: public abstract class ASN1Type implements ASN1Constants {
035:
036: /**
037: * Integer representation of primitive identifier.
038: */
039: public final int id;
040:
041: /**
042: * Integer representation of constructed identifier.
043: */
044: public final int constrId;
045:
046: /**
047: * Constructs a primitive, universal ASN.1 type.
048: *
049: * @param tagNumber - ASN.1 tag number
050: * @throws IllegalArgumentException - if tagNumber is invalid
051: */
052: public ASN1Type(int tagNumber) {
053: this (CLASS_UNIVERSAL, tagNumber);
054: }
055:
056: /**
057: * Constructs an ASN.1 type.
058: *
059: * @param tagClass - tag class. MUST be
060: * CLASS_UNIVERSAL, CLASS_APPLICATION, CLASS_CONTEXTSPECIFIC, CLASS_PRIVATE
061: * @param isConstructed - is ASN.1 type is a constructed type.
062: * @param tagNumber - ASN.1 tag number.
063: * @throws IllegalArgumentException - if tagClass or tagNumber is invalid
064: */
065: public ASN1Type(int tagClass, int tagNumber) {
066:
067: if (tagNumber < 0) {
068: throw new IllegalArgumentException(Messages
069: .getString("security.102")); //$NON-NLS-1$
070: }
071:
072: if (tagClass != CLASS_UNIVERSAL
073: && tagClass != CLASS_APPLICATION
074: && tagClass != CLASS_CONTEXTSPECIFIC
075: && tagClass != CLASS_PRIVATE) {
076: throw new IllegalArgumentException(Messages
077: .getString("security.103")); //$NON-NLS-1$
078: }
079:
080: if (tagNumber < 31) {
081: // short form
082: this .id = tagClass + tagNumber;
083: } else {
084: // long form
085: throw new IllegalArgumentException(Messages
086: .getString("security.104")); //$NON-NLS-1$
087: }
088: this .constrId = this .id + PC_CONSTRUCTED;
089: }
090:
091: //
092: //
093: // Stubs for DER
094: //
095: //
096:
097: public final Object decode(byte[] encoded) throws IOException {
098: return decode(new DerInputStream(encoded));
099: }
100:
101: public final Object decode(byte[] encoded, int offset,
102: int encodingLen) throws IOException {
103: return decode(new DerInputStream(encoded, offset, encodingLen));
104: }
105:
106: public final Object decode(InputStream in) throws IOException {
107: return decode(new DerInputStream(in));
108: }
109:
110: public final void verify(byte[] encoded) throws IOException {
111: DerInputStream decoder = new DerInputStream(encoded);
112: decoder.setVerify();
113: decode(decoder);
114: }
115:
116: public final void verify(InputStream in) throws IOException {
117: DerInputStream decoder = new DerInputStream(in);
118: decoder.setVerify();
119: decode(decoder);
120: }
121:
122: public final byte[] encode(Object object) {
123:
124: DerOutputStream out = new DerOutputStream(this , object);
125: return out.encoded;
126: }
127:
128: //
129: //
130: // Decode
131: //
132: //
133:
134: /**
135: * Decodes ASN.1 type.
136: *
137: * @param in -
138: * BER input stream
139: * @throws IOException -
140: * if an I/O error occurs or the end of the stream is reached
141: */
142: public abstract Object decode(BerInputStream in) throws IOException;
143:
144: /**
145: * Tests provided identifier.
146: *
147: * @param identifier -
148: * identifier to be verified
149: * @return - true if identifier is associated with this ASN.1 type,
150: * otherwise false
151: */
152: public abstract boolean checkTag(int identifier);
153:
154: /**
155: * Creates decoded object.
156: *
157: * Derived classes should override this method to provide creation for a
158: * selected class of objects during decoding.
159: *
160: * The default implementation returns an object created by decoding stream.
161: *
162: * @param -
163: * input stream
164: * @return - created object
165: */
166: //FIXME make me public
167: protected Object getDecodedObject(BerInputStream in)
168: throws IOException {
169: return in.content;
170: }
171:
172: //
173: //
174: // Encode
175: //
176: //
177:
178: /**
179: * Encodes ASN.1 type.
180: *
181: * @param out - BER output stream
182: */
183: public abstract void encodeASN(BerOutputStream out);
184:
185: public abstract void encodeContent(BerOutputStream out);
186:
187: public abstract void setEncodingContent(BerOutputStream out);
188:
189: public int getEncodedLength(BerOutputStream out) { //FIXME name
190:
191: //tag length
192: int len = 1; //FIXME tag length = 1. what about long form?
193: //for (; tag > 0; tag = tag >> 8, len++);
194:
195: // length length :-)
196: len++;
197: if (out.length > 127) {
198:
199: len++;
200: for (int cur = out.length >> 8; cur > 0; len++) {
201: cur = cur >> 8;
202: }
203: }
204: len += out.length;
205:
206: return len;
207: }
208:
209: public String toString() {
210: // TODO decide whether this method is necessary
211: //FIXME fix performance
212: return this .getClass().getName() + "(tag: 0x" //$NON-NLS-1$
213: + Integer.toHexString(0xff & this .id) + ")"; //$NON-NLS-1$
214: }
215: }
|