~ubuntu-branches/ubuntu/vivid/freerdp/vivid

« back to all changes in this revision

Viewing changes to libfreerdp-core/ber.c

  • Committer: Package Import Robot
  • Author(s): Iain Lane
  • Date: 2014-11-11 12:20:50 UTC
  • mfrom: (1.1.9) (9.1.17 sid)
  • Revision ID: package-import@ubuntu.com-20141111122050-wyr8hrnwco9fcmum
Tags: 1.1.0~git20140921.1.440916e+dfsg1-2ubuntu1
* Merge with Debian unstable, remaining changes
  - Disable ffmpeg support
* Disable gstreamer support, this relies on gstreamer 0.10 and we don't want
  to add any more deps on that.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**
2
 
 * FreeRDP: A Remote Desktop Protocol Client
3
 
 * ASN.1 Basic Encoding Rules (BER)
4
 
 *
5
 
 * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6
 
 *
7
 
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 
 * you may not use this file except in compliance with the License.
9
 
 * You may obtain a copy of the License at
10
 
 *
11
 
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 
 *
13
 
 * Unless required by applicable law or agreed to in writing, software
14
 
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 
 * See the License for the specific language governing permissions and
17
 
 * limitations under the License.
18
 
 */
19
 
 
20
 
#include "ber.h"
21
 
 
22
 
void ber_read_length(STREAM* s, int* length)
23
 
{
24
 
        uint8 byte;
25
 
 
26
 
        stream_read_uint8(s, byte);
27
 
 
28
 
        if (byte & 0x80)
29
 
        {
30
 
                byte &= ~(0x80);
31
 
 
32
 
                if (byte == 1)
33
 
                        stream_read_uint8(s, *length);
34
 
                if (byte == 2)
35
 
                        stream_read_uint16_be(s, *length);
36
 
        }
37
 
        else
38
 
        {
39
 
                *length = byte;
40
 
        }
41
 
}
42
 
 
43
 
/**
44
 
 * Write BER length.
45
 
 * @param s stream
46
 
 * @param length length
47
 
 */
48
 
 
49
 
int ber_write_length(STREAM* s, int length)
50
 
{
51
 
        if (length > 0x7F)
52
 
        {
53
 
                stream_write_uint8(s, 0x82);
54
 
                stream_write_uint16_be(s, length);
55
 
                return 3;
56
 
        }
57
 
        else
58
 
        {
59
 
                stream_write_uint8(s, length);
60
 
                return 1;
61
 
        }
62
 
}
63
 
 
64
 
int _ber_skip_length(int length)
65
 
{
66
 
        if (length > 0x7F)
67
 
                return 3;
68
 
        else
69
 
                return 1;
70
 
}
71
 
 
72
 
int ber_get_content_length(int length)
73
 
{
74
 
        if (length - 1 > 0x7F)
75
 
                return length - 4;
76
 
        else
77
 
                return length - 2;
78
 
}
79
 
 
80
 
/**
81
 
 * Read BER Universal tag.
82
 
 * @param s stream
83
 
 * @param tag BER universally-defined tag
84
 
 * @return
85
 
 */
86
 
 
87
 
boolean ber_read_universal_tag(STREAM* s, uint8 tag, boolean pc)
88
 
{
89
 
        uint8 byte;
90
 
 
91
 
        stream_read_uint8(s, byte);
92
 
 
93
 
        if (byte != (BER_CLASS_UNIV | BER_PC(pc) | (BER_TAG_MASK & tag)))
94
 
                return false;
95
 
 
96
 
        return true;
97
 
}
98
 
 
99
 
/**
100
 
 * Write BER Universal tag.
101
 
 * @param s stream
102
 
 * @param tag BER universally-defined tag
103
 
 * @param pc primitive (false) or constructed (true)
104
 
 */
105
 
 
106
 
void ber_write_universal_tag(STREAM* s, uint8 tag, boolean pc)
107
 
