20 #include <winpr/assert.h>
21 #include <winpr/print.h>
23 #include <freerdp/config.h>
24 #include <freerdp/crypto/per.h>
26 #include <freerdp/log.h>
27 #define TAG FREERDP_TAG("crypto.per")
38 BOOL per_read_length(
wStream* s, UINT16* length)
43 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
46 Stream_Read_UINT8(s,
byte);
50 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
54 *length = (
byte << 8);
55 Stream_Read_UINT8(s,
byte);
74 BOOL per_write_length(
wStream* s, UINT16 length)
78 if (!Stream_EnsureRemainingCapacity(s, 2))
80 Stream_Write_UINT16_BE(s, (length | 0x8000));
84 if (!Stream_EnsureRemainingCapacity(s, 1))
86 Stream_Write_UINT8(s, (UINT8)length);
99 BOOL per_read_choice(
wStream* s, BYTE* choice)
101 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
104 Stream_Read_UINT8(s, *choice);
116 BOOL per_write_choice(
wStream* s, BYTE choice)
118 if (!Stream_EnsureRemainingCapacity(s, 1))
120 Stream_Write_UINT8(s, choice);
132 BOOL per_read_selection(
wStream* s, BYTE* selection)
134 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
137 WINPR_ASSERT(selection);
138 Stream_Read_UINT8(s, *selection);
150 BOOL per_write_selection(
wStream* s, BYTE selection)
152 if (!Stream_EnsureRemainingCapacity(s, 1))
154 Stream_Write_UINT8(s, selection);
166 BOOL per_read_number_of_sets(
wStream* s, BYTE* number)
168 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
171 WINPR_ASSERT(number);
172 Stream_Read_UINT8(s, *number);
185 BOOL per_write_number_of_sets(
wStream* s, BYTE number)
187 if (!Stream_EnsureRemainingCapacity(s, 1))
189 Stream_Write_UINT8(s, number);
202 BOOL per_read_padding(
wStream* s, UINT16 length)
204 if (!Stream_CheckAndLogRequiredLength(TAG, s, length))
207 Stream_Seek(s, length);
219 BOOL per_write_padding(
wStream* s, UINT16 length)
221 if (!Stream_EnsureRemainingCapacity(s, length))
223 Stream_Zero(s, length);
235 BOOL per_read_integer(
wStream* s, UINT32* integer)
239 WINPR_ASSERT(integer);
241 if (!per_read_length(s, &length))
244 if (!Stream_CheckAndLogRequiredLength(TAG, s, length))
249 else if (length == 1)
250 Stream_Read_UINT8(s, *integer);
251 else if (length == 2)
252 Stream_Read_UINT16_BE(s, *integer);
267 BOOL per_write_integer(
wStream* s, UINT32 integer)
269 if (integer <= UINT8_MAX)
271 if (!per_write_length(s, 1))
273 if (!Stream_EnsureRemainingCapacity(s, 1))
275 Stream_Write_UINT8(s, integer);
277 else if (integer <= UINT16_MAX)
279 if (!per_write_length(s, 2))
281 if (!Stream_EnsureRemainingCapacity(s, 2))
283 Stream_Write_UINT16_BE(s, integer);
285 else if (integer <= UINT32_MAX)
287 if (!per_write_length(s, 4))
289 if (!Stream_EnsureRemainingCapacity(s, 4))
291 Stream_Write_UINT32_BE(s, integer);
306 BOOL per_read_integer16(
wStream* s, UINT16* integer, UINT16 min)
308 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
311 Stream_Read_UINT16_BE(s, *integer);
313 if (*integer > UINT16_MAX - min)
315 WLog_WARN(TAG,
"PER uint16 invalid value %" PRIu16
" > %" PRIu16, *integer,
334 BOOL per_write_integer16(
wStream* s, UINT16 integer, UINT16 min)
338 if (!Stream_EnsureRemainingCapacity(s, 2))
340 Stream_Write_UINT16_BE(s, integer - min);
354 BOOL per_read_enumerated(
wStream* s, BYTE* enumerated, BYTE count)
356 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
359 WINPR_ASSERT(enumerated);
360 Stream_Read_UINT8(s, *enumerated);
363 if (*enumerated + 1 > count)
365 WLog_WARN(TAG,
"PER invalid data, expected %" PRIu8
" < %" PRIu8, *enumerated, count);
382 BOOL per_write_enumerated(
wStream* s, BYTE enumerated, BYTE count)
384 if (!Stream_EnsureRemainingCapacity(s, 1))
386 Stream_Write_UINT8(s, enumerated);
390 static BOOL per_check_oid_and_log_mismatch(
const BYTE* got,
const BYTE* expect,
size_t length)
392 if (memcmp(got, expect, length) == 0)
398 char* got_str = winpr_BinToHexString(got, length, TRUE);
399 char* expect_str = winpr_BinToHexString(expect, length, TRUE);
401 WLog_WARN(TAG,
"PER OID mismatch, got %s, expected %s", got_str, expect_str);
418 BOOL per_read_object_identifier(
wStream* s,
const BYTE oid[6])
422 BYTE a_oid[6] = { 0 };
424 if (!per_read_length(s, &length))
429 WLog_WARN(TAG,
"PER length, got %" PRIu16
", expected 5", length);
433 if (!Stream_CheckAndLogRequiredLength(TAG, s, length))
436 Stream_Read_UINT8(s, t12);
440 Stream_Read_UINT8(s, a_oid[2]);
441 Stream_Read_UINT8(s, a_oid[3]);
442 Stream_Read_UINT8(s, a_oid[4]);
443 Stream_Read_UINT8(s, a_oid[5]);
445 return per_check_oid_and_log_mismatch(a_oid, oid,
sizeof(a_oid));
457 BOOL per_write_object_identifier(
wStream* s,
const BYTE oid[6])
459 BYTE t12 = oid[0] * 40 + oid[1];
460 if (!Stream_EnsureRemainingCapacity(s, 6))
462 Stream_Write_UINT8(s, 5);
463 Stream_Write_UINT8(s, t12);
464 Stream_Write_UINT8(s, oid[2]);
465 Stream_Write_UINT8(s, oid[3]);
466 Stream_Write_UINT8(s, oid[4]);
467 Stream_Write_UINT8(s, oid[5]);
478 static void per_write_string(
wStream* s, BYTE* str,
int length)
480 for (
int i = 0; i < length; i++)
481 Stream_Write_UINT8(s, str[i]);
495 BOOL per_read_octet_string(
wStream* s,
const BYTE* oct_str, UINT16 length, UINT16 min)
499 if (!per_read_length(s, &mlength))
502 if (mlength + min != length)
504 WLog_ERR(TAG,
"length mismatch: %" PRIu16
"!= %" PRIu16, mlength + min, length);
508 if (!Stream_CheckAndLogRequiredLength(TAG, s, length))
511 const BYTE* a_oct_str = Stream_ConstPointer(s);
512 Stream_Seek(s, length);
514 return per_check_oid_and_log_mismatch(a_oct_str, oct_str, length);
527 BOOL per_write_octet_string(
wStream* s,
const BYTE* oct_str, UINT16 length, UINT16 min)
531 mlength = (length >= min) ? length - min : min;
533 if (!per_write_length(s, mlength))
536 if (!Stream_EnsureRemainingCapacity(s, length))
538 for (UINT16 i = 0; i < length; i++)
539 Stream_Write_UINT8(s, oct_str[i]);
551 BOOL per_read_numeric_string(
wStream* s, UINT16 min)
556 if (!per_read_length(s, &mlength))
559 length = (mlength + min + 1) / 2;
561 if (!Stream_CheckAndLogRequiredLength(TAG, s, length))
564 Stream_Seek(s, length);
578 BOOL per_write_numeric_string(
wStream* s,
const BYTE* num_str, UINT16 length, UINT16 min)
580 WINPR_ASSERT(num_str || (length == 0));
582 const UINT16 mlength = (length >= min) ? length - min : min;
584 if (!per_write_length(s, mlength))
587 if (!Stream_EnsureRemainingCapacity(s, length))
589 for (UINT16 i = 0; i < length; i += 2)
591 BYTE c1 = num_str[i];
592 BYTE c2 = ((i + 1) < length) ? num_str[i + 1] : 0x30;
594 if ((c1 < 0x30) || (c2 < 0x30))
597 c1 = (c1 - 0x30) % 10;
598 c2 = (c2 - 0x30) % 10;
599 const BYTE num = (c1 << 4) | c2;
601 Stream_Write_UINT8(s, num);