2 * FreeRDP: A Remote Desktop Protocol Client
3 * ASN.1 Basic Encoding Rules (BER)
5 * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
22 void ber_read_length(STREAM* s, int* length)
26 stream_read_uint8(s, byte);
33 stream_read_uint8(s, *length);
35 stream_read_uint16_be(s, *length);
46 * @param length length
49 int ber_write_length(STREAM* s, int length)
53 stream_write_uint8(s, 0x82);
54 stream_write_uint16_be(s, length);
59 stream_write_uint8(s, length);
64 int _ber_skip_length(int length)
72 int ber_get_content_length(int length)
74 if (length - 1 > 0x7F)
81 * Read BER Universal tag.
83 * @param tag BER universally-defined tag
87 boolean ber_read_universal_tag(STREAM* s, uint8 tag, boolean pc)
91 stream_read_uint8(s, byte);
93 if (byte != (BER_CLASS_UNIV | BER_PC(pc) | (BER_TAG_MASK & tag)))
100 * Write BER Universal tag.
102 * @param tag BER universally-defined tag
103 * @param pc primitive (false) or constructed (true)
106 void ber_write_universal_tag(STREAM* s, uint8 tag, boolean pc)
108 stream_write_uint8(s, (BER_CLASS_UNIV | BER_PC(pc)) | (BER_TAG_MASK & tag));
112 * Read BER Application tag.
114 * @param tag BER application-defined tag
115 * @param length length
118 boolean ber_read_application_tag(STREAM* s, uint8 tag, int* length)
124 stream_read_uint8(s, byte);
126 if (byte != ((BER_CLASS_APPL | BER_CONSTRUCT) | BER_TAG_MASK))
129 stream_read_uint8(s, byte);
134 ber_read_length(s, length);
138 stream_read_uint8(s, byte);
140 if (byte != ((BER_CLASS_APPL | BER_CONSTRUCT) | (BER_TAG_MASK & tag)))
143 ber_read_length(s, length);
150 * Write BER Application tag.
152 * @param tag BER application-defined tag
153 * @param length length
156 void ber_write_application_tag(STREAM* s, uint8 tag, int length)
160 stream_write_uint8(s, (BER_CLASS_APPL | BER_CONSTRUCT) | BER_TAG_MASK);
161 stream_write_uint8(s, tag);
162 ber_write_length(s, length);
166 stream_write_uint8(s, (BER_CLASS_APPL | BER_CONSTRUCT) | (BER_TAG_MASK & tag));
167 ber_write_length(s, length);
171 boolean ber_read_contextual_tag(STREAM* s, uint8 tag, int* length, boolean pc)
175 stream_read_uint8(s, byte);
177 if (byte != ((BER_CLASS_CTXT | BER_PC(pc)) | (BER_TAG_MASK & tag)))
183 ber_read_length(s, length);
188 int ber_write_contextual_tag(STREAM* s, uint8 tag, int length, boolean pc)
190 stream_write_uint8(s, (BER_CLASS_CTXT | BER_PC(pc)) | (BER_TAG_MASK & tag));
191 return ber_write_length(s, length) + 1;
194 int ber_skip_contextual_tag(int length)
196 return _ber_skip_length(length) + 1;
199 boolean ber_read_sequence_tag(STREAM* s, int* length)
203 stream_read_uint8(s, byte);
205 if (byte != ((BER_CLASS_UNIV | BER_CONSTRUCT) | (BER_TAG_SEQUENCE_OF)))
208 ber_read_length(s, length);
214 * Write BER SEQUENCE tag.
216 * @param length length
219 int ber_write_sequence_tag(STREAM* s, int length)
221 stream_write_uint8(s, (BER_CLASS_UNIV | BER_CONSTRUCT) | (BER_TAG_MASK & BER_TAG_SEQUENCE));
222 return ber_write_length(s, length) + 1;
225 int ber_skip_sequence(int length)
227 return 1 + _ber_skip_length(length) + length;
230 int ber_skip_sequence_tag(int length)
232 return 1 + _ber_skip_length(length);
235 boolean ber_read_enumerated(STREAM* s, uint8* enumerated, uint8 count)
239 ber_read_universal_tag(s, BER_TAG_ENUMERATED, false);
240 ber_read_length(s, &length);
243 stream_read_uint8(s, *enumerated);
247 /* check that enumerated value falls within expected range */
248 if (*enumerated + 1 > count)
254 void ber_write_enumerated(STREAM* s, uint8 enumerated, uint8 count)
256 ber_write_universal_tag(s, BER_TAG_ENUMERATED, false);
257 ber_write_length(s, 1);
258 stream_write_uint8(s, enumerated);
261 boolean ber_read_bit_string(STREAM* s, int* length, uint8* padding)
263 ber_read_universal_tag(s, BER_TAG_BIT_STRING, false);
264 ber_read_length(s, length);
265 stream_read_uint8(s, *padding);
270 boolean ber_read_octet_string(STREAM* s, int* length)
272 ber_read_universal_tag(s, BER_TAG_OCTET_STRING, false);
273 ber_read_length(s, length);
279 * Write a BER OCTET_STRING
281 * @param oct_str octet string
282 * @param length string length
285 void ber_write_octet_string(STREAM* s, const uint8* oct_str, int length)
287 ber_write_universal_tag(s, BER_TAG_OCTET_STRING, false);
288 ber_write_length(s, length);
289 stream_write(s, oct_str, length);
292 int ber_write_octet_string_tag(STREAM* s, int length)
294 ber_write_universal_tag(s, BER_TAG_OCTET_STRING, false);
295 ber_write_length(s, length);
296 return 1 + _ber_skip_length(length);
299 int ber_skip_octet_string(int length)
301 return 1 + _ber_skip_length(length) + length;
310 boolean ber_read_boolean(STREAM* s, boolean* value)
315 if (!ber_read_universal_tag(s, BER_TAG_BOOLEAN, false))
317 ber_read_length(s, &length);
320 stream_read_uint8(s, v);
321 *value = (v ? true : false);
326 * Write a BER BOOLEAN
331 void ber_write_boolean(STREAM* s, boolean value)
333 ber_write_universal_tag(s, BER_TAG_BOOLEAN, false);
334 ber_write_length(s, 1);
335 stream_write_uint8(s, (value == true) ? 0xFF : 0);
338 boolean ber_read_integer(STREAM* s, uint32* value)
342 ber_read_universal_tag(s, BER_TAG_INTEGER, false);
343 ber_read_length(s, &length);
347 stream_seek(s, length);
352 stream_read_uint8(s, *value);
353 else if (length == 2)
354 stream_read_uint16_be(s, *value);
355 else if (length == 3)
358 stream_read_uint8(s, byte);
359 stream_read_uint16_be(s, *value);
360 *value += (byte << 16);
362 else if (length == 4)
363 stream_read_uint32_be(s, *value);
371 * Write a BER INTEGER
376 int ber_write_integer(STREAM* s, uint32 value)
378 ber_write_universal_tag(s, BER_TAG_INTEGER, false);
382 ber_write_length(s, 1);
383 stream_write_uint8(s, value);
386 else if (value < 0xFF80)
388 ber_write_length(s, 2);
389 stream_write_uint16_be(s, value);
392 else if (value < 0xFF8000)
394 ber_write_length(s, 3);
395 stream_write_uint8(s, (value >> 16));
396 stream_write_uint16_be(s, (value & 0xFFFF));
399 else if (value <= 0xFFFFFFFF)
401 ber_write_length(s, 4);
402 stream_write_uint32_be(s, value);
409 int ber_skip_integer(uint32 value)
413 return _ber_skip_length(1) + 2;
415 else if (value <= 0xFFFF)
417 return _ber_skip_length(2) + 3;
419 else if (value <= 0xFFFFFFFF)
421 return _ber_skip_length(4) + 5;
427 boolean ber_read_integer_length(STREAM* s, int* length)
429 ber_read_universal_tag(s, BER_TAG_INTEGER, false);
430 ber_read_length(s, length);