2
* Copyright (C) 2011-2012 ANSSI
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
* 3. The name of the author may not be used to endorse or promote products
14
* derived from this software without specific prior written permission.
16
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
17
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
19
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
* \author Pierre Chifflier <pierre.chifflier@ssi.gouv.fr>
36
* An ASN.1 Parser for DER-encoded structures.
37
* This parser is not written to be complete or fast, but is rather
38
* focused on stability and security.
39
* It does not support all ASN.1 structure, only a meaningful subset
40
* to decode x509v3 certificates (See RFC 3280).
42
* References (like 8.19.4) are relative to the ISO/IEC 8825-1:2003 document
53
#include <sys/types.h>
57
#include "suricata-common.h"
59
#include "util-decode-der.h"
61
#define MAX_OID_LENGTH 256
63
static Asn1Generic * DecodeAsn1DerBitstring(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode);
64
static Asn1Generic * DecodeAsn1DerBoolean(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode);
65
static Asn1Generic * DecodeAsn1DerIA5String(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode);
66
static Asn1Generic * DecodeAsn1DerInteger(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode);
67
static Asn1Generic * DecodeAsn1DerNull(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode);
68
static Asn1Generic * DecodeAsn1DerOctetString(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode);
69
static Asn1Generic * DecodeAsn1DerUTF8String(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode);
70
static Asn1Generic * DecodeAsn1DerOid(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode);
71
static Asn1Generic * DecodeAsn1DerPrintableString(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode);
72
static Asn1Generic * DecodeAsn1DerSequence(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode);
73
static Asn1Generic * DecodeAsn1DerSet(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode);
74
static Asn1Generic * DecodeAsn1DerT61String(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode);
75
static Asn1Generic * DecodeAsn1DerUTCTime(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode);
77
static Asn1Generic * Asn1GenericNew(void)
81
obj = SCMalloc(sizeof(Asn1Generic));
83
memset(obj, 0, sizeof(Asn1Generic));
88
static void Asn1SequenceAppend(Asn1Generic *seq, Asn1Generic *node)
90
Asn1Generic *it, *new_container;
92
if (seq->data == NULL) {
97
new_container = Asn1GenericNew();
98
if (new_container == NULL)
100
new_container->data = node;
102
for (it=seq; it->next != NULL; it=it->next)
105
it->next = new_container;
108
static Asn1Generic * DecodeAsn1DerGeneric(const unsigned char *buffer, uint32_t max_size, uint8_t depth, int seq_index, uint32_t *errcode)
110
const unsigned char *d_ptr = buffer;
111
uint32_t numbytes, el_max_size;
118
el.cls = (d_ptr[0] & 0xc0) >> 6;
119
el.pc = (d_ptr[0] & 0x20) >> 5;
120
el.tag = (d_ptr[0] & 0x1f);
128
case ASN1_CLASS_CONTEXTSPEC:
129
/* get element type from definition
130
* see http://www.ietf.org/rfc/rfc3280.txt)
132
if (depth == 2 && el.tag == 0) {
133
el_type = ASN1_SEQUENCE; /* TBSCertificate */
136
if (depth == 2 && el.tag == 1) {
137
el_type = ASN1_BITSTRING; /* issuerUniqueID */
140
if (depth == 2 && el.tag == 2) {
141
el_type = ASN1_BITSTRING; /* subjectUniqueID */
144
if (depth == 2 && el.tag == 3) {
145
el_type = ASN1_SEQUENCE; /* extensions */
148
/* unknown context specific value - do not decode */
152
el_max_size = max_size - (d_ptr-buffer);
155
child = DecodeAsn1DerInteger(d_ptr, el_max_size, depth+1, errcode);
158
child = DecodeAsn1DerBoolean(d_ptr, el_max_size, depth+1, errcode);
161
child = DecodeAsn1DerNull(d_ptr, el_max_size, depth+1, errcode);
164
child = DecodeAsn1DerBitstring(d_ptr, el_max_size, depth+1, errcode);
167
child = DecodeAsn1DerOid(d_ptr, el_max_size, depth+1, errcode);
170
child = DecodeAsn1DerIA5String(d_ptr, el_max_size, depth+1, errcode);
172
case ASN1_OCTETSTRING:
173
child = DecodeAsn1DerOctetString(d_ptr, el_max_size, depth+1, errcode);
175
case ASN1_UTF8STRING:
176
child = DecodeAsn1DerUTF8String(d_ptr, el_max_size, depth+1, errcode);
178
case ASN1_PRINTSTRING:
179
child = DecodeAsn1DerPrintableString(d_ptr, el_max_size, depth+1, errcode);
182
child = DecodeAsn1DerSequence(d_ptr, el_max_size, depth+1, errcode);
185
child = DecodeAsn1DerSet(d_ptr, el_max_size, depth+1, errcode);
188
child = DecodeAsn1DerT61String(d_ptr, el_max_size, depth+1, errcode);
191
child = DecodeAsn1DerUTCTime(d_ptr, el_max_size, depth+1, errcode);
194
/* unknown ASN.1 type */
196
child = Asn1GenericNew();
199
child->type = el.tag;
200
/* total sequence length */
201
const unsigned char * save_d_ptr = d_ptr;
204
if ((c & (1<<7))>>7 == 0) { /* short form 8.1.3.4 */
207
} else { /* long form 8.1.3.5 */
209
if (numbytes > el_max_size) {
212
*errcode = ERR_DER_ELEMENT_SIZE_TOO_BIG;
217
for (i=0; i<numbytes; i++) {
218
child->length = child->length<<8 | d_ptr[0];
222
/* fix the length for unknown objects, else
223
* sequence parsing will fail
225
child->length += (d_ptr - save_d_ptr);
235
static Asn1Generic * DecodeAsn1DerInteger(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode)
237
const unsigned char *d_ptr = buffer;
245
if (numbytes > size) {
247
*errcode = ERR_DER_ELEMENT_SIZE_TOO_BIG;
254
/* Here we need to ensure that numbytes is less than 4
255
so integer affectation is possible. We set the value
256
to 0xffffffff which is by convention the unknown value.
257
In this case, the hexadecimal value must be used. */
261
for (i=0; i<numbytes; i++) {
262
value = value<<8 | d_ptr[i];
266
a = Asn1GenericNew();
269
a->type = ASN1_INTEGER;
270
a->length = (d_ptr - buffer) + numbytes;
273
a->str = SCMalloc(2*numbytes + 1);
274
if (a->str == NULL) {
278
for (i=0; i<numbytes; i++) {
279
snprintf(a->str + 2*i, 2*(numbytes-i)+1, "%02X", d_ptr[i]);
281
a->str[2*numbytes]='\0';
286
static int DecodeAsn1BuildValue(const unsigned char **d_ptr, uint32_t *val, uint8_t numbytes, uint32_t *errcode)
292
*errcode = ERR_DER_INVALID_SIZE;
293
/* too big won't fit: set it to 0xffffffff by convention */
298
for (i=0; i<numbytes; i++) {
299
value = value<<8 | (*d_ptr)[0];
307
static Asn1Generic * DecodeAsn1DerBoolean(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode)
309
const unsigned char *d_ptr = buffer;
317
if (DecodeAsn1BuildValue(&d_ptr, &value, numbytes, errcode) == -1) {
320
a = Asn1GenericNew();
323
a->type = ASN1_BOOLEAN;
324
a->length = (d_ptr - buffer);
330
static Asn1Generic * DecodeAsn1DerNull(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode)
332
const unsigned char *d_ptr = buffer;
339
if (DecodeAsn1BuildValue(&d_ptr, &value, numbytes, errcode) == -1) {
342
a = Asn1GenericNew();
346
a->length = (d_ptr - buffer);
352
static Asn1Generic * DecodeAsn1DerBitstring(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode)
354
const unsigned char *d_ptr = buffer;
363
if ((c & (1<<7))>>7 == 0) { /* short form 8.1.3.4 */
366
} else { /* long form 8.1.3.5 */
369
if (DecodeAsn1BuildValue(&d_ptr, &length, numbytes, errcode) == -1) {
373
if (length > max_size)
376
a = Asn1GenericNew();
379
a->type = ASN1_BITSTRING;
381
a->str = SCMalloc(length);
382
if (a->str == NULL) {
386
memcpy(a->str, (const char*)d_ptr, length);
390
a->length = (d_ptr - buffer);
394
static Asn1Generic * DecodeAsn1DerOid(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode)
396
const unsigned char *d_ptr = buffer;
397
uint32_t oid_length, oid_value;
406
if ((c & (1<<7))>>7 == 0) { /* short form 8.1.3.4 */
409
} else { /* long form 8.1.3.5 */
412
if (DecodeAsn1BuildValue(&d_ptr, &oid_length, numbytes, errcode) == -1) {
416
if (oid_length > max_size)
419
a = Asn1GenericNew();
423
a->str = SCMalloc(MAX_OID_LENGTH);
424
if (a->str == NULL) {
429
/* first element = X*40 + Y (See 8.19.4) */
430
snprintf(a->str, MAX_OID_LENGTH, "%d.%d", (d_ptr[0]/40), (d_ptr[0]%40));
433
/* sub-identifiers are multi valued, coded and 7 bits, first bit of the 8bits is used
434
to indicate, if a new value is starting */
435
for (i=1; i<oid_length; ) {
436
int s = strlen(a->str);
439
while ( i<oid_length && (c & (1<<7)) == 1<<7 ) {
440
oid_value = oid_value<<7 | (c & ~(1<<7));
445
oid_value = oid_value<<7 | c;
448
snprintf(a->str + s, MAX_OID_LENGTH - s, ".%d", oid_value);
451
a->length = (d_ptr - buffer);
455
static Asn1Generic * DecodeAsn1DerIA5String(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode)
457
const unsigned char *d_ptr = buffer;
458
uint32_t length, numbytes;
464
/* total sequence length */
466
if ((c & (1<<7))>>7 == 0) { /* short form 8.1.3.4 */
469
} else { /* long form 8.1.3.5 */
472
if (DecodeAsn1BuildValue(&d_ptr, &length, numbytes, errcode) == -1) {
476
if (length > max_size)
479
a = Asn1GenericNew();
482
a->type = ASN1_IA5STRING;
484
a->str = SCMalloc(length+1);
485
if (a->str == NULL) {
489
strlcpy(a->str, (const char*)d_ptr, length+1);
493
a->length = (d_ptr - buffer);
497
static Asn1Generic * DecodeAsn1DerOctetString(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode)
499
const unsigned char *d_ptr = buffer;
500
uint32_t length, numbytes;
506
/* total sequence length */
508
if ((c & (1<<7))>>7 == 0) { /* short form 8.1.3.4 */
511
} else { /* long form 8.1.3.5 */
514
if (DecodeAsn1BuildValue(&d_ptr, &length, numbytes, errcode) == -1) {
518
if (length > max_size)
521
a = Asn1GenericNew();
524
a->type = ASN1_OCTETSTRING;
526
/* Add one to the octet string for the 0. This will then
527
* allow us to use the string in printf */
528
a->str = SCMalloc(length + 1);
529
if (a->str == NULL) {
533
memcpy(a->str, (const char*)d_ptr, length);
538
a->length = (d_ptr - buffer);
542
static Asn1Generic * DecodeAsn1DerUTF8String(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode)
544
Asn1Generic *a = DecodeAsn1DerOctetString(buffer, max_size, depth, errcode);
546
a->type = ASN1_UTF8STRING;
550
static Asn1Generic * DecodeAsn1DerPrintableString(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode)
552
const unsigned char *d_ptr = buffer;
553
uint32_t length, numbytes;
559
/* total sequence length */
561
if ((c & (1<<7))>>7 == 0) { /* short form 8.1.3.4 */
564
} else { /* long form 8.1.3.5 */
567
if (DecodeAsn1BuildValue(&d_ptr, &length, numbytes, errcode) == -1) {
571
if (length > max_size)
574
a = Asn1GenericNew();
577
a->type = ASN1_PRINTSTRING;
579
a->str = SCMalloc(length+1);
580
if (a->str == NULL) {
584
strlcpy(a->str, (const char*)d_ptr, length+1);
585
a->str[length] = '\0';
589
a->length = (d_ptr - buffer);
593
static Asn1Generic * DecodeAsn1DerSequence(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode)
595
const unsigned char *d_ptr = buffer;
596
uint32_t d_length, parsed_bytes, numbytes, el_max_size;
604
node = Asn1GenericNew();
607
node->type = ASN1_SEQUENCE;
609
/* total sequence length */
611
if ((c & (1<<7))>>7 == 0) { /* short form 8.1.3.4 */
614
} else { /* long form 8.1.3.5 */
617
if (DecodeAsn1BuildValue(&d_ptr, &d_length, numbytes, errcode) == -1) {
622
node->length = d_length + (d_ptr - buffer);
623
if (node->length > max_size) {
631
/* decode child elements */
632
while (parsed_bytes < d_length) {
633
el_max_size = max_size - (d_ptr-buffer);
634
child = DecodeAsn1DerGeneric(d_ptr, el_max_size, depth, seq_index, errcode);
639
Asn1SequenceAppend(node, child);
640
parsed_bytes += child->length;
641
d_ptr += child->length;
645
return (Asn1Generic *)node;
648
static Asn1Generic * DecodeAsn1DerSet(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode)
650
const unsigned char *d_ptr = buffer;
651
uint32_t d_length, numbytes, el_max_size;
659
node = Asn1GenericNew();
662
node->type = ASN1_SET;
665
/* total sequence length */
667
if ((c & (1<<7))>>7 == 0) { /* short form 8.1.3.4 */
670
} else { /* long form 8.1.3.5 */
673
if (DecodeAsn1BuildValue(&d_ptr, &d_length, numbytes, errcode) == -1) {
678
node->length = d_length + (d_ptr - buffer);
680
if (node->length > max_size) {
682
*errcode = ERR_DER_ELEMENT_SIZE_TOO_BIG;
689
el_max_size = max_size - (d_ptr-buffer);
690
child = DecodeAsn1DerGeneric(d_ptr, el_max_size, depth, seq_index, errcode);
694
return (Asn1Generic *)node;
697
static Asn1Generic * DecodeAsn1DerT61String(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode)
701
a = DecodeAsn1DerIA5String(buffer, max_size, depth, errcode);
703
a->type = ASN1_T61STRING;
708
static Asn1Generic * DecodeAsn1DerUTCTime(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode)
712
a = DecodeAsn1DerIA5String(buffer, max_size, depth, errcode);
714
a->type = ASN1_UTCTIME;
719
Asn1Generic * DecodeDer(const unsigned char *buffer, uint32_t size, uint32_t *errcode)
721
const unsigned char *d_ptr = buffer;
722
uint32_t d_length, numbytes;
726
/* Check that buffer is an ASN.1 structure (basic checks) */
727
if (d_ptr[0] != 0x30 && d_ptr[1] != 0x82) /* Sequence */
731
if ((c & (1<<7))>>7 != 1)
736
if (DecodeAsn1BuildValue(&d_ptr, &d_length, numbytes, errcode) == -1) {
739
if (d_length+(d_ptr-buffer) != size)
745
cert = DecodeAsn1DerGeneric(buffer, size, 0 /* depth */, 0, errcode);
750
void DerFree(Asn1Generic *a)
765
memset(it, 0xff, sizeof(Asn1Generic));