diff --git a/crypto/src/asn1/ASN1StreamParser.cs b/crypto/src/asn1/ASN1StreamParser.cs
index 55b5bc656..5c6854e1d 100644
--- a/crypto/src/asn1/ASN1StreamParser.cs
+++ b/crypto/src/asn1/ASN1StreamParser.cs
@@ -35,91 +35,102 @@ namespace Org.BouncyCastle.Asn1
this.tmpBuffers = tmpBuffers;
}
- internal IAsn1Convertible ReadIndef(int tagValue)
+ internal IAsn1Convertible ReadIndef(int tagNo)
{
// Note: INDEF => CONSTRUCTED
// TODO There are other tags that may be constructed (e.g. BIT_STRING)
- switch (tagValue)
+ switch (tagNo)
{
- case Asn1Tags.External:
- return new DerExternalParser(this);
- case Asn1Tags.OctetString:
- return new BerOctetStringParser(this);
- case Asn1Tags.Sequence:
- return new BerSequenceParser(this);
- case Asn1Tags.Set:
- return new BerSetParser(this);
- default:
- throw new Asn1Exception("unknown BER object encountered: 0x" + tagValue.ToString("X"));
+ case Asn1Tags.External:
+ return new DerExternalParser(this);
+ case Asn1Tags.OctetString:
+ return new BerOctetStringParser(this);
+ case Asn1Tags.Sequence:
+ return new BerSequenceParser(this);
+ case Asn1Tags.Set:
+ return new BerSetParser(this);
+ default:
+ throw new Asn1Exception("unknown BER object encountered: 0x" + tagNo.ToString("X"));
}
}
- internal IAsn1Convertible ReadImplicit(bool constructed, int tag)
+ internal IAsn1Convertible ReadImplicit(bool constructed, int tagNo)
{
if (_in is IndefiniteLengthInputStream)
{
if (!constructed)
throw new IOException("indefinite-length primitive encoding encountered");
- return ReadIndef(tag);
+ return ReadIndef(tagNo);
}
if (constructed)
{
- switch (tag)
+ switch (tagNo)
{
- case Asn1Tags.Set:
- return new DerSetParser(this);
- case Asn1Tags.Sequence:
- return new DerSequenceParser(this);
- case Asn1Tags.OctetString:
- return new BerOctetStringParser(this);
+ case Asn1Tags.Set:
+ return new DerSetParser(this);
+ case Asn1Tags.Sequence:
+ return new DerSequenceParser(this);
+ case Asn1Tags.OctetString:
+ return new BerOctetStringParser(this);
}
}
else
{
- switch (tag)
+ switch (tagNo)
{
- case Asn1Tags.Set:
- throw new Asn1Exception("sequences must use constructed encoding (see X.690 8.9.1/8.10.1)");
- case Asn1Tags.Sequence:
- throw new Asn1Exception("sets must use constructed encoding (see X.690 8.11.1/8.12.1)");
- case Asn1Tags.OctetString:
- return new DerOctetStringParser((DefiniteLengthInputStream)_in);
+ case Asn1Tags.Set:
+ throw new Asn1Exception("sequences must use constructed encoding (see X.690 8.9.1/8.10.1)");
+ case Asn1Tags.Sequence:
+ throw new Asn1Exception("sets must use constructed encoding (see X.690 8.11.1/8.12.1)");
+ case Asn1Tags.OctetString:
+ return new DerOctetStringParser((DefiniteLengthInputStream)_in);
}
}
throw new Asn1Exception("implicit tagging not implemented");
}
- internal Asn1Object ReadTaggedObject(bool constructed, int tag)
+ internal Asn1Object ReadTaggedObject(int tagClass, int tagNo, bool constructed)
{
- if (!constructed)
+ if (!constructed)
{
- // Note: !CONSTRUCTED => IMPLICIT
- DefiniteLengthInputStream defIn = (DefiniteLengthInputStream)_in;
- return new DLTaggedObject(false, tag, new DerOctetString(defIn.ToArray()));
+ // Note: !CONSTRUCTED => IMPLICIT
+ DefiniteLengthInputStream defIn = (DefiniteLengthInputStream)_in;
+ byte[] contentsOctets = defIn.ToArray();
+
+ if (Asn1Tags.Application == tagClass)
+ return new DerApplicationSpecific(false, tagNo, contentsOctets);
+
+ return new DLTaggedObject(false, tagNo, new DerOctetString(contentsOctets));
}
- Asn1EncodableVector v = ReadVector();
+ Asn1EncodableVector contentsElements = ReadVector();
if (_in is IndefiniteLengthInputStream)
{
- return v.Count == 1
- ? new BerTaggedObject(true, tag, v[0])
- : new BerTaggedObject(false, tag, BerSequence.FromVector(v));
+ if (Asn1Tags.Application == tagClass)
+ return new BerApplicationSpecific(tagNo, contentsElements);
+
+ return contentsElements.Count == 1
+ ? new BerTaggedObject(true, tagNo, contentsElements[0])
+ : new BerTaggedObject(false, tagNo, BerSequence.FromVector(contentsElements));
}
- return v.Count == 1
- ? new DLTaggedObject(true, tag, v[0])
- : new DLTaggedObject(false, tag, DLSequence.FromVector(v));
+ if (Asn1Tags.Application == tagClass)
+ return new DerApplicationSpecific(tagNo, contentsElements);
+
+ return contentsElements.Count == 1
+ ? new DLTaggedObject(true, tagNo, contentsElements[0])
+ : new DLTaggedObject(false, tagNo, DLSequence.FromVector(contentsElements));
}
public virtual IAsn1Convertible ReadObject()
{
- int tag = _in.ReadByte();
- if (tag == -1)
+ int tagHdr = _in.ReadByte();
+ if (tagHdr == -1)
return null;
// turn off looking for "00" while we resolve the tag
@@ -128,15 +139,16 @@ namespace Org.BouncyCastle.Asn1
//
// calculate tag number
//
- int tagNo = Asn1InputStream.ReadTagNumber(_in, tag);
+ int tagNo = Asn1InputStream.ReadTagNumber(_in, tagHdr);
- bool isConstructed = (tag & Asn1Tags.Constructed) != 0;
+ bool isConstructed = (tagHdr & Asn1Tags.Constructed) != 0;
//
// calculate length
//
int length = Asn1InputStream.ReadLength(_in, _limit,
- tagNo == Asn1Tags.OctetString || tagNo == Asn1Tags.Sequence || tagNo == Asn1Tags.Set || tagNo == Asn1Tags.External);
+ tagNo == Asn1Tags.OctetString || tagNo == Asn1Tags.Sequence || tagNo == Asn1Tags.Set ||
+ tagNo == Asn1Tags.External);
if (length < 0) // indefinite-length method
{
@@ -146,13 +158,13 @@ namespace Org.BouncyCastle.Asn1
IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(_in, _limit);
Asn1StreamParser sp = new Asn1StreamParser(indIn, _limit, tmpBuffers);
- int tagClass = tag & Asn1Tags.Private;
+ int tagClass = tagHdr & Asn1Tags.Private;
if (0 != tagClass)
{
- if ((tag & Asn1Tags.Application) != 0)
+ if (Asn1Tags.Application == tagClass)
return new BerApplicationSpecificParser(tagNo, sp);
- return new BerTaggedObjectParser(true, tagNo, sp);
+ return new BerTaggedObjectParser(tagClass, tagNo, true, sp);
}
return sp.ReadIndef(tagNo);
@@ -161,14 +173,15 @@ namespace Org.BouncyCastle.Asn1
{
DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(_in, length, _limit);
- int tagClass = tag & Asn1Tags.Private;
+ int tagClass = tagHdr & Asn1Tags.Private;
if (0 != tagClass)
{
- if ((tag & Asn1Tags.Application) != 0)
- return new DerApplicationSpecific(isConstructed, tagNo, defIn.ToArray());
+ Asn1StreamParser sub = new Asn1StreamParser(defIn, defIn.Remaining, tmpBuffers);
+
+ if (Asn1Tags.Application == tagClass)
+ return (DerApplicationSpecific)sub.ReadTaggedObject(tagClass, tagNo, isConstructed);
- return new BerTaggedObjectParser(isConstructed, tagNo,
- new Asn1StreamParser(defIn, defIn.Remaining, tmpBuffers));
+ return new BerTaggedObjectParser(tagClass, tagNo, isConstructed, sub);
}
if (!isConstructed)
@@ -176,8 +189,8 @@ namespace Org.BouncyCastle.Asn1
// Some primitive encodings can be handled by parsers too...
switch (tagNo)
{
- case Asn1Tags.OctetString:
- return new DerOctetStringParser(defIn);
+ case Asn1Tags.OctetString:
+ return new DerOctetStringParser(defIn);
}
try
@@ -195,19 +208,16 @@ namespace Org.BouncyCastle.Asn1
// TODO There are other tags that may be constructed (e.g. BitString)
switch (tagNo)
{
- case Asn1Tags.OctetString:
- //
- // yes, people actually do this...
- //
- return new BerOctetStringParser(sp);
- case Asn1Tags.Sequence:
- return new DerSequenceParser(sp);
- case Asn1Tags.Set:
- return new DerSetParser(sp);
- case Asn1Tags.External:
- return new DerExternalParser(sp);
- default:
- throw new IOException("unknown tag " + tagNo + " encountered");
+ case Asn1Tags.OctetString:
+ return new BerOctetStringParser(sp);
+ case Asn1Tags.Sequence:
+ return new DerSequenceParser(sp);
+ case Asn1Tags.Set:
+ return new DerSetParser(sp);
+ case Asn1Tags.External:
+ return new DerExternalParser(sp);
+ default:
+ throw new IOException("unknown tag " + tagNo + " encountered");
}
}
}
diff --git a/crypto/src/asn1/ASN1TaggedObjectParser.cs b/crypto/src/asn1/ASN1TaggedObjectParser.cs
index 32327a269..dd031ad07 100644
--- a/crypto/src/asn1/ASN1TaggedObjectParser.cs
+++ b/crypto/src/asn1/ASN1TaggedObjectParser.cs
@@ -3,6 +3,8 @@ namespace Org.BouncyCastle.Asn1
public interface Asn1TaggedObjectParser
: IAsn1Convertible
{
+ int TagClass { get; }
+
int TagNo { get; }
IAsn1Convertible GetObjectParser(int tag, bool isExplicit);
diff --git a/crypto/src/asn1/Asn1InputStream.cs b/crypto/src/asn1/Asn1InputStream.cs
index 27c583338..6e097e86d 100644
--- a/crypto/src/asn1/Asn1InputStream.cs
+++ b/crypto/src/asn1/Asn1InputStream.cs
@@ -1,5 +1,4 @@
using System;
-using System.Diagnostics;
using System.IO;
using Org.BouncyCastle.Utilities;
@@ -74,23 +73,15 @@ namespace Org.BouncyCastle.Asn1
/**
* build an object given its tag and the number of bytes to construct it from.
*/
- private Asn1Object BuildObject(
- int tag,
- int tagNo,
- int length)
+ private Asn1Object BuildObject(int tagHdr, int tagNo, int length)
{
- bool isConstructed = (tag & Asn1Tags.Constructed) != 0;
+ bool isConstructed = (tagHdr & Asn1Tags.Constructed) != 0;
DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(this, length, limit);
- int tagClass = tag & Asn1Tags.Private;
+ int tagClass = tagHdr & Asn1Tags.Private;
if (0 != tagClass)
- {
- if ((tag & Asn1Tags.Application) != 0)
- return new DerApplicationSpecific(isConstructed, tagNo, defIn.ToArray());
-
- return new Asn1StreamParser(defIn, defIn.Remaining, tmpBuffers).ReadTaggedObject(isConstructed, tagNo);
- }
+ return ReadTaggedObject(tagClass, tagNo, isConstructed, defIn);
if (!isConstructed)
return CreatePrimitiveDerObject(tagNo, defIn, tmpBuffers);
@@ -98,16 +89,9 @@ namespace Org.BouncyCastle.Asn1
switch (tagNo)
{
case Asn1Tags.BitString:
- {
return BuildConstructedBitString(ReadVector(defIn));
- }
case Asn1Tags.OctetString:
- {
- //
- // yes, people actually do this...
- //
return BuildConstructedOctetString(ReadVector(defIn));
- }
case Asn1Tags.Sequence:
return CreateDLSequence(defIn);
case Asn1Tags.Set:
@@ -119,6 +103,29 @@ namespace Org.BouncyCastle.Asn1
}
}
+ internal Asn1Object ReadTaggedObject(int tagClass, int tagNo, bool constructed, DefiniteLengthInputStream defIn)
+ {
+ if (!constructed)
+ {
+ // Note: !CONSTRUCTED => IMPLICIT
+ byte[] contentsOctets = defIn.ToArray();
+
+ if (Asn1Tags.Application == tagClass)
+ return new DerApplicationSpecific(false, tagNo, contentsOctets);
+
+ return new DLTaggedObject(false, tagNo, new DerOctetString(contentsOctets));
+ }
+
+ Asn1EncodableVector contentsElements = ReadVector(defIn);
+
+ if (Asn1Tags.Application == tagClass)
+ return new DerApplicationSpecific(tagNo, contentsElements);
+
+ return contentsElements.Count == 1
+ ? new DLTaggedObject(true, tagNo, contentsElements[0])
+ : new DLTaggedObject(false, tagNo, DLSequence.FromVector(contentsElements));
+ }
+
internal virtual Asn1EncodableVector ReadVector()
{
Asn1Object o = ReadObject();
@@ -155,16 +162,16 @@ namespace Org.BouncyCastle.Asn1
public Asn1Object ReadObject()
{
- int tag = ReadByte();
- if (tag <= 0)
+ int tagHdr = ReadByte();
+ if (tagHdr <= 0)
{
- if (tag == 0)
+ if (tagHdr == 0)
throw new IOException("unexpected end-of-contents marker");
return null;
}
- int tagNo = ReadTagNumber(this, tag);
+ int tagNo = ReadTagNumber(this, tagHdr);
int length = ReadLength(this, limit, false);
if (length >= 0)
@@ -172,7 +179,7 @@ namespace Org.BouncyCastle.Asn1
// definite-length
try
{
- return BuildObject(tag, tagNo, length);
+ return BuildObject(tagHdr, tagNo, length);
}
catch (ArgumentException e)
{
@@ -182,20 +189,15 @@ namespace Org.BouncyCastle.Asn1
// indefinite-length
- if (0 == (tag & Asn1Tags.Constructed))
+ if (0 == (tagHdr & Asn1Tags.Constructed))
throw new IOException("indefinite-length primitive encoding encountered");
IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(this, limit);
Asn1StreamParser sp = new Asn1StreamParser(indIn, limit, tmpBuffers);
- int tagClass = tag & Asn1Tags.Private;
+ int tagClass = tagHdr & Asn1Tags.Private;
if (0 != tagClass)
- {
- if ((tag & Asn1Tags.Application) != 0)
- return new BerApplicationSpecificParser(tagNo, sp).ToAsn1Object();
-
- return new BerTaggedObjectParser(true, tagNo, sp).ToAsn1Object();
- }
+ return sp.ReadTaggedObject(tagClass, tagNo, true);
// TODO There are other tags that may be constructed (e.g. BitString)
switch (tagNo)
@@ -254,9 +256,9 @@ namespace Org.BouncyCastle.Asn1
get { return limit; }
}
- internal static int ReadTagNumber(Stream s, int tag)
+ internal static int ReadTagNumber(Stream s, int tagHdr)
{
- int tagNo = tag & 0x1f;
+ int tagNo = tagHdr & 0x1f;
//
// with tagged object tag number is bottom 5 bits, or stored at the start of the content
@@ -403,71 +405,69 @@ namespace Org.BouncyCastle.Asn1
return str;
}
- internal static Asn1Object CreatePrimitiveDerObject(
- int tagNo,
- DefiniteLengthInputStream defIn,
- byte[][] tmpBuffers)
+ internal static Asn1Object CreatePrimitiveDerObject(int tagNo, DefiniteLengthInputStream defIn,
+ byte[][] tmpBuffers)
{
switch (tagNo)
{
- case Asn1Tags.BmpString:
- return new DerBmpString(GetBmpCharBuffer(defIn));
- case Asn1Tags.Boolean:
- return DerBoolean.FromOctetString(GetBuffer(defIn, tmpBuffers));
- case Asn1Tags.Enumerated:
- return DerEnumerated.FromOctetString(GetBuffer(defIn, tmpBuffers));
- case Asn1Tags.ObjectIdentifier:
- // TODO Ideally only clone if we used a buffer
- return DerObjectIdentifier.CreatePrimitive(GetBuffer(defIn, tmpBuffers), true);
+ case Asn1Tags.BmpString:
+ return new DerBmpString(GetBmpCharBuffer(defIn));
+ case Asn1Tags.Boolean:
+ return DerBoolean.FromOctetString(GetBuffer(defIn, tmpBuffers));
+ case Asn1Tags.Enumerated:
+ return DerEnumerated.FromOctetString(GetBuffer(defIn, tmpBuffers));
+ case Asn1Tags.ObjectIdentifier:
+ // TODO Ideally only clone if we used a buffer
+ return DerObjectIdentifier.CreatePrimitive(GetBuffer(defIn, tmpBuffers), true);
}
byte[] bytes = defIn.ToArray();
switch (tagNo)
{
- case Asn1Tags.BitString:
- return DerBitString.CreatePrimitive(bytes);
- case Asn1Tags.GeneralizedTime:
- return new DerGeneralizedTime(bytes);
- case Asn1Tags.GeneralString:
- return new DerGeneralString(bytes);
- case Asn1Tags.GraphicString:
- return DerGraphicString.CreatePrimitive(bytes);
- case Asn1Tags.IA5String:
- return new DerIA5String(bytes);
- case Asn1Tags.Integer:
- return new DerInteger(bytes, false);
- case Asn1Tags.Null:
- {
- if (0 != bytes.Length)
- throw new InvalidOperationException("malformed NULL encoding encountered");
+ case Asn1Tags.BitString:
+ return DerBitString.CreatePrimitive(bytes);
+ case Asn1Tags.GeneralizedTime:
+ return new DerGeneralizedTime(bytes);
+ case Asn1Tags.GeneralString:
+ return new DerGeneralString(bytes);
+ case Asn1Tags.GraphicString:
+ return DerGraphicString.CreatePrimitive(bytes);
+ case Asn1Tags.IA5String:
+ return new DerIA5String(bytes);
+ case Asn1Tags.Integer:
+ return new DerInteger(bytes, false);
+ case Asn1Tags.Null:
+ {
+ if (0 != bytes.Length)
+ throw new InvalidOperationException("malformed NULL encoding encountered");
- return DerNull.Instance;
- }
- case Asn1Tags.NumericString:
- return new DerNumericString(bytes);
- case Asn1Tags.ObjectDescriptor:
- return Asn1ObjectDescriptor.CreatePrimitive(bytes);
- case Asn1Tags.OctetString:
- return new DerOctetString(bytes);
- case Asn1Tags.PrintableString:
- return new DerPrintableString(bytes);
- case Asn1Tags.RelativeOid:
- return Asn1RelativeOid.CreatePrimitive(bytes, false);
- case Asn1Tags.T61String:
- return new DerT61String(bytes);
- case Asn1Tags.UniversalString:
- return new DerUniversalString(bytes);
- case Asn1Tags.UtcTime:
- return new DerUtcTime(bytes);
- case Asn1Tags.Utf8String:
- return new DerUtf8String(bytes);
- case Asn1Tags.VideotexString:
- return new DerVideotexString(bytes);
- case Asn1Tags.VisibleString:
- return new DerVisibleString(bytes);
- default:
- throw new IOException("unknown tag " + tagNo + " encountered");
+ return DerNull.Instance;
+ }
+ case Asn1Tags.NumericString:
+ return new DerNumericString(bytes);
+ case Asn1Tags.ObjectDescriptor:
+ return Asn1ObjectDescriptor.CreatePrimitive(bytes);
+ case Asn1Tags.OctetString:
+ return new DerOctetString(bytes);
+ case Asn1Tags.PrintableString:
+ return new DerPrintableString(bytes);
+ case Asn1Tags.RelativeOid:
+ return Asn1RelativeOid.CreatePrimitive(bytes, false);
+ case Asn1Tags.T61String:
+ return new DerT61String(bytes);
+ case Asn1Tags.UniversalString:
+ return new DerUniversalString(bytes);
+ case Asn1Tags.UtcTime:
+ return new DerUtcTime(bytes);
+ case Asn1Tags.Utf8String:
+ return new DerUtf8String(bytes);
+ case Asn1Tags.VideotexString:
+ return new DerVideotexString(bytes);
+ case Asn1Tags.VisibleString:
+ return new DerVisibleString(bytes);
+ default:
+ throw new IOException("unknown tag " + tagNo + " encountered");
}
}
}
diff --git a/crypto/src/asn1/BERTaggedObjectParser.cs b/crypto/src/asn1/BERTaggedObjectParser.cs
index 354437a6a..55ad36d46 100644
--- a/crypto/src/asn1/BERTaggedObjectParser.cs
+++ b/crypto/src/asn1/BERTaggedObjectParser.cs
@@ -1,66 +1,58 @@
using System;
using System.IO;
-using Org.BouncyCastle.Utilities;
-
namespace Org.BouncyCastle.Asn1
{
public class BerTaggedObjectParser
: Asn1TaggedObjectParser
{
- private bool _constructed;
- private int _tagNumber;
- private Asn1StreamParser _parser;
-
- [Obsolete]
- internal BerTaggedObjectParser(
- int baseTag,
- int tagNumber,
- Stream contentStream)
- : this((baseTag & Asn1Tags.Constructed) != 0, tagNumber, new Asn1StreamParser(contentStream))
- {
- }
+ private readonly int m_tagClass;
+ private readonly int m_tagNo;
+ private readonly bool m_constructed;
+ private readonly Asn1StreamParser m_parser;
- internal BerTaggedObjectParser(
- bool constructed,
- int tagNumber,
- Asn1StreamParser parser)
+ internal BerTaggedObjectParser(int tagClass, int tagNo, bool constructed, Asn1StreamParser parser)
{
- _constructed = constructed;
- _tagNumber = tagNumber;
- _parser = parser;
+ this.m_tagClass = tagClass;
+ this.m_tagNo = tagNo;
+ this.m_constructed = constructed;
+ this.m_parser = parser;
}
public bool IsConstructed
{
- get { return _constructed; }
+ get { return m_constructed; }
}
+ public int TagClass
+ {
+ get { return m_tagClass; }
+ }
+
public int TagNo
{
- get { return _tagNumber; }
+ get { return m_tagNo; }
}
- public IAsn1Convertible GetObjectParser(
- int tag,
- bool isExplicit)
+ public IAsn1Convertible GetObjectParser(int baseTagNo, bool declaredExplicit)
{
- if (isExplicit)
- {
- if (!_constructed)
- throw new IOException("Explicit tags must be constructed (see X.690 8.14.2)");
+ if (Asn1Tags.ContextSpecific != TagClass)
+ throw new Asn1Exception("this method only valid for CONTEXT_SPECIFIC tags");
- return _parser.ReadObject();
- }
+ if (!declaredExplicit)
+ return m_parser.ReadImplicit(m_constructed, baseTagNo);
+
+ if (!m_constructed)
+ throw new IOException("Explicit tags must be constructed (see X.690 8.14.2)");
- return _parser.ReadImplicit(_constructed, tag);
+ return m_parser.ReadObject();
}
public Asn1Object ToAsn1Object()
{
try
{
- return _parser.ReadTaggedObject(_constructed, _tagNumber);
+ return m_parser.ReadTaggedObject(TagClass, TagNo, IsConstructed);
}
catch (IOException e)
{
|