培训考核三期,新版培训,网页版培训登录器
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

243 lines
6.9 KiB

#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
#pragma warning disable
using System;
using System.IO;
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1
{
public class Asn1StreamParser
{
private readonly Stream _in;
private readonly int _limit;
private readonly byte[][] tmpBuffers;
public Asn1StreamParser(Stream input)
: this(input, Asn1InputStream.FindLimit(input))
{
}
public Asn1StreamParser(byte[] encoding)
: this(new MemoryStream(encoding, false), encoding.Length)
{
}
public Asn1StreamParser(Stream input, int limit)
: this(input, limit, new byte[16][])
{
}
internal Asn1StreamParser(Stream input, int limit, byte[][] tmpBuffers)
{
if (!input.CanRead)
throw new ArgumentException("Expected stream to be readable", "input");
this._in = input;
this._limit = limit;
this.tmpBuffers = tmpBuffers;
}
internal IAsn1Convertible ReadIndef(int tagValue)
{
// Note: INDEF => CONSTRUCTED
// TODO There are other tags that may be constructed (e.g. BIT_STRING)
switch (tagValue)
{
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"));
}
}
internal IAsn1Convertible ReadImplicit(bool constructed, int tag)
{
if (_in is IndefiniteLengthInputStream)
{
if (!constructed)
throw new IOException("indefinite-length primitive encoding encountered");
return ReadIndef(tag);
}
if (constructed)
{
switch (tag)
{
case Asn1Tags.Set:
return new DerSetParser(this);
case Asn1Tags.Sequence:
return new DerSequenceParser(this);
case Asn1Tags.OctetString:
return new BerOctetStringParser(this);
}
}
else
{
switch (tag)
{
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)
{
if (!constructed)
{
// Note: !CONSTRUCTED => IMPLICIT
DefiniteLengthInputStream defIn = (DefiniteLengthInputStream)_in;
return new DerTaggedObject(false, tag, new DerOctetString(defIn.ToArray()));
}
Asn1EncodableVector v = ReadVector();
if (_in is IndefiniteLengthInputStream)
{
return v.Count == 1
? new BerTaggedObject(true, tag, v[0])
: new BerTaggedObject(false, tag, BerSequence.FromVector(v));
}
return v.Count == 1
? new DerTaggedObject(true, tag, v[0])
: new DerTaggedObject(false, tag, DerSequence.FromVector(v));
}
public virtual IAsn1Convertible ReadObject()
{
int tag = _in.ReadByte();
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);
bool isConstructed = (tag & Asn1Tags.Constructed) != 0;
//
// calculate length
//
int length = Asn1InputStream.ReadLength(_in, _limit,
tagNo == Asn1Tags.OctetString || tagNo == Asn1Tags.Sequence || tagNo == Asn1Tags.Set || tagNo == Asn1Tags.External);
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, tmpBuffers);
int tagClass = tag & Asn1Tags.Private;
if (0 != tagClass)
{
if ((tag & Asn1Tags.Application) != 0)
return new BerApplicationSpecificParser(tagNo, sp);
return new BerTaggedObjectParser(true, tagNo, sp);
}
return sp.ReadIndef(tagNo);
}
else
{
DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(_in, length, _limit);
int tagClass = tag & Asn1Tags.Private;
if (0 != tagClass)
{
if ((tag & Asn1Tags.Application) != 0)
return new DerApplicationSpecific(isConstructed, tagNo, defIn.ToArray());
return new BerTaggedObjectParser(isConstructed, tagNo,
new Asn1StreamParser(defIn, defIn.Remaining, tmpBuffers));
}
if (!isConstructed)
{
// Some primitive encodings can be handled by parsers too...
switch (tagNo)
{
case Asn1Tags.OctetString:
return new DerOctetStringParser(defIn);
}
try
{
return Asn1InputStream.CreatePrimitiveDerObject(tagNo, defIn, tmpBuffers);
}
catch (ArgumentException e)
{
throw new Asn1Exception("corrupted stream detected", e);
}
}
Asn1StreamParser sp = new Asn1StreamParser(defIn, defIn.Remaining, tmpBuffers);
// 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");
}
}
}
private void Set00Check(
bool enabled)
{
if (_in is IndefiniteLengthInputStream)
{
((IndefiniteLengthInputStream) _in).SetEofOn00(enabled);
}
}
internal Asn1EncodableVector ReadVector()
{
IAsn1Convertible obj = ReadObject();
if (null == obj)
return new Asn1EncodableVector(0);
Asn1EncodableVector v = new Asn1EncodableVector();
do
{
v.Add(obj.ToAsn1Object());
}
while ((obj = ReadObject()) != null);
return v;
}
}
}
#pragma warning restore
#endif