aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/suricata/src/util-decode-asn1.h
blob: d3ff9a3e86745553ec5b400899bd271303e4daf8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
/* Copyright (C) 2007-2010 Open Information Security Foundation
 *
 * You can copy, redistribute or modify this Program under the terms of
 * the GNU General Public License version 2 as published by the Free
 * Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * version 2 along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 */

/**
 * \file
 *
 * \author Pablo Rincon Crespo <pablo.rincon.crespo@gmail.com>
 *
 * Implements ASN1 decoding (needed for the asn1 keyword)
 */

#ifndef __DECODE_ASN1_H__
#define __DECODE_ASN1_H__
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <inttypes.h>
#include <limits.h>
#include <ctype.h>
#include <string.h>

#define ASN1_MAX_FRAMES 128

/* For future enconding type implementations */
enum {
    ASN1_BER_ENC,
    ASN1_ENC_UNKNOWN
};

/* Class of tag */
#define ASN1_BER_CLASS_UNIV                 0
#define ASN1_BER_CLASS_APP                  1
#define ASN1_BER_CLASS_CTX_SPECIFIC         2
#define ASN1_BER_CLASS_PRIV                 3

/* For low tag numbers */
#define ASN1_BER_GET_CLASS_TAG(id_octet)    \
             ((id_octet >> 6) & 0x03)           /* (8.1.2.2a) */
#define ASN1_BER_IS_CONSTRUCTED(id_octet)   \
             ((id_octet >> 5) & 0x01)           /* (8.1.2.5) Constructed Tag */
#define ASN1_BER_IS_PRIMITIVE(id_octet)     \
             (((id_octet >> 5) & 0x01)?0:1)     /* (8.1.2.5) Primitive Tag */
#define ASN1_BER_IS_LOW_TAG(id_octet)       \
             ASN1_BER_IS_PRIMITIVE(id_octet)    /* (8.1.2.5) Is Low Tag
                                                             Number */
#define ASN1_BER_GET_LOW_TAG_NUM(id_octet)  \
             (id_octet & 0x1F)                  /* (8.1.2.2c) Get LowTag Number */

/* For high tag numbers */
#define ASN1_BER_IS_HIGH_TAG(id_octet)      \
        ((ASN1_BER_GET_LOW_TAG_NUM(id_octet) == 0x1F) && \
        ASN1_BER_IS_CONSTRUCTED(id_octet))      /* (8.1.2.4) High Tag Number */
#define ASN1_BER_IS_HIGH_TAG_END(id_octet)  \
        ( !((id_octet >> 7) & 0x01))            /* (8.1.2.4) Is End of Tag Num */
#define ASN1_BER_GET_HIGH_TAG_NUM(id_octet) \
        (id_octet & 0x7F)                       /* (8.1.2.4) Part of High Tag
                                                             Number */


#define ASN1_BER_IS_SHORT_LEN(id_octet)        \
             ( !((id_octet >> 7) & 0x01))        /* (8.1.3.3) Is short form */
#define ASN1_BER_GET_SHORT_LEN(id_octet)       \
             (id_octet & 0x7F)                   /* (8.1.3.3) length value */
#define ASN1_BER_GET_LONG_LEN_OCTETS(id_octet) \
             (id_octet & 0x7F)                   /* (8.1.3.5) the number of
                                                              bytes */
#define ASN1_BER_GET_LONG_LEN(id_octet) \
             (id_octet)                          /* (8.1.3.5) the byte itself*/
#define ASN1_BER_LONG_LEN_HAS_NEXT(id_octet)   \
             ( !((id_octet >> 7) & 0x01))        /* (8.1.3.5) Has next octets
                                                              lenght */
#define ASN1_BER_IS_INDEFINITE_LEN(id_octet)   \
             (id_octet == 0x80)                /* (8.1.3.6) Need end-of-ccontent */
#define ASN1_BER_IS_EOC(tmp_iter) (*tmp_iter == 0 && *(tmp_iter + 1) == 0)

/* Return the current node/frame that we are filling */
#define ASN1CTX_CUR_NODE(ac) (ac->asn1_stack[ac->cur_frame])
#define ASN1CTX_GET_NODE(ac, node) (ac->asn1_stack[node])

