FreeRDP
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 
31 void 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 
65 int 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 
74 int _er_skip_length(int length)
75 {
76  if (length > 0x7F)
77  return 3;
78  else
79  return 1;
80 }
81 
82 int er_get_content_length(int length)
83 {
84  if (length - 1 > 0x7F)
85  return length - 4;
86  else
87  return length - 2;
88 }
89 
97 BOOL 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 
116 void 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 
128 BOOL 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 
166 void 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 
181 BOOL 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 
198 int 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 
204 int er_skip_contextual_tag(int length)
205 {
206  return _er_skip_length(length) + 1;
207 }
208 
209 BOOL 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 
229 int 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 
235 int er_skip_sequence(int length)
236 {
237  return 1 + _er_skip_length(length) + length;
238 }
239 
240 int er_skip_sequence_tag(int length)
241 {
242  return 1 + _er_skip_length(length);
243 }
244 
245 BOOL 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 
264 void er_write_enumerated(wStream* s, BYTE enumerated, 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 
271 BOOL 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 
280 BOOL 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 
288 BOOL 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 
304 void 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 
311 int 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 
318 int er_skip_octet_string(int length)
319 {
320  return 1 + _er_skip_length(length) + length;
321 }
322 
329 BOOL 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 
350 void 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 
357 BOOL 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 
403 int 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 
427 int 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 
443 BOOL 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 }