diff options
43 files changed, 567 insertions, 370 deletions
diff --git a/crypto/src/asn1/Asn1Object.cs b/crypto/src/asn1/Asn1Object.cs index 2f438c236..67c0f37c4 100644 --- a/crypto/src/asn1/Asn1Object.cs +++ b/crypto/src/asn1/Asn1Object.cs @@ -62,9 +62,9 @@ namespace Org.BouncyCastle.Asn1 return this; } - internal abstract bool EncodeConstructed(); + internal abstract bool EncodeConstructed(int encoding); - internal abstract int EncodedLength(bool withID); + internal abstract int EncodedLength(int encoding, bool withID); internal abstract void Encode(Asn1OutputStream asn1Out, bool withID); diff --git a/crypto/src/asn1/Asn1ObjectDescriptor.cs b/crypto/src/asn1/Asn1ObjectDescriptor.cs index e5cc42450..4d25da77b 100644 --- a/crypto/src/asn1/Asn1ObjectDescriptor.cs +++ b/crypto/src/asn1/Asn1ObjectDescriptor.cs @@ -78,14 +78,14 @@ namespace Org.BouncyCastle.Asn1 get { return m_baseGraphicString; } } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { return false; } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { - return m_baseGraphicString.EncodedLength(withID); + return m_baseGraphicString.EncodedLength(encoding, withID); } internal override void Encode(Asn1OutputStream asn1Out, bool withID) diff --git a/crypto/src/asn1/Asn1OctetString.cs b/crypto/src/asn1/Asn1OctetString.cs index d5766e299..66d6fb8d1 100644 --- a/crypto/src/asn1/Asn1OctetString.cs +++ b/crypto/src/asn1/Asn1OctetString.cs @@ -58,14 +58,36 @@ namespace Org.BouncyCastle.Asn1 */ public static Asn1OctetString GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) { + if (declaredExplicit) + { + if (!taggedObject.IsExplicit()) + throw new ArgumentException("object implicit - explicit expected."); + + return GetInstance(taggedObject.GetObject()); + } + Asn1Object baseObject = taggedObject.GetObject(); - if (declaredExplicit || baseObject is Asn1OctetString) + // If parsed as explicit though declared implicit, it should have been a set of one + if (taggedObject.IsExplicit()) { - return GetInstance(baseObject); + Asn1OctetString singleSegment = GetInstance(baseObject); + + if (taggedObject is BerTaggedObject) + return new BerOctetString(new Asn1OctetString[]{ singleSegment }); + + return singleSegment; } - return BerOctetString.FromSequence(Asn1Sequence.GetInstance(baseObject)); + if (baseObject is Asn1OctetString) + return (Asn1OctetString)baseObject; + + // Parser assumes implicit constructed encodings are sequences + if (baseObject is Asn1Sequence) + return ((Asn1Sequence)baseObject).ToAsn1OctetString(); + + throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(taggedObject), + "taggedObject"); } internal readonly byte[] contents; diff --git a/crypto/src/asn1/Asn1OutputStream.cs b/crypto/src/asn1/Asn1OutputStream.cs index b0d4a18fa..79ab84b74 100644 --- a/crypto/src/asn1/Asn1OutputStream.cs +++ b/crypto/src/asn1/Asn1OutputStream.cs @@ -6,6 +6,9 @@ namespace Org.BouncyCastle.Asn1 public class Asn1OutputStream : DerOutputStream { + internal const int EncodingBer = 1; + internal const int EncodingDer = 2; + public static Asn1OutputStream Create(Stream output) { return new Asn1OutputStream(output); @@ -52,14 +55,14 @@ namespace Org.BouncyCastle.Asn1 // Placeholder to support future internal buffering } - internal virtual bool IsBer + internal virtual DerOutputStreamNew GetDerSubStream() { - get { return true; } + return new DerOutputStreamNew(s); } - internal virtual bool IsDer + internal virtual int Encoding { - get { return false; } + get { return EncodingBer; } } internal void WriteDL(int length) diff --git a/crypto/src/asn1/Asn1RelativeOid.cs b/crypto/src/asn1/Asn1RelativeOid.cs index e1ee5309a..efa050413 100644 --- a/crypto/src/asn1/Asn1RelativeOid.cs +++ b/crypto/src/asn1/Asn1RelativeOid.cs @@ -110,12 +110,12 @@ namespace Org.BouncyCastle.Asn1 return identifier.GetHashCode(); } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { return false; } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { return Asn1OutputStream.GetLengthOfEncodingDL(withID, GetContents().Length); } diff --git a/crypto/src/asn1/Asn1Sequence.cs b/crypto/src/asn1/Asn1Sequence.cs index 8025492d2..9ab41ffd3 100644 --- a/crypto/src/asn1/Asn1Sequence.cs +++ b/crypto/src/asn1/Asn1Sequence.cs @@ -62,16 +62,16 @@ namespace Org.BouncyCastle.Asn1 */ public static Asn1Sequence GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) { - Asn1Object baseObject = taggedObject.GetObject(); - if (declaredExplicit) { if (!taggedObject.IsExplicit()) throw new ArgumentException("object implicit - explicit expected."); - return (Asn1Sequence)baseObject; + return GetInstance(taggedObject.GetObject()); } + Asn1Object baseObject = taggedObject.GetObject(); + // If parsed as explicit though declared implicit, it should have been a sequence of one if (taggedObject.IsExplicit()) { @@ -235,7 +235,7 @@ namespace Org.BouncyCastle.Asn1 return true; } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { return true; } @@ -245,6 +245,17 @@ namespace Org.BouncyCastle.Asn1 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 b1439be47..6193e8178 100644 --- a/crypto/src/asn1/Asn1Set.cs +++ b/crypto/src/asn1/Asn1Set.cs @@ -68,16 +68,16 @@ namespace Org.BouncyCastle.Asn1 */ public static Asn1Set GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) { - Asn1Object baseObject = taggedObject.GetObject(); - if (declaredExplicit) { if (!taggedObject.IsExplicit()) throw new ArgumentException("object implicit - explicit expected."); - return (Asn1Set)baseObject; + return GetInstance(taggedObject.GetObject()); } + Asn1Object baseObject = taggedObject.GetObject(); + // If parsed as explicit though declared implicit, it should have been a set of one if (taggedObject.IsExplicit()) { @@ -266,7 +266,7 @@ namespace Org.BouncyCastle.Asn1 return true; } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { return true; } @@ -276,7 +276,18 @@ namespace Org.BouncyCastle.Asn1 return CollectionUtilities.ToString(elements); } - private static Asn1Encodable[] Sort(Asn1Encodable[] 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; if (count < 2) diff --git a/crypto/src/asn1/Asn1TaggedObject.cs b/crypto/src/asn1/Asn1TaggedObject.cs index 87a66ffe0..9f7eab576 100644 --- a/crypto/src/asn1/Asn1TaggedObject.cs +++ b/crypto/src/asn1/Asn1TaggedObject.cs @@ -198,17 +198,6 @@ 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() - { - return EncodeConstructed(); - } - - /** * return whatever was following the tag. * <p> * Note: tagged objects are generally context dependent if you're diff --git a/crypto/src/asn1/BERBitString.cs b/crypto/src/asn1/BERBitString.cs index 156ea2d1f..a012d2a7c 100644 --- a/crypto/src/asn1/BERBitString.cs +++ b/crypto/src/asn1/BERBitString.cs @@ -1,8 +1,6 @@ using System; using System.Diagnostics; -using Org.BouncyCastle.Utilities; - namespace Org.BouncyCastle.Asn1 { public class BerBitString @@ -113,54 +111,56 @@ namespace Org.BouncyCastle.Asn1 this.segmentLimit = DefaultSegmentLimit; } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { - // NOTE: Assumes BER encoding + if (Asn1OutputStream.EncodingBer != encoding) + return base.EncodeConstructed(encoding); + return null != elements || contents.Length > segmentLimit; } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { - throw Platform.CreateNotImplementedException("BerBitString.EncodedLength"); - - // TODO This depends on knowing it's not DER - //if (!EncodeConstructed()) - // 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(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); - //} - - //return totalLength; + 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); + } + + return totalLength; } internal override void Encode(Asn1OutputStream asn1Out, bool withID) { - if (!asn1Out.IsBer) + if (Asn1OutputStream.EncodingBer != asn1Out.Encoding) { base.Encode(asn1Out, withID); return; } - if (!EncodeConstructed()) + if (!EncodeConstructed(asn1Out.Encoding)) { Encode(asn1Out, withID, contents, 0, contents.Length); return; diff --git a/crypto/src/asn1/BerOctetString.cs b/crypto/src/asn1/BerOctetString.cs index 0dab617b9..52ddd51c3 100644 --- a/crypto/src/asn1/BerOctetString.cs +++ b/crypto/src/asn1/BerOctetString.cs @@ -120,52 +120,60 @@ namespace Org.BouncyCastle.Asn1 return GetEnumerator(); } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { - // NOTE: Assumes BER encoding + if (Asn1OutputStream.EncodingBer != encoding) + return base.EncodeConstructed(encoding); + return null != elements || contents.Length > segmentLimit; } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { - throw Platform.CreateNotImplementedException("BerOctetString.EncodedLength"); - - // TODO This depends on knowing it's not DER - //if (!EncodeConstructed()) - // 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(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); - // } - //} - - //return totalLength; + 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); + } + } + + return totalLength; } internal override void Encode(Asn1OutputStream asn1Out, bool withID) { - if (!asn1Out.IsBer || !EncodeConstructed()) + 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); diff --git a/crypto/src/asn1/BerSequence.cs b/crypto/src/asn1/BerSequence.cs index c8c5bbbbd..a92b70f98 100644 --- a/crypto/src/asn1/BerSequence.cs +++ b/crypto/src/asn1/BerSequence.cs @@ -1,7 +1,5 @@ using System; -using Org.BouncyCastle.Utilities; - namespace Org.BouncyCastle.Asn1 { public class BerSequence @@ -48,14 +46,25 @@ namespace Org.BouncyCastle.Asn1 { } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { - throw Platform.CreateNotImplementedException("BerSequence.EncodedLength"); + if (Asn1OutputStream.EncodingBer != encoding) + return base.EncodedLength(encoding, withID); + + 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; } internal override void Encode(Asn1OutputStream asn1Out, bool withID) { - if (!asn1Out.IsBer) + if (Asn1OutputStream.EncodingBer != asn1Out.Encoding) { base.Encode(asn1Out, withID); return; diff --git a/crypto/src/asn1/BerSet.cs b/crypto/src/asn1/BerSet.cs index 2cfda2f09..c0d00537c 100644 --- a/crypto/src/asn1/BerSet.cs +++ b/crypto/src/asn1/BerSet.cs @@ -48,14 +48,25 @@ namespace Org.BouncyCastle.Asn1 { } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { - throw Platform.CreateNotImplementedException("BerSet.EncodedLength"); + if (Asn1OutputStream.EncodingBer != encoding) + return base.EncodedLength(encoding, withID); + + 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; } internal override void Encode(Asn1OutputStream asn1Out, bool withID) { - if (!asn1Out.IsBer) + if (Asn1OutputStream.EncodingBer != asn1Out.Encoding) { base.Encode(asn1Out, withID); return; diff --git a/crypto/src/asn1/BerTaggedObject.cs b/crypto/src/asn1/BerTaggedObject.cs index 4bf27e12f..fc4d1835a 100644 --- a/crypto/src/asn1/BerTaggedObject.cs +++ b/crypto/src/asn1/BerTaggedObject.cs @@ -1,7 +1,4 @@ using System; -using System.Collections; - -using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Asn1 { @@ -52,75 +49,67 @@ namespace Org.BouncyCastle.Asn1 get { return Ber; } } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { - throw Platform.CreateNotImplementedException("BerTaggedObject.EncodeConstructed"); + if (Asn1OutputStream.EncodingBer != encoding) + return base.EncodeConstructed(encoding); - // TODO This depends on knowing it's not DER - //return IsExplicit() || obj.ToAsn1Object().EncodeConstructed(); + return IsExplicit() || GetBaseObject().ToAsn1Object().EncodeConstructed(encoding); } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { - throw Platform.CreateNotImplementedException("BerTaggedObject.EncodedLength"); + if (Asn1OutputStream.EncodingBer != encoding) + return base.EncodedLength(encoding, withID); + + Asn1Object baseObject = GetBaseObject().ToAsn1Object(); + bool withBaseID = IsExplicit(); + + int length = baseObject.EncodedLength(encoding, withBaseID); + + if (withBaseID) + { + length += 3; + } + + length += withID ? Asn1OutputStream.GetLengthOfIdentifier(TagNo) : 0; + + return length; } internal override void Encode(Asn1OutputStream asn1Out, bool withID) { - if (asn1Out.IsBer) - { - if (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)) { - asn1Out.WriteIdentifier(true, Asn1Tags.Constructed | TagClass, TagNo); + flags |= Asn1Tags.Constructed; } - asn1Out.WriteByte(0x80); + asn1Out.WriteIdentifier(true, flags, TagNo); + } - if (!explicitly) - { - IEnumerable eObj; - if (obj is Asn1OctetString) - { - if (obj is BerOctetString) - { - eObj = (BerOctetString) obj; - } - else - { - Asn1OctetString octs = (Asn1OctetString)obj; - eObj = new BerOctetString(octs.GetOctets()); - } - } - else if (obj is Asn1Sequence) - { - eObj = (Asn1Sequence) obj; - } - else if (obj is Asn1Set) - { - eObj = (Asn1Set) obj; - } - else - { - throw Platform.CreateNotImplementedException(Platform.GetTypeName(obj)); - } - - foreach (Asn1Encodable o in eObj) - { - asn1Out.WritePrimitive(o.ToAsn1Object(), true); - } - } - else - { - asn1Out.WritePrimitive(obj.ToAsn1Object(), true); - } - - asn1Out.WriteByte(0x00); - asn1Out.WriteByte(0x00); - } - else - { - base.Encode(asn1Out, withID); - } + 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) diff --git a/crypto/src/asn1/DERExternal.cs b/crypto/src/asn1/DERExternal.cs index ae707a2f5..32fc8d6d8 100644 --- a/crypto/src/asn1/DERExternal.cs +++ b/crypto/src/asn1/DERExternal.cs @@ -155,15 +155,15 @@ namespace Org.BouncyCastle.Asn1 return new DerSequence(v); } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { - //return BuildSequence().EncodeConstructed(); + //return BuildSequence().EncodeConstructed(encoding); return true; } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { - return BuildSequence().EncodedLength(withID); + return BuildSequence().EncodedLength(encoding, withID); } internal override void Encode(Asn1OutputStream asn1Out, bool withID) diff --git a/crypto/src/asn1/DLSequence.cs b/crypto/src/asn1/DLSequence.cs index 56a0e6932..0fede574a 100644 --- a/crypto/src/asn1/DLSequence.cs +++ b/crypto/src/asn1/DLSequence.cs @@ -1,7 +1,4 @@ using System; -using System.IO; - -using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Asn1 { @@ -15,6 +12,8 @@ namespace Org.BouncyCastle.Asn1 return elementVector.Count < 1 ? Empty : new DLSequence(elementVector); } + private int m_contentsLengthDL = -1; + /** * create an empty sequence */ @@ -49,48 +48,73 @@ namespace Org.BouncyCastle.Asn1 { } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { - throw Platform.CreateNotImplementedException("DLSequence.EncodedLength"); + if (Asn1OutputStream.EncodingDer == encoding) + return base.EncodedLength(encoding, withID); + + return Asn1OutputStream.GetLengthOfEncodingDL(withID, GetContentsLengthDL()); } internal override void Encode(Asn1OutputStream asn1Out, bool withID) { - if (asn1Out.IsDer) + if (Asn1OutputStream.EncodingDer == asn1Out.Encoding) { base.Encode(asn1Out, withID); return; } - if (Count < 1) - { - asn1Out.WriteEncodingDL(withID, Asn1Tags.Constructed | Asn1Tags.Sequence, Asn1OctetString.EmptyOctets); - return; - } - - // TODO Intermediate buffer could be avoided if we could calculate expected length - MemoryStream bOut = new MemoryStream(); - // TODO Once DLOutputStream exists, this should create one - Asn1OutputStream dOut = Asn1OutputStream.Create(bOut); - dOut.WriteElements(elements); - dOut.FlushInternal(); + // TODO[asn1] Use DL encoding when supported + //asn1Out = asn1Out.GetDLSubStream(); -#if PORTABLE - byte[] bytes = bOut.ToArray(); - int length = bytes.Length; -#else - byte[] bytes = bOut.GetBuffer(); - int length = (int)bOut.Position; -#endif + asn1Out.WriteIdentifier(withID, Asn1Tags.Constructed | Asn1Tags.Sequence); - asn1Out.WriteEncodingDL(withID, Asn1Tags.Constructed | Asn1Tags.Sequence, bytes, 0, length); + int count = elements.Length; + if (m_contentsLengthDL >= 0 || count > 16) + { + asn1Out.WriteDL(GetContentsLengthDL()); - Platform.Dispose(dOut); + 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); + } + } } 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 0605a0167..7dcac25c2 100644 --- a/crypto/src/asn1/DLSet.cs +++ b/crypto/src/asn1/DLSet.cs @@ -1,7 +1,4 @@ using System; -using System.IO; - -using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Asn1 { @@ -15,6 +12,8 @@ namespace Org.BouncyCastle.Asn1 return elementVector.Count < 1 ? Empty : new DLSet(elementVector); } + private int m_contentsLengthDL = -1; + /** * create an empty set */ @@ -49,43 +48,80 @@ namespace Org.BouncyCastle.Asn1 { } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { - throw Platform.CreateNotImplementedException("DLSet.EncodedLength"); + 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 Asn1OutputStream.GetLengthOfEncodingDL(withID, contentsLength); } internal override void Encode(Asn1OutputStream asn1Out, bool withID) { - if (asn1Out.IsDer) + if (Asn1OutputStream.EncodingDer == asn1Out.Encoding) { base.Encode(asn1Out, withID); return; } - if (Count < 1) + // 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.WriteEncodingDL(withID, Asn1Tags.Constructed | Asn1Tags.Set, Asn1OctetString.EmptyOctets); - return; + asn1Out.WriteDL(GetContentsLengthDL()); + + for (int i = 0; i < count; ++i) + { + Asn1Object asn1Object = elements[i].ToAsn1Object(); + asn1Object.Encode(asn1Out, true); + } } + else + { + int contentsLength = 0; - // TODO Intermediate buffer could be avoided if we could calculate expected length - MemoryStream bOut = new MemoryStream(); - // TODO Once DLOutputStream exists, this should create one - Asn1OutputStream dOut = Asn1OutputStream.Create(bOut); - dOut.WriteElements(elements); - dOut.FlushInternal(); + 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); + } -#if PORTABLE - byte[] bytes = bOut.ToArray(); - int length = bytes.Length; -#else - byte[] bytes = bOut.GetBuffer(); - int length = (int)bOut.Position; -#endif + this.m_contentsLengthDL = contentsLength; + asn1Out.WriteDL(contentsLength); - asn1Out.WriteEncodingDL(withID, Asn1Tags.Constructed | Asn1Tags.Set, bytes, 0, length); + for (int i = 0; i < count; ++i) + { + asn1Objects[i].Encode(asn1Out, true); + } + } + } - Platform.Dispose(dOut); + 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/DerApplicationSpecific.cs b/crypto/src/asn1/DerApplicationSpecific.cs index a71526876..bc48d24e5 100644 --- a/crypto/src/asn1/DerApplicationSpecific.cs +++ b/crypto/src/asn1/DerApplicationSpecific.cs @@ -163,12 +163,12 @@ namespace Org.BouncyCastle.Asn1 return FromByteArray(tmp); } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { - throw Platform.CreateNotImplementedException("DerApplicationSpecific.EncodeConstructed"); + return isConstructed; } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { return Asn1OutputStream.GetLengthOfEncodingDL(withID, tag, octets.Length); } diff --git a/crypto/src/asn1/DerBMPString.cs b/crypto/src/asn1/DerBMPString.cs index f3fe6aa42..d3c7b3b46 100644 --- a/crypto/src/asn1/DerBMPString.cs +++ b/crypto/src/asn1/DerBMPString.cs @@ -111,12 +111,12 @@ namespace Org.BouncyCastle.Asn1 return this.str.Equals(other.str); } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { return false; } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { return Asn1OutputStream.GetLengthOfEncodingDL(withID, str.Length * 2); } diff --git a/crypto/src/asn1/DerBitString.cs b/crypto/src/asn1/DerBitString.cs index 9cf84db1e..2814b9677 100644 --- a/crypto/src/asn1/DerBitString.cs +++ b/crypto/src/asn1/DerBitString.cs @@ -216,12 +216,12 @@ namespace Org.BouncyCastle.Asn1 } } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { return false; } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { return Asn1OutputStream.GetLengthOfEncodingDL(withID, contents.Length); } diff --git a/crypto/src/asn1/DerBoolean.cs b/crypto/src/asn1/DerBoolean.cs index e2cd145a1..a6f972629 100644 --- a/crypto/src/asn1/DerBoolean.cs +++ b/crypto/src/asn1/DerBoolean.cs @@ -81,20 +81,25 @@ namespace Org.BouncyCastle.Asn1 get { return value != 0; } } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { return false; } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { return Asn1OutputStream.GetLengthOfEncodingDL(withID, 1); } internal override void Encode(Asn1OutputStream asn1Out, bool withID) { - // TODO Should we make sure the byte value is one of '0' or '0xff' here? - asn1Out.WriteEncodingDL(withID, Asn1Tags.Boolean, value); + byte contents = value; + if (Asn1OutputStream.EncodingDer == asn1Out.Encoding && IsTrue) + { + contents = 0xFF; + } + + asn1Out.WriteEncodingDL(withID, Asn1Tags.Boolean, contents); } protected override bool Asn1Equals( diff --git a/crypto/src/asn1/DerEnumerated.cs b/crypto/src/asn1/DerEnumerated.cs index 03d85fbfd..af9e6330a 100644 --- a/crypto/src/asn1/DerEnumerated.cs +++ b/crypto/src/asn1/DerEnumerated.cs @@ -119,12 +119,12 @@ namespace Org.BouncyCastle.Asn1 } } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { return false; } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { return Asn1OutputStream.GetLengthOfEncodingDL(withID, bytes.Length); } diff --git a/crypto/src/asn1/DerGeneralString.cs b/crypto/src/asn1/DerGeneralString.cs index 9724870b1..f5575650b 100644 --- a/crypto/src/asn1/DerGeneralString.cs +++ b/crypto/src/asn1/DerGeneralString.cs @@ -61,12 +61,12 @@ namespace Org.BouncyCastle.Asn1 return Strings.ToAsciiByteArray(str); } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { return false; } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { return Asn1OutputStream.GetLengthOfEncodingDL(withID, str.Length); } diff --git a/crypto/src/asn1/DerGeneralizedTime.cs b/crypto/src/asn1/DerGeneralizedTime.cs index c17fcbdce..e70a481dc 100644 --- a/crypto/src/asn1/DerGeneralizedTime.cs +++ b/crypto/src/asn1/DerGeneralizedTime.cs @@ -295,12 +295,12 @@ namespace Org.BouncyCastle.Asn1 return Strings.ToAsciiByteArray(time); } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { return false; } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { return Asn1OutputStream.GetLengthOfEncodingDL(withID, time.Length); } diff --git a/crypto/src/asn1/DerGraphicString.cs b/crypto/src/asn1/DerGraphicString.cs index f037c648b..4a864ea8c 100644 --- a/crypto/src/asn1/DerGraphicString.cs +++ b/crypto/src/asn1/DerGraphicString.cs @@ -83,12 +83,12 @@ namespace Org.BouncyCastle.Asn1 return Arrays.Clone(m_contents); } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { return false; } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { return Asn1OutputStream.GetLengthOfEncodingDL(withID, m_contents.Length); } diff --git a/crypto/src/asn1/DerIA5String.cs b/crypto/src/asn1/DerIA5String.cs index 47c1395cf..97a9222c2 100644 --- a/crypto/src/asn1/DerIA5String.cs +++ b/crypto/src/asn1/DerIA5String.cs @@ -100,12 +100,12 @@ namespace Org.BouncyCastle.Asn1 return Strings.ToAsciiByteArray(str); } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { return false; } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { return Asn1OutputStream.GetLengthOfEncodingDL(withID, str.Length); } diff --git a/crypto/src/asn1/DerInteger.cs b/crypto/src/asn1/DerInteger.cs index 791b6e7e3..36fd58870 100644 --- a/crypto/src/asn1/DerInteger.cs +++ b/crypto/src/asn1/DerInteger.cs @@ -169,12 +169,12 @@ namespace Org.BouncyCastle.Asn1 } } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { return false; } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { return Asn1OutputStream.GetLengthOfEncodingDL(withID, bytes.Length); } diff --git a/crypto/src/asn1/DerNull.cs b/crypto/src/asn1/DerNull.cs index 5ca8ba771..947acaf0b 100644 --- a/crypto/src/asn1/DerNull.cs +++ b/crypto/src/asn1/DerNull.cs @@ -16,12 +16,12 @@ namespace Org.BouncyCastle.Asn1 { } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { return false; } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { return Asn1OutputStream.GetLengthOfEncodingDL(withID, 0); } diff --git a/crypto/src/asn1/DerNumericString.cs b/crypto/src/asn1/DerNumericString.cs index cb73817be..4412f973e 100644 --- a/crypto/src/asn1/DerNumericString.cs +++ b/crypto/src/asn1/DerNumericString.cs @@ -100,12 +100,12 @@ namespace Org.BouncyCastle.Asn1 return Strings.ToAsciiByteArray(str); } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { return false; } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { return Asn1OutputStream.GetLengthOfEncodingDL(withID, str.Length); } diff --git a/crypto/src/asn1/DerObjectIdentifier.cs b/crypto/src/asn1/DerObjectIdentifier.cs index 08451b82f..f24bbf984 100644 --- a/crypto/src/asn1/DerObjectIdentifier.cs +++ b/crypto/src/asn1/DerObjectIdentifier.cs @@ -128,12 +128,12 @@ namespace Org.BouncyCastle.Asn1 return identifier.GetHashCode(); } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { return false; } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { return Asn1OutputStream.GetLengthOfEncodingDL(withID, GetContents().Length); } diff --git a/crypto/src/asn1/DerOctetString.cs b/crypto/src/asn1/DerOctetString.cs index 55c099360..d49393641 100644 --- a/crypto/src/asn1/DerOctetString.cs +++ b/crypto/src/asn1/DerOctetString.cs @@ -21,12 +21,12 @@ namespace Org.BouncyCastle.Asn1 { } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { return false; } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { return Asn1OutputStream.GetLengthOfEncodingDL(withID, contents.Length); } diff --git a/crypto/src/asn1/DerOutputStream.cs b/crypto/src/asn1/DerOutputStream.cs index f384c20a8..47b945635 100644 --- a/crypto/src/asn1/DerOutputStream.cs +++ b/crypto/src/asn1/DerOutputStream.cs @@ -34,14 +34,14 @@ namespace Org.BouncyCastle.Asn1 { } - internal override bool IsBer + internal override DerOutputStreamNew GetDerSubStream() { - get { return false; } + return this; } - internal override bool IsDer + internal override int Encoding { - get { return true; } + get { return EncodingDer; } } internal override void WritePrimitive(Asn1Object primitive, bool withID) diff --git a/crypto/src/asn1/DerPrintableString.cs b/crypto/src/asn1/DerPrintableString.cs index e930e2845..3d911a6ac 100644 --- a/crypto/src/asn1/DerPrintableString.cs +++ b/crypto/src/asn1/DerPrintableString.cs @@ -1,5 +1,4 @@ using System; -using System.Text; using Org.BouncyCastle.Utilities; @@ -100,12 +99,12 @@ namespace Org.BouncyCastle.Asn1 return Strings.ToAsciiByteArray(str); } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { return false; } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { return Asn1OutputStream.GetLengthOfEncodingDL(withID, str.Length); } diff --git a/crypto/src/asn1/DerSequence.cs b/crypto/src/asn1/DerSequence.cs index 157d99c93..e60796091 100644 --- a/crypto/src/asn1/DerSequence.cs +++ b/crypto/src/asn1/DerSequence.cs @@ -1,7 +1,4 @@ using System; -using System.IO; - -using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Asn1 { @@ -15,10 +12,12 @@ namespace Org.BouncyCastle.Asn1 return elementVector.Count < 1 ? Empty : new DerSequence(elementVector); } - /** + private int m_contentsLengthDer = -1; + + /** * create an empty sequence */ - public DerSequence() + public DerSequence() : base() { } @@ -49,9 +48,9 @@ namespace Org.BouncyCastle.Asn1 { } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { - throw Platform.CreateNotImplementedException("DerSequence.EncodedLength"); + return Asn1OutputStream.GetLengthOfEncodingDL(withID, GetContentsLengthDer()); } /* @@ -64,29 +63,41 @@ namespace Org.BouncyCastle.Asn1 */ internal override void Encode(Asn1OutputStream asn1Out, bool withID) { - if (Count < 1) - { - asn1Out.WriteEncodingDL(withID, Asn1Tags.Constructed | Asn1Tags.Sequence, Asn1OctetString.EmptyOctets); - return; - } - - // TODO Intermediate buffer could be avoided if we could calculate expected length - MemoryStream bOut = new MemoryStream(); - Asn1OutputStream dOut = Asn1OutputStream.Create(bOut, Der); - dOut.WriteElements(elements); - dOut.FlushInternal(); + asn1Out = asn1Out.GetDerSubStream(); -#if PORTABLE - byte[] bytes = bOut.ToArray(); - int length = bytes.Length; -#else - byte[] bytes = bOut.GetBuffer(); - int length = (int)bOut.Position; -#endif + asn1Out.WriteIdentifier(withID, Asn1Tags.Constructed | Asn1Tags.Sequence); - asn1Out.WriteEncodingDL(withID, Asn1Tags.Constructed | Asn1Tags.Sequence, bytes, 0, length); + int count = elements.Length; + if (m_contentsLengthDer >= 0 || count > 16) + { + asn1Out.WriteDL(GetContentsLengthDer()); - Platform.Dispose(dOut); + 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); + } + } } internal override DerBitString ToAsn1BitString() @@ -109,5 +120,14 @@ 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 030b0a38f..d89285d9e 100644 --- a/crypto/src/asn1/DerSet.cs +++ b/crypto/src/asn1/DerSet.cs @@ -1,7 +1,4 @@ using System; -using System.IO; - -using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Asn1 { @@ -18,10 +15,12 @@ namespace Org.BouncyCastle.Asn1 return elementVector.Count < 1 ? Empty : new DerSet(elementVector); } - /** + private int m_contentsLengthDer = -1; + + /** * create an empty set */ - public DerSet() + public DerSet() : base() { } @@ -62,9 +61,20 @@ namespace Org.BouncyCastle.Asn1 { } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { - throw Platform.CreateNotImplementedException("DerSet.EncodedLength"); + 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); } /* @@ -83,34 +93,56 @@ namespace Org.BouncyCastle.Asn1 return; } + Asn1Encodable[] elements = this.elements; if (!isSorted) { - new DerSet(elements, true).ImplEncode(asn1Out, withID); - return; + elements = Sort((Asn1Encodable[])elements.Clone()); } - ImplEncode(asn1Out, withID); + asn1Out = asn1Out.GetDerSubStream(); + + asn1Out.WriteIdentifier(withID, Asn1Tags.Constructed | Asn1Tags.Set); + + 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); + } + } } - private void ImplEncode(Asn1OutputStream asn1Out, bool withID) + private int GetContentsLengthDer() { - // TODO Intermediate buffer could be avoided if we could calculate expected length - MemoryStream bOut = new MemoryStream(); - Asn1OutputStream dOut = Asn1OutputStream.Create(bOut, Der); - dOut.WriteElements(elements); - dOut.FlushInternal(); - -#if PORTABLE - byte[] bytes = bOut.ToArray(); - int length = bytes.Length; -#else - byte[] bytes = bOut.GetBuffer(); - int length = (int)bOut.Position; -#endif - - asn1Out.WriteEncodingDL(withID, Asn1Tags.Constructed | Asn1Tags.Set, bytes, 0, length); - - Platform.Dispose(dOut); + if (m_contentsLengthDer < 0) + { + m_contentsLengthDer = CalculateContentsLength(Asn1OutputStream.EncodingDer); + } + return m_contentsLengthDer; } } } diff --git a/crypto/src/asn1/DerT61String.cs b/crypto/src/asn1/DerT61String.cs index cf2123131..79a7ef8e4 100644 --- a/crypto/src/asn1/DerT61String.cs +++ b/crypto/src/asn1/DerT61String.cs @@ -77,12 +77,12 @@ namespace Org.BouncyCastle.Asn1 return str; } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { return false; } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { return Asn1OutputStream.GetLengthOfEncodingDL(withID, str.Length); } diff --git a/crypto/src/asn1/DerTaggedObject.cs b/crypto/src/asn1/DerTaggedObject.cs index b75e0879d..e58590c8d 100644 --- a/crypto/src/asn1/DerTaggedObject.cs +++ b/crypto/src/asn1/DerTaggedObject.cs @@ -1,7 +1,5 @@ using System; -using Org.BouncyCastle.Utilities; - namespace Org.BouncyCastle.Asn1 { /** @@ -12,11 +10,13 @@ namespace Org.BouncyCastle.Asn1 public class DerTaggedObject : Asn1TaggedObject { - /** + private int m_contentsLengthDer = -1; + + /** * @param tagNo the tag number for this object. * @param obj the tagged object. */ - public DerTaggedObject( + public DerTaggedObject( int tagNo, Asn1Encodable obj) : base(tagNo, obj) @@ -51,50 +51,70 @@ namespace Org.BouncyCastle.Asn1 get { return Der; } } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { - throw Platform.CreateNotImplementedException("DerTaggedObject.EncodeConstructed"); + encoding = Asn1OutputStream.EncodingDer; - //return IsExplicit() || obj.ToAsn1Object().ToDerObject().EncodeConstructed(); + return IsExplicit() || GetBaseObject().ToAsn1Object().EncodeConstructed(encoding); } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { - throw Platform.CreateNotImplementedException("DerTaggedObject.EncodedLength"); + encoding = Asn1OutputStream.EncodingDer; + + Asn1Object baseObject = GetBaseObject().ToAsn1Object(); + bool withBaseID = IsExplicit(); + + int length = GetContentsLengthDer(baseObject, withBaseID); + + if (withBaseID) + { + length += Asn1OutputStream.GetLengthOfDL(length); + } + + length += withID ? Asn1OutputStream.GetLengthOfIdentifier(TagNo) : 0; + + return length; } internal override void Encode(Asn1OutputStream asn1Out, bool withID) { - byte[] bytes = obj.GetDerEncoded(); + asn1Out = asn1Out.GetDerSubStream(); - if (explicitly) - { - asn1Out.WriteEncodingDL(withID, Asn1Tags.Constructed | TagClass, TagNo, bytes); - } - else + Asn1Object baseObject = GetBaseObject().ToAsn1Object(); + bool withBaseID = IsExplicit(); + + if (withID) { - int tagHdr = bytes[0], tagLen = 1; - if ((tagHdr & 0x1F) == 0x1F) + int flags = TagClass; + if (withBaseID || baseObject.EncodeConstructed(asn1Out.Encoding)) { - while ((bytes[tagLen++] & 0x80) != 0) - { - } + flags |= Asn1Tags.Constructed; } - if (withID) - { - int flags = (tagHdr & Asn1Tags.Constructed) | TagClass; - - asn1Out.WriteIdentifier(true, flags, TagNo); - } + asn1Out.WriteIdentifier(true, flags, TagNo); + } - asn1Out.Write(bytes, tagLen, bytes.Length - tagLen); + if (withBaseID) + { + asn1Out.WriteDL(GetContentsLengthDer(baseObject, true)); } + + baseObject.Encode(asn1Out, withBaseID); } internal override Asn1Sequence RebuildConstructed(Asn1Object asn1Object) { return new DerSequence(asn1Object); } + + 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 5124af12f..17d02df19 100644 --- a/crypto/src/asn1/DerUTCTime.cs +++ b/crypto/src/asn1/DerUTCTime.cs @@ -237,12 +237,12 @@ namespace Org.BouncyCastle.Asn1 return Strings.ToAsciiByteArray(time); } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { return false; } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { return Asn1OutputStream.GetLengthOfEncodingDL(withID, time.Length); } diff --git a/crypto/src/asn1/DerUTF8String.cs b/crypto/src/asn1/DerUTF8String.cs index 0406f4a71..7bc9ff524 100644 --- a/crypto/src/asn1/DerUTF8String.cs +++ b/crypto/src/asn1/DerUTF8String.cs @@ -89,12 +89,12 @@ namespace Org.BouncyCastle.Asn1 return this.str.Equals(other.str); } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { return false; } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { return Asn1OutputStream.GetLengthOfEncodingDL(withID, Encoding.UTF8.GetByteCount(str)); } diff --git a/crypto/src/asn1/DerUniversalString.cs b/crypto/src/asn1/DerUniversalString.cs index e9188b202..ab89a0e12 100644 --- a/crypto/src/asn1/DerUniversalString.cs +++ b/crypto/src/asn1/DerUniversalString.cs @@ -86,12 +86,12 @@ namespace Org.BouncyCastle.Asn1 return (byte[]) str.Clone(); } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { return false; } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { return Asn1OutputStream.GetLengthOfEncodingDL(withID, this.str.Length); } diff --git a/crypto/src/asn1/DerVideotexString.cs b/crypto/src/asn1/DerVideotexString.cs index 377cd060a..5b9ad09f9 100644 --- a/crypto/src/asn1/DerVideotexString.cs +++ b/crypto/src/asn1/DerVideotexString.cs @@ -79,12 +79,12 @@ namespace Org.BouncyCastle.Asn1 return Arrays.Clone(mString); } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { return false; } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { return Asn1OutputStream.GetLengthOfEncodingDL(withID, mString.Length); } diff --git a/crypto/src/asn1/DerVisibleString.cs b/crypto/src/asn1/DerVisibleString.cs index ae2aaeec2..9e34ef65e 100644 --- a/crypto/src/asn1/DerVisibleString.cs +++ b/crypto/src/asn1/DerVisibleString.cs @@ -86,12 +86,12 @@ namespace Org.BouncyCastle.Asn1 return Strings.ToAsciiByteArray(str); } - internal override bool EncodeConstructed() + internal override bool EncodeConstructed(int encoding) { return false; } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { return Asn1OutputStream.GetLengthOfEncodingDL(withID, str.Length); } diff --git a/crypto/src/asn1/LazyDLSequence.cs b/crypto/src/asn1/LazyDLSequence.cs index fe924365e..bf9fc0800 100644 --- a/crypto/src/asn1/LazyDLSequence.cs +++ b/crypto/src/asn1/LazyDLSequence.cs @@ -63,21 +63,25 @@ namespace Org.BouncyCastle.Asn1 return base.ToString(); } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { - // TODO This depends on knowing it's BER - byte[] encoded = GetContents(); - if (encoded != null) + if (Asn1OutputStream.EncodingBer == encoding) { - return Asn1OutputStream.GetLengthOfEncodingDL(withID, encoded.Length); + byte[] encoded = GetContents(); + if (null != encoded) + return Asn1OutputStream.GetLengthOfEncodingDL(withID, encoded.Length); + } + else + { + Force(); } - return base.EncodedLength(withID); + return base.EncodedLength(encoding, withID); } internal override void Encode(Asn1OutputStream asn1Out, bool withID) { - if (asn1Out.IsBer) + if (Asn1OutputStream.EncodingBer == asn1Out.Encoding) { byte[] encoded = GetContents(); if (encoded != null) diff --git a/crypto/src/asn1/LazyDLSet.cs b/crypto/src/asn1/LazyDLSet.cs index bdee0bc22..a426bb4cb 100644 --- a/crypto/src/asn1/LazyDLSet.cs +++ b/crypto/src/asn1/LazyDLSet.cs @@ -63,21 +63,25 @@ namespace Org.BouncyCastle.Asn1 return base.ToString(); } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { - // TODO This depends on knowing it's BER - byte[] encoded = GetContents(); - if (encoded != null) + if (Asn1OutputStream.EncodingBer == encoding) { - return Asn1OutputStream.GetLengthOfEncodingDL(withID, encoded.Length); + byte[] encoded = GetContents(); + if (null != encoded) + return Asn1OutputStream.GetLengthOfEncodingDL(withID, encoded.Length); + } + else + { + Force(); } - return base.EncodedLength(withID); + return base.EncodedLength(encoding, withID); } internal override void Encode(Asn1OutputStream asn1Out, bool withID) { - if (asn1Out.IsBer) + if (Asn1OutputStream.EncodingBer == asn1Out.Encoding) { byte[] encoded = GetContents(); if (encoded != null) |