/* BER Universal tags */
#define ASN1_UNITAG_EOC                  0   /* EOC */
#define ASN1_UNITAG_BOOLEAN              1
#define ASN1_UNITAG_INTEGER              2
#define ASN1_UNITAG_BIT_STRING           3
#define ASN1_UNITAG_OCTET_STRING         4
#define ASN1_UNITAG_NULL                 5
#define ASN1_UNITAG_OID                  6
#define ASN1_UNITAG_OBJECT_DESCRIPTOR    7
#define ASN1_UNITAG_EXTERNAL             8
#define ASN1_UNITAG_REAL                 9
#define ASN1_UNITAG_ENUMERATED           10
#define ASN1_UNITAG_EMBEDDED_PDV         11
#define ASN1_UNITAG_UTF8_STRING          12
#define ASN1_UNITAG_RELATIVE_OID         13
#define ASN1_UNITAG_SEQUENCE             16
#define ASN1_UNITAG_SET                  17
#define ASN1_UNITAG_NUMERIC_STRING       18
#define ASN1_UNITAG_PRINTABLE_STRING     19
#define ASN1_UNITAG_TELETEX_STRING       20
#define ASN1_UNITAG_VIDEOTEX_STRING      21
#define ASN1_UNITAG_IA5_STRING           22
#define ASN1_UNITAG_UTCTIME              23
#define ASN1_UNITAG_GENERALIZED_TIME     24
#define ASN1_UNITAG_GRAPHIC_STRING       25
#define ASN1_UNITAG_VISIBLE_STRING       26
#define ASN1_UNITAG_GENERAL_STRING       27
#define ASN1_UNITAG_UNIVERSAL_STRING     28
#define ASN1_UNITAG_CHARACTER_STRING     29
#define ASN1_UNITAG_BMP_STRING           30

/* Length form */
#define ASN1_BER_LEN_SHORT          0
#define ASN1_BER_LEN_LONG           1
#define ASN1_BER_LEN_INDEFINITE     2


/* Error events/flags */
#define ASN1_BER_EVENT_ID_TOO_LONG            0x01
#define ASN1_BER_EVENT_INVALID_ID             0x02 /* (8.1.2.4.2c) First subsequent
                                                      id val (from bit 7 to 0) Shall
                                                      not be 0 */
#define ASN1_BER_EVENT_INVALID_LEN            0x04 /* (8.1.3.2a) we expect a simple
                                                      form, or (8.1.3.5c) we got
                                                      0xFF, or not enough data */
#define ASN1_BER_EVENT_LEN_TOO_LONG           0x08
#define ASN1_BER_EVENT_EOC_NOT_FOUND          0x10 /* EOC not found */


/* Helper flags */
#define ASN1_NODE_IS_EOC 1
#define ASN1_TAG_TYPE_PRIMITIVE 0
#define ASN1_TAG_TYPE_CONSTRUCTED 1

typedef struct Asn1Len_ {
    uint8_t form;
    uint32_t len;
    uint8_t *ptr;
} Asn1Len;

typedef struct Asn1Id_ {
    uint8_t *ptr;
    uint8_t class_tag;
    uint8_t tag_type;
    uint32_t tag_num;
} Asn1Id;

typedef struct Asn1Data_ {
    uint8_t *ptr;
    uint32_t len;
    uint8_t type;
} Asn1Data;

typedef struct Asn1Node_ {
    uint8_t *raw_str;
    uint8_t data_len;
    Asn1Len len;
    Asn1Id id;
    Asn1Data data;
    uint8_t flags;
} Asn1Node;

typedef struct Asn1Ctx_ {
    uint8_t *data;
    uint8_t *end;
    uint16_t len;

    uint8_t *iter;

    uint16_t cur_frame;
    Asn1Node *asn1_stack2[ASN1_MAX_FRAMES];
    Asn1Node **asn1_stack;

    uint8_t parser_status;

    uint8_t ctx_flags;
} Asn1Ctx;

/* Return codes of the decoder */
#define ASN1_PARSER_OK          0x01 /* Everything ok */
#define ASN1_PARSER_ERR         0x02 /* Internal error, fatal error, we can't continue decoding */

/* Status of the parser  */
#define ASN1_STATUS_OK          0x00 /* On the road */
#define ASN1_STATUS_INVALID     0x01 /* We found something weird/invalid by the specification, but we can try to continue parsing */
#define ASN1_STATUS_OOB         0x02 /* We don't have enough data or ran out of bounds */
#define ASN1_STATUS_DONE        0x04 /* We have finished cleanly */

void SCPrintByteBin(uint8_t);

Asn1Ctx *SCAsn1CtxNew(void);
void SCAsn1CtxInit(Asn1Ctx *, uint8_t *, uint16_t);
void SCAsn1CtxDestroy(Asn1Ctx *);

uint8_t SCAsn1Decode(Asn1Ctx *, uint16_t);
uint8_t SCAsn1DecodeIdentifier(Asn1Ctx *);
uint8_t SCAsn1DecodeLength(Asn1Ctx *);
uint8_t SCAsn1DecodeContent(Asn1Ctx *);

uint8_t SCAsn1CheckBounds(Asn1Ctx *);

void DecodeAsn1RegisterTests(void);
void SCAsn1LoadConfig();

#endif /* __DECODE_ASN1_H__ */