FreeRDP
Loading...
Searching...
No Matches
er.c
1
21#include <freerdp/config.h>
22
23#include <winpr/crt.h>
24#include <winpr/assert.h>
25#include <winpr/cast.h>
26
27#include <freerdp/crypto/er.h>
28#include <freerdp/crypto/ber.h>
29#include <freerdp/crypto/der.h>
30
31void er_read_length(wStream* s, int* length)
32{
33 BYTE byte = 0;
34
35 Stream_Read_UINT8(s, byte);
36
37 if (!length)
38 return;
39
40 *length = 0;
41 if (!s)
42 return;
43
44 if (byte & 0x80)
45 {
46 byte &= ~(0x80);
47
48 if (byte == 1)
49 Stream_Read_UINT8(s, *length);
50 if (byte == 2)
51 Stream_Read_UINT16_BE(s, *length);
52 }
53 else
54 {
55 *length = byte;
56 }
57}
58
65int er_write_length(wStream* s, int length, BOOL flag)
66{
67 WINPR_ASSERT(length >= 0);
68 if (flag)
69 return der_write_length(s, length);
70 else
71 return (int)ber_write_length(s, (size_t)length);
72}
73
74int _er_skip_length(int length)
75{
76 if (length > 0x7F)
77 return 3;
78 else
79 return 1;
80}
81
82int er_get_content_length(int length)
83{
84 if (length - 1 > 0x7F)
85 return length - 4;
86 else
87 return length - 2;
88}
89
97BOOL er_read_universal_tag(wStream* s, BYTE tag, BOOL pc)
98{
99 BYTE byte = 0;
100
101 Stream_Read_UINT8(s, byte);
102
103 if (byte != (ER_CLASS_UNIV | ER_PC(pc) | (ER_TAG_MASK & tag)))
104 return FALSE;
105
106 return TRUE;
107}
108
116void er_write_universal_tag(wStream* s, BYTE tag, BOOL pc)
117{
118 Stream_Write_UINT8(s, (ER_CLASS_UNIV | ER_PC(pc)) | (ER_TAG_MASK & tag));
119}
120
128BOOL er_read_application_tag(wStream* s, BYTE tag, int* length)
129{
130 BYTE byte = 0;
131
132 if (tag > 30)
133 {
134 Stream_Read_UINT8(s, byte);
135
136 if (byte != ((ER_CLASS_APPL | ER_CONSTRUCT) | ER_TAG_MASK))
137 return FALSE;
138
139 Stream_Read_UINT8(s, byte);
140
141 if (byte != tag)
142 return FALSE;
143
144 er_read_length(s, length);
145 }
146 else
147 {
148 Stream_Read_UINT8(s, byte);
149
150 if (byte != ((ER_CLASS_APPL | ER_CONSTRUCT) | (ER_TAG_MASK & tag)))
151 return FALSE;
152
153 er_read_length(s, length);
154 }
155
156 return TRUE;
157}
158
166void er_write_application_tag(wStream* s, BYTE tag, int length, BOOL flag)
167{
168 if (tag > 30)
169 {
170 Stream_Write_UINT8(s, (ER_CLASS_APPL | ER_CONSTRUCT) | ER_TAG_MASK);
171 Stream_Write_UINT8(s, tag);
172 er_write_length(s, length, flag);
173 }
174 else
175 {
176 Stream_Write_UINT8(s, (ER_CLASS_APPL | ER_CONSTRUCT) | (ER_TAG_MASK & tag));
177 er_write_length(s, length, flag);
178 }
179}
180
181BOOL er_read_contextual_tag(wStream* s, BYTE tag, int* length, BOOL pc)
182{
183 BYTE byte = 0;
184
185 Stream_Read_UINT8(s, byte);
186
187 if (byte != ((ER_CLASS_CTXT | ER_PC(pc)) | (ER_TAG_MASK & tag)))
188 {
189 Stream_Rewind(s, 1);
190 return FALSE;
191 }
192
193 er_read_length(s, length);
194
195 return TRUE;
196}
197
198int er_write_contextual_tag(wStream* s, BYTE tag, int length, BOOL pc, BOOL flag)
199{
200 Stream_Write_UINT8(s, (ER_CLASS_CTXT | ER_PC(pc)) | (ER_TAG_MASK & tag));
201 return er_write_length(s, length, flag) + 1;
202}
203
204int er_skip_contextual_tag(int length)
205{
206 return _er_skip_length(length) + 1;
207}
208
209BOOL er_read_sequence_tag(wStream* s, int* length)
210{
211 BYTE byte = 0;
212
213 Stream_Read_UINT8(s, byte);
214
215 if (byte != ((ER_CLASS_UNIV | ER_CONSTRUCT) | (ER_TAG_SEQUENCE_OF)))
216 return FALSE;
217
218 er_read_length(s, length);
219
220 return TRUE;
221}
222
229int er_write_sequence_tag(wStream* s, int length, BOOL flag)
230{
231 Stream_Write_UINT8(s, (ER_CLASS_UNIV | ER_CONSTRUCT) | (ER_TAG_MASK & ER_TAG_SEQUENCE));
232 return er_write_length(s, length, flag) + 1;
233}
234
235int er_skip_sequence(int length)
236{
237 return 1 + _er_skip_length(length) + length;
238}
239
240int er_skip_sequence_tag(int length)
241{
242 return 1 + _er_skip_length(length);
243}
244
245BOOL er_read_enumerated(wStream* s, BYTE* enumerated, BYTE count)
246{
247 int length = 0;
248
249 er_read_universal_tag(s, ER_TAG_ENUMERATED, FALSE);
250 er_read_length(s, &length);
251
252 if (length == 1)
253 Stream_Read_UINT8(s, *enumerated);
254 else
255 return FALSE;
256
257 /* check that enumerated value falls within expected range */
258 if (*enumerated + 1 > count)
259 return FALSE;
260
261 return TRUE;
262}
263
264void er_write_enumerated(wStream* s, BYTE enumerated, WINPR_ATTR_UNUSED BYTE count, BOOL flag)
265{
266 er_write_universal_tag(s, ER_TAG_ENUMERATED, FALSE);
267 er_write_length(s, 1, flag);
268 Stream_Write_UINT8(s, enumerated);
269}
270
271BOOL er_read_bit_string(wStream* s, int* length, BYTE* padding)
272{
273 er_read_universal_tag(s, ER_TAG_BIT_STRING, FALSE);
274 er_read_length(s, length);
275 Stream_Read_UINT8(s, *padding);
276
277 return TRUE;
278}
279
280BOOL er_write_bit_string_tag(wStream* s, UINT32 length, BYTE padding, BOOL flag)
281{
282 er_write_universal_tag(s, ER_TAG_BIT_STRING, FALSE);
283 er_write_length(s, WINPR_ASSERTING_INT_CAST(int, length), flag);
284 Stream_Write_UINT8(s, padding);
285 return TRUE;
286}
287
288BOOL er_read_octet_string(wStream* s, int* length)
289{
290 if (!er_read_universal_tag(s, ER_TAG_OCTET_STRING, FALSE))
291 return FALSE;
292 er_read_length(s, length);
293
294 return TRUE;
295}
296
304void er_write_octet_string(wStream* s, BYTE* oct_str, int length, BOOL flag)
305{
306 er_write_universal_tag(s, ER_TAG_OCTET_STRING, FALSE);
307 er_write_length(s, length, flag);
308 Stream_Write(s, oct_str, WINPR_ASSERTING_INT_CAST(size_t, length));
309}
310
311int er_write_octet_string_tag(wStream* s, int length, BOOL flag)
312{
313 er_write_universal_tag(s, ER_TAG_OCTET_STRING, FALSE);
314 er_write_length(s, length, flag);
315 return 1 + _er_skip_length(length);
316}
317
318int er_skip_octet_string(int length)
319{
320 return 1 + _er_skip_length(length) + length;
321}
322
329BOOL er_read_BOOL(wStream* s, BOOL* value)
330{
331 int length = 0;
332 BYTE v = 0;
333
334 if (!er_read_universal_tag(s, ER_TAG_BOOLEAN, FALSE))
335 return FALSE;
336 er_read_length(s, &length);
337 if (length != 1)
338 return FALSE;
339 Stream_Read_UINT8(s, v);
340 *value = (v ? TRUE : FALSE);
341 return TRUE;
342}
343
350void er_write_BOOL(wStream* s, BOOL value)
351{
352 er_write_universal_tag(s, ER_TAG_BOOLEAN, FALSE);
353 er_write_length(s, 1, FALSE);
354 Stream_Write_UINT8(s, (value == TRUE) ? 0xFF : 0);
355}
356
357BOOL er_read_integer(wStream* s, UINT32* value)
358{
359 int length = 0;
360
361 er_read_universal_tag(s, ER_TAG_INTEGER, FALSE);
362 er_read_length(s, &length);
363
364 if (value == NULL)
365 {
366 Stream_Seek(s, WINPR_ASSERTING_INT_CAST(size_t, length));
367 return TRUE;
368 }
369
370 if (length == 1)
371 {
372 Stream_Read_UINT8(s, *value);
373 }
374 else if (length == 2)
375 {
376 Stream_Read_UINT16_BE(s, *value);
377 }
378 else if (length == 3)
379 {
380 BYTE byte = 0;
381 Stream_Read_UINT8(s, byte);
382 Stream_Read_UINT16_BE(s, *value);
383 *value += (byte << 16) & 0xFF0000;
384 }
385 else if (length == 4)
386 {
387 Stream_Read_UINT32_BE(s, *value);
388 }
389 else
390 {
391 return FALSE;
392 }
393
394 return TRUE;
395}
396
403int er_write_integer(wStream* s, INT32 value)
404{
405 er_write_universal_tag(s, ER_TAG_INTEGER, FALSE);
406
407 if (value <= 127 && value >= -128)
408 {
409 er_write_length(s, 1, FALSE);
410 Stream_Write_INT8(s, WINPR_ASSERTING_INT_CAST(INT8, value));
411 return 2;
412 }
413 else if (value <= 32767 && value >= -32768)
414 {
415 er_write_length(s, 2, FALSE);
416 Stream_Write_INT16_BE(s, WINPR_ASSERTING_INT_CAST(INT16, value));
417 return 3;
418 }
419 else
420 {
421 er_write_length(s, 4, FALSE);
422 Stream_Write_INT32_BE(s, value);
423 return 5;
424 }
425}
426
427int er_skip_integer(INT32 value)
428{
429 if (value <= 127 && value >= -128)
430 {
431 return _er_skip_length(1) + 2;
432 }
433 else if (value <= 32767 && value >= -32768)
434 {
435 return _er_skip_length(2) + 3;
436 }
437 else
438 {
439 return _er_skip_length(4) + 5;
440 }
441}
442
443BOOL er_read_integer_length(wStream* s, int* length)
444{
445 er_read_universal_tag(s, ER_TAG_INTEGER, FALSE);
446 er_read_length(s, length);
447 return TRUE;
448}