{
108
 
        stream_write_uint8(s, (BER_CLASS_UNIV | BER_PC(pc)) | (BER_TAG_MASK & tag));
109
 
}
110
 
 
111
 
/**
112
 
 * Read BER Application tag.
113
 
 * @param s stream
114
 
 * @param tag BER application-defined tag
115
 
 * @param length length
116
 
 */
117
 
 
118
 
boolean ber_read_application_tag(STREAM* s, uint8 tag, int* length)
119
 
{
120
 
        uint8 byte;
121
 
 
122
 
        if (tag > 30)
123
 
        {
124
 
                stream_read_uint8(s, byte);
125
 
 
126
 
                if (byte != ((BER_CLASS_APPL | BER_CONSTRUCT) | BER_TAG_MASK))
127
 
                        return false;
128
 
 
129
 
                stream_read_uint8(s, byte);
130
 
 
131
 
                if (byte != tag)
132
 
                        return false;
133
 
 
134
 
                ber_read_length(s, length);
135
 
        }
136
 
        else
137
 
        {
138
 
                stream_read_uint8(s, byte);
139
 
 
140
 
                if (byte != ((BER_CLASS_APPL | BER_CONSTRUCT) | (BER_TAG_MASK & tag)))
141
 
                        return false;
142
 
 
143
 
                ber_read_length(s, length);
144
 
        }
145
 
 
146
 
        return true;
147
 
}
148
 
 
149
 
/**
150
 
 * Write BER Application tag.
151
 
 * @param s stream
152
 
 * @param tag BER application-defined tag
153
 
 * @param length length
154
 
 */
155
 
 
156
 
void ber_write_application_tag(STREAM* s, uint8 tag, int length)
157
 
{
158
 
        if (tag > 30)
159
 
        {
160
 
                stream_write_uint8(s, (BER_CLASS_APPL | BER_CONSTRUCT) | BER_TAG_MASK);
161
 
                stream_write_uint8(s, tag);
162
 
                ber_write_length(s, length);
163
 
        }
164
 
        else
165
 
        {
166
 
                stream_write_uint8(s, (BER_CLASS_APPL | BER_CONSTRUCT) | (BER_TAG_MASK & tag));
167
 
                ber_write_length(s, length);
168
 
        }
169
 
}
170
 
 
171
 
boolean ber_read_contextual_tag(STREAM* s, uint8 tag, int* length, boolean pc)
172
 
{
173
 
        uint8 byte;
174
 
 
175
 
        stream_read_uint8(s, byte);
176
 
 
177
 
        if (byte != ((BER_CLASS_CTXT | BER_PC(pc)) | (BER_TAG_MASK & tag)))
178
 
        {
179
 
                stream_rewind(s, 1);
180
 
                return false;
181
 
        }
182
 
 
183
 
        ber_read_length(s, length);
184
 
 
185
 
        return true;
186
 
}
187
 
 
188
 
int ber_write_contextual_tag(STREAM* s, uint8 tag, int length, boolean pc)
189
 
{
190
 
        stream_write_uint8(s, (BER_CLASS_CTXT | BER_PC(pc)) | (BER_TAG_MASK & tag));
191
 
        return ber_write_length(s, length) + 1;
192
 
}
193
 
 
194
 
int ber_skip_contextual_tag(int length)
195
 
{
196
 
        return _ber_skip_length(length) + 1;
197
 
}
198
 
 
199
 
boolean ber_read_sequence_tag(STREAM* s, int* length)
200
 
{
201
 
        uint8 byte;
202
 
 
203
 
        stream_read_uint8(s, byte);
204
 
 
205
 
        if (byte != ((BER_CLASS_UNIV | BER_CONSTRUCT) | (BER_TAG_SEQUENCE_OF)))
206
 
                return false;
207
 
 
208
 
        ber_read_length(s, length);
209
 
 
210
 
        return true;
211
 
}
212
 
 
213
 
