* first bits of decoding facility information elements
[asterisk/asterisk.git] / channels / misdn / asn1.c
1
2 #include "asn1.h"
3 #include <string.h>
4
5 /*
6 ** ASN.1 Encoding
7 */
8
9 int _enc_null (__u8 *dest, int tag)
10 {
11         dest[0] = tag;
12         dest[1] = 0;
13         return 2;
14 }
15
16 int _enc_bool (__u8 *dest, __u32 i, int tag)
17 {
18         dest[0] = tag;
19         dest[1] = 1;
20         dest[2] = i ? 1:0;
21         return 3;
22 }
23
24 int _enc_int (__u8 *dest, __u32 i, int tag)
25 {
26         __u8 *p;
27         dest[0] = tag;
28         p = &dest[2];
29         do {
30                 *p++ = i;
31                 i >>= 8;
32         } while (i);
33         dest[1] = p - &dest[2];
34         return p - dest;
35 }
36
37 int _enc_enum (__u8 *dest, __u32 i, int tag)
38 {
39         __u8 *p;
40
41         dest[0] = tag;
42         p = &dest[2];
43         do {
44                 *p++ = i;
45                 i >>= 8;
46         } while (i);
47         dest[1] = p - &dest[2];
48         return p - dest;
49 }
50
51 int _enc_num_string (__u8 *dest, __u8 *nd, __u8 len, int tag)
52 {
53         __u8 *p;
54         int i;
55
56         dest[0] = tag;
57         p = &dest[2];
58         for (i = 0; i < len; i++)
59                 *p++ = *nd++;
60         dest[1] = p - &dest[2];
61         return p - dest;
62 }
63
64 int _enc_sequence_start (__u8 *dest, __u8 **id, int tag)
65 {
66         dest[0] = tag;
67         *id = &dest[1];
68         return 2;
69 }
70
71 int _enc_sequence_end (__u8 *dest, __u8 *id, int tag_dummy)
72 {
73         *id = dest - id - 1;
74         return 0;
75 }
76
77 /*
78 ** ASN.1 Decoding
79 */
80
81 #define CHECK_P                                                 \
82         do { \
83                 if (p >= end) \
84                         return -1; \
85         } while (0) 
86
87 #define CallASN1(ret, p, end, todo)             \
88         do { \
89                 ret = todo; \
90                 if (ret < 0) { \
91                         return -1; \
92                 } \
93                 p += ret; \
94         } while (0)
95
96 #define INIT                                                    \
97         int len, ret; \
98         __u8 *begin = p; \
99         if (tag) \
100                 *tag = *p; \
101         p++; \
102         CallASN1(ret, p, end, dec_len(p, &len)); \
103         if (len >= 0) { \
104                 if (p + len > end) \
105                         return -1; \
106                 end = p + len; \
107         }
108
109 int _dec_null (__u8 *p, __u8 *end, int *tag)
110 {
111         INIT;
112         return p - begin;
113 }
114
115 int _dec_bool (__u8 *p, __u8 *end, int *i, int *tag)
116 {
117         INIT;
118         *i = 0;
119         while (len--) {
120                 CHECK_P;
121                 *i = (*i >> 8) + *p;
122                 p++;
123         }
124         return p - begin;
125 }
126
127 int _dec_int (__u8 *p, __u8 *end, int *i, int *tag)
128 {
129         INIT;
130
131         *i = 0;
132         while (len--) {
133                 CHECK_P;
134                 *i = (*i << 8) + *p;
135                 p++;
136         }
137         return p - begin;
138 }
139
140 int _dec_enum (__u8 *p, __u8 *end, int *i, int *tag)
141 {
142         INIT;
143
144         *i = 0;
145         while (len--) {
146                 CHECK_P;
147                 *i = (*i << 8) + *p;
148                 p++;
149         }
150         return p - begin;
151 }
152
153 int _dec_num_string (__u8 *p, __u8 *end, char *str, int *tag)
154 {
155         INIT;
156
157         while (len--) {
158                 CHECK_P;
159                 *str++ = *p;
160                 p++;
161         }
162         *str = 0;
163         return p - begin;
164 }
165
166 int _dec_octet_string (__u8 *p, __u8 *end, char *str, int *tag)
167 {
168         return _dec_num_string(p, end, str, tag);
169 }
170
171 int _dec_sequence (__u8 *p, __u8 *end, int *tag)
172 {
173         INIT;
174         return p - begin;
175 }
176
177 int dec_len (__u8 *p, int *len)
178 {
179         *len = *p;
180         return 1;
181 }