From be15049124860ccb7335b92215e8b8dfa1821bf9 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Tue, 16 Nov 2021 22:37:52 +0700 Subject: ASN.1: Staged encoding --- crypto/src/asn1/Asn1Object.cs | 10 +- crypto/src/asn1/Asn1ObjectDescriptor.cs | 14 +-- crypto/src/asn1/Asn1OutputStream.cs | 179 ++++++++------------------- crypto/src/asn1/Asn1RelativeOid.cs | 13 +- crypto/src/asn1/Asn1Sequence.cs | 16 --- crypto/src/asn1/Asn1Set.cs | 16 --- crypto/src/asn1/Asn1TaggedObject.cs | 24 ++-- crypto/src/asn1/BERBitString.cs | 88 ++----------- crypto/src/asn1/BEROctetStringGenerator.cs | 8 +- crypto/src/asn1/BerOctetString.cs | 78 ++---------- crypto/src/asn1/BerSequence.cs | 31 ++--- crypto/src/asn1/BerSet.cs | 27 ++-- crypto/src/asn1/BerTaggedObject.cs | 63 ++-------- crypto/src/asn1/ConstructedDLEncoding.cs | 35 ++++++ crypto/src/asn1/ConstructedILEncoding.cs | 35 ++++++ crypto/src/asn1/ConstructedLazyDLEncoding.cs | 33 +++++ crypto/src/asn1/DERExternal.cs | 15 +-- crypto/src/asn1/DLSequence.cs | 66 ++-------- crypto/src/asn1/DLSet.cs | 78 ++---------- crypto/src/asn1/DLTaggedObject.cs | 72 ++--------- crypto/src/asn1/DerApplicationSpecific.cs | 14 +-- crypto/src/asn1/DerBMPString.cs | 14 +-- crypto/src/asn1/DerBitString.cs | 70 +++++------ crypto/src/asn1/DerBoolean.cs | 30 ++--- crypto/src/asn1/DerEnumerated.cs | 13 +- crypto/src/asn1/DerGeneralString.cs | 13 +- crypto/src/asn1/DerGeneralizedTime.cs | 13 +- crypto/src/asn1/DerGraphicString.cs | 13 +- crypto/src/asn1/DerIA5String.cs | 13 +- crypto/src/asn1/DerInteger.cs | 13 +- crypto/src/asn1/DerNull.cs | 13 +- crypto/src/asn1/DerNumericString.cs | 13 +- crypto/src/asn1/DerObjectIdentifier.cs | 13 +- crypto/src/asn1/DerOctetString.cs | 24 ++-- crypto/src/asn1/DerOutputStream.cs | 5 - crypto/src/asn1/DerPrintableString.cs | 13 +- crypto/src/asn1/DerSequence.cs | 63 +--------- crypto/src/asn1/DerSet.cs | 89 +++---------- crypto/src/asn1/DerT61String.cs | 13 +- crypto/src/asn1/DerTaggedObject.cs | 57 ++------- crypto/src/asn1/DerUTCTime.cs | 13 +- crypto/src/asn1/DerUTF8String.cs | 13 +- crypto/src/asn1/DerUniversalString.cs | 13 +- crypto/src/asn1/DerVideotexString.cs | 13 +- crypto/src/asn1/DerVisibleString.cs | 13 +- crypto/src/asn1/IAsn1Encoding.cs | 11 ++ crypto/src/asn1/LazyDLSequence.cs | 19 ++- crypto/src/asn1/LazyDLSet.cs | 21 ++-- crypto/src/asn1/PrimitiveEncoding.cs | 33 +++++ crypto/src/asn1/PrimitiveEncodingSuffixed.cs | 36 ++++++ 50 files changed, 535 insertions(+), 1060 deletions(-) create mode 100644 crypto/src/asn1/ConstructedDLEncoding.cs create mode 100644 crypto/src/asn1/ConstructedILEncoding.cs create mode 100644 crypto/src/asn1/ConstructedLazyDLEncoding.cs create mode 100644 crypto/src/asn1/IAsn1Encoding.cs create mode 100644 crypto/src/asn1/PrimitiveEncoding.cs create mode 100644 crypto/src/asn1/PrimitiveEncodingSuffixed.cs (limited to 'crypto/src/asn1') diff --git a/crypto/src/asn1/Asn1Object.cs b/crypto/src/asn1/Asn1Object.cs index 9945a7fae..0cf89052b 100644 --- a/crypto/src/asn1/Asn1Object.cs +++ b/crypto/src/asn1/Asn1Object.cs @@ -9,14 +9,14 @@ namespace Org.BouncyCastle.Asn1 public override void EncodeTo(Stream output) { Asn1OutputStream asn1Out = Asn1OutputStream.Create(output); - Encode(asn1Out, true); + GetEncoding(asn1Out.Encoding).Encode(asn1Out); asn1Out.FlushInternal(); } public override void EncodeTo(Stream output, string encoding) { Asn1OutputStream asn1Out = Asn1OutputStream.Create(output, encoding); - Encode(asn1Out, true); + GetEncoding(asn1Out.Encoding).Encode(asn1Out); asn1Out.FlushInternal(); } @@ -71,11 +71,9 @@ namespace Org.BouncyCastle.Asn1 return this; } - internal abstract bool EncodeConstructed(int encoding); + internal abstract IAsn1Encoding GetEncoding(int encoding); - internal abstract int EncodedLength(int encoding, bool withID); - - internal abstract void Encode(Asn1OutputStream asn1Out, bool withID); + internal abstract IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo); protected abstract bool Asn1Equals(Asn1Object asn1Object); protected abstract int Asn1GetHashCode(); diff --git a/crypto/src/asn1/Asn1ObjectDescriptor.cs b/crypto/src/asn1/Asn1ObjectDescriptor.cs index e306d827e..289a0e16f 100644 --- a/crypto/src/asn1/Asn1ObjectDescriptor.cs +++ b/crypto/src/asn1/Asn1ObjectDescriptor.cs @@ -78,20 +78,14 @@ namespace Org.BouncyCastle.Asn1 get { return m_baseGraphicString; } } - internal override bool EncodeConstructed(int encoding) + internal override IAsn1Encoding GetEncoding(int encoding) { - return false; + return m_baseGraphicString.GetEncodingImplicit(encoding, Asn1Tags.Universal, Asn1Tags.ObjectDescriptor); } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - return m_baseGraphicString.EncodedLength(encoding, withID); - } - - internal override void Encode(Asn1OutputStream asn1Out, bool withID) - { - asn1Out.WriteIdentifier(withID, Asn1Tags.ObjectDescriptor); - m_baseGraphicString.Encode(asn1Out, false); + return m_baseGraphicString.GetEncodingImplicit(encoding, tagClass, tagNo); } protected override int Asn1GetHashCode() diff --git a/crypto/src/asn1/Asn1OutputStream.cs b/crypto/src/asn1/Asn1OutputStream.cs index eeca2754c..096b569e3 100644 --- a/crypto/src/asn1/Asn1OutputStream.cs +++ b/crypto/src/asn1/Asn1OutputStream.cs @@ -37,7 +37,7 @@ namespace Org.BouncyCastle.Asn1 if (null == asn1Encodable) throw new ArgumentNullException("asn1Encodable"); - asn1Encodable.ToAsn1Object().Encode(this, true); + asn1Encodable.ToAsn1Object().GetEncoding(this.Encoding).Encode(this); FlushInternal(); } @@ -46,18 +46,16 @@ namespace Org.BouncyCastle.Asn1 if (null == asn1Object) throw new ArgumentNullException("asn1Object"); - asn1Object.Encode(this, true); + asn1Object.GetEncoding(this.Encoding).Encode(this); FlushInternal(); } - internal void FlushInternal() + internal void EncodeContents(IAsn1Encoding[] contentsEncodings) { - // Placeholder to support future internal buffering - } - - internal virtual DerOutputStreamNew GetDerSubStream() - { - return new DerOutputStreamNew(s); + for (int i = 0, count = contentsEncodings.Length; i < count; ++i) + { + contentsEncodings[i].Encode(this); + } } internal virtual int Encoding @@ -65,136 +63,77 @@ namespace Org.BouncyCastle.Asn1 get { return EncodingBer; } } - internal void WriteDL(int length) + internal void FlushInternal() { - if (length < 128) - { - WriteByte((byte)length); - } - else - { - byte[] stack = new byte[5]; - int pos = stack.Length; - - do - { - stack[--pos] = (byte)length; - length >>= 8; - } - while (length > 0); - - int count = stack.Length - pos; - stack[--pos] = (byte)(0x80 | count); - - Write(stack, pos, count + 1); - } + // Placeholder to support future internal buffering } - internal virtual void WriteElements(Asn1Encodable[] elements) + internal void WriteDL(int dl) { - for (int i = 0, count = elements.Length; i < count; ++i) + if (dl < 128) { - elements[i].ToAsn1Object().Encode(this, true); + WriteByte((byte)dl); + return; } - } - internal void WriteEncodingDL(bool withID, int identifier, byte contents) - { - WriteIdentifier(withID, identifier); - WriteDL(1); - WriteByte(contents); - } - - internal void WriteEncodingDL(bool withID, int identifier, byte[] contents) - { - WriteIdentifier(withID, identifier); - WriteDL(contents.Length); - Write(contents, 0, contents.Length); - } - - internal void WriteEncodingDL(bool withID, int identifier, byte[] contents, int contentsOff, int contentsLen) - { - WriteIdentifier(withID, identifier); - WriteDL(contentsLen); - Write(contents, contentsOff, contentsLen); - } + byte[] stack = new byte[5]; + int pos = stack.Length; - internal void WriteEncodingDL(bool withID, int identifier, byte contentsPrefix, byte[] contents, - int contentsOff, int contentsLen) - { - WriteIdentifier(withID, identifier); - WriteDL(1 + contentsLen); - WriteByte(contentsPrefix); - Write(contents, contentsOff, contentsLen); - } + do + { + stack[--pos] = (byte)dl; + dl >>= 8; + } + while (dl > 0); - internal void WriteEncodingDL(bool withID, int identifier, byte[] contents, int contentsOff, int contentsLen, - byte contentsSuffix) - { - WriteIdentifier(withID, identifier); - WriteDL(contentsLen + 1); - Write(contents, contentsOff, contentsLen); - WriteByte(contentsSuffix); - } + int count = stack.Length - pos; + stack[--pos] = (byte)(0x80 | count); - internal void WriteEncodingDL(bool withID, int flags, int tag, byte[] contents) - { - WriteIdentifier(withID, flags, tag); - WriteDL(contents.Length); - Write(contents, 0, contents.Length); + Write(stack, pos, count + 1); } - internal void WriteEncodingIL(bool withID, int identifier, Asn1Encodable[] elements) + internal void WriteIdentifier(int tagClass, int tagNo) { - WriteIdentifier(withID, identifier); - WriteByte(0x80); - WriteElements(elements); - WriteByte(0x00); - WriteByte(0x00); - } - - internal void WriteIdentifier(bool withID, int identifier) - { - if (withID) + if (tagNo < 31) { - WriteByte((byte)identifier); + WriteByte((byte)(tagClass | tagNo)); + return; } - } - internal void WriteIdentifier(bool withID, int flags, int tag) - { - if (!withID) - { - // Don't write the identifier - } - else if (tag < 31) + byte[] stack = new byte[6]; + int pos = stack.Length; + + stack[--pos] = (byte)(tagNo & 0x7F); + while (tagNo > 127) { - WriteByte((byte)(flags | tag)); + tagNo >>= 7; + stack[--pos] = (byte)(tagNo & 0x7F | 0x80); } - else - { - byte[] stack = new byte[6]; - int pos = stack.Length; - stack[--pos] = (byte)(tag & 0x7F); - while (tag > 127) - { - tag >>= 7; - stack[--pos] = (byte)(tag & 0x7F | 0x80); - } + stack[--pos] = (byte)(tagClass | 0x1F); - stack[--pos] = (byte)(flags | 0x1F); + Write(stack, pos, stack.Length - pos); + } - Write(stack, pos, stack.Length - pos); + internal static IAsn1Encoding[] GetContentsEncodings(int encoding, Asn1Encodable[] elements) + { + int count = elements.Length; + IAsn1Encoding[] contentsEncodings = new IAsn1Encoding[count]; + for (int i = 0; i < count; ++i) + { + contentsEncodings[i] = elements[i].ToAsn1Object().GetEncoding(encoding); } + return contentsEncodings; } - internal void WritePrimitives(Asn1Object[] primitives) + internal static int GetLengthOfContents(IAsn1Encoding[] contentsEncodings) { - for (int i = 0, count = primitives.Length; i < count; ++i) + int contentsLength = 0; + for (int i = 0, count = contentsEncodings.Length; i < count; ++i) { - primitives[i].Encode(this, true); + contentsLength += contentsEncodings[i].GetLength(); } + return contentsLength; } internal static int GetLengthOfDL(int dl) @@ -210,23 +149,13 @@ namespace Org.BouncyCastle.Asn1 return length; } - internal static int GetLengthOfEncodingDL(bool withID, int contentsLength) - { - return (withID ? 1 : 0) + GetLengthOfDL(contentsLength) + contentsLength; - } - - internal static int GetLengthOfEncodingDL(bool withID, int tag, int contentsLength) - { - return (withID ? GetLengthOfIdentifier(tag) : 0) + GetLengthOfDL(contentsLength) + contentsLength; - } - - internal static int GetLengthOfIdentifier(int tag) + internal static int GetLengthOfIdentifier(int tagNo) { - if (tag < 31) + if (tagNo < 31) return 1; int length = 2; - while ((tag >>= 7) > 0) + while ((tagNo >>= 7) > 0) { ++length; } diff --git a/crypto/src/asn1/Asn1RelativeOid.cs b/crypto/src/asn1/Asn1RelativeOid.cs index efa050413..a960b50bf 100644 --- a/crypto/src/asn1/Asn1RelativeOid.cs +++ b/crypto/src/asn1/Asn1RelativeOid.cs @@ -110,19 +110,14 @@ namespace Org.BouncyCastle.Asn1 return identifier.GetHashCode(); } - internal override bool EncodeConstructed(int encoding) + internal override IAsn1Encoding GetEncoding(int encoding) { - return false; + return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.RelativeOid, GetContents()); } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - return Asn1OutputStream.GetLengthOfEncodingDL(withID, GetContents().Length); - } - - internal override void Encode(Asn1OutputStream asn1Out, bool withID) - { - asn1Out.WriteEncodingDL(withID, Asn1Tags.RelativeOid, GetContents()); + return new PrimitiveEncoding(tagClass, tagNo, GetContents()); } private void DoOutput(MemoryStream bOut) diff --git a/crypto/src/asn1/Asn1Sequence.cs b/crypto/src/asn1/Asn1Sequence.cs index bd1b46b49..cfe0d37aa 100644 --- a/crypto/src/asn1/Asn1Sequence.cs +++ b/crypto/src/asn1/Asn1Sequence.cs @@ -235,27 +235,11 @@ namespace Org.BouncyCastle.Asn1 return true; } - internal override bool EncodeConstructed(int encoding) - { - return true; - } - public override string ToString() { return CollectionUtilities.ToString(elements); } - internal int CalculateContentsLength(int encoding) - { - int contentsLength = 0; - for (int i = 0, count = elements.Length; i < count; ++i) - { - Asn1Object asn1Object = elements[i].ToAsn1Object(); - contentsLength += asn1Object.EncodedLength(encoding, true); - } - return contentsLength; - } - // TODO[asn1] Preferably return an Asn1BitString[] (doesn't exist yet) internal DerBitString[] GetConstructedBitStrings() { diff --git a/crypto/src/asn1/Asn1Set.cs b/crypto/src/asn1/Asn1Set.cs index 45febabaf..42180fd71 100644 --- a/crypto/src/asn1/Asn1Set.cs +++ b/crypto/src/asn1/Asn1Set.cs @@ -266,27 +266,11 @@ namespace Org.BouncyCastle.Asn1 return true; } - internal override bool EncodeConstructed(int encoding) - { - return true; - } - public override string ToString() { return CollectionUtilities.ToString(elements); } - internal int CalculateContentsLength(int encoding) - { - int contentsLength = 0; - for (int i = 0, count = elements.Length; i < count; ++i) - { - Asn1Object asn1Object = elements[i].ToAsn1Object(); - contentsLength += asn1Object.EncodedLength(encoding, true); - } - return contentsLength; - } - internal static Asn1Encodable[] Sort(Asn1Encodable[] elements) { int count = elements.Length; diff --git a/crypto/src/asn1/Asn1TaggedObject.cs b/crypto/src/asn1/Asn1TaggedObject.cs index 13d1ff283..7fafa4c52 100644 --- a/crypto/src/asn1/Asn1TaggedObject.cs +++ b/crypto/src/asn1/Asn1TaggedObject.cs @@ -234,16 +234,24 @@ namespace Org.BouncyCastle.Asn1 } } - /** - * Return true if the object is marked as constructed, false otherwise. - * - * @return true if constructed, otherwise false. - */ - // TODO Need this public if/when DerApplicationSpecific extends Asn1TaggedObject internal bool IsConstructed() { - int encoding = Asn1Encoding == Ber ? Asn1OutputStream.EncodingBer : Asn1OutputStream.EncodingDer; - return EncodeConstructed(encoding); + switch (explicitness) + { + case DeclaredImplicit: + { + Asn1Object baseObject = obj.ToAsn1Object(); + if (baseObject is Asn1Sequence || baseObject is Asn1Set) + return true; + + Asn1TaggedObject baseTagged = baseObject as Asn1TaggedObject; + return null != baseTagged && baseTagged.IsConstructed(); + } + case ParsedImplicit: + return obj is Asn1Sequence; + default: + return true; + } } /** diff --git a/crypto/src/asn1/BERBitString.cs b/crypto/src/asn1/BERBitString.cs index a012d2a7c..2f5bd9cb7 100644 --- a/crypto/src/asn1/BERBitString.cs +++ b/crypto/src/asn1/BERBitString.cs @@ -111,90 +111,28 @@ namespace Org.BouncyCastle.Asn1 this.segmentLimit = DefaultSegmentLimit; } - internal override bool EncodeConstructed(int encoding) + internal override IAsn1Encoding GetEncoding(int encoding) { if (Asn1OutputStream.EncodingBer != encoding) - return base.EncodeConstructed(encoding); + return base.GetEncoding(encoding); - return null != elements || contents.Length > segmentLimit; - } - - internal override int EncodedLength(int encoding, bool withID) - { - if (Asn1OutputStream.EncodingBer != encoding) - return base.EncodedLength(encoding, withID); - - if (!EncodeConstructed(encoding)) - return EncodedLength(withID, contents.Length); - - int totalLength = withID ? 4 : 3; - - if (null != elements) - { - for (int i = 0; i < elements.Length; ++i) - { - totalLength += elements[i].EncodedLength(encoding, true); - } - } - else if (contents.Length < 2) - { - // No bits - } - else - { - int extraSegments = (contents.Length - 2) / (segmentLimit - 1); - totalLength += extraSegments * EncodedLength(true, segmentLimit); - - int lastSegmentLength = contents.Length - (extraSegments * (segmentLimit - 1)); - totalLength += EncodedLength(true, lastSegmentLength); - } + if (null == elements) + return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.BitString, contents); - return totalLength; + return new ConstructedILEncoding(Asn1Tags.Universal, Asn1Tags.BitString, + Asn1OutputStream.GetContentsEncodings(encoding, elements)); } - internal override void Encode(Asn1OutputStream asn1Out, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - if (Asn1OutputStream.EncodingBer != asn1Out.Encoding) - { - base.Encode(asn1Out, withID); - return; - } - - if (!EncodeConstructed(asn1Out.Encoding)) - { - Encode(asn1Out, withID, contents, 0, contents.Length); - return; - } - - asn1Out.WriteIdentifier(withID, Asn1Tags.Constructed | Asn1Tags.BitString); - asn1Out.WriteByte(0x80); - - if (null != elements) - { - asn1Out.WritePrimitives(elements); - } - else if (contents.Length < 2) - { - // No bits - } - else - { - byte pad = contents[0]; - int length = contents.Length; - int remaining = length - 1; - int segmentLength = segmentLimit - 1; - - while (remaining > segmentLength) - { - Encode(asn1Out, true, (byte)0, contents, length - remaining, segmentLength); - remaining -= segmentLength; - } + if (Asn1OutputStream.EncodingBer != encoding) + return base.GetEncodingImplicit(encoding, tagClass, tagNo); - Encode(asn1Out, true, pad, contents, length - remaining, remaining); - } + if (null == elements) + return new PrimitiveEncoding(tagClass, tagNo, contents); - asn1Out.WriteByte(0x00); - asn1Out.WriteByte(0x00); + return new ConstructedILEncoding(tagClass, tagNo, + Asn1OutputStream.GetContentsEncodings(encoding, elements)); } } } diff --git a/crypto/src/asn1/BEROctetStringGenerator.cs b/crypto/src/asn1/BEROctetStringGenerator.cs index 37e46bea5..de0a6c0b8 100644 --- a/crypto/src/asn1/BEROctetStringGenerator.cs +++ b/crypto/src/asn1/BEROctetStringGenerator.cs @@ -67,7 +67,7 @@ namespace Org.BouncyCastle.Asn1 if (_off == _buf.Length) { - DerOctetString.Encode(_derOut, true, _buf, 0, _off); + DerOctetString.Encode(_derOut, _buf, 0, _off); _off = 0; } } @@ -88,13 +88,13 @@ namespace Org.BouncyCastle.Asn1 { Array.Copy(b, off, _buf, _off, available); count += available; - DerOctetString.Encode(_derOut, true, _buf, 0, bufLen); + DerOctetString.Encode(_derOut, _buf, 0, bufLen); } int remaining; while ((remaining = len - count) >= bufLen) { - DerOctetString.Encode(_derOut, true, b, off + count, bufLen); + DerOctetString.Encode(_derOut, b, off + count, bufLen); count += bufLen; } @@ -123,7 +123,7 @@ namespace Org.BouncyCastle.Asn1 { if (_off != 0) { - DerOctetString.Encode(_derOut, true, _buf, 0, _off); + DerOctetString.Encode(_derOut, _buf, 0, _off); } _derOut.FlushInternal(); diff --git a/crypto/src/asn1/BerOctetString.cs b/crypto/src/asn1/BerOctetString.cs index 52ddd51c3..8e51f8bca 100644 --- a/crypto/src/asn1/BerOctetString.cs +++ b/crypto/src/asn1/BerOctetString.cs @@ -120,80 +120,28 @@ namespace Org.BouncyCastle.Asn1 return GetEnumerator(); } - internal override bool EncodeConstructed(int encoding) + internal override IAsn1Encoding GetEncoding(int encoding) { if (Asn1OutputStream.EncodingBer != encoding) - return base.EncodeConstructed(encoding); + return base.GetEncoding(encoding); - return null != elements || contents.Length > segmentLimit; - } - - internal override int EncodedLength(int encoding, bool withID) - { - if (Asn1OutputStream.EncodingBer != encoding) - return base.EncodedLength(encoding, withID); - - if (!EncodeConstructed(encoding)) - return EncodedLength(withID, contents.Length); - - int totalLength = withID ? 4 : 3; - - if (null != elements) - { - for (int i = 0; i < elements.Length; ++i) - { - totalLength += elements[i].EncodedLength(encoding, true); - } - } - else - { - int fullSegments = contents.Length / segmentLimit; - totalLength += fullSegments * EncodedLength(true, segmentLimit); - - int lastSegmentLength = contents.Length - (fullSegments * segmentLimit); - if (lastSegmentLength > 0) - { - totalLength += EncodedLength(true, lastSegmentLength); - } - } + if (null == elements) + return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.OctetString, contents); - return totalLength; + return new ConstructedILEncoding(Asn1Tags.Universal, Asn1Tags.OctetString, + Asn1OutputStream.GetContentsEncodings(encoding, elements)); } - internal override void Encode(Asn1OutputStream asn1Out, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - if (Asn1OutputStream.EncodingBer != asn1Out.Encoding) - { - base.Encode(asn1Out, withID); - return; - } - - if (!EncodeConstructed(asn1Out.Encoding)) - { - Encode(asn1Out, withID, contents, 0, contents.Length); - return; - } - - asn1Out.WriteIdentifier(withID, Asn1Tags.Constructed | Asn1Tags.OctetString); - asn1Out.WriteByte(0x80); + if (Asn1OutputStream.EncodingBer != encoding) + return base.GetEncodingImplicit(encoding, tagClass, tagNo); - if (null != elements) - { - asn1Out.WritePrimitives(elements); - } - else - { - int pos = 0; - while (pos < contents.Length) - { - int segmentLength = System.Math.Min(contents.Length - pos, segmentLimit); - Encode(asn1Out, true, contents, pos, segmentLength); - pos += segmentLength; - } - } + if (null == elements) + return new PrimitiveEncoding(tagClass, tagNo, contents); - asn1Out.WriteByte(0x00); - asn1Out.WriteByte(0x00); + return new ConstructedILEncoding(tagClass, tagNo, + Asn1OutputStream.GetContentsEncodings(encoding, elements)); } private class ChunkEnumerator diff --git a/crypto/src/asn1/BerSequence.cs b/crypto/src/asn1/BerSequence.cs index a92b70f98..deed8fbb9 100644 --- a/crypto/src/asn1/BerSequence.cs +++ b/crypto/src/asn1/BerSequence.cs @@ -46,32 +46,23 @@ namespace Org.BouncyCastle.Asn1 { } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncoding(int encoding) { if (Asn1OutputStream.EncodingBer != encoding) - return base.EncodedLength(encoding, withID); + return base.GetEncoding(encoding); - int totalLength = withID ? 4 : 3; - - for (int i = 0, count = elements.Length; i < count; ++i) - { - Asn1Object asn1Object = elements[i].ToAsn1Object(); - totalLength += asn1Object.EncodedLength(encoding, true); - } - - return totalLength; + return new ConstructedILEncoding(Asn1Tags.Universal, Asn1Tags.Sequence, + Asn1OutputStream.GetContentsEncodings(encoding, elements)); } - internal override void Encode(Asn1OutputStream asn1Out, bool withID) - { - if (Asn1OutputStream.EncodingBer != asn1Out.Encoding) - { - base.Encode(asn1Out, withID); - return; - } + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) + { + if (Asn1OutputStream.EncodingBer != encoding) + return base.GetEncodingImplicit(encoding, tagClass, tagNo); - asn1Out.WriteEncodingIL(withID, Asn1Tags.Constructed | Asn1Tags.Sequence, elements); - } + return new ConstructedILEncoding(tagClass, tagNo, + Asn1OutputStream.GetContentsEncodings(encoding, elements)); + } internal override DerBitString ToAsn1BitString() { diff --git a/crypto/src/asn1/BerSet.cs b/crypto/src/asn1/BerSet.cs index c0d00537c..0a273b3f3 100644 --- a/crypto/src/asn1/BerSet.cs +++ b/crypto/src/asn1/BerSet.cs @@ -48,31 +48,22 @@ namespace Org.BouncyCastle.Asn1 { } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncoding(int encoding) { if (Asn1OutputStream.EncodingBer != encoding) - return base.EncodedLength(encoding, withID); + return base.GetEncoding(encoding); - int totalLength = withID ? 4 : 3; - - for (int i = 0, count = elements.Length; i < count; ++i) - { - Asn1Object asn1Object = elements[i].ToAsn1Object(); - totalLength += asn1Object.EncodedLength(encoding, true); - } - - return totalLength; + return new ConstructedILEncoding(Asn1Tags.Universal, Asn1Tags.Set, + Asn1OutputStream.GetContentsEncodings(encoding, elements)); } - internal override void Encode(Asn1OutputStream asn1Out, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - if (Asn1OutputStream.EncodingBer != asn1Out.Encoding) - { - base.Encode(asn1Out, withID); - return; - } + if (Asn1OutputStream.EncodingBer != encoding) + return base.GetEncodingImplicit(encoding, tagClass, tagNo); - asn1Out.WriteEncodingIL(withID, Asn1Tags.Constructed | Asn1Tags.Set, elements); + return new ConstructedILEncoding(tagClass, tagNo, + Asn1OutputStream.GetContentsEncodings(encoding, elements)); } } } diff --git a/crypto/src/asn1/BerTaggedObject.cs b/crypto/src/asn1/BerTaggedObject.cs index a97a8e143..e613d98d9 100644 --- a/crypto/src/asn1/BerTaggedObject.cs +++ b/crypto/src/asn1/BerTaggedObject.cs @@ -59,69 +59,32 @@ namespace Org.BouncyCastle.Asn1 get { return Ber; } } - internal override bool EncodeConstructed(int encoding) + internal override IAsn1Encoding GetEncoding(int encoding) { if (Asn1OutputStream.EncodingBer != encoding) - return base.EncodeConstructed(encoding); + return base.GetEncoding(encoding); - return IsExplicit() || GetBaseObject().ToAsn1Object().EncodeConstructed(encoding); + Asn1Object baseObject = GetBaseObject().ToAsn1Object(); + + if (!IsExplicit()) + return baseObject.GetEncodingImplicit(encoding, TagClass, TagNo); + + return new ConstructedILEncoding(TagClass, TagNo, new IAsn1Encoding[]{ baseObject.GetEncoding(encoding) }); } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { if (Asn1OutputStream.EncodingBer != encoding) - return base.EncodedLength(encoding, withID); + return base.GetEncodingImplicit(encoding, tagClass, tagNo); Asn1Object baseObject = GetBaseObject().ToAsn1Object(); - bool withBaseID = IsExplicit(); - - int length = baseObject.EncodedLength(encoding, withBaseID); - - if (withBaseID) - { - length += 3; - } - length += withID ? Asn1OutputStream.GetLengthOfIdentifier(TagNo) : 0; + if (!IsExplicit()) + return baseObject.GetEncodingImplicit(encoding, tagClass, tagNo); - return length; + return new ConstructedILEncoding(tagClass, tagNo, new IAsn1Encoding[]{ baseObject.GetEncoding(encoding) }); } - internal override void Encode(Asn1OutputStream asn1Out, bool withID) - { - if (Asn1OutputStream.EncodingBer != asn1Out.Encoding) - { - base.Encode(asn1Out, withID); - return; - } - - Asn1Object baseObject = GetBaseObject().ToAsn1Object(); - bool withBaseID = IsExplicit(); - - if (withID) - { - int flags = TagClass; - if (withBaseID || baseObject.EncodeConstructed(asn1Out.Encoding)) - { - flags |= Asn1Tags.Constructed; - } - - asn1Out.WriteIdentifier(true, flags, TagNo); - } - - if (withBaseID) - { - asn1Out.WriteByte(0x80); - baseObject.Encode(asn1Out, true); - asn1Out.WriteByte(0x00); - asn1Out.WriteByte(0x00); - } - else - { - baseObject.Encode(asn1Out, false); - } - } - internal override Asn1Sequence RebuildConstructed(Asn1Object asn1Object) { return new BerSequence(asn1Object); diff --git a/crypto/src/asn1/ConstructedDLEncoding.cs b/crypto/src/asn1/ConstructedDLEncoding.cs new file mode 100644 index 000000000..f7d8bec5d --- /dev/null +++ b/crypto/src/asn1/ConstructedDLEncoding.cs @@ -0,0 +1,35 @@ +using System; + +namespace Org.BouncyCastle.Asn1 +{ + internal class ConstructedDLEncoding + : IAsn1Encoding + { + private readonly int m_tagClass; + private readonly int m_tagNo; + private readonly IAsn1Encoding[] m_contentsElements; + private readonly int m_contentsLength; + + internal ConstructedDLEncoding(int tagClass, int tagNo, IAsn1Encoding[] contentsElements) + { + m_tagClass = tagClass; + m_tagNo = tagNo; + m_contentsElements = contentsElements; + m_contentsLength = Asn1OutputStream.GetLengthOfContents(contentsElements); + } + + void IAsn1Encoding.Encode(Asn1OutputStream asn1Out) + { + asn1Out.WriteIdentifier(Asn1Tags.Constructed | m_tagClass, m_tagNo); + asn1Out.WriteDL(m_contentsLength); + asn1Out.EncodeContents(m_contentsElements); + } + + int IAsn1Encoding.GetLength() + { + return Asn1OutputStream.GetLengthOfIdentifier(m_tagNo) + + Asn1OutputStream.GetLengthOfDL(m_contentsLength) + + m_contentsLength; + } + } +} diff --git a/crypto/src/asn1/ConstructedILEncoding.cs b/crypto/src/asn1/ConstructedILEncoding.cs new file mode 100644 index 000000000..1934c6f48 --- /dev/null +++ b/crypto/src/asn1/ConstructedILEncoding.cs @@ -0,0 +1,35 @@ +using System; + +namespace Org.BouncyCastle.Asn1 +{ + internal class ConstructedILEncoding + : IAsn1Encoding + { + private readonly int m_tagClass; + private readonly int m_tagNo; + private readonly IAsn1Encoding[] m_contentsElements; + + internal ConstructedILEncoding(int tagClass, int tagNo, IAsn1Encoding[] contentsElements) + { + m_tagClass = tagClass; + m_tagNo = tagNo; + m_contentsElements = contentsElements; + } + + void IAsn1Encoding.Encode(Asn1OutputStream asn1Out) + { + asn1Out.WriteIdentifier(Asn1Tags.Constructed | m_tagClass, m_tagNo); + asn1Out.WriteByte(0x80); + asn1Out.EncodeContents(m_contentsElements); + asn1Out.WriteByte(0x00); + asn1Out.WriteByte(0x00); + } + + int IAsn1Encoding.GetLength() + { + return Asn1OutputStream.GetLengthOfIdentifier(m_tagNo) + + 3 + + Asn1OutputStream.GetLengthOfContents(m_contentsElements); + } + } +} diff --git a/crypto/src/asn1/ConstructedLazyDLEncoding.cs b/crypto/src/asn1/ConstructedLazyDLEncoding.cs new file mode 100644 index 000000000..3847b465b --- /dev/null +++ b/crypto/src/asn1/ConstructedLazyDLEncoding.cs @@ -0,0 +1,33 @@ +using System; + +namespace Org.BouncyCastle.Asn1 +{ + internal class ConstructedLazyDLEncoding + : IAsn1Encoding + { + private readonly int m_tagClass; + private readonly int m_tagNo; + private readonly byte[] m_contentsOctets; + + internal ConstructedLazyDLEncoding(int tagClass, int tagNo, byte[] contentsOctets) + { + m_tagClass = tagClass; + m_tagNo = tagNo; + m_contentsOctets = contentsOctets; + } + + void IAsn1Encoding.Encode(Asn1OutputStream asn1Out) + { + asn1Out.WriteIdentifier(Asn1Tags.Constructed | m_tagClass, m_tagNo); + asn1Out.WriteDL(m_contentsOctets.Length); + asn1Out.Write(m_contentsOctets, 0, m_contentsOctets.Length); + } + + int IAsn1Encoding.GetLength() + { + return Asn1OutputStream.GetLengthOfIdentifier(m_tagNo) + + Asn1OutputStream.GetLengthOfDL(m_contentsOctets.Length) + + m_contentsOctets.Length; + } + } +} diff --git a/crypto/src/asn1/DERExternal.cs b/crypto/src/asn1/DERExternal.cs index 32fc8d6d8..67dad0534 100644 --- a/crypto/src/asn1/DERExternal.cs +++ b/crypto/src/asn1/DERExternal.cs @@ -155,21 +155,14 @@ namespace Org.BouncyCastle.Asn1 return new DerSequence(v); } - internal override bool EncodeConstructed(int encoding) + internal override IAsn1Encoding GetEncoding(int encoding) { - //return BuildSequence().EncodeConstructed(encoding); - return true; + return BuildSequence().GetEncodingImplicit(encoding, Asn1Tags.Universal, Asn1Tags.External); } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - return BuildSequence().EncodedLength(encoding, withID); - } - - internal override void Encode(Asn1OutputStream asn1Out, bool withID) - { - asn1Out.WriteIdentifier(withID, Asn1Tags.Constructed | Asn1Tags.External); - BuildSequence().Encode(asn1Out, false); + return BuildSequence().GetEncodingImplicit(encoding, tagClass, tagNo); } protected override int Asn1GetHashCode() diff --git a/crypto/src/asn1/DLSequence.cs b/crypto/src/asn1/DLSequence.cs index 0fede574a..8cf8d5bcb 100644 --- a/crypto/src/asn1/DLSequence.cs +++ b/crypto/src/asn1/DLSequence.cs @@ -12,8 +12,6 @@ namespace Org.BouncyCastle.Asn1 return elementVector.Count < 1 ? Empty : new DLSequence(elementVector); } - private int m_contentsLengthDL = -1; - /** * create an empty sequence */ @@ -48,73 +46,27 @@ namespace Org.BouncyCastle.Asn1 { } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncoding(int encoding) { if (Asn1OutputStream.EncodingDer == encoding) - return base.EncodedLength(encoding, withID); + return base.GetEncoding(encoding); - return Asn1OutputStream.GetLengthOfEncodingDL(withID, GetContentsLengthDL()); + return new ConstructedDLEncoding(Asn1Tags.Universal, Asn1Tags.Sequence, + Asn1OutputStream.GetContentsEncodings(encoding, elements)); } - internal override void Encode(Asn1OutputStream asn1Out, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - if (Asn1OutputStream.EncodingDer == asn1Out.Encoding) - { - base.Encode(asn1Out, withID); - return; - } - - // TODO[asn1] Use DL encoding when supported - //asn1Out = asn1Out.GetDLSubStream(); - - asn1Out.WriteIdentifier(withID, Asn1Tags.Constructed | Asn1Tags.Sequence); - - int count = elements.Length; - if (m_contentsLengthDL >= 0 || count > 16) - { - asn1Out.WriteDL(GetContentsLengthDL()); - - for (int i = 0; i < count; ++i) - { - Asn1Object asn1Object = elements[i].ToAsn1Object(); - asn1Object.Encode(asn1Out, true); - } - } - else - { - int contentsLength = 0; - - Asn1Object[] asn1Objects = new Asn1Object[count]; - for (int i = 0; i < count; ++i) - { - Asn1Object asn1Object = elements[i].ToAsn1Object(); - asn1Objects[i] = asn1Object; - contentsLength += asn1Object.EncodedLength(asn1Out.Encoding, true); - } - - this.m_contentsLengthDL = contentsLength; - asn1Out.WriteDL(contentsLength); + if (Asn1OutputStream.EncodingDer == encoding) + return base.GetEncodingImplicit(encoding, tagClass, tagNo); - for (int i = 0; i < count; ++i) - { - asn1Objects[i].Encode(asn1Out, true); - } - } + return new ConstructedDLEncoding(tagClass, tagNo, + Asn1OutputStream.GetContentsEncodings(encoding, elements)); } internal override Asn1Set ToAsn1Set() { return new DLSet(false, elements); } - - private int GetContentsLengthDL() - { - if (m_contentsLengthDL < 0) - { - // TODO[asn1] Use DL encoding when supported - m_contentsLengthDL = CalculateContentsLength(Asn1OutputStream.EncodingBer); - } - return m_contentsLengthDL; - } } } diff --git a/crypto/src/asn1/DLSet.cs b/crypto/src/asn1/DLSet.cs index 7dcac25c2..ba55be826 100644 --- a/crypto/src/asn1/DLSet.cs +++ b/crypto/src/asn1/DLSet.cs @@ -12,8 +12,6 @@ namespace Org.BouncyCastle.Asn1 return elementVector.Count < 1 ? Empty : new DLSet(elementVector); } - private int m_contentsLengthDL = -1; - /** * create an empty set */ @@ -48,80 +46,22 @@ namespace Org.BouncyCastle.Asn1 { } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncoding(int encoding) { if (Asn1OutputStream.EncodingDer == encoding) - return base.EncodedLength(encoding, withID); - - // TODO[asn1] Force DL encoding when supported - //encoding = Asn1OutputStream.EncodingDL; - - int count = elements.Length; - int contentsLength = 0; - - for (int i = 0; i < count; ++i) - { - Asn1Object asn1Object = elements[i].ToAsn1Object(); - contentsLength += asn1Object.EncodedLength(encoding, true); - } + return base.GetEncoding(encoding); - return Asn1OutputStream.GetLengthOfEncodingDL(withID, contentsLength); + return new ConstructedDLEncoding(Asn1Tags.Universal, Asn1Tags.Set, + Asn1OutputStream.GetContentsEncodings(encoding, elements)); } - internal override void Encode(Asn1OutputStream asn1Out, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - if (Asn1OutputStream.EncodingDer == asn1Out.Encoding) - { - base.Encode(asn1Out, withID); - return; - } - - // TODO[asn1] Force DL encoding when supported - //asn1Out = asn1Out.GetDLSubStream(); - - asn1Out.WriteIdentifier(withID, Asn1Tags.Constructed | Asn1Tags.Set); - - int count = elements.Length; - if (m_contentsLengthDL >= 0 || count > 16) - { - asn1Out.WriteDL(GetContentsLengthDL()); - - for (int i = 0; i < count; ++i) - { - Asn1Object asn1Object = elements[i].ToAsn1Object(); - asn1Object.Encode(asn1Out, true); - } - } - else - { - int contentsLength = 0; - - Asn1Object[] asn1Objects = new Asn1Object[count]; - for (int i = 0; i < count; ++i) - { - Asn1Object asn1Object = elements[i].ToAsn1Object(); - asn1Objects[i] = asn1Object; - contentsLength += asn1Object.EncodedLength(asn1Out.Encoding, true); - } - - this.m_contentsLengthDL = contentsLength; - asn1Out.WriteDL(contentsLength); - - for (int i = 0; i < count; ++i) - { - asn1Objects[i].Encode(asn1Out, true); - } - } - } + if (Asn1OutputStream.EncodingDer == encoding) + return base.GetEncodingImplicit(encoding, tagClass, tagNo); - private int GetContentsLengthDL() - { - if (m_contentsLengthDL < 0) - { - // TODO[asn1] Use DL encoding when supported - m_contentsLengthDL = CalculateContentsLength(Asn1OutputStream.EncodingBer); - } - return m_contentsLengthDL; + return new ConstructedDLEncoding(tagClass, tagNo, + Asn1OutputStream.GetContentsEncodings(encoding, elements)); } } } diff --git a/crypto/src/asn1/DLTaggedObject.cs b/crypto/src/asn1/DLTaggedObject.cs index 314b42799..c06dd8e87 100644 --- a/crypto/src/asn1/DLTaggedObject.cs +++ b/crypto/src/asn1/DLTaggedObject.cs @@ -5,8 +5,6 @@ namespace Org.BouncyCastle.Asn1 internal class DLTaggedObject : DerTaggedObject { - private int m_contentsLengthDL = -1; - internal DLTaggedObject(int tagNo, Asn1Encodable obj) : base(tagNo, obj) { @@ -38,68 +36,30 @@ namespace Org.BouncyCastle.Asn1 get { return Ber; } } - internal override bool EncodeConstructed(int encoding) + internal override IAsn1Encoding GetEncoding(int encoding) { if (Asn1OutputStream.EncodingDer == encoding) - return base.EncodeConstructed(encoding); - - // TODO[asn1] Use DL encoding when supported - //encoding = Asn1OutputStream.EncodingDL; - - return IsExplicit() || GetBaseObject().ToAsn1Object().EncodeConstructed(encoding); - } - - internal override int EncodedLength(int encoding, bool withID) - { - if (Asn1OutputStream.EncodingDer == encoding) - return base.EncodedLength(encoding, withID); + return base.GetEncoding(encoding); Asn1Object baseObject = GetBaseObject().ToAsn1Object(); - bool withBaseID = IsExplicit(); - - int length = GetContentsLengthDL(baseObject, withBaseID); - if (withBaseID) - { - length += Asn1OutputStream.GetLengthOfDL(length); - } + if (!IsExplicit()) + return baseObject.GetEncodingImplicit(encoding, TagClass, TagNo); - length += withID ? Asn1OutputStream.GetLengthOfIdentifier(TagNo) : 0; - - return length; + return new ConstructedDLEncoding(TagClass, TagNo, new IAsn1Encoding[]{ baseObject.GetEncoding(encoding) }); } - internal override void Encode(Asn1OutputStream asn1Out, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - if (Asn1OutputStream.EncodingDer == asn1Out.Encoding) - { - base.Encode(asn1Out, withID); - return; - } - - // TODO[asn1] Use DL encoding when supported - //asn1Out = asn1Out.GetDLSubStream(); + if (Asn1OutputStream.EncodingDer == encoding) + return base.GetEncodingImplicit(encoding, tagClass, tagNo); Asn1Object baseObject = GetBaseObject().ToAsn1Object(); - bool withBaseID = IsExplicit(); - - if (withID) - { - int flags = TagClass; - if (withBaseID || baseObject.EncodeConstructed(asn1Out.Encoding)) - { - flags |= Asn1Tags.Constructed; - } - asn1Out.WriteIdentifier(true, flags, TagNo); - } + if (!IsExplicit()) + return baseObject.GetEncodingImplicit(encoding, tagClass, tagNo); - if (withBaseID) - { - asn1Out.WriteDL(GetContentsLengthDL(baseObject, true)); - } - - baseObject.Encode(asn1Out, withBaseID); + return new ConstructedDLEncoding(tagClass, tagNo, new IAsn1Encoding[]{ baseObject.GetEncoding(encoding) }); } internal override Asn1Sequence RebuildConstructed(Asn1Object asn1Object) @@ -111,15 +71,5 @@ namespace Org.BouncyCastle.Asn1 { return new DLTaggedObject(explicitness, tagClass, tagNo, obj); } - - private int GetContentsLengthDL(Asn1Object baseObject, bool withBaseID) - { - if (m_contentsLengthDL < 0) - { - // TODO[asn1] Use DL encoding when supported - m_contentsLengthDL = baseObject.EncodedLength(Asn1OutputStream.EncodingBer, withBaseID); - } - return m_contentsLengthDL; - } } } diff --git a/crypto/src/asn1/DerApplicationSpecific.cs b/crypto/src/asn1/DerApplicationSpecific.cs index 39c2aec28..13b725325 100644 --- a/crypto/src/asn1/DerApplicationSpecific.cs +++ b/crypto/src/asn1/DerApplicationSpecific.cs @@ -134,6 +134,7 @@ namespace Org.BouncyCastle.Asn1 return m_taggedObject.HasTag(Asn1Tags.Application, tagNo); } + [Obsolete("Will be removed")] public bool IsConstructed() { return m_taggedObject.IsConstructed(); @@ -175,19 +176,14 @@ namespace Org.BouncyCastle.Asn1 return m_taggedObject.CallAsn1GetHashCode(); } - internal override bool EncodeConstructed(int encoding) + internal override IAsn1Encoding GetEncoding(int encoding) { - return m_taggedObject.EncodeConstructed(encoding); + return m_taggedObject.GetEncoding(encoding); } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - return m_taggedObject.EncodedLength(encoding, withID); - } - - internal override void Encode(Asn1OutputStream asn1Out, bool withID) - { - m_taggedObject.Encode(asn1Out, withID); + return m_taggedObject.GetEncodingImplicit(encoding, tagClass, tagNo); } private byte[] ReplaceTagNumber(int newTag, byte[] input) diff --git a/crypto/src/asn1/DerBMPString.cs b/crypto/src/asn1/DerBMPString.cs index d3c7b3b46..4e35dfff8 100644 --- a/crypto/src/asn1/DerBMPString.cs +++ b/crypto/src/asn1/DerBMPString.cs @@ -111,28 +111,28 @@ namespace Org.BouncyCastle.Asn1 return this.str.Equals(other.str); } - internal override bool EncodeConstructed(int encoding) + internal override IAsn1Encoding GetEncoding(int encoding) { - return false; + return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.BmpString, GetContents()); } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - return Asn1OutputStream.GetLengthOfEncodingDL(withID, str.Length * 2); + return new PrimitiveEncoding(tagClass, tagNo, GetContents()); } - internal override void Encode(Asn1OutputStream asn1Out, bool withID) + private byte[] GetContents() { char[] c = str.ToCharArray(); byte[] b = new byte[c.Length * 2]; - for (int i = 0; i != c.Length; i++) + for (int i = 0; i != c.Length; i++) { b[2 * i] = (byte)(c[i] >> 8); b[2 * i + 1] = (byte)c[i]; } - asn1Out.WriteEncodingDL(withID, Asn1Tags.BmpString, b); + return b; } } } diff --git a/crypto/src/asn1/DerBitString.cs b/crypto/src/asn1/DerBitString.cs index 2814b9677..375abb479 100644 --- a/crypto/src/asn1/DerBitString.cs +++ b/crypto/src/asn1/DerBitString.cs @@ -216,34 +216,37 @@ namespace Org.BouncyCastle.Asn1 } } - internal override bool EncodeConstructed(int encoding) + internal override IAsn1Encoding GetEncoding(int encoding) { - return false; - } + int padBits = contents[0]; + if (padBits != 0) + { + int last = contents.Length - 1; + byte lastBer = contents[last]; + byte lastDer = (byte)(lastBer & (0xFF << padBits)); - internal override int EncodedLength(int encoding, bool withID) - { - return Asn1OutputStream.GetLengthOfEncodingDL(withID, contents.Length); + if (lastBer != lastDer) + return new PrimitiveEncodingSuffixed(Asn1Tags.Universal, Asn1Tags.BitString, contents, lastDer); + } + + return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.BitString, contents); } - internal override void Encode(Asn1OutputStream asn1Out, bool withID) - { + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) + { int padBits = contents[0]; - int length = contents.Length; - int last = length - 1; - - byte lastOctet = contents[last]; - byte lastOctetDer = (byte)(contents[last] & (0xFF << padBits)); - - if (lastOctet == lastOctetDer) - { - asn1Out.WriteEncodingDL(withID, Asn1Tags.BitString, contents); - } - else + if (padBits != 0) { - asn1Out.WriteEncodingDL(withID, Asn1Tags.BitString, contents, 0, last, lastOctetDer); + int last = contents.Length - 1; + byte lastBer = contents[last]; + byte lastDer = (byte)(lastBer & (0xFF << padBits)); + + if (lastBer != lastDer) + return new PrimitiveEncodingSuffixed(tagClass, tagNo, contents, lastDer); } - } + + return new PrimitiveEncoding(tagClass, tagNo, contents); + } protected override int Asn1GetHashCode() { @@ -253,11 +256,11 @@ namespace Org.BouncyCastle.Asn1 int padBits = contents[0]; int last = contents.Length - 1; - byte lastOctetDer = (byte)(contents[last] & (0xFF << padBits)); + byte lastDer = (byte)(contents[last] & (0xFF << padBits)); int hc = Arrays.GetHashCode(contents, 0, last); hc *= 257; - hc ^= lastOctetDer; + hc ^= lastDer; return hc; } @@ -283,10 +286,10 @@ namespace Org.BouncyCastle.Asn1 } int padBits = thisContents[0]; - byte thisLastOctetDer = (byte)(thisContents[last] & (0xFF << padBits)); - byte thatLastOctetDer = (byte)(thatContents[last] & (0xFF << padBits)); + byte thisLastDer = (byte)(thisContents[last] & (0xFF << padBits)); + byte thatLastDer = (byte)(thatContents[last] & (0xFF << padBits)); - return thisLastOctetDer == thatLastOctetDer; + return thisLastDer == thatLastDer; } public override string GetString() @@ -306,21 +309,6 @@ namespace Org.BouncyCastle.Asn1 return buffer.ToString(); } - internal static int EncodedLength(bool withID, int contentsLength) - { - return Asn1OutputStream.GetLengthOfEncodingDL(withID, contentsLength); - } - - internal static void Encode(Asn1OutputStream asn1Out, bool withID, byte[] buf, int off, int len) - { - asn1Out.WriteEncodingDL(withID, Asn1Tags.BitString, buf, off, len); - } - - internal static void Encode(Asn1OutputStream asn1Out, bool withID, byte pad, byte[] buf, int off, int len) - { - asn1Out.WriteEncodingDL(withID, Asn1Tags.BitString, pad, buf, off, len); - } - internal static DerBitString CreatePrimitive(byte[] contents) { int length = contents.Length; diff --git a/crypto/src/asn1/DerBoolean.cs b/crypto/src/asn1/DerBoolean.cs index a6f972629..29e2d8bd9 100644 --- a/crypto/src/asn1/DerBoolean.cs +++ b/crypto/src/asn1/DerBoolean.cs @@ -81,25 +81,14 @@ namespace Org.BouncyCastle.Asn1 get { return value != 0; } } - internal override bool EncodeConstructed(int encoding) + internal override IAsn1Encoding GetEncoding(int encoding) { - return false; + return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.Boolean, GetContents(encoding)); } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - return Asn1OutputStream.GetLengthOfEncodingDL(withID, 1); - } - - internal override void Encode(Asn1OutputStream asn1Out, bool withID) - { - byte contents = value; - if (Asn1OutputStream.EncodingDer == asn1Out.Encoding && IsTrue) - { - contents = 0xFF; - } - - asn1Out.WriteEncodingDL(withID, Asn1Tags.Boolean, contents); + return new PrimitiveEncoding(tagClass, tagNo, GetContents(encoding)); } protected override bool Asn1Equals( @@ -134,5 +123,16 @@ namespace Org.BouncyCastle.Asn1 return b == 0 ? False : b == 0xFF ? True : new DerBoolean(value); } + + private byte[] GetContents(int encoding) + { + byte contents = value; + if (Asn1OutputStream.EncodingDer == encoding && IsTrue) + { + contents = 0xFF; + } + + return new byte[]{ contents }; + } } } diff --git a/crypto/src/asn1/DerEnumerated.cs b/crypto/src/asn1/DerEnumerated.cs index af9e6330a..6fd2f9b62 100644 --- a/crypto/src/asn1/DerEnumerated.cs +++ b/crypto/src/asn1/DerEnumerated.cs @@ -119,19 +119,14 @@ namespace Org.BouncyCastle.Asn1 } } - internal override bool EncodeConstructed(int encoding) + internal override IAsn1Encoding GetEncoding(int encoding) { - return false; + return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.Enumerated, bytes); } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - return Asn1OutputStream.GetLengthOfEncodingDL(withID, bytes.Length); - } - - internal override void Encode(Asn1OutputStream asn1Out, bool withID) - { - asn1Out.WriteEncodingDL(withID, Asn1Tags.Enumerated, bytes); + return new PrimitiveEncoding(tagClass, tagNo, bytes); } protected override bool Asn1Equals(Asn1Object asn1Object) diff --git a/crypto/src/asn1/DerGeneralString.cs b/crypto/src/asn1/DerGeneralString.cs index f5575650b..f2a47c370 100644 --- a/crypto/src/asn1/DerGeneralString.cs +++ b/crypto/src/asn1/DerGeneralString.cs @@ -61,19 +61,14 @@ namespace Org.BouncyCastle.Asn1 return Strings.ToAsciiByteArray(str); } - internal override bool EncodeConstructed(int encoding) + internal override IAsn1Encoding GetEncoding(int encoding) { - return false; + return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.GeneralString, GetOctets()); } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - return Asn1OutputStream.GetLengthOfEncodingDL(withID, str.Length); - } - - internal override void Encode(Asn1OutputStream asn1Out, bool withID) - { - asn1Out.WriteEncodingDL(withID, Asn1Tags.GeneralString, GetOctets()); + return new PrimitiveEncoding(tagClass, tagNo, GetOctets()); } protected override bool Asn1Equals( diff --git a/crypto/src/asn1/DerGeneralizedTime.cs b/crypto/src/asn1/DerGeneralizedTime.cs index e70a481dc..41c897751 100644 --- a/crypto/src/asn1/DerGeneralizedTime.cs +++ b/crypto/src/asn1/DerGeneralizedTime.cs @@ -295,19 +295,14 @@ namespace Org.BouncyCastle.Asn1 return Strings.ToAsciiByteArray(time); } - internal override bool EncodeConstructed(int encoding) + internal override IAsn1Encoding GetEncoding(int encoding) { - return false; + return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.GeneralizedTime, GetOctets()); } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - return Asn1OutputStream.GetLengthOfEncodingDL(withID, time.Length); - } - - internal override void Encode(Asn1OutputStream asn1Out, bool withID) - { - asn1Out.WriteEncodingDL(withID, Asn1Tags.GeneralizedTime, GetOctets()); + return new PrimitiveEncoding(tagClass, tagNo, GetOctets()); } protected override bool Asn1Equals( diff --git a/crypto/src/asn1/DerGraphicString.cs b/crypto/src/asn1/DerGraphicString.cs index 4a864ea8c..52ccb7e93 100644 --- a/crypto/src/asn1/DerGraphicString.cs +++ b/crypto/src/asn1/DerGraphicString.cs @@ -83,19 +83,14 @@ namespace Org.BouncyCastle.Asn1 return Arrays.Clone(m_contents); } - internal override bool EncodeConstructed(int encoding) + internal override IAsn1Encoding GetEncoding(int encoding) { - return false; + return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.GraphicString, m_contents); } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - return Asn1OutputStream.GetLengthOfEncodingDL(withID, m_contents.Length); - } - - internal override void Encode(Asn1OutputStream asn1Out, bool withID) - { - asn1Out.WriteEncodingDL(withID, Asn1Tags.GraphicString, m_contents); + return new PrimitiveEncoding(tagClass, tagNo, m_contents); } protected override int Asn1GetHashCode() diff --git a/crypto/src/asn1/DerIA5String.cs b/crypto/src/asn1/DerIA5String.cs index 97a9222c2..d608930fd 100644 --- a/crypto/src/asn1/DerIA5String.cs +++ b/crypto/src/asn1/DerIA5String.cs @@ -100,19 +100,14 @@ namespace Org.BouncyCastle.Asn1 return Strings.ToAsciiByteArray(str); } - internal override bool EncodeConstructed(int encoding) + internal override IAsn1Encoding GetEncoding(int encoding) { - return false; + return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.IA5String, GetOctets()); } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - return Asn1OutputStream.GetLengthOfEncodingDL(withID, str.Length); - } - - internal override void Encode(Asn1OutputStream asn1Out, bool withID) - { - asn1Out.WriteEncodingDL(withID, Asn1Tags.IA5String, GetOctets()); + return new PrimitiveEncoding(tagClass, tagNo, GetOctets()); } protected override int Asn1GetHashCode() diff --git a/crypto/src/asn1/DerInteger.cs b/crypto/src/asn1/DerInteger.cs index 36fd58870..8b112f693 100644 --- a/crypto/src/asn1/DerInteger.cs +++ b/crypto/src/asn1/DerInteger.cs @@ -169,19 +169,14 @@ namespace Org.BouncyCastle.Asn1 } } - internal override bool EncodeConstructed(int encoding) + internal override IAsn1Encoding GetEncoding(int encoding) { - return false; + return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.Integer, bytes); } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - return Asn1OutputStream.GetLengthOfEncodingDL(withID, bytes.Length); - } - - internal override void Encode(Asn1OutputStream asn1Out, bool withID) - { - asn1Out.WriteEncodingDL(withID, Asn1Tags.Integer, bytes); + return new PrimitiveEncoding(tagClass, tagNo, bytes); } protected override int Asn1GetHashCode() diff --git a/crypto/src/asn1/DerNull.cs b/crypto/src/asn1/DerNull.cs index 947acaf0b..ddf61391b 100644 --- a/crypto/src/asn1/DerNull.cs +++ b/crypto/src/asn1/DerNull.cs @@ -16,19 +16,14 @@ namespace Org.BouncyCastle.Asn1 { } - internal override bool EncodeConstructed(int encoding) + internal override IAsn1Encoding GetEncoding(int encoding) { - return false; + return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.Null, ZeroBytes); } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - return Asn1OutputStream.GetLengthOfEncodingDL(withID, 0); - } - - internal override void Encode(Asn1OutputStream asn1Out, bool withID) - { - asn1Out.WriteEncodingDL(withID, Asn1Tags.Null, ZeroBytes); + return new PrimitiveEncoding(tagClass, tagNo, ZeroBytes); } protected override bool Asn1Equals(Asn1Object asn1Object) diff --git a/crypto/src/asn1/DerNumericString.cs b/crypto/src/asn1/DerNumericString.cs index 4412f973e..bec0c3a52 100644 --- a/crypto/src/asn1/DerNumericString.cs +++ b/crypto/src/asn1/DerNumericString.cs @@ -100,19 +100,14 @@ namespace Org.BouncyCastle.Asn1 return Strings.ToAsciiByteArray(str); } - internal override bool EncodeConstructed(int encoding) + internal override IAsn1Encoding GetEncoding(int encoding) { - return false; + return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.NumericString, GetOctets()); } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - return Asn1OutputStream.GetLengthOfEncodingDL(withID, str.Length); - } - - internal override void Encode(Asn1OutputStream asn1Out, bool withID) - { - asn1Out.WriteEncodingDL(withID, Asn1Tags.NumericString, GetOctets()); + return new PrimitiveEncoding(tagClass, tagNo, GetOctets()); } protected override bool Asn1Equals( diff --git a/crypto/src/asn1/DerObjectIdentifier.cs b/crypto/src/asn1/DerObjectIdentifier.cs index f24bbf984..f91ad2150 100644 --- a/crypto/src/asn1/DerObjectIdentifier.cs +++ b/crypto/src/asn1/DerObjectIdentifier.cs @@ -128,19 +128,14 @@ namespace Org.BouncyCastle.Asn1 return identifier.GetHashCode(); } - internal override bool EncodeConstructed(int encoding) + internal override IAsn1Encoding GetEncoding(int encoding) { - return false; + return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.ObjectIdentifier, GetContents()); } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - return Asn1OutputStream.GetLengthOfEncodingDL(withID, GetContents().Length); - } - - internal override void Encode(Asn1OutputStream asn1Out, bool withID) - { - asn1Out.WriteEncodingDL(withID, Asn1Tags.ObjectIdentifier, GetContents()); + return new PrimitiveEncoding(tagClass, tagNo, GetContents()); } private void DoOutput(MemoryStream bOut) diff --git a/crypto/src/asn1/DerOctetString.cs b/crypto/src/asn1/DerOctetString.cs index d49393641..d9913f065 100644 --- a/crypto/src/asn1/DerOctetString.cs +++ b/crypto/src/asn1/DerOctetString.cs @@ -21,29 +21,21 @@ namespace Org.BouncyCastle.Asn1 { } - internal override bool EncodeConstructed(int encoding) + internal override IAsn1Encoding GetEncoding(int encoding) { - return false; + return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.OctetString, contents); } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - return Asn1OutputStream.GetLengthOfEncodingDL(withID, contents.Length); + return new PrimitiveEncoding(tagClass, tagNo, contents); } - internal override void Encode(Asn1OutputStream asn1Out, bool withID) - { - asn1Out.WriteEncodingDL(withID, Asn1Tags.OctetString, contents); - } - - internal static void Encode(Asn1OutputStream asn1Out, bool withID, byte[] buf, int off, int len) + internal static void Encode(Asn1OutputStream asn1Out, byte[] buf, int off, int len) { - asn1Out.WriteEncodingDL(withID, Asn1Tags.OctetString, buf, off, len); - } - - internal static int EncodedLength(bool withID, int contentsLength) - { - return Asn1OutputStream.GetLengthOfEncodingDL(withID, contentsLength); + asn1Out.WriteIdentifier(Asn1Tags.Universal, Asn1Tags.OctetString); + asn1Out.WriteDL(len); + asn1Out.Write(buf, off, len); } } } diff --git a/crypto/src/asn1/DerOutputStream.cs b/crypto/src/asn1/DerOutputStream.cs index dda9ce1c0..4c7dd1fd7 100644 --- a/crypto/src/asn1/DerOutputStream.cs +++ b/crypto/src/asn1/DerOutputStream.cs @@ -34,11 +34,6 @@ namespace Org.BouncyCastle.Asn1 { } - internal override DerOutputStreamNew GetDerSubStream() - { - return this; - } - internal override int Encoding { get { return EncodingDer; } diff --git a/crypto/src/asn1/DerPrintableString.cs b/crypto/src/asn1/DerPrintableString.cs index 3d911a6ac..30358e219 100644 --- a/crypto/src/asn1/DerPrintableString.cs +++ b/crypto/src/asn1/DerPrintableString.cs @@ -99,19 +99,14 @@ namespace Org.BouncyCastle.Asn1 return Strings.ToAsciiByteArray(str); } - internal override bool EncodeConstructed(int encoding) + internal override IAsn1Encoding GetEncoding(int encoding) { - return false; + return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.PrintableString, GetOctets()); } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - return Asn1OutputStream.GetLengthOfEncodingDL(withID, str.Length); - } - - internal override void Encode(Asn1OutputStream asn1Out, bool withID) - { - asn1Out.WriteEncodingDL(withID, Asn1Tags.PrintableString, GetOctets()); + return new PrimitiveEncoding(tagClass, tagNo, GetOctets()); } protected override bool Asn1Equals( diff --git a/crypto/src/asn1/DerSequence.cs b/crypto/src/asn1/DerSequence.cs index e60796091..2ac977fe0 100644 --- a/crypto/src/asn1/DerSequence.cs +++ b/crypto/src/asn1/DerSequence.cs @@ -12,8 +12,6 @@ namespace Org.BouncyCastle.Asn1 return elementVector.Count < 1 ? Empty : new DerSequence(elementVector); } - private int m_contentsLengthDer = -1; - /** * create an empty sequence */ @@ -48,56 +46,16 @@ namespace Org.BouncyCastle.Asn1 { } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncoding(int encoding) { - return Asn1OutputStream.GetLengthOfEncodingDL(withID, GetContentsLengthDer()); + return new ConstructedDLEncoding(Asn1Tags.Universal, Asn1Tags.Sequence, + Asn1OutputStream.GetContentsEncodings(Asn1OutputStream.EncodingDer, elements)); } - /* - * A note on the implementation: - *

- * As Der requires the constructed, definite-length model to - * be used for structured types, this varies slightly from the - * ASN.1 descriptions given. Rather than just outputing Sequence, - * we also have to specify Constructed, and the objects length. - */ - internal override void Encode(Asn1OutputStream asn1Out, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - asn1Out = asn1Out.GetDerSubStream(); - - asn1Out.WriteIdentifier(withID, Asn1Tags.Constructed | Asn1Tags.Sequence); - - int count = elements.Length; - if (m_contentsLengthDer >= 0 || count > 16) - { - asn1Out.WriteDL(GetContentsLengthDer()); - - for (int i = 0; i < count; ++i) - { - Asn1Object asn1Object = elements[i].ToAsn1Object(); - asn1Object.Encode(asn1Out, true); - } - } - else - { - int contentsLength = 0; - - Asn1Object[] asn1Objects = new Asn1Object[count]; - for (int i = 0; i < count; ++i) - { - Asn1Object asn1Object = elements[i].ToAsn1Object(); - asn1Objects[i] = asn1Object; - contentsLength += asn1Object.EncodedLength(asn1Out.Encoding, true); - } - - this.m_contentsLengthDer = contentsLength; - asn1Out.WriteDL(contentsLength); - - for (int i = 0; i < count; ++i) - { - asn1Objects[i].Encode(asn1Out, true); - } - } + return new ConstructedDLEncoding(tagClass, tagNo, + Asn1OutputStream.GetContentsEncodings(Asn1OutputStream.EncodingDer, elements)); } internal override DerBitString ToAsn1BitString() @@ -120,14 +78,5 @@ namespace Org.BouncyCastle.Asn1 // NOTE: DLSet is intentional, we don't want sorting return new DLSet(false, elements); } - - private int GetContentsLengthDer() - { - if (m_contentsLengthDer < 0) - { - m_contentsLengthDer = CalculateContentsLength(Asn1OutputStream.EncodingDer); - } - return m_contentsLengthDer; - } } } diff --git a/crypto/src/asn1/DerSet.cs b/crypto/src/asn1/DerSet.cs index d89285d9e..3e52094c3 100644 --- a/crypto/src/asn1/DerSet.cs +++ b/crypto/src/asn1/DerSet.cs @@ -15,8 +15,6 @@ namespace Org.BouncyCastle.Asn1 return elementVector.Count < 1 ? Empty : new DerSet(elementVector); } - private int m_contentsLengthDer = -1; - /** * create an empty set */ @@ -61,88 +59,31 @@ namespace Org.BouncyCastle.Asn1 { } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncoding(int encoding) { - encoding = Asn1OutputStream.EncodingDer; - - int count = elements.Length; - int contentsLength = 0; - - for (int i = 0; i < count; ++i) - { - Asn1Object asn1Object = elements[i].ToAsn1Object(); - contentsLength += asn1Object.EncodedLength(encoding, true); - } - - return Asn1OutputStream.GetLengthOfEncodingDL(withID, contentsLength); + return new ConstructedDLEncoding(Asn1Tags.Universal, Asn1Tags.Set, + Asn1OutputStream.GetContentsEncodings(Asn1OutputStream.EncodingDer, GetSortedElements())); } - /* - * A note on the implementation: - *

- * As Der requires the constructed, definite-length model to - * be used for structured types, this varies slightly from the - * ASN.1 descriptions given. Rather than just outputing Set, - * we also have to specify Constructed, and the objects length. - */ - internal override void Encode(Asn1OutputStream asn1Out, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - if (Count < 1) - { - asn1Out.WriteEncodingDL(withID, Asn1Tags.Constructed | Asn1Tags.Set, Asn1OctetString.EmptyOctets); - return; - } - - Asn1Encodable[] elements = this.elements; - if (!isSorted) - { - elements = Sort((Asn1Encodable[])elements.Clone()); - } - - asn1Out = asn1Out.GetDerSubStream(); + return new ConstructedDLEncoding(tagClass, tagNo, + Asn1OutputStream.GetContentsEncodings(Asn1OutputStream.EncodingDer, GetSortedElements())); + } - asn1Out.WriteIdentifier(withID, Asn1Tags.Constructed | Asn1Tags.Set); + private Asn1Encodable[] GetSortedElements() + { + if (isSorted) + return elements; int count = elements.Length; - if (m_contentsLengthDer >= 0 || count > 16) - { - asn1Out.WriteDL(GetContentsLengthDer()); - - for (int i = 0; i < count; ++i) - { - Asn1Object asn1Object = elements[i].ToAsn1Object(); - asn1Object.Encode(asn1Out, true); - } - } - else + Asn1Object[] asn1Objects = new Asn1Object[count]; + for (int i = 0; i < count; ++i) { - int contentsLength = 0; - - Asn1Object[] asn1Objects = new Asn1Object[count]; - for (int i = 0; i < count; ++i) - { - Asn1Object asn1Object = elements[i].ToAsn1Object(); - asn1Objects[i] = asn1Object; - contentsLength += asn1Object.EncodedLength(asn1Out.Encoding, true); - } - - this.m_contentsLengthDer = contentsLength; - asn1Out.WriteDL(contentsLength); - - for (int i = 0; i < count; ++i) - { - asn1Objects[i].Encode(asn1Out, true); - } + asn1Objects[i] = elements[i].ToAsn1Object(); } - } - private int GetContentsLengthDer() - { - if (m_contentsLengthDer < 0) - { - m_contentsLengthDer = CalculateContentsLength(Asn1OutputStream.EncodingDer); - } - return m_contentsLengthDer; + return Sort(asn1Objects); } } } diff --git a/crypto/src/asn1/DerT61String.cs b/crypto/src/asn1/DerT61String.cs index 79a7ef8e4..64a9bd469 100644 --- a/crypto/src/asn1/DerT61String.cs +++ b/crypto/src/asn1/DerT61String.cs @@ -77,19 +77,14 @@ namespace Org.BouncyCastle.Asn1 return str; } - internal override bool EncodeConstructed(int encoding) + internal override IAsn1Encoding GetEncoding(int encoding) { - return false; + return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.T61String, GetOctets()); } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - return Asn1OutputStream.GetLengthOfEncodingDL(withID, str.Length); - } - - internal override void Encode(Asn1OutputStream asn1Out, bool withID) - { - asn1Out.WriteEncodingDL(withID, Asn1Tags.T61String, GetOctets()); + return new PrimitiveEncoding(tagClass, tagNo, GetOctets()); } public byte[] GetOctets() diff --git a/crypto/src/asn1/DerTaggedObject.cs b/crypto/src/asn1/DerTaggedObject.cs index 66f804ebb..68a32e435 100644 --- a/crypto/src/asn1/DerTaggedObject.cs +++ b/crypto/src/asn1/DerTaggedObject.cs @@ -10,8 +10,6 @@ namespace Org.BouncyCastle.Asn1 public class DerTaggedObject : Asn1TaggedObject { - private int m_contentsLengthDer = -1; - /** * create an implicitly tagged object that contains a zero * length sequence. @@ -57,56 +55,28 @@ namespace Org.BouncyCastle.Asn1 get { return Der; } } - internal override bool EncodeConstructed(int encoding) - { - encoding = Asn1OutputStream.EncodingDer; - - return IsExplicit() || GetBaseObject().ToAsn1Object().EncodeConstructed(encoding); - } - - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncoding(int encoding) { encoding = Asn1OutputStream.EncodingDer; Asn1Object baseObject = GetBaseObject().ToAsn1Object(); - bool withBaseID = IsExplicit(); - - int length = GetContentsLengthDer(baseObject, withBaseID); - if (withBaseID) - { - length += Asn1OutputStream.GetLengthOfDL(length); - } + if (!IsExplicit()) + return baseObject.GetEncodingImplicit(encoding, TagClass, TagNo); - length += withID ? Asn1OutputStream.GetLengthOfIdentifier(TagNo) : 0; - - return length; + return new ConstructedDLEncoding(TagClass, TagNo, new IAsn1Encoding[]{ baseObject.GetEncoding(encoding) }); } - internal override void Encode(Asn1OutputStream asn1Out, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - asn1Out = asn1Out.GetDerSubStream(); + encoding = Asn1OutputStream.EncodingDer; Asn1Object baseObject = GetBaseObject().ToAsn1Object(); - bool withBaseID = IsExplicit(); - - if (withID) - { - int flags = TagClass; - if (withBaseID || baseObject.EncodeConstructed(asn1Out.Encoding)) - { - flags |= Asn1Tags.Constructed; - } - - asn1Out.WriteIdentifier(true, flags, TagNo); - } - if (withBaseID) - { - asn1Out.WriteDL(GetContentsLengthDer(baseObject, true)); - } + if (!IsExplicit()) + return baseObject.GetEncodingImplicit(encoding, tagClass, tagNo); - baseObject.Encode(asn1Out, withBaseID); + return new ConstructedDLEncoding(tagClass, tagNo, new IAsn1Encoding[]{ baseObject.GetEncoding(encoding) }); } internal override Asn1Sequence RebuildConstructed(Asn1Object asn1Object) @@ -118,14 +88,5 @@ namespace Org.BouncyCastle.Asn1 { return new DerTaggedObject(explicitness, tagClass, tagNo, obj); } - - private int GetContentsLengthDer(Asn1Object baseObject, bool withBaseID) - { - if (m_contentsLengthDer < 0) - { - m_contentsLengthDer = baseObject.EncodedLength(Asn1OutputStream.EncodingDer, withBaseID); - } - return m_contentsLengthDer; - } } } diff --git a/crypto/src/asn1/DerUTCTime.cs b/crypto/src/asn1/DerUTCTime.cs index 17d02df19..eaa902e71 100644 --- a/crypto/src/asn1/DerUTCTime.cs +++ b/crypto/src/asn1/DerUTCTime.cs @@ -237,19 +237,14 @@ namespace Org.BouncyCastle.Asn1 return Strings.ToAsciiByteArray(time); } - internal override bool EncodeConstructed(int encoding) + internal override IAsn1Encoding GetEncoding(int encoding) { - return false; + return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.UtcTime, GetOctets()); } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - return Asn1OutputStream.GetLengthOfEncodingDL(withID, time.Length); - } - - internal override void Encode(Asn1OutputStream asn1Out, bool withID) - { - asn1Out.WriteEncodingDL(withID, Asn1Tags.UtcTime, GetOctets()); + return new PrimitiveEncoding(tagClass, tagNo, GetOctets()); } protected override bool Asn1Equals( diff --git a/crypto/src/asn1/DerUTF8String.cs b/crypto/src/asn1/DerUTF8String.cs index 7bc9ff524..24023cd6c 100644 --- a/crypto/src/asn1/DerUTF8String.cs +++ b/crypto/src/asn1/DerUTF8String.cs @@ -89,19 +89,14 @@ namespace Org.BouncyCastle.Asn1 return this.str.Equals(other.str); } - internal override bool EncodeConstructed(int encoding) + internal override IAsn1Encoding GetEncoding(int encoding) { - return false; + return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.Utf8String, Encoding.UTF8.GetBytes(str)); } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - return Asn1OutputStream.GetLengthOfEncodingDL(withID, Encoding.UTF8.GetByteCount(str)); - } - - internal override void Encode(Asn1OutputStream asn1Out, bool withID) - { - asn1Out.WriteEncodingDL(withID, Asn1Tags.Utf8String, Encoding.UTF8.GetBytes(str)); + return new PrimitiveEncoding(tagClass, tagNo, Encoding.UTF8.GetBytes(str)); } } } diff --git a/crypto/src/asn1/DerUniversalString.cs b/crypto/src/asn1/DerUniversalString.cs index ab89a0e12..1ae989f93 100644 --- a/crypto/src/asn1/DerUniversalString.cs +++ b/crypto/src/asn1/DerUniversalString.cs @@ -86,19 +86,14 @@ namespace Org.BouncyCastle.Asn1 return (byte[]) str.Clone(); } - internal override bool EncodeConstructed(int encoding) + internal override IAsn1Encoding GetEncoding(int encoding) { - return false; + return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.UniversalString, this.str); } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - return Asn1OutputStream.GetLengthOfEncodingDL(withID, this.str.Length); - } - - internal override void Encode(Asn1OutputStream asn1Out, bool withID) - { - asn1Out.WriteEncodingDL(withID, Asn1Tags.UniversalString, this.str); + return new PrimitiveEncoding(tagClass, tagNo, this.str); } protected override bool Asn1Equals( diff --git a/crypto/src/asn1/DerVideotexString.cs b/crypto/src/asn1/DerVideotexString.cs index 5b9ad09f9..3511663d2 100644 --- a/crypto/src/asn1/DerVideotexString.cs +++ b/crypto/src/asn1/DerVideotexString.cs @@ -79,19 +79,14 @@ namespace Org.BouncyCastle.Asn1 return Arrays.Clone(mString); } - internal override bool EncodeConstructed(int encoding) + internal override IAsn1Encoding GetEncoding(int encoding) { - return false; + return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.VideotexString, mString); } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - return Asn1OutputStream.GetLengthOfEncodingDL(withID, mString.Length); - } - - internal override void Encode(Asn1OutputStream asn1Out, bool withID) - { - asn1Out.WriteEncodingDL(withID, Asn1Tags.VideotexString, mString); + return new PrimitiveEncoding(tagClass, tagNo, mString); } protected override int Asn1GetHashCode() diff --git a/crypto/src/asn1/DerVisibleString.cs b/crypto/src/asn1/DerVisibleString.cs index 9e34ef65e..cbbd9cc98 100644 --- a/crypto/src/asn1/DerVisibleString.cs +++ b/crypto/src/asn1/DerVisibleString.cs @@ -86,19 +86,14 @@ namespace Org.BouncyCastle.Asn1 return Strings.ToAsciiByteArray(str); } - internal override bool EncodeConstructed(int encoding) + internal override IAsn1Encoding GetEncoding(int encoding) { - return false; + return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.VisibleString, GetOctets()); } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - return Asn1OutputStream.GetLengthOfEncodingDL(withID, str.Length); - } - - internal override void Encode(Asn1OutputStream asn1Out, bool withID) - { - asn1Out.WriteEncodingDL(withID, Asn1Tags.VisibleString, GetOctets()); + return new PrimitiveEncoding(tagClass, tagNo, GetOctets()); } protected override bool Asn1Equals( diff --git a/crypto/src/asn1/IAsn1Encoding.cs b/crypto/src/asn1/IAsn1Encoding.cs new file mode 100644 index 000000000..557064af8 --- /dev/null +++ b/crypto/src/asn1/IAsn1Encoding.cs @@ -0,0 +1,11 @@ +using System; + +namespace Org.BouncyCastle.Asn1 +{ + internal interface IAsn1Encoding + { + void Encode(Asn1OutputStream asn1Out); + + int GetLength(); + } +} diff --git a/crypto/src/asn1/LazyDLSequence.cs b/crypto/src/asn1/LazyDLSequence.cs index bf9fc0800..96b9bbca1 100644 --- a/crypto/src/asn1/LazyDLSequence.cs +++ b/crypto/src/asn1/LazyDLSequence.cs @@ -63,39 +63,36 @@ namespace Org.BouncyCastle.Asn1 return base.ToString(); } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncoding(int encoding) { if (Asn1OutputStream.EncodingBer == encoding) { byte[] encoded = GetContents(); - if (null != encoded) - return Asn1OutputStream.GetLengthOfEncodingDL(withID, encoded.Length); + if (encoded != null) + return new ConstructedLazyDLEncoding(Asn1Tags.Universal, Asn1Tags.Sequence, encoded); } else { Force(); } - return base.EncodedLength(encoding, withID); + return base.GetEncoding(encoding); } - internal override void Encode(Asn1OutputStream asn1Out, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - if (Asn1OutputStream.EncodingBer == asn1Out.Encoding) + if (Asn1OutputStream.EncodingBer == encoding) { byte[] encoded = GetContents(); if (encoded != null) - { - asn1Out.WriteEncodingDL(withID, Asn1Tags.Constructed | Asn1Tags.Sequence, encoded); - return; - } + return new ConstructedLazyDLEncoding(tagClass, tagNo, encoded); } else { Force(); } - base.Encode(asn1Out, withID); + return base.GetEncodingImplicit(encoding, tagClass, tagNo); } private void Force() diff --git a/crypto/src/asn1/LazyDLSet.cs b/crypto/src/asn1/LazyDLSet.cs index a426bb4cb..551200513 100644 --- a/crypto/src/asn1/LazyDLSet.cs +++ b/crypto/src/asn1/LazyDLSet.cs @@ -32,9 +32,7 @@ namespace Org.BouncyCastle.Asn1 { byte[] encoded = GetContents(); if (null != encoded) - { return new LazyDLEnumerator(encoded); - } return base.GetEnumerator(); } @@ -63,39 +61,36 @@ namespace Org.BouncyCastle.Asn1 return base.ToString(); } - internal override int EncodedLength(int encoding, bool withID) + internal override IAsn1Encoding GetEncoding(int encoding) { if (Asn1OutputStream.EncodingBer == encoding) { byte[] encoded = GetContents(); if (null != encoded) - return Asn1OutputStream.GetLengthOfEncodingDL(withID, encoded.Length); + return new ConstructedLazyDLEncoding(Asn1Tags.Universal, Asn1Tags.Set, encoded); } else { Force(); } - return base.EncodedLength(encoding, withID); + return base.GetEncoding(encoding); } - internal override void Encode(Asn1OutputStream asn1Out, bool withID) + internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) { - if (Asn1OutputStream.EncodingBer == asn1Out.Encoding) + if (Asn1OutputStream.EncodingBer == encoding) { byte[] encoded = GetContents(); - if (encoded != null) - { - asn1Out.WriteEncodingDL(withID, Asn1Tags.Constructed | Asn1Tags.Set, encoded); - return; - } + if (null != encoded) + return new ConstructedLazyDLEncoding(tagClass, tagNo, encoded); } else { Force(); } - base.Encode(asn1Out, withID); + return base.GetEncodingImplicit(encoding, tagClass, tagNo); } private void Force() diff --git a/crypto/src/asn1/PrimitiveEncoding.cs b/crypto/src/asn1/PrimitiveEncoding.cs new file mode 100644 index 000000000..72c3219ef --- /dev/null +++ b/crypto/src/asn1/PrimitiveEncoding.cs @@ -0,0 +1,33 @@ +using System; + +namespace Org.BouncyCastle.Asn1 +{ + internal class PrimitiveEncoding + : IAsn1Encoding + { + private readonly int m_tagClass; + private readonly int m_tagNo; + private readonly byte[] m_contentsOctets; + + internal PrimitiveEncoding(int tagClass, int tagNo, byte[] contentsOctets) + { + m_tagClass = tagClass; + m_tagNo = tagNo; + m_contentsOctets = contentsOctets; + } + + void IAsn1Encoding.Encode(Asn1OutputStream asn1Out) + { + asn1Out.WriteIdentifier(m_tagClass, m_tagNo); + asn1Out.WriteDL(m_contentsOctets.Length); + asn1Out.Write(m_contentsOctets, 0, m_contentsOctets.Length); + } + + int IAsn1Encoding.GetLength() + { + return Asn1OutputStream.GetLengthOfIdentifier(m_tagNo) + + Asn1OutputStream.GetLengthOfDL(m_contentsOctets.Length) + + m_contentsOctets.Length; + } + } +} diff --git a/crypto/src/asn1/PrimitiveEncodingSuffixed.cs b/crypto/src/asn1/PrimitiveEncodingSuffixed.cs new file mode 100644 index 000000000..ef0ef49ac --- /dev/null +++ b/crypto/src/asn1/PrimitiveEncodingSuffixed.cs @@ -0,0 +1,36 @@ +using System; + +namespace Org.BouncyCastle.Asn1 +{ + internal class PrimitiveEncodingSuffixed + : IAsn1Encoding + { + private readonly int m_tagClass; + private readonly int m_tagNo; + private readonly byte[] m_contentsOctets; + private readonly byte m_contentsSuffix; + + internal PrimitiveEncodingSuffixed(int tagClass, int tagNo, byte[] contentsOctets, byte contentsSuffix) + { + m_tagClass = tagClass; + m_tagNo = tagNo; + m_contentsOctets = contentsOctets; + m_contentsSuffix = contentsSuffix; + } + + void IAsn1Encoding.Encode(Asn1OutputStream asn1Out) + { + asn1Out.WriteIdentifier(m_tagClass, m_tagNo); + asn1Out.WriteDL(m_contentsOctets.Length); + asn1Out.Write(m_contentsOctets, 0, m_contentsOctets.Length - 1); + asn1Out.WriteByte(m_contentsSuffix); + } + + int IAsn1Encoding.GetLength() + { + return Asn1OutputStream.GetLengthOfIdentifier(m_tagNo) + + Asn1OutputStream.GetLengthOfDL(m_contentsOctets.Length) + + m_contentsOctets.Length; + } + } +} -- cgit 1.4.1