suricata
util-decode-asn1.h
Go to the documentation of this file.
1 /* Copyright (C) 2007-2010 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Pablo Rincon Crespo <pablo.rincon.crespo@gmail.com>
22  *
23  * Implements ASN1 decoding (needed for the asn1 keyword)
24  */
25 
26 #ifndef __DECODE_ASN1_H__
27 #define __DECODE_ASN1_H__
28 #include <stdio.h>
29 #include <stdint.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <inttypes.h>
33 #include <limits.h>
34 #include <ctype.h>
35 #include <string.h>
36 
37 #define ASN1_MAX_FRAMES 256
38 
39 /* For future enconding type implementations */
40 enum {
43 };
44 
45 /* Class of tag */
46 #define ASN1_BER_CLASS_UNIV 0
47 #define ASN1_BER_CLASS_APP 1
48 #define ASN1_BER_CLASS_CTX_SPECIFIC 2
49 #define ASN1_BER_CLASS_PRIV 3
50 
51 /* For low tag numbers */
52 #define ASN1_BER_GET_CLASS_TAG(id_octet) \
53  ((id_octet >> 6) & 0x03) /* (8.1.2.2a) */
54 #define ASN1_BER_IS_CONSTRUCTED(id_octet) \
55  ((id_octet >> 5) & 0x01) /* (8.1.2.5) Constructed Tag */
56 #define ASN1_BER_IS_PRIMITIVE(id_octet) \
57  (((id_octet >> 5) & 0x01)?0:1) /* (8.1.2.5) Primitive Tag */
58 #define ASN1_BER_IS_LOW_TAG(id_octet) \
59  ASN1_BER_IS_PRIMITIVE(id_octet) /* (8.1.2.5) Is Low Tag
60  Number */
61 #define ASN1_BER_GET_LOW_TAG_NUM(id_octet) \
62  (id_octet & 0x1F) /* (8.1.2.2c) Get LowTag Number */
63 
64 /* For high tag numbers */
65 #define ASN1_BER_IS_HIGH_TAG(id_octet) \
66  ((ASN1_BER_GET_LOW_TAG_NUM(id_octet) == 0x1F) && \
67  ASN1_BER_IS_CONSTRUCTED(id_octet)) /* (8.1.2.4) High Tag Number */
68 #define ASN1_BER_IS_HIGH_TAG_END(id_octet) \
69  ( !((id_octet >> 7) & 0x01)) /* (8.1.2.4) Is End of Tag Num */
70 #define ASN1_BER_GET_HIGH_TAG_NUM(id_octet) \
71  (id_octet & 0x7F) /* (8.1.2.4) Part of High Tag
72  Number */
73 
74 
75 #define ASN1_BER_IS_SHORT_LEN(id_octet) \
76  ( !((id_octet >> 7) & 0x01)) /* (8.1.3.3) Is short form */
77 #define ASN1_BER_GET_SHORT_LEN(id_octet) \
78  (id_octet & 0x7F) /* (8.1.3.3) length value */
79 #define ASN1_BER_GET_LONG_LEN_OCTETS(id_octet) \
80  (id_octet & 0x7F) /* (8.1.3.5) the number of
81  bytes */
82 #define ASN1_BER_GET_LONG_LEN(id_octet) \
83  (id_octet) /* (8.1.3.5) the byte itself*/
84 #define ASN1_BER_LONG_LEN_HAS_NEXT(id_octet) \
85  ( !((id_octet >> 7) & 0x01)) /* (8.1.3.5) Has next octets
86  lenght */
87 #define ASN1_BER_IS_INDEFINITE_LEN(id_octet) \
88  (id_octet == 0x80) /* (8.1.3.6) Need end-of-ccontent */
89 #define ASN1_BER_IS_EOC(tmp_iter) (*tmp_iter == 0 && *(tmp_iter + 1) == 0)
90 
91 /* Return the current node/frame that we are filling */
92 #define ASN1CTX_CUR_NODE(ac) (ac->asn1_stack[ac->cur_frame])
93 #define ASN1CTX_GET_NODE(ac, node) (ac->asn1_stack[node])
94 
95 /* BER Universal tags */
96 #define ASN1_UNITAG_EOC 0 /* EOC */
97 #define ASN1_UNITAG_BOOLEAN 1
98 #define ASN1_UNITAG_INTEGER 2
99 #define ASN1_UNITAG_BIT_STRING 3
100 #define ASN1_UNITAG_OCTET_STRING 4
101 #define ASN1_UNITAG_NULL 5
102 #define ASN1_UNITAG_OID 6
103 #define ASN1_UNITAG_OBJECT_DESCRIPTOR 7
104 #define ASN1_UNITAG_EXTERNAL 8
105 #define ASN1_UNITAG_REAL 9
106 #define ASN1_UNITAG_ENUMERATED 10
107 #define ASN1_UNITAG_EMBEDDED_PDV 11
108 #define ASN1_UNITAG_UTF8_STRING 12
109 #define ASN1_UNITAG_RELATIVE_OID 13
110 #define ASN1_UNITAG_SEQUENCE 16
111 #define ASN1_UNITAG_SET 17
112 #define ASN1_UNITAG_NUMERIC_STRING 18
113 #define ASN1_UNITAG_PRINTABLE_STRING 19
114 #define ASN1_UNITAG_TELETEX_STRING 20
115 #define ASN1_UNITAG_VIDEOTEX_STRING 21
116 #define ASN1_UNITAG_IA5_STRING 22
117 #define ASN1_UNITAG_UTCTIME 23
118 #define ASN1_UNITAG_GENERALIZED_TIME 24
119 #define ASN1_UNITAG_GRAPHIC_STRING 25
120 #define ASN1_UNITAG_VISIBLE_STRING 26
121 #define ASN1_UNITAG_GENERAL_STRING 27
122 #define ASN1_UNITAG_UNIVERSAL_STRING 28
123 #define ASN1_UNITAG_CHARACTER_STRING 29
124 #define ASN1_UNITAG_BMP_STRING 30
125 
126 /* Length form */
127 #define ASN1_BER_LEN_SHORT 0
128 #define ASN1_BER_LEN_LONG 1
129 #define ASN1_BER_LEN_INDEFINITE 2
130 
131 
132 /* Error events/flags */
133 #define ASN1_BER_EVENT_ID_TOO_LONG 0x01
134 #define ASN1_BER_EVENT_INVALID_ID 0x02 /* (8.1.2.4.2c) First subsequent
135  id val (from bit 7 to 0) Shall
136  not be 0 */
137 #define ASN1_BER_EVENT_INVALID_LEN 0x04 /* (8.1.3.2a) we expect a simple
138  form, or (8.1.3.5c) we got
139  0xFF, or not enough data */
140 #define ASN1_BER_EVENT_LEN_TOO_LONG 0x08
141 #define ASN1_BER_EVENT_EOC_NOT_FOUND 0x10 /* EOC not found */
142 
143 
144 /* Helper flags */
145 #define ASN1_NODE_IS_EOC 1
146 #define ASN1_TAG_TYPE_PRIMITIVE 0
147 #define ASN1_TAG_TYPE_CONSTRUCTED 1
148 
149 typedef struct Asn1Len_ {
150  uint8_t form;
151  uint32_t len;
152  uint8_t *ptr;
153 } Asn1Len;
154 
155 typedef struct Asn1Id_ {
156  uint8_t *ptr;
157  uint8_t class_tag;
158  uint8_t tag_type;
159  uint32_t tag_num;
160 } Asn1Id;
161 
162 typedef struct Asn1Data_ {
163  uint8_t *ptr;
164  uint32_t len;
165  uint8_t type;
166 } Asn1Data;
167 
168 typedef struct Asn1Node_ {
169  uint8_t *raw_str;
170  uint8_t data_len;
174  uint8_t flags;
175 } Asn1Node;
176 
177 typedef struct Asn1Ctx_ {
178  uint8_t *data;
179  uint8_t *end;
180  uint16_t len;
181 
182  uint8_t *iter;
183 
184  uint16_t cur_frame;
185  Asn1Node *asn1_stack2[ASN1_MAX_FRAMES];
187 
188  uint8_t parser_status;
189 
190  uint8_t ctx_flags;
191 } Asn1Ctx;
192 
193 /* Return codes of the decoder */
194 #define ASN1_PARSER_OK 0x01 /* Everything ok */
195 #define ASN1_PARSER_ERR 0x02 /* Internal error, fatal error, we can't continue decoding */
196 
197 /* Status of the parser */
198 #define ASN1_STATUS_OK 0x00 /* On the road */
199 #define ASN1_STATUS_INVALID 0x01 /* We found something weird/invalid by the specification, but we can try to continue parsing */
200 #define ASN1_STATUS_OOB 0x02 /* We don't have enough data or ran out of bounds */
201 #define ASN1_STATUS_DONE 0x04 /* We have finished cleanly */
202 
203 void SCPrintByteBin(uint8_t);
204 
205 Asn1Ctx *SCAsn1CtxNew(void);
206 void SCAsn1CtxInit(Asn1Ctx *, uint8_t *, uint16_t);
207 void SCAsn1CtxDestroy(Asn1Ctx *);
208 
209 uint8_t SCAsn1Decode(Asn1Ctx *, uint16_t);
211 uint8_t SCAsn1DecodeLength(Asn1Ctx *);
212 uint8_t SCAsn1DecodeContent(Asn1Ctx *);
213 
214 uint8_t SCAsn1CheckBounds(Asn1Ctx *);
215 
216 void DecodeAsn1RegisterTests(void);
217 void SCAsn1LoadConfig(void);
218 
219 #endif /* __DECODE_ASN1_H__ */
220 
struct Asn1Ctx_ Asn1Ctx
struct Asn1Id_ Asn1Id
uint8_t SCAsn1DecodeContent(Asn1Ctx *)
Check the content length and perform other inspections and decodings if necessary.
Asn1Data data
uint8_t * raw_str
uint16_t len
uint32_t tag_num
uint32_t len
void SCAsn1CtxDestroy(Asn1Ctx *)
Destroy an ASN1 Parsing context.
void SCPrintByteBin(uint8_t)
Helper function that print the bits of a byte to check encoding internals.
void DecodeAsn1RegisterTests(void)
struct Asn1Data_ Asn1Data
Asn1Ctx * SCAsn1CtxNew(void)
Create a new ASN1 Parsing context.
uint8_t SCAsn1CheckBounds(Asn1Ctx *)
check if we have remaining data available, otherwise the parser should stop
uint8_t parser_status
uint8_t form
uint8_t * data
uint8_t data_len
uint8_t SCAsn1DecodeLength(Asn1Ctx *)
Decode and check the length, of the current node that we are parsing, also check invalid opts...
struct Asn1Node_ Asn1Node
void SCAsn1CtxInit(Asn1Ctx *, uint8_t *, uint16_t)
Initialize the data of the ASN1 parser ctx with the asn1 raw buffer.
uint8_t class_tag
struct Asn1Len_ Asn1Len
Asn1Node ** asn1_stack
uint8_t * ptr
void SCAsn1LoadConfig(void)
uint8_t * ptr
uint8_t * ptr
uint8_t SCAsn1DecodeIdentifier(Asn1Ctx *)
Decode and check the identifier information of the current node that we are parsing, also check invalid opts.
uint8_t SCAsn1Decode(Asn1Ctx *, uint16_t)
Decode the nodes/frames located at certain position/level.
uint8_t ctx_flags
uint16_t cur_frame
#define ASN1_MAX_FRAMES
uint32_t len
uint8_t tag_type
uint8_t * iter
uint8_t * end