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 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: * Decodes ASN.1 types encoded with DER (X.690)
030: *
031: * @see http://asn1.elibel.tm.fr/en/standards/index.htm
032: */
033:
034: public final class DerInputStream extends BerInputStream {
035:
036: public DerInputStream(byte[] encoded) throws IOException {
037: super (encoded, 0, encoded.length);
038: }
039:
040: public DerInputStream(byte[] encoded, int offset, int encodingLen)
041: throws IOException {
042: super (encoded, offset, encodingLen);
043: }
044:
045: public DerInputStream(InputStream in) throws IOException {
046: super (in);
047: }
048:
049: /**
050: * @see org.apache.harmony.security.asn1.BerInputStream#next()
051: */
052: public final int next() throws IOException {
053:
054: int tag = super .next();
055:
056: if (length == INDEFINIT_LENGTH) {
057: throw new ASN1Exception(Messages.getString("security.105")); //$NON-NLS-1$
058: }
059:
060: // FIXME add check: length encoding uses minimum number of octets
061:
062: return tag;
063: }
064:
065: // mask for verifying unused bits for ASN.1 bitstring
066: private static final byte[] UNUSED_BITS_MASK = new byte[] { 0x01,
067: 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F };
068:
069: /**
070: * @see org.apache.harmony.security.asn1.BerInputStream#readBitString()
071: */
072: public void readBitString() throws IOException {
073:
074: if (tag == ASN1Constants.TAG_C_BITSTRING) {
075: throw new ASN1Exception(Messages.getString(
076: "security.106", tagOffset)); //$NON-NLS-1$
077: }
078:
079: super .readBitString();
080:
081: //check: unused bits values - MUST be 0
082: if (length > 1
083: && buffer[contentOffset] != 0
084: && (buffer[offset - 1] & UNUSED_BITS_MASK[buffer[contentOffset] - 1]) != 0) {
085: throw new ASN1Exception(Messages.getString(
086: "security.107", contentOffset)); //$NON-NLS-1$
087: }
088: }
089:
090: /**
091: * @see org.apache.harmony.security.asn1.BerInputStream#readBoolean()
092: */
093: public void readBoolean() throws IOException {
094:
095: super .readBoolean();
096:
097: // check encoded content
098: if (buffer[contentOffset] != 0
099: && buffer[contentOffset] != (byte) 0xFF) {
100: throw new ASN1Exception(Messages.getString(
101: "security.108", contentOffset)); //$NON-NLS-1$
102: }
103: }
104:
105: /**
106: * @see org.apache.harmony.security.asn1.BerInputStream#readOctetString()
107: */
108: public void readOctetString() throws IOException {
109:
110: if (tag == ASN1Constants.TAG_C_OCTETSTRING) {
111: throw new ASN1Exception(Messages.getString(
112: "security.109", tagOffset)); //$NON-NLS-1$
113: }
114: super .readOctetString();
115: }
116:
117: /**
118: * @see org.apache.harmony.security.asn1.BerInputStream#readSequence(org.apache.harmony.security.asn1.ASN1Sequence)
119: */
120: public void readSequence(ASN1Sequence sequence) throws IOException {
121: //
122: // According to ASN.1 DER spec. sequence MUST not include
123: // any encoding which value is equal to its default value
124: //
125: // Verification of this assertion is not implemented
126: //
127: super .readSequence(sequence);
128: }
129:
130: /**
131: * @see org.apache.harmony.security.asn1.BerInputStream#readSetOf(org.apache.harmony.security.asn1.ASN1SetOf)
132: */
133: public void readSetOf(ASN1SetOf setOf) throws IOException {
134: //
135: // According to ASN.1 DER spec. set of MUST appear in
136: // ascending order (short component are padded for comparison)
137: //
138: // Verification of this assertion is not implemented
139: //
140: super .readSetOf(setOf);
141: }
142:
143: /**
144: * @see org.apache.harmony.security.asn1.BerInputStream#readString()
145: */
146: public void readString(ASN1StringType type) throws IOException {
147:
148: if (tag == type.constrId) {
149: throw new ASN1Exception(Messages.getString(
150: "security.10A", tagOffset)); //$NON-NLS-1$
151: }
152: super .readString(type);
153: }
154:
155: /**
156: * @see org.apache.harmony.security.asn1.BerInputStream#readUTCTime()
157: */
158: public void readUTCTime() throws IOException {
159:
160: if (tag == ASN1Constants.TAG_C_UTCTIME) {
161: // It is a string type and it can be encoded as primitive or constructed.
162: throw new ASN1Exception(Messages.getString(
163: "security.10B", tagOffset)); //$NON-NLS-1$
164: }
165:
166: // check format: DER uses YYMMDDHHMMSS'Z' only
167: if (length != ASN1UTCTime.UTC_HMS) {
168: throw new ASN1Exception(Messages.getString(
169: "security.10C", tagOffset)); //$NON-NLS-1$
170: }
171:
172: super .readUTCTime();
173: }
174:
175: /**
176: * @see org.apache.harmony.security.asn1.BerInputStream#readGeneralizedTime()
177: */
178: public void readGeneralizedTime() throws IOException {
179:
180: if (tag == ASN1Constants.TAG_C_GENERALIZEDTIME) {
181: // It is a string type and it can be encoded as primitive or constructed.
182: throw new ASN1Exception(Messages.getString(
183: "security.10D", tagOffset)); //$NON-NLS-1$
184: }
185:
186: super .readGeneralizedTime();
187:
188: // FIXME makes sense only if we support all GeneralizedTime formats
189: // late check syntax: the last char MUST be Z
190: //if (buffer[offset - 1] != 'Z') {
191: // throw new ASN1Exception(
192: // "ASN.1 GeneralizedTime wrongly encoded at ["
193: // + contentOffset + ']');
194: //}
195:
196: // the fractional-seconds elements, if present MUST
197: // omit all trailing zeros
198: // FIXME implement me
199: // if () {
200: // throw new IOException(
201: // "DER ASN.1 GeneralizedTime wrongly encoded at ["
202: // + contentOffset
203: // + "]. Trailing zeros MUST be omitted");
204: // }
205: }
206: }
|