/**
214
 
 * Write BER SEQUENCE tag.
215
 
 * @param s stream
216
 
 * @param length length
217
 
 */
218
 
 
219
 
int ber_write_sequence_tag(STREAM* s, int length)
220
 
{
221
 
        stream_write_uint8(s, (BER_CLASS_UNIV | BER_CONSTRUCT) | (BER_TAG_MASK & BER_TAG_SEQUENCE));
222
 
        return ber_write_length(s, length) + 1;
223
 
}
224
 
 
225
 
int ber_skip_sequence(int length)
226
 
{
227
 
        return 1 + _ber_skip_length(length) + length;
228
 
}
229
 
 
230
 
int ber_skip_sequence_tag(int length)
231
 
{
232
 
        return 1 + _ber_skip_length(length);
233
 
}
234
 
 
235
 
boolean ber_read_enumerated(STREAM* s, uint8* enumerated, uint8 count)
236
 
{
237
 
        int length;
238
 
 
239
 
        ber_read_universal_tag(s, BER_TAG_ENUMERATED, false);
240
 
        ber_read_length(s, &length);
241
 
 
242
 
        if (length == 1)
243
 
                stream_read_uint8(s, *enumerated);
244
 
        else
245
 
                return false;
246
 
 
247
 
        /* check that enumerated value falls within expected range */
248
 
        if (*enumerated + 1 > count)
249
 
                return false;
250
 
 
251
 
        return true;
252
 
}
253
 
 
254
 
void ber_write_enumerated(STREAM* s, uint8 enumerated, uint8 count)
255
 
{
256
 
        ber_write_universal_tag(s, BER_TAG_ENUMERATED, false);
257
 
        ber_write_length(s, 1);
258
 
        stream_write_uint8(s, enumerated);
259
 
}
260
 
 
261
 
boolean ber_read_bit_string(STREAM* s, int* length, uint8* padding)
262
 
{
263
 
        ber_read_universal_tag(s, BER_TAG_BIT_STRING, false);
264
 
        ber_read_length(s, length);
265
 
        stream_read_uint8(s, *padding);
266
 
 
267
 
        return true;
268
 
}
269
 
 
270
 
boolean ber_read_octet_string(STREAM* s, int* length)
271
 
{
272
 
        ber_read_universal_tag(s, BER_TAG_OCTET_STRING, false);
273
 
        ber_read_length(s, length);
274
 
 
275
 
        return true;
276
 
}
277
 
 
278
 
/**
279
 
 * Write a BER OCTET_STRING
280
 
 * @param s stream
281
 
 * @param oct_str octet string
282
 
 * @param length string length
283
 
 */
284
 
 
285
 
void ber_write_octet_string(STREAM* s, const uint8* oct_str, int length)
286
 
{
287
 
        ber_write_universal_tag(s, BER_TAG_OCTET_STRING, false);
288
 
        ber_write_length(s, length);
289
 
        stream_write(s, oct_str, length);
290
 
}
291
 
 
292
 
int ber_write_octet_string_tag(STREAM* s, int length)
293
 
{
294
 
        ber_write_universal_tag(s, BER_TAG_OCTET_STRING, false);
295
 
        ber_write_length(s, length);
296
 
        return 1 + _ber_skip_length(length);
297
 
}
298
 
 
299
 
int ber_skip_octet_string(int length)
300
 
{
301
 
        return 1 + _ber_skip_length(length) + length;
302
 
}
303
 
 
304
 
/**
305
 
 * Read a BER BOOLEAN
306
 
 * @param s
307
 
 * @param value
308
 
 */
309
 
 
310
 
boolean ber_read_boolean(STREAM* s, boolean* value)
311
 
