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 return (byte == (ER_CLASS_UNIV | ER_PC(pc) | (ER_TAG_MASK & tag)));
104}
105
113void er_write_universal_tag(wStream* s, BYTE tag, BOOL pc)
114{
115 Stream_Write_UINT8(s, (ER_CLASS_UNIV | ER_PC(pc)) | (ER_TAG_MASK & tag));
116}
117
125BOOL er_read_application_tag(wStream* s, BYTE tag, int* length)
126{
127 BYTE byte = 0;
128
129 if (tag > 30)
130 {
131 Stream_Read_UINT8(s, byte);
132
133 if (byte != ((ER_CLASS_APPL | ER_CONSTRUCT) | ER_TAG_MASK))
134 return FALSE;
135
136 Stream_Read_UINT8(s, byte);
137
138 if (byte != tag)
139 return FALSE;
140
141 er_read_length(s, length);
142 }
143 else
144 {
145 Stream_Read_UINT8(s, byte);
146
147 if (byte != ((ER_CLASS_APPL | ER_CONSTRUCT) | (ER_TAG_MASK & tag)))
148 return FALSE;
149
150 er_read_length(s, length);
151 }
152
153 return TRUE;
154}
155
163void er_write_application_tag(wStream* s, BYTE tag, int length, BOOL flag)
164{
165 if (tag > 30)
166 {
167 Stream_Write_UINT8(s, (ER_CLASS_APPL | ER_CONSTRUCT) | ER_TAG_MASK);
168 Stream_Write_UINT8(s, tag);
169 er_write_length(s, length, flag);
170 }
171 else
172 {
173 Stream_Write_UINT8(s, (ER_CLASS_APPL | ER_CONSTRUCT) | (ER_TAG_MASK & tag));
174 er_write_length(s, length, flag);
175 }
176}
177
178BOOL er_read_contextual_tag(wStream* s, BYTE tag, int* length, BOOL pc)
179{
180 BYTE byte = 0;
181
182 Stream_Read_UINT8(s, byte);
183
184 if (byte != ((ER_CLASS_CTXT | ER_PC(pc)) | (ER_TAG_MASK & tag)))
185 {
186 Stream_Rewind(s, 1);
187 return FALSE;
188 }
189
190 er_read_length(s, length);
191
192 return TRUE;
193}
194
195int er_write_contextual_tag(wStream* s, BYTE tag, int length, BOOL pc, BOOL flag)
196{
197 Stream_Write_UINT8(s, (ER_CLASS_CTXT | ER_PC(pc)) | (ER_TAG_MASK & tag));
198 return er_write_length(s, length, flag) + 1;
199}
200
201int er_skip_contextual_tag(int length)
202{
203 return _er_skip_length(length) + 1;
204}
205
206BOOL er_read_sequence_tag(wStream* s, int* length)
207{
208 BYTE byte = 0;
209
210 Stream_Read_UINT8(s, byte);
211
212 if (byte != ((ER_CLASS_UNIV | ER_CONSTRUCT) | (ER_TAG_SEQUENCE_OF)))
213 return FALSE;
214
215 er_read_length(s, length);
216
217 return TRUE;
218}
219
226int er_write_sequence_tag(wStream* s, int length, BOOL flag)
227{
228 Stream_Write_UINT8(s, (ER_CLASS_UNIV | ER_CONSTRUCT) | (ER_TAG_MASK & ER_TAG_SEQUENCE));
229 return er_write_length(s, length, flag) + 1;
230}
231
232int er_skip_sequence(int length)
233{
234 return 1 + _er_skip_length(length) + length;
235}
236
237int er_skip_sequence_tag(int length)
238{
239 return 1 + _er_skip_length(length);
240}
241
242BOOL er_read_enumerated(wStream* s, BYTE* enumerated, BYTE count)
243{
244 int length = 0;
245
246 er_read_universal_tag(s, ER_TAG_ENUMERATED, FALSE);
247 er_read_length(s, &length);
248
249 if (length == 1)
250 Stream_Read_UINT8(s, *enumerated);
251 else
252 return FALSE;
253
254 /* check that enumerated value falls within expected range */
255 if (*enumerated + 1 > count)
256 return FALSE;
257
258 return TRUE;
259}
260
261void er_write_enumerated(wStream* s, BYTE enumerated, WINPR_ATTR_UNUSED BYTE count, BOOL flag)
262{
263 er_write_universal_tag(s, ER_TAG_ENUMERATED, FALSE);
264 er_write_length(s, 1, flag);
265 Stream_Write_UINT8(s, enumerated);
266}
267
268BOOL er_read_bit_string(wStream* s, int* length, BYTE* padding)
269{
270 er_read_universal_tag(s, ER_TAG_BIT_STRING, FALSE);
271 er_read_length(s, length);
272 Stream_Read_UINT8(s, *padding);
273
274 return TRUE;
275}
276
277BOOL er_write_bit_string_tag(wStream* s, UINT32 length, BYTE padding, BOOL flag)
278{
279 er_write_universal_tag(s, ER_TAG_BIT_STRING, FALSE);
280 er_write_length(s, WINPR_ASSERTING_INT_CAST(int, length), flag);
281 Stream_Write_UINT8(s, padding);
282 return TRUE;
283}
284
285BOOL er_read_octet_string(wStream* s, int* length)
286{
287 if (!er_read_universal_tag(s, ER_TAG_OCTET_STRING, FALSE))
288 return FALSE;
289 er_read_length(s, length);
290
291 return TRUE;
292}
293
301void er_write_octet_string(wStream* s, BYTE* oct_str, int length, BOOL flag)
302{
303 er_write_universal_tag(s, ER_TAG_OCTET_STRING, FALSE);
304 er_write_length(s, length, flag);
305 Stream_Write(s, oct_str, WINPR_ASSERTING_INT_CAST(size_t, length));
306}
307
308int er_write_octet_string_tag(wStream* s, int length, BOOL flag)
309{
310 er_write_universal_tag(s, ER_TAG_OCTET_STRING, FALSE);
311 er_write_length(s, length, flag);
312 return 1 + _er_skip_length(length);
313}
314
315int er_skip_octet_string(int length)
316{
317 return 1 + _er_skip_length(length) + length;
318}
319
326BOOL er_read_BOOL(wStream* s, BOOL* value)
327{
328 int length = 0;
329 BYTE v = 0;
330
331 if (!er_read_universal_tag(s, ER_TAG_BOOLEAN, FALSE))
332 return FALSE;
333 er_read_length(s, &length);
334 if (length != 1)
335 return FALSE;
336 Stream_Read_UINT8(s, v);
337 *value = v != 0;
338 return TRUE;
339}
340
347void er_write_BOOL(wStream* s, BOOL value)
348{
349 er_write_universal_tag(s, ER_TAG_BOOLEAN, FALSE);
350 er_write_length(s, 1, FALSE);
351 Stream_Write_UINT8(s, (value == TRUE) ? 0xFF : 0);
352}
353
354BOOL er_read_integer(wStream* s, UINT32* value)
355{
356 int length = 0;
357
358 er_read_universal_tag(s, ER_TAG_INTEGER, FALSE);
359 er_read_length(s, &length);
360
361 if (value == nullptr)
362 {
363 Stream_Seek(s, WINPR_ASSERTING_INT_CAST(size_t, length));
364 return TRUE;
365 }
366
367 if (length == 1)
368 {
369 Stream_Read_UINT8(s, *value);
370 }
371 else if (length == 2)
372 {
373 Stream_Read_UINT16_BE(s, *value);
374 }
375 else if (length == 3)
376 {
377 BYTE byte = 0;
378 Stream_Read_UINT8(s, byte);
379 Stream_Read_UINT16_BE(s, *value);
380 *value += (byte << 16) & 0xFF0000;
381 }
382 else if (length == 4)
383 {
384 Stream_Read_UINT32_BE(s, *value);
385 }
386 else
387 {
388 return FALSE;
389 }
390
391 return TRUE;
392}
393
400int er_write_integer(wStream* s, INT32 value)
401{
402 er_write_universal_tag(s, ER_TAG_INTEGER, FALSE);
403
404 if (value <= 127 && value >= -128)
405 {
406 er_write_length(s, 1, FALSE);
407 Stream_Write_INT8(s, WINPR_ASSERTING_INT_CAST(INT8, value));
408 return 2;
409 }
410 else if (value <= 32767 && value >= -32768)
411 {
412 er_write_length(s, 2, FALSE);
413 Stream_Write_INT16_BE(s, WINPR_ASSERTING_INT_CAST(INT16, value));
414 return 3;
415 }
416 else
417 {
418 er_write_length(s, 4, FALSE);
419 Stream_Write_INT32_BE(s, value);
420 return 5;
421 }
422}
423
424int er_skip_integer(INT32 value)
425{
426 if (value <= 127 && value >= -128)
427 {
428 return _er_skip_length(1) + 2;
429 }
430 else if (value <= 32767 && value >= -32768)
431 {
432 return _er_skip_length(2) + 3;
433 }
434 else
435 {
436 return _er_skip_length(4) + 5;
437 }
438}
439
440BOOL er_read_integer_length(wStream* s, int* length)
441{
442 er_read_universal_tag(s, ER_TAG_INTEGER, FALSE);
443 er_read_length(s, length);
444 return TRUE;
445}