summary refs log tree commit diff
path: root/crypto/src/asn1/DERExternal.cs
blob: f457917cab03b782ce4e1517dfdaa34e6c4fbcee (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
using System;
using System.IO;

using Org.BouncyCastle.Utilities;

namespace Org.BouncyCastle.Asn1
{
	/**
	* Class representing the DER-type External
	*/
	public class DerExternal
		: Asn1Object
	{
		private DerObjectIdentifier	directReference;
		private DerInteger			indirectReference;
		private Asn1Object			dataValueDescriptor;
		private int					encoding;
		private Asn1Object			externalContent;

		public DerExternal(
			Asn1EncodableVector vector)
		{
			int offset = 0;
			Asn1Object enc = GetObjFromVector(vector, offset);
			if (enc is DerObjectIdentifier)
			{
				directReference = (DerObjectIdentifier)enc;
				offset++;
				enc = GetObjFromVector(vector, offset);
			}
			if (enc is DerInteger)
			{
				indirectReference = (DerInteger) enc;
				offset++;
				enc = GetObjFromVector(vector, offset);
			}
			if (!(enc is Asn1TaggedObject))
			{
				dataValueDescriptor = enc;
				offset++;
				enc = GetObjFromVector(vector, offset);
			}

            if (vector.Count != offset + 1)
				throw new ArgumentException("input vector too large", "vector");

            if (!(enc is Asn1TaggedObject))
				throw new ArgumentException("No tagged object found in vector. Structure doesn't seem to be of type External", "vector");

            Asn1TaggedObject obj = (Asn1TaggedObject)enc;

			// Use property accessor to include check on value
			Encoding = obj.TagNo;

			if (encoding < 0 || encoding > 2)
				throw new InvalidOperationException("invalid encoding value");

			externalContent = obj.GetObject();
		}

		/**
		* Creates a new instance of DerExternal
		* See X.690 for more informations about the meaning of these parameters
		* @param directReference The direct reference or <code>null</code> if not set.
		* @param indirectReference The indirect reference or <code>null</code> if not set.
		* @param dataValueDescriptor The data value descriptor or <code>null</code> if not set.
		* @param externalData The external data in its encoded form.
		*/
		public DerExternal(DerObjectIdentifier directReference, DerInteger indirectReference, Asn1Object dataValueDescriptor, DerTaggedObject externalData)
			: this(directReference, indirectReference, dataValueDescriptor, externalData.TagNo, externalData.ToAsn1Object())
		{
		}

		/**
		* Creates a new instance of DerExternal.
		* See X.690 for more informations about the meaning of these parameters
		* @param directReference The direct reference or <code>null</code> if not set.
		* @param indirectReference The indirect reference or <code>null</code> if not set.
		* @param dataValueDescriptor The data value descriptor or <code>null</code> if not set.
		* @param encoding The encoding to be used for the external data
		* @param externalData The external data
		*/
		public DerExternal(DerObjectIdentifier directReference, DerInteger indirectReference, Asn1Object dataValueDescriptor, int encoding, Asn1Object externalData)
		{
			DirectReference = directReference;
			IndirectReference = indirectReference;
			DataValueDescriptor = dataValueDescriptor;
			Encoding = encoding;
			ExternalContent = externalData.ToAsn1Object();
		}

        internal override int EncodedLength(bool withID)
        {
            int contentsLength = 0;
            if (directReference != null)
            {
                contentsLength += directReference.EncodedLength(true);
            }
            if (indirectReference != null)
            {
                contentsLength += indirectReference.EncodedLength(true);
            }
            if (dataValueDescriptor != null)
            {
                // TODO[asn1]
                //contentsLength += dataValueDescriptor.ToDerObject().EncodedLength(true);
                contentsLength += dataValueDescriptor.GetDerEncoded().Length;
            }

            // TODO[asn1]
            //contentsLength += new DerTaggedObject(true, encoding, externalContent).EncodedLength(true);
            contentsLength += new DerTaggedObject(Asn1Tags.External, externalContent).EncodedLength(true);

            return Asn1OutputStream.GetLengthOfEncodingDL(withID, contentsLength);
        }

        internal override void Encode(Asn1OutputStream asn1Out, bool withID)
		{
			MemoryStream ms = new MemoryStream();
			WriteEncodable(ms, directReference);
			WriteEncodable(ms, indirectReference);
			WriteEncodable(ms, dataValueDescriptor);
			WriteEncodable(ms, new DerTaggedObject(Asn1Tags.External, externalContent));

            asn1Out.WriteEncodingDL(withID, Asn1Tags.Constructed | Asn1Tags.External, ms.ToArray());
		}

		protected override int Asn1GetHashCode()
		{
			int ret = externalContent.GetHashCode();
			if (directReference != null)
			{
				ret ^= directReference.GetHashCode();
			}
			if (indirectReference != null)
			{
				ret ^= indirectReference.GetHashCode();
			}
			if (dataValueDescriptor != null)
			{
				ret ^= dataValueDescriptor.GetHashCode();
			}
			return ret;
		}

		protected override bool Asn1Equals(
			Asn1Object asn1Object)
		{
			if (this == asn1Object)
				return true;

			DerExternal other = asn1Object as DerExternal;

			if (other == null)
				return false;

			return Platform.Equals(directReference, other.directReference)
				&& Platform.Equals(indirectReference, other.indirectReference)
				&& Platform.Equals(dataValueDescriptor, other.dataValueDescriptor)
				&& externalContent.Equals(other.externalContent);
		}

		public Asn1Object DataValueDescriptor
		{
			get { return dataValueDescriptor; }
			set { this.dataValueDescriptor = value; }
		}

		public DerObjectIdentifier DirectReference
		{
			get { return directReference; }
			set { this.directReference = value; }
		}

		/**
		* The encoding of the content. Valid values are
		* <ul>
		* <li><code>0</code> single-ASN1-type</li>
		* <li><code>1</code> OCTET STRING</li>
		* <li><code>2</code> BIT STRING</li>
		* </ul>
		*/
		public int Encoding
		{
			get
			{
				return encoding;
			}
			set
			{
				if (encoding < 0 || encoding > 2)
					throw new InvalidOperationException("invalid encoding value: " + encoding);

				this.encoding = value;
			}
		}

		public Asn1Object ExternalContent
		{
			get { return externalContent; }
			set { this.externalContent = value; }
		}

		public DerInteger IndirectReference
		{
			get { return indirectReference; }
			set { this.indirectReference = value; }
		}

		private static Asn1Object GetObjFromVector(Asn1EncodableVector v, int index)
		{
			if (v.Count <= index)
				throw new ArgumentException("too few objects in input vector", "v");

			return v[index].ToAsn1Object();
		}

		private static void WriteEncodable(MemoryStream ms, Asn1Encodable e)
		{
			if (e != null)
			{
				byte[] bs = e.GetDerEncoded();
				ms.Write(bs, 0, bs.Length);
			}
		}
	}
}