1 /* -*- c-basic-offset: 8 -*- 2 rdesktop: A Remote Desktop Protocol client. 3 ASN.1 utility functions 4 Copyright 2012 Henrik Andersson <hean01@cendio.se> for Cendio AB 5 6 This program is free software: you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include "precomp.h" 21 22 23 /* Parse an ASN.1 BER header */ 24 RD_BOOL 25 ber_parse_header(STREAM s, int tagval, int *length) 26 { 27 int tag, len; 28 29 if (tagval > 0xff) 30 { 31 in_uint16_be(s, tag); 32 } 33 else 34 { 35 in_uint8(s, tag); 36 } 37 38 if (tag != tagval) 39 { 40 error("expected tag %d, got %d\n", tagval, tag); 41 return False; 42 } 43 44 in_uint8(s, len); 45 46 if (len & 0x80) 47 { 48 len &= ~0x80; 49 *length = 0; 50 while (len--) 51 next_be(s, *length); 52 } 53 else 54 *length = len; 55 56 return s_check(s); 57 } 58 59 /* Output an ASN.1 BER header */ 60 void 61 ber_out_header(STREAM s, int tagval, int length) 62 { 63 if (tagval > 0xff) 64 { 65 out_uint16_be(s, tagval); 66 } 67 else 68 { 69 out_uint8(s, tagval); 70 } 71 72 if (length >= 0x80) 73 { 74 out_uint8(s, 0x82); 75 out_uint16_be(s, length); 76 } 77 else 78 out_uint8(s, length); 79 } 80 81 /* Output an ASN.1 BER integer */ 82 void 83 ber_out_integer(STREAM s, int value) 84 { 85 ber_out_header(s, BER_TAG_INTEGER, 2); 86 out_uint16_be(s, value); 87 } 88 89 RD_BOOL 90 ber_in_header(STREAM s, int *tagval, int *decoded_len) 91 { 92 in_uint8(s, *tagval); 93 in_uint8(s, *decoded_len); 94 95 if (*decoded_len < 0x80) 96 return True; 97 else if (*decoded_len == 0x81) 98 { 99 in_uint8(s, *decoded_len); 100 return True; 101 } 102 else if (*decoded_len == 0x82) 103 { 104 in_uint16_be(s, *decoded_len); 105 return True; 106 } 107 108 return False; 109 } 110