20 #include <freerdp/config.h>
23 #include <winpr/assert.h>
24 #include <winpr/crt.h>
25 #include <winpr/string.h>
27 #include <freerdp/log.h>
28 #include <freerdp/crypto/ber.h>
30 #define TAG FREERDP_TAG("crypto")
32 BOOL ber_read_length(
wStream* s,
size_t* length)
39 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
42 Stream_Read_UINT8(s,
byte);
48 if (!Stream_CheckAndLogRequiredLength(TAG, s,
byte))
52 Stream_Read_UINT8(s, *length);
54 Stream_Read_UINT16_BE(s, *length);
57 WLog_ERR(TAG,
"ber: unexpected byte 0x%02" PRIx8
", expected [1,2]",
byte);
75 size_t ber_write_length(
wStream* s,
size_t length)
81 WINPR_ASSERT(length <= UINT16_MAX);
82 WINPR_ASSERT(Stream_GetRemainingCapacity(s) >= 3);
83 Stream_Write_UINT8(s, 0x80 ^ 2);
84 Stream_Write_UINT16_BE(s, (UINT16)length);
88 WINPR_ASSERT(length <= UINT8_MAX);
91 WINPR_ASSERT(Stream_GetRemainingCapacity(s) >= 2);
92 Stream_Write_UINT8(s, 0x80 ^ 1);
93 Stream_Write_UINT8(s, (UINT8)length);
97 WINPR_ASSERT(Stream_GetRemainingCapacity(s) >= 1);
98 Stream_Write_UINT8(s, (UINT8)length);
102 size_t _ber_sizeof_length(
size_t length)
122 BOOL ber_read_universal_tag(
wStream* s, BYTE tag, BOOL pc)
125 const BYTE expect = (BER_CLASS_UNIV | BER_PC(pc) | (BER_TAG_MASK & tag));
129 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
132 Stream_Read_UINT8(s,
byte);
136 WLog_WARN(TAG,
"invalid tag, got 0x%02" PRIx8
", expected 0x%02" PRIx8,
byte, expect);
150 size_t ber_write_universal_tag(
wStream* s, BYTE tag, BOOL pc)
153 Stream_Write_UINT8(s, (BER_CLASS_UNIV | BER_PC(pc)) | (BER_TAG_MASK & tag));
164 BOOL ber_read_application_tag(
wStream* s, BYTE tag,
size_t* length)
169 WINPR_ASSERT(length);
173 const BYTE expect = ((BER_CLASS_APPL | BER_CONSTRUCT) | BER_TAG_MASK);
175 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
178 Stream_Read_UINT8(s,
byte);
182 WLog_WARN(TAG,
"invalid tag, got 0x%02" PRIx8
", expected 0x%02" PRIx8,
byte, expect);
186 Stream_Read_UINT8(s,
byte);
190 WLog_WARN(TAG,
"invalid tag, got 0x%02" PRIx8
", expected 0x%02" PRIx8,
byte, tag);
194 return ber_read_length(s, length);
198 const BYTE expect = ((BER_CLASS_APPL | BER_CONSTRUCT) | (BER_TAG_MASK & tag));
200 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
203 Stream_Read_UINT8(s,
byte);
207 WLog_WARN(TAG,
"invalid tag, got 0x%02" PRIx8
", expected 0x%02" PRIx8,
byte, expect);
211 return ber_read_length(s, length);
224 void ber_write_application_tag(
wStream* s, BYTE tag,
size_t length)
230 WINPR_ASSERT(Stream_GetRemainingCapacity(s) >= 2);
231 Stream_Write_UINT8(s, (BER_CLASS_APPL | BER_CONSTRUCT) | BER_TAG_MASK);
232 Stream_Write_UINT8(s, tag);
233 ber_write_length(s, length);
237 WINPR_ASSERT(Stream_GetRemainingCapacity(s) >= 1);
238 Stream_Write_UINT8(s, (BER_CLASS_APPL | BER_CONSTRUCT) | (BER_TAG_MASK & tag));
239 ber_write_length(s, length);
243 BOOL ber_read_contextual_tag(
wStream* s, BYTE tag,
size_t* length, BOOL pc)
245 const BYTE expect = ((BER_CLASS_CTXT | BER_PC(pc)) | (BER_TAG_MASK & tag));
249 WINPR_ASSERT(length);
251 if (Stream_GetRemainingLength(s) < 1)
253 WLog_VRB(TAG,
"short data, got %" PRIuz
", expected %" PRIuz, Stream_GetRemainingLength(s),
258 Stream_Read_UINT8(s,
byte);
262 WLog_VRB(TAG,
"invalid tag, got 0x%02" PRIx8
", expected 0x%02" PRIx8,
byte, expect);
267 return ber_read_length(s, length);
270 size_t ber_write_contextual_tag(
wStream* s, BYTE tag,
size_t length, BOOL pc)
273 WINPR_ASSERT(Stream_GetRemainingCapacity(s) >= 1);
274 Stream_Write_UINT8(s, (BER_CLASS_CTXT | BER_PC(pc)) | (BER_TAG_MASK & tag));
275 return 1 + ber_write_length(s, length);
278 size_t ber_sizeof_contextual_tag(
size_t length)
280 return 1 + _ber_sizeof_length(length);
283 BOOL ber_read_sequence_tag(
wStream* s,
size_t* length)
285 const BYTE expect = ((BER_CLASS_UNIV | BER_CONSTRUCT) | (BER_TAG_SEQUENCE_OF));
288 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
291 Stream_Read_UINT8(s,
byte);
295 WLog_WARN(TAG,
"invalid tag, got 0x%02" PRIx8
", expected 0x%02" PRIx8,
byte, expect);
299 return ber_read_length(s, length);
308 size_t ber_write_sequence_tag(
wStream* s,
size_t length)
310 Stream_Write_UINT8(s, (BER_CLASS_UNIV | BER_CONSTRUCT) | (BER_TAG_MASK & BER_TAG_SEQUENCE));
311 return 1 + ber_write_length(s, length);
314 size_t ber_sizeof_sequence(
size_t length)
316 return 1 + _ber_sizeof_length(length) + length;
319 size_t ber_sizeof_sequence_tag(
size_t length)
321 return 1 + _ber_sizeof_length(length);
324 BOOL ber_read_enumerated(
wStream* s, BYTE* enumerated, BYTE count)
328 WINPR_ASSERT(enumerated);
330 if (!ber_read_universal_tag(s, BER_TAG_ENUMERATED, FALSE) || !ber_read_length(s, &length))
335 WLog_WARN(TAG,
"short data, got %" PRIuz
", expected %" PRIuz, length, 1);
338 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
341 Stream_Read_UINT8(s, *enumerated);
344 if (*enumerated + 1 > count)
346 WLog_WARN(TAG,
"invalid data, expected %" PRIu8
" < %" PRIu8, *enumerated, count);
353 void ber_write_enumerated(
wStream* s, BYTE enumerated, BYTE count)
355 ber_write_universal_tag(s, BER_TAG_ENUMERATED, FALSE);
356 ber_write_length(s, 1);
357 Stream_Write_UINT8(s, enumerated);
360 BOOL ber_read_bit_string(
wStream* s,
size_t* length, BYTE* padding)
362 if (!ber_read_universal_tag(s, BER_TAG_BIT_STRING, FALSE) || !ber_read_length(s, length))
365 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
368 Stream_Read_UINT8(s, *padding);
379 size_t ber_write_octet_string(
wStream* s,
const BYTE* oct_str,
size_t length)
383 WINPR_ASSERT(oct_str || (length == 0));
384 size += ber_write_universal_tag(s, BER_TAG_OCTET_STRING, FALSE);
385 size += ber_write_length(s, length);
386 Stream_Write(s, oct_str, length);
391 size_t ber_write_contextual_octet_string(
wStream* s, BYTE tag,
const BYTE* oct_str,
size_t length)
393 size_t inner = ber_sizeof_octet_string(length);
397 ret = ber_write_contextual_tag(s, tag, inner, TRUE);
401 r = ber_write_octet_string(s, oct_str, length);
407 size_t ber_write_char_to_unicode_octet_string(
wStream* s,
const char* str)
411 size_t length = strlen(str) + 1;
412 size += ber_write_universal_tag(s, BER_TAG_OCTET_STRING, FALSE);
413 size += ber_write_length(s, length *
sizeof(WCHAR));
415 if (Stream_Write_UTF16_String_From_UTF8(s, length, str, length, TRUE) < 0)
417 return size + length *
sizeof(WCHAR);
420 size_t ber_write_contextual_unicode_octet_string(
wStream* s, BYTE tag, LPWSTR str)
423 size_t len = _wcslen(str) *
sizeof(WCHAR);
424 size_t inner_len = ber_sizeof_octet_string(len);
427 ret = ber_write_contextual_tag(s, tag, inner_len, TRUE);
428 return ret + ber_write_octet_string(s, (
const BYTE*)str, len);
431 size_t ber_write_contextual_char_to_unicode_octet_string(
wStream* s, BYTE tag,
const char* str)
434 size_t len = strlen(str);
435 size_t inner_len = ber_sizeof_octet_string(len * 2);
437 WINPR_ASSERT(Stream_GetRemainingCapacity(s) < ber_sizeof_contextual_tag(inner_len) + inner_len);
439 ret = ber_write_contextual_tag(s, tag, inner_len, TRUE);
440 ret += ber_write_universal_tag(s, BER_TAG_OCTET_STRING, FALSE);
441 ret += ber_write_length(s, len *
sizeof(WCHAR));
443 if (Stream_Write_UTF16_String_From_UTF8(s, len, str, len, TRUE) < 0)
449 BOOL ber_read_unicode_octet_string(
wStream* s, LPWSTR* str)
454 if (!ber_read_octet_string_tag(s, &length))
457 if (!Stream_CheckAndLogRequiredLength(TAG, s, length))
460 ret = calloc(1, length + 2);
464 memcpy(ret, Stream_ConstPointer(s), length);
466 Stream_Seek(s, length);
471 BOOL ber_read_char_from_unicode_octet_string(
wStream* s,
char** str)
477 if (!ber_read_octet_string_tag(s, &length))
480 ptr = Stream_Read_UTF16_String_As_UTF8(s, length /
sizeof(WCHAR), NULL);
487 BOOL ber_read_octet_string_tag(
wStream* s,
size_t* length)
489 return ber_read_universal_tag(s, BER_TAG_OCTET_STRING, FALSE) && ber_read_length(s, length);
492 BOOL ber_read_octet_string(
wStream* s, BYTE** content,
size_t* length)
497 WINPR_ASSERT(content);
498 WINPR_ASSERT(length);
500 if (!ber_read_octet_string_tag(s, length))
502 if (!Stream_CheckAndLogRequiredLength(TAG, s, *length))
505 ret = malloc(*length);
509 Stream_Read(s, ret, *length);
514 size_t ber_write_octet_string_tag(
wStream* s,
size_t length)
516 ber_write_universal_tag(s, BER_TAG_OCTET_STRING, FALSE);
517 ber_write_length(s, length);
518 return 1 + _ber_sizeof_length(length);
521 size_t ber_sizeof_octet_string(
size_t length)
523 return 1 + _ber_sizeof_length(length) + length;
526 size_t ber_sizeof_contextual_octet_string(
size_t length)
528 size_t ret = ber_sizeof_octet_string(length);
529 return ber_sizeof_contextual_tag(ret) + ret;
540 BOOL ber_read_BOOL(
wStream* s, BOOL* value)
546 if (!ber_read_universal_tag(s, BER_TAG_BOOLEAN, FALSE) || !ber_read_length(s, &length))
551 WLog_WARN(TAG,
"short data, got %" PRIuz
", expected %" PRIuz, length, 1);
554 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
557 Stream_Read_UINT8(s, v);
558 *value = (v ? TRUE : FALSE);
569 void ber_write_BOOL(
wStream* s, BOOL value)
571 ber_write_universal_tag(s, BER_TAG_BOOLEAN, FALSE);
572 ber_write_length(s, 1);
573 Stream_Write_UINT8(s, (value == TRUE) ? 0xFF : 0);
576 BOOL ber_read_integer(
wStream* s, UINT32* value)
582 if (!ber_read_universal_tag(s, BER_TAG_INTEGER, FALSE))
584 if (!ber_read_length(s, &length))
586 if (!Stream_CheckAndLogRequiredLength(TAG, s, length))
592 return Stream_SafeSeek(s, length);
597 Stream_Read_UINT8(s, *value);
599 else if (length == 2)
601 Stream_Read_UINT16_BE(s, *value);
603 else if (length == 3)
606 Stream_Read_UINT8(s,
byte);
607 Stream_Read_UINT16_BE(s, *value);
608 *value += (
byte << 16);
610 else if (length == 4)
612 Stream_Read_UINT32_BE(s, *value);
614 else if (length == 8)
616 WLog_ERR(TAG,
"should implement reading an 8 bytes integer");
621 WLog_ERR(TAG,
"should implement reading an integer with length=%" PRIuz, length);
637 size_t ber_write_integer(
wStream* s, UINT32 value)
643 ber_write_universal_tag(s, BER_TAG_INTEGER, FALSE);
644 ber_write_length(s, 1);
646 Stream_Write_UINT8(s, value);
649 else if (value < 0x8000)
651 ber_write_universal_tag(s, BER_TAG_INTEGER, FALSE);
652 ber_write_length(s, 2);
654 Stream_Write_UINT16_BE(s, value);
657 else if (value < 0x800000)
659 ber_write_universal_tag(s, BER_TAG_INTEGER, FALSE);
660 ber_write_length(s, 3);
662 Stream_Write_UINT8(s, (value >> 16));
663 Stream_Write_UINT16_BE(s, (value & 0xFFFF));
666 else if (value < 0x80000000)
668 ber_write_universal_tag(s, BER_TAG_INTEGER, FALSE);
669 ber_write_length(s, 4);
671 Stream_Write_UINT32_BE(s, value);
677 ber_write_universal_tag(s, BER_TAG_INTEGER, FALSE);
678 ber_write_length(s, 4);
680 Stream_Write_UINT32_BE(s, value);
685 size_t ber_write_contextual_integer(
wStream* s, BYTE tag, UINT32 value)
687 size_t len = ber_sizeof_integer(value);
691 WINPR_ASSERT(Stream_EnsureRemainingCapacity(s, len + 5));
693 len += ber_write_contextual_tag(s, tag, len, TRUE);
694 ber_write_integer(s, value);
698 size_t ber_sizeof_integer(UINT32 value)
704 else if (value < 0x8000)
708 else if (value < 0x800000)
712 else if (value < 0x80000000)
723 size_t ber_sizeof_contextual_integer(UINT32 value)
725 size_t intSize = ber_sizeof_integer(value);
726 return ber_sizeof_contextual_tag(intSize) + intSize;
729 BOOL ber_read_integer_length(
wStream* s,
size_t* length)
731 return ber_read_universal_tag(s, BER_TAG_INTEGER, FALSE) && ber_read_length(s, length);