{
312
 
        int length;
313
 
        uint8 v;
314
 
 
315
 
        if (!ber_read_universal_tag(s, BER_TAG_BOOLEAN, false))
316
 
                return false;
317
 
        ber_read_length(s, &length);
318
 
        if (length != 1)
319
 
                return false;
320
 
        stream_read_uint8(s, v);
321
 
        *value = (v ? true : false);
322
 
        return true;
323
 
}
324
 
 
325
 
/**
326
 
 * Write a BER BOOLEAN
327
 
 * @param s
328
 
 * @param value
329
 
 */
330
 
 
331
 
void ber_write_boolean(STREAM* s, boolean value)
332
 
{
333
 
        ber_write_universal_tag(s, BER_TAG_BOOLEAN, false);
334
 
        ber_write_length(s, 1);
335
 
        stream_write_uint8(s, (value == true) ? 0xFF : 0);
336
 
}
337
 
 
338
 
boolean ber_read_integer(STREAM* s, uint32* value)
339
 
{
340
 
        int length;
341
 
 
342
 
        ber_read_universal_tag(s, BER_TAG_INTEGER, false);
343
 
        ber_read_length(s, &length);
344
 
 
345
 
        if (value == NULL)
346
 
        {
347
 
                stream_seek(s, length);
348
 
                return true;
349
 
        }
350
 
 
351
 
        if (length == 1)
352
 
                stream_read_uint8(s, *value);
353
 
        else if (length == 2)
354
 
                stream_read_uint16_be(s, *value);
355
 
        else if (length == 3)
356
 
        {
357
 
                uint8 byte;
358
 
                stream_read_uint8(s, byte);
359
 
                stream_read_uint16_be(s, *value);
360
 
                *value += (byte << 16);
361
 
        }
362
 
        else if (length == 4)
363
 
                stream_read_uint32_be(s, *value);
364
 
        else
365
 
                return false;
366
 
 
367
 
        return true;
368
 
}
369
 
 
370
 
/**
371
 
 * Write a BER INTEGER
372
 
 * @param s
373
 
 * @param value
374
 
 */
375
 
 
376
 
int ber_write_integer(STREAM* s, uint32 value)
377
 
{
378
 
        ber_write_universal_tag(s, BER_TAG_INTEGER, false);
379
 
 
380
 
        if (value <= 0xFF)
381
 
        {
382
 
                ber_write_length(s, 1);
383
 
                stream_write_uint8(s, value);
384
 
                return 2;
385
 
        }
386
 
        else if (value < 0xFF80)
387
 
        {
388
 
                ber_write_length(s, 2);
389
 
                stream_write_uint16_be(s, value);
390
 
                return 3;
391
 
        }
392
 
        else if (value < 0xFF8000)
393
 
        {
394
 
                ber_write_length(s, 3);
395
 
                stream_write_uint8(s, (value >> 16));
396
 
                stream_write_uint16_be(s, (value & 0xFFFF));
397
 
                return 4;
398
 
        }
399
 
        else if (value <= 0xFFFFFFFF)
400
 
        {
401
 
                ber_write_length(s, 4);
402
 
                stream_write_uint32_be(s, value);
403
 
                return 5;
404
 
        }
405
 
 
406
 
        return 0;
407
 
}
408
 
 
409
 
int ber_skip_integer(uint32 value)
410
 
{
411
 
        if (value <= 0xFF)
412
 
        {
413
 
                return _ber_skip_length(1) + 2;
414
 
        }
415
 
        else if (value <= 0xFFFF)
416
 
        {
417
 
                return _ber_skip_length(2) + 3;
418
 
        }
419
 
        else if (value <= 0xFFFFFFFF)
420
 
        {
421
 
                return _ber_skip_length(4) + 5;
422
 
        }
423
 
 
424
 
        return 0;
425
 
}
426
 
 
427
 
boolean ber_read_integer_length(STREAM* s, int* length)
428
 
{
429
 
        ber_read_universal_tag(s, BER_TAG_INTEGER, false);
430
 
        ber_read_length(s, length);
431
 
        return true;
432
 
}