From 4d9ade7d08091fdfad3bcaf56f75612267d023b3 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Tue, 18 Jul 2023 13:40:07 +0700 Subject: Custom encoding classes for tagged objects --- crypto/src/asn1/Asn1OutputStream.cs | 5 +++++ crypto/src/asn1/BerTaggedObject.cs | 4 ++-- crypto/src/asn1/DLTaggedObject.cs | 4 ++-- crypto/src/asn1/DerTaggedObject.cs | 8 +++---- crypto/src/asn1/TaggedDLEncoding.cs | 33 +++++++++++++++++++++++++++ crypto/src/asn1/TaggedDerEncoding.cs | 43 ++++++++++++++++++++++++++++++++++++ crypto/src/asn1/TaggedILEncoding.cs | 33 +++++++++++++++++++++++++++ 7 files changed, 122 insertions(+), 8 deletions(-) create mode 100644 crypto/src/asn1/TaggedDLEncoding.cs create mode 100644 crypto/src/asn1/TaggedDerEncoding.cs create mode 100644 crypto/src/asn1/TaggedILEncoding.cs diff --git a/crypto/src/asn1/Asn1OutputStream.cs b/crypto/src/asn1/Asn1OutputStream.cs index 5fd36aa42..86006877b 100644 --- a/crypto/src/asn1/Asn1OutputStream.cs +++ b/crypto/src/asn1/Asn1OutputStream.cs @@ -220,6 +220,11 @@ namespace Org.BouncyCastle.Asn1 return GetLengthOfIdentifier(tagNo) + GetLengthOfDL(contentsLength) + contentsLength; } + internal static int GetLengthOfEncodingIL(int tagNo, IAsn1Encoding contentsEncoding) + { + return GetLengthOfIdentifier(tagNo) + 3 + contentsEncoding.GetLength(); + } + internal static int GetLengthOfEncodingIL(int tagNo, IAsn1Encoding[] contentsEncodings) { return GetLengthOfIdentifier(tagNo) + 3 + GetLengthOfContents(contentsEncodings); diff --git a/crypto/src/asn1/BerTaggedObject.cs b/crypto/src/asn1/BerTaggedObject.cs index c200a74de..f3d12fdda 100644 --- a/crypto/src/asn1/BerTaggedObject.cs +++ b/crypto/src/asn1/BerTaggedObject.cs @@ -59,7 +59,7 @@ namespace Org.BouncyCastle.Asn1 if (!IsExplicit()) return baseObject.GetEncodingImplicit(encoding, TagClass, TagNo); - return new ConstructedILEncoding(TagClass, TagNo, new IAsn1Encoding[]{ baseObject.GetEncoding(encoding) }); + return new TaggedILEncoding(TagClass, TagNo, baseObject.GetEncoding(encoding)); } internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) @@ -72,7 +72,7 @@ namespace Org.BouncyCastle.Asn1 if (!IsExplicit()) return baseObject.GetEncodingImplicit(encoding, tagClass, tagNo); - return new ConstructedILEncoding(tagClass, tagNo, new IAsn1Encoding[]{ baseObject.GetEncoding(encoding) }); + return new TaggedILEncoding(tagClass, tagNo, baseObject.GetEncoding(encoding)); } internal override Asn1Sequence RebuildConstructed(Asn1Object asn1Object) diff --git a/crypto/src/asn1/DLTaggedObject.cs b/crypto/src/asn1/DLTaggedObject.cs index 30e3334e2..09a370690 100644 --- a/crypto/src/asn1/DLTaggedObject.cs +++ b/crypto/src/asn1/DLTaggedObject.cs @@ -46,7 +46,7 @@ namespace Org.BouncyCastle.Asn1 if (!IsExplicit()) return baseObject.GetEncodingImplicit(encoding, TagClass, TagNo); - return new ConstructedDLEncoding(TagClass, TagNo, new IAsn1Encoding[]{ baseObject.GetEncoding(encoding) }); + return new TaggedDLEncoding(TagClass, TagNo, baseObject.GetEncoding(encoding)); } internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) @@ -59,7 +59,7 @@ namespace Org.BouncyCastle.Asn1 if (!IsExplicit()) return baseObject.GetEncodingImplicit(encoding, tagClass, tagNo); - return new ConstructedDLEncoding(tagClass, tagNo, new IAsn1Encoding[]{ baseObject.GetEncoding(encoding) }); + return new TaggedDLEncoding(tagClass, tagNo, baseObject.GetEncoding(encoding)); } internal override Asn1Sequence RebuildConstructed(Asn1Object asn1Object) diff --git a/crypto/src/asn1/DerTaggedObject.cs b/crypto/src/asn1/DerTaggedObject.cs index 3e8067c0c..2cbe22445 100644 --- a/crypto/src/asn1/DerTaggedObject.cs +++ b/crypto/src/asn1/DerTaggedObject.cs @@ -54,7 +54,7 @@ namespace Org.BouncyCastle.Asn1 if (!IsExplicit()) return baseObject.GetEncodingImplicit(encoding, TagClass, TagNo); - return new ConstructedDLEncoding(TagClass, TagNo, new IAsn1Encoding[]{ baseObject.GetEncoding(encoding) }); + return new TaggedDLEncoding(TagClass, TagNo, baseObject.GetEncoding(encoding)); } internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo) @@ -66,7 +66,7 @@ namespace Org.BouncyCastle.Asn1 if (!IsExplicit()) return baseObject.GetEncodingImplicit(encoding, tagClass, tagNo); - return new ConstructedDLEncoding(tagClass, tagNo, new IAsn1Encoding[]{ baseObject.GetEncoding(encoding) }); + return new TaggedDLEncoding(tagClass, tagNo, baseObject.GetEncoding(encoding)); } internal sealed override DerEncoding GetEncodingDer() @@ -76,7 +76,7 @@ namespace Org.BouncyCastle.Asn1 if (!IsExplicit()) return baseObject.GetEncodingDerImplicit(TagClass, TagNo); - return new ConstructedDerEncoding(TagClass, TagNo, new DerEncoding[]{ baseObject.GetEncodingDer() }); + return new TaggedDerEncoding(TagClass, TagNo, baseObject.GetEncodingDer()); } internal sealed override DerEncoding GetEncodingDerImplicit(int tagClass, int tagNo) @@ -86,7 +86,7 @@ namespace Org.BouncyCastle.Asn1 if (!IsExplicit()) return baseObject.GetEncodingDerImplicit(tagClass, tagNo); - return new ConstructedDerEncoding(tagClass, tagNo, new DerEncoding[]{ baseObject.GetEncodingDer() }); + return new TaggedDerEncoding(tagClass, tagNo, baseObject.GetEncodingDer()); } internal override Asn1Sequence RebuildConstructed(Asn1Object asn1Object) diff --git a/crypto/src/asn1/TaggedDLEncoding.cs b/crypto/src/asn1/TaggedDLEncoding.cs new file mode 100644 index 000000000..dd85045ea --- /dev/null +++ b/crypto/src/asn1/TaggedDLEncoding.cs @@ -0,0 +1,33 @@ +using System; + +namespace Org.BouncyCastle.Asn1 +{ + internal class TaggedDLEncoding + : IAsn1Encoding + { + private readonly int m_tagClass; + private readonly int m_tagNo; + private readonly IAsn1Encoding m_contentsElement; + private readonly int m_contentsLength; + + internal TaggedDLEncoding(int tagClass, int tagNo, IAsn1Encoding contentsElement) + { + m_tagClass = tagClass; + m_tagNo = tagNo; + m_contentsElement = contentsElement; + m_contentsLength = contentsElement.GetLength(); + } + + void IAsn1Encoding.Encode(Asn1OutputStream asn1Out) + { + asn1Out.WriteIdentifier(Asn1Tags.Constructed | m_tagClass, m_tagNo); + asn1Out.WriteDL(m_contentsLength); + m_contentsElement.Encode(asn1Out); + } + + int IAsn1Encoding.GetLength() + { + return Asn1OutputStream.GetLengthOfEncodingDL(m_tagNo, m_contentsLength); + } + } +} diff --git a/crypto/src/asn1/TaggedDerEncoding.cs b/crypto/src/asn1/TaggedDerEncoding.cs new file mode 100644 index 000000000..c683ec071 --- /dev/null +++ b/crypto/src/asn1/TaggedDerEncoding.cs @@ -0,0 +1,43 @@ +using System; +using System.Diagnostics; + +namespace Org.BouncyCastle.Asn1 +{ + internal class TaggedDerEncoding + : DerEncoding + { + private readonly DerEncoding m_contentsElement; + private readonly int m_contentsLength; + + internal TaggedDerEncoding(int tagClass, int tagNo, DerEncoding contentsElement) + : base(tagClass, tagNo) + { + Debug.Assert(contentsElement != null); + m_contentsElement = contentsElement; + m_contentsLength = contentsElement.GetLength(); + } + + protected internal override int CompareLengthAndContents(DerEncoding other) + { + if (!(other is TaggedDerEncoding that)) + throw new InvalidOperationException(); + + if (this.m_contentsLength != that.m_contentsLength) + return this.m_contentsLength - that.m_contentsLength; + + return this.m_contentsElement.CompareTo(that.m_contentsElement); + } + + public override void Encode(Asn1OutputStream asn1Out) + { + asn1Out.WriteIdentifier(Asn1Tags.Constructed | m_tagClass, m_tagNo); + asn1Out.WriteDL(m_contentsLength); + m_contentsElement.Encode(asn1Out); + } + + public override int GetLength() + { + return Asn1OutputStream.GetLengthOfEncodingDL(m_tagNo, m_contentsLength); + } + } +} diff --git a/crypto/src/asn1/TaggedILEncoding.cs b/crypto/src/asn1/TaggedILEncoding.cs new file mode 100644 index 000000000..63c54e7bd --- /dev/null +++ b/crypto/src/asn1/TaggedILEncoding.cs @@ -0,0 +1,33 @@ +using System; + +namespace Org.BouncyCastle.Asn1 +{ + internal class TaggedILEncoding + : IAsn1Encoding + { + private readonly int m_tagClass; + private readonly int m_tagNo; + private readonly IAsn1Encoding m_contentsElement; + + internal TaggedILEncoding(int tagClass, int tagNo, IAsn1Encoding contentsElement) + { + m_tagClass = tagClass; + m_tagNo = tagNo; + m_contentsElement = contentsElement; + } + + void IAsn1Encoding.Encode(Asn1OutputStream asn1Out) + { + asn1Out.WriteIdentifier(Asn1Tags.Constructed | m_tagClass, m_tagNo); + asn1Out.WriteByte(0x80); + m_contentsElement.Encode(asn1Out); + asn1Out.WriteByte(0x00); + asn1Out.WriteByte(0x00); + } + + int IAsn1Encoding.GetLength() + { + return Asn1OutputStream.GetLengthOfEncodingIL(m_tagNo, m_contentsElement); + } + } +} -- cgit 1.4.1