diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2021-11-12 01:54:30 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2021-11-12 01:54:30 +0700 |
commit | 8c32dba3fc4f2033e7597ee1999e793cf6552584 (patch) | |
tree | c48d45537cfbea6f7e0ab92de4793a2b35204573 /crypto/src/asn1/DerApplicationSpecific.cs | |
parent | Add new Equals method (diff) | |
download | BouncyCastle.NET-ed25519-8c32dba3fc4f2033e7597ee1999e793cf6552584.tar.xz |
Reimplement application-specific over tagged object
Diffstat (limited to 'crypto/src/asn1/DerApplicationSpecific.cs')
-rw-r--r-- | crypto/src/asn1/DerApplicationSpecific.cs | 334 |
1 files changed, 164 insertions, 170 deletions
diff --git a/crypto/src/asn1/DerApplicationSpecific.cs b/crypto/src/asn1/DerApplicationSpecific.cs index bc48d24e5..39c2aec28 100644 --- a/crypto/src/asn1/DerApplicationSpecific.cs +++ b/crypto/src/asn1/DerApplicationSpecific.cs @@ -11,225 +11,219 @@ namespace Org.BouncyCastle.Asn1 public class DerApplicationSpecific : Asn1Object { - private readonly bool isConstructed; - private readonly int tag; - private readonly byte[] octets; - - internal DerApplicationSpecific( - bool isConstructed, - int tag, - byte[] octets) - { - this.isConstructed = isConstructed; - this.tag = tag; - this.octets = octets; - } - - public DerApplicationSpecific( - int tag, - byte[] octets) - : this(false, tag, octets) - { - } - - public DerApplicationSpecific( - int tag, - Asn1Encodable obj) - : this(true, tag, obj) - { - } - - public DerApplicationSpecific( - bool isExplicit, - int tag, - Asn1Encodable obj) - { - Asn1Object asn1Obj = obj.ToAsn1Object(); - - byte[] data = asn1Obj.GetDerEncoded(); - - this.isConstructed = Asn1TaggedObject.IsConstructed(isExplicit, asn1Obj); - this.tag = tag; - - if (isExplicit) - { - this.octets = data; - } - else - { - int lenBytes = GetLengthOfHeader(data); - byte[] tmp = new byte[data.Length - lenBytes]; - Array.Copy(data, lenBytes, tmp, 0, tmp.Length); - this.octets = tmp; - } - } - - public DerApplicationSpecific( - int tagNo, - Asn1EncodableVector vec) - { - this.tag = tagNo; - this.isConstructed = true; - MemoryStream bOut = new MemoryStream(); - - for (int i = 0; i != vec.Count; i++) - { - try - { - byte[] bs = vec[i].GetDerEncoded(); - bOut.Write(bs, 0, bs.Length); - } - catch (IOException e) - { - throw new InvalidOperationException("malformed object", e); - } - } - this.octets = bOut.ToArray(); - } - - private int GetLengthOfHeader( - byte[] data) - { - int length = data[1]; // TODO: assumes 1 byte tag - - if (length == 0x80) + public static DerApplicationSpecific GetInstance(object obj) + { + if (obj == null || obj is DerApplicationSpecific) { - return 2; // indefinite-length encoding + return (DerApplicationSpecific)obj; } - - if (length > 127) + else if (obj is byte[]) { - int size = length & 0x7f; - - // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here - if (size > 4) + try { - throw new InvalidOperationException("DER length more than 4 bytes: " + size); + return GetInstance(FromByteArray((byte[])obj)); + } + catch (IOException e) + { + throw new ArgumentException("failed to construct application-specific from byte[]: " + e.Message); } - - return size + 2; } - return 2; + throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj), "obj"); } - public bool IsConstructed() + internal readonly Asn1TaggedObject m_taggedObject; + + /** + * Create an application specific object from the passed in data. This will assume + * the data does not represent a constructed object. + * + * @param tagNo the tag number for this object. + * @param contentsOctets the encoding of the object's body. + */ + public DerApplicationSpecific(int tagNo, byte[] contentsOctets) + : this(new DerTaggedObject(false, Asn1Tags.Application, tagNo, new DerOctetString(contentsOctets))) { - return isConstructed; } - public byte[] GetContents() + /** + * Create an application specific object with a tagging of explicit/constructed. + * + * @param tag the tag number for this object. + * @param object the object to be contained. + */ + public DerApplicationSpecific(int tag, Asn1Encodable baseEncodable) + : this(true, tag, baseEncodable) { - return octets; } - public int ApplicationTag + /** + * Create an application specific object with the tagging style given by the value of explicit. + * + * @param explicit true if the object is explicitly tagged. + * @param tagNo the tag number for this object. + * @param baseEncodable the object to be contained. + */ + public DerApplicationSpecific(bool isExplicit, int tagNo, Asn1Encodable baseEncodable) + : this(new DerTaggedObject(isExplicit, Asn1Tags.Application, tagNo, baseEncodable)) { - get { return tag; } } - /** - * Return the enclosed object assuming explicit tagging. - * - * @return the resulting object - * @throws IOException if reconstruction fails. - */ - public Asn1Object GetObject() + /** + * Create an application specific object which is marked as constructed + * + * @param tagNo the tag number for this object. + * @param contentsElements the objects making up the application specific object. + */ + public DerApplicationSpecific(int tagNo, Asn1EncodableVector contentsElements) + : this(new DerTaggedObject(false, Asn1Tags.Application, tagNo, DerSequence.FromVector(contentsElements))) { - return FromByteArray(GetContents()); - } + } - /** - * Return the enclosed object assuming implicit tagging. - * - * @param derTagNo the type tag that should be applied to the object's contents. - * @return the resulting object - * @throws IOException if reconstruction fails. - */ - public Asn1Object GetObject( - int derTagNo) - { - if (derTagNo >= 0x1f) - throw new IOException("unsupported tag number"); + internal DerApplicationSpecific(Asn1TaggedObject taggedObject) + //: base(taggedObject.explicitness, CheckTagClass(taggedObject.tagClass), taggedObject.tagNo, + // taggedObject.obj) + { + CheckTagClass(taggedObject.TagClass); - byte[] orig = this.GetEncoded(); - byte[] tmp = ReplaceTagNumber(derTagNo, orig); + this.m_taggedObject = taggedObject; + } - if ((orig[0] & Asn1Tags.Constructed) != 0) - { - tmp[0] |= Asn1Tags.Constructed; - } + public int ApplicationTag + { + get { return m_taggedObject.TagNo; } + } - return FromByteArray(tmp); - } + public byte[] GetContents() + { + return m_taggedObject.GetContents(); + } - internal override bool EncodeConstructed(int encoding) + public Asn1Object GetEnclosedObject() { - return isConstructed; + return m_taggedObject.GetBaseObject().ToAsn1Object(); } - internal override int EncodedLength(int encoding, bool withID) + [Obsolete("Use GetEnclosedObject instead")] + public Asn1Object GetObject() { - return Asn1OutputStream.GetLengthOfEncodingDL(withID, tag, octets.Length); + return GetEnclosedObject(); } - internal override void Encode(Asn1OutputStream asn1Out, bool withID) + public Asn1Object GetObject(int tagNo) + { + // TODO[asn1] Implement Asn1TaggedObject.GetBaseUniversal + //return taggedObject.GetBaseUniversal(false, tagNo); + + if (tagNo >= 0x1F) + throw new IOException("unsupported tag number"); + + byte[] orig = this.GetEncoded(); + byte[] tmp = ReplaceTagNumber(tagNo, orig); + + if ((orig[0] & Asn1Tags.Constructed) != 0) + { + tmp[0] |= Asn1Tags.Constructed; + } + + return FromByteArray(tmp); + } + + public bool HasApplicationTag(int tagNo) + { + return m_taggedObject.HasTag(Asn1Tags.Application, tagNo); + } + + public bool IsConstructed() + { + return m_taggedObject.IsConstructed(); + } + + /** + * DerApplicationSpecific uses an internal Asn1TaggedObject for the + * implementation, and will soon be deprecated in favour of using + * Asn1TaggedObject with a tag class of {@link Asn1Tags#Application}. This method + * lets you get the internal Asn1TaggedObject so that client code can begin the + * migration. + */ + public Asn1TaggedObject TaggedObject { - int flags = Asn1Tags.Application; - if (isConstructed) - { - flags |= Asn1Tags.Constructed; - } + get { return m_taggedObject; } + } - asn1Out.WriteEncodingDL(withID, flags, tag, octets); - } + protected override bool Asn1Equals(Asn1Object asn1Object) + { + Asn1TaggedObject that; + if (asn1Object is DerApplicationSpecific) + { + that = ((DerApplicationSpecific)asn1Object).m_taggedObject; + } + else if (asn1Object is Asn1TaggedObject) + { + that = (Asn1TaggedObject)asn1Object; + } + else + { + return false; + } + + return m_taggedObject.Equals(that); + } - protected override bool Asn1Equals( - Asn1Object asn1Object) + protected override int Asn1GetHashCode() { - DerApplicationSpecific other = asn1Object as DerApplicationSpecific; + return m_taggedObject.CallAsn1GetHashCode(); + } - if (other == null) - return false; + internal override bool EncodeConstructed(int encoding) + { + return m_taggedObject.EncodeConstructed(encoding); + } - return this.isConstructed == other.isConstructed - && this.tag == other.tag - && Arrays.AreEqual(this.octets, other.octets); + internal override int EncodedLength(int encoding, bool withID) + { + return m_taggedObject.EncodedLength(encoding, withID); } - protected override int Asn1GetHashCode() - { - return isConstructed.GetHashCode() ^ tag.GetHashCode() ^ Arrays.GetHashCode(octets); + internal override void Encode(Asn1OutputStream asn1Out, bool withID) + { + m_taggedObject.Encode(asn1Out, withID); } - private byte[] ReplaceTagNumber( - int newTag, - byte[] input) - { - int tagNo = input[0] & 0x1f; - int index = 1; + private byte[] ReplaceTagNumber(int newTag, byte[] input) + { + int tagNo = input[0] & 0x1f; + int index = 1; // with tagged object tag number is bottom 5 bits, or stored at the start of the content - if (tagNo == 0x1f) - { - int b = input[index++]; + if (tagNo == 0x1f) + { + int b = input[index++]; // X.690-0207 8.1.2.4.2 - // "c) bits 7 to 1 of the first subsequent octet shall not all be zero." - if ((b & 0x7f) == 0) // Note: -1 will pass - throw new IOException("corrupted stream - invalid high tag number found"); + // "c) bits 7 to 1 of the first subsequent octet shall not all be zero." + if ((b & 0x7f) == 0) // Note: -1 will pass + throw new IOException("corrupted stream - invalid high tag number found"); while ((b & 0x80) != 0) - { - b = input[index++]; - } - } + { + b = input[index++]; + } + } int remaining = input.Length - index; byte[] tmp = new byte[1 + remaining]; tmp[0] = (byte)newTag; - Array.Copy(input, index, tmp, 1, remaining); - return tmp; - } + Array.Copy(input, index, tmp, 1, remaining); + return tmp; + } + + private static int CheckTagClass(int tagClass) + { + if (Asn1Tags.Application != tagClass) + throw new ArgumentException(); + + return tagClass; + } } } |