port.org.bouncycastle.asn1.ASN1StreamParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dss-model Show documentation
Show all versions of dss-model Show documentation
DSS Model contains the data model representation for DSS
package port.org.bouncycastle.asn1;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* A parser for ASN.1 streams which also returns, where possible, parsers for the objects it encounters.
*/
public class ASN1StreamParser {
private final InputStream _in;
private final int _limit;
private final byte[][] tmpBuffers;
public ASN1StreamParser(InputStream in) {
this(in, StreamUtil.findLimit(in));
}
public ASN1StreamParser(InputStream in, int limit) {
this._in = in;
this._limit = limit;
this.tmpBuffers = new byte[11][];
}
public ASN1StreamParser(byte[] encoding) {
this(new ByteArrayInputStream(encoding), encoding.length);
}
ASN1Encodable readIndef(int tagValue) throws IOException {
// Note: INDEF => CONSTRUCTED
// TODO There are other tags that may be constructed (e.g. BIT_STRING)
switch (tagValue) {
case BERTags.EXTERNAL:
return new DERExternalParser(this);
case BERTags.OCTET_STRING:
return new BEROctetStringParser(this);
case BERTags.SEQUENCE:
return new BERSequenceParser(this);
case BERTags.SET:
return new BERSetParser(this);
default:
throw new ASN1Exception("unknown BER object encountered: 0x" + Integer.toHexString(tagValue));
}
}
ASN1Encodable readImplicit(boolean constructed, int tag) throws IOException {
if (_in instanceof IndefiniteLengthInputStream) {
if (!constructed) {
throw new IOException("indefinite length primitive encoding encountered");
}
return readIndef(tag);
}
if (constructed) {
switch (tag) {
case BERTags.SET:
return new DERSetParser(this);
case BERTags.SEQUENCE:
return new DERSequenceParser(this);
case BERTags.OCTET_STRING:
return new BEROctetStringParser(this);
}
} else {
switch (tag) {
case BERTags.SET:
throw new ASN1Exception("sequences must use constructed encoding (see X.690 8.9.1/8.10.1)");
case BERTags.SEQUENCE:
throw new ASN1Exception("sets must use constructed encoding (see X.690 8.11.1/8.12.1)");
case BERTags.OCTET_STRING:
return new DEROctetStringParser((DefiniteLengthInputStream) _in);
}
}
// TODO ASN1Exception
throw new RuntimeException("implicit tagging not implemented");
}
ASN1Primitive readTaggedObject(boolean constructed, int tag) throws IOException {
if (!constructed) {
// Note: !CONSTRUCTED => IMPLICIT
DefiniteLengthInputStream defIn = (DefiniteLengthInputStream) _in;
return new DERTaggedObject(false, tag, new DEROctetString(defIn.toByteArray()));
}
ASN1EncodableVector v = readVector();
if (_in instanceof IndefiniteLengthInputStream) {
return v.size() == 1 ? new BERTaggedObject(true, tag, v.get(0)) : new BERTaggedObject(false, tag, BERFactory.createSequence(v));
}
return v.size() == 1 ? new DERTaggedObject(true, tag, v.get(0)) : new DERTaggedObject(false, tag, DERFactory.createSequence(v));
}
public ASN1Encodable readObject() throws IOException {
int tag = _in.read();
if (tag == -1) {
return null;
}
//
// turn of looking for "00" while we resolve the tag
//
set00Check(false);
//
// calculate tag number
//
int tagNo = ASN1InputStream.readTagNumber(_in, tag);
boolean isConstructed = (tag & BERTags.CONSTRUCTED) != 0;
//
// calculate length
//
int length = ASN1InputStream.readLength(_in, _limit);
if (length < 0) // indefinite length method
{
if (!isConstructed) {
throw new IOException("indefinite length primitive encoding encountered");
}
IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(_in, _limit);
ASN1StreamParser sp = new ASN1StreamParser(indIn, _limit);
if ((tag & BERTags.APPLICATION) != 0) {
return new BERApplicationSpecificParser(tagNo, sp);
}
if ((tag & BERTags.TAGGED) != 0) {
return new BERTaggedObjectParser(true, tagNo, sp);
}
return sp.readIndef(tagNo);
} else {
DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(_in, length);
if ((tag & BERTags.APPLICATION) != 0) {
return new DERApplicationSpecific(isConstructed, tagNo, defIn.toByteArray());
}
if ((tag & BERTags.TAGGED) != 0) {
return new BERTaggedObjectParser(isConstructed, tagNo, new ASN1StreamParser(defIn));
}
if (isConstructed) {
// TODO There are other tags that may be constructed (e.g. BIT_STRING)
switch (tagNo) {
case BERTags.OCTET_STRING:
//
// yes, people actually do this...
//
return new BEROctetStringParser(new ASN1StreamParser(defIn));
case BERTags.SEQUENCE:
return new DERSequenceParser(new ASN1StreamParser(defIn));
case BERTags.SET:
return new DERSetParser(new ASN1StreamParser(defIn));
case BERTags.EXTERNAL:
return new DERExternalParser(new ASN1StreamParser(defIn));
default:
throw new IOException("unknown tag " + tagNo + " encountered");
}
}
// Some primitive encodings can be handled by parsers too...
switch (tagNo) {
case BERTags.OCTET_STRING:
return new DEROctetStringParser(defIn);
}
try {
return ASN1InputStream.createPrimitiveDERObject(tagNo, defIn, tmpBuffers);
} catch (IllegalArgumentException e) {
throw new ASN1Exception("corrupted stream detected", e);
}
}
}
private void set00Check(boolean enabled) {
if (_in instanceof IndefiniteLengthInputStream) {
((IndefiniteLengthInputStream) _in).setEofOn00(enabled);
}
}
ASN1EncodableVector readVector() throws IOException {
ASN1EncodableVector v = new ASN1EncodableVector();
ASN1Encodable obj;
while ((obj = readObject()) != null) {
if (obj instanceof InMemoryRepresentable) {
v.add(((InMemoryRepresentable) obj).getLoadedObject());
} else {
v.add(obj.toASN1Primitive());
}
}
return v;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy