38FILE_RCSID(
"@(#)$File: der.c,v 1.27 2022/09/24 20:30:13 christos Exp $")
41#define SIZE_T_FORMAT "z"
42#define CAST(a, b) ((a)(b))
64#define DER_BAD CAST(uint32_t, -1)
66#define DER_CLASS_UNIVERSAL 0
67#define DER_CLASS_APPLICATION 1
68#define DER_CLASS_CONTEXT 2
69#define DER_CLASS_PRIVATE 3
70#if defined(DEBUG_DER) || defined(TEST_DER)
71static const char der_class[] =
"UACP";
74#define DER_TYPE_PRIMITIVE 0
75#define DER_TYPE_CONSTRUCTED 1
76#if defined(DEBUG_DER) || defined(TEST_DER)
77static const char der_type[] =
"PC";
80#define DER_TAG_EOC 0x00
81#define DER_TAG_BOOLEAN 0x01
82#define DER_TAG_INTEGER 0x02
83#define DER_TAG_BIT STRING 0x03
84#define DER_TAG_OCTET_STRING 0x04
85#define DER_TAG_NULL 0x05
86#define DER_TAG_OBJECT_IDENTIFIER 0x06
87#define DER_TAG_OBJECT_DESCRIPTOR 0x07
88#define DER_TAG_EXTERNAL 0x08
89#define DER_TAG_REAL 0x09
90#define DER_TAG_ENUMERATED 0x0a
91#define DER_TAG_EMBEDDED_PDV 0x0b
92#define DER_TAG_UTF8_STRING 0x0c
93#define DER_TAG_RELATIVE_OID 0x0d
94#define DER_TAG_TIME 0x0e
95#define DER_TAG_RESERVED_2 0x0f
96#define DER_TAG_SEQUENCE 0x10
97#define DER_TAG_SET 0x11
98#define DER_TAG_NUMERIC_STRING 0x12
99#define DER_TAG_PRINTABLE_STRING 0x13
100#define DER_TAG_T61_STRING 0x14
101#define DER_TAG_VIDEOTEX_STRING 0x15
102#define DER_TAG_IA5_STRING 0x16
103#define DER_TAG_UTCTIME 0x17
104#define DER_TAG_GENERALIZED_TIME 0x18
105#define DER_TAG_GRAPHIC_STRING 0x19
106#define DER_TAG_VISIBLE_STRING 0x1a
107#define DER_TAG_GENERAL_STRING 0x1b
108#define DER_TAG_UNIVERSAL_STRING 0x1c
109#define DER_TAG_CHARACTER_STRING 0x1d
110#define DER_TAG_BMP_STRING 0x1e
111#define DER_TAG_DATE 0x1f
112#define DER_TAG_TIME_OF_DAY 0x20
113#define DER_TAG_DATE_TIME 0x21
114#define DER_TAG_DURATION 0x22
115#define DER_TAG_OID_IRI 0x23
116#define DER_TAG_RELATIVE_OID_IRI 0x24
117#define DER_TAG_LAST 0x25
119static const char *der__tag[] = {
120 "eoc",
"bool",
"int",
"bit_str",
"octet_str",
121 "null",
"obj_id",
"obj_desc",
"ext",
"real",
122 "enum",
"embed",
"utf8_str",
"rel_oid",
"time",
123 "res2",
"seq",
"set",
"num_str",
"prt_str",
124 "t61_str",
"vid_str",
"ia5_str",
"utc_time",
"gen_time",
125 "gr_str",
"vis_str",
"gen_str",
"univ_str",
"char_str",
126 "bmp_str",
"date",
"tod",
"datetime",
"duration",
127 "oid-iri",
"rel-oid-iri",
131#define DPRINTF(a) printf a
151gettag(
const uint8_t *c,
size_t *
p,
size_t l)
158 tag = c[(*p)++] & 0x1f;
166 while (c[*
p] >= 0x80) {
167 tag = tag * 128 + c[(*p)++] - 0x80;
184getlength(
const uint8_t *c,
size_t *
p,
size_t l)
188 int is_onebyte_result;
191 DPRINTF((
"%s:[1] %zu >= %zu\n", __func__, *
p, l));
200 is_onebyte_result = (c[*
p] & 0x80) == 0;
201 digits = c[(*p)++] & 0x7f;
202 if (*
p + digits >= l) {
203 DPRINTF((
"%s:[2] %zu + %u >= %zu\n", __func__, *
p, digits, l));
207 if (is_onebyte_result)
215 for (i = 0; i < digits; i++)
216 len = (
len << 8) | c[(*p)++];
219 DPRINTF((
"%s:[3] bad len %zu + %zu >= %zu\n",
220 __func__, *
p,
len, l));
227der_tag(
char *
buf,
size_t len, uint32_t tag)
238der_data(
char *
buf,
size_t blen, uint32_t tag,
const void *q, uint32_t
len)
241 const uint8_t *d =
CAST(
const uint8_t *, q);
251 "20%c%c-%c%c-%c%c %c%c:%c%c:%c%c GMT", d[0], d[1], d[2],
252 d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11]);
257 for (i = 0; i <
len; i++) {
268 const uint8_t *b =
RCAST(
const uint8_t *, ms->
search.
s);
272 DPRINTF((
"%s: bad tag 1\n", __func__));
278 uint32_t tlen = getlength(b, &offs,
len);
280 DPRINTF((
"%s: bad tag 2\n", __func__));
295 if (offs + tlen > nbytes)
301 return CAST(int32_t, offs);
307 const uint8_t *b =
RCAST(
const uint8_t *, ms->
search.
s);
313 DPRINTF((
"%s: compare %zu bytes\n", __func__,
len));
315 tag = gettag(b, &offs,
len);
317 DPRINTF((
"%s: bad tag 1\n", __func__));
324 tlen = getlength(b, &offs,
len);
326 DPRINTF((
"%s: bad tag 2\n", __func__));
330 der_tag(
buf,
sizeof(
buf), tag);
332 fprintf(stderr,
"%s: tag %p got=%s exp=%s\n", __func__, b,
337 DPRINTF((
"%s: no string match %s != %s\n", __func__,
buf,
s));
346 DPRINTF((
"%s: EOF match\n", __func__));
352 if (!isdigit(
CAST(
unsigned char, *
s))) {
353 DPRINTF((
"%s: no digit %c\n", __func__, *
s));
359 slen = slen * 10 + *
s -
'0';
360 while (isdigit(
CAST(
unsigned char, *++
s)));
363 __func__, slen, tlen);
365 DPRINTF((
"%s: len %u != %zu\n", __func__, tlen, slen));
373 der_data(
buf,
sizeof(
buf), tag, b + offs, tlen);
375 fprintf(stderr,
"%s: data %s %s\n", __func__,
buf,
s);
377 DPRINTF((
"%s: no string match %s != %s\n", __func__,
buf,
s));
381 DPRINTF((
"%s: complete match\n", __func__));
388printtag(uint32_t tag,
const void *q, uint32_t
len)
390 const uint8_t *d = q;
402 for (uint32_t i = 0; i <
len; i++)
408printdata(
size_t level,
const void *
v,
size_t x,
size_t l)
410 const uint8_t *
p =
v, *ep =
p + l;
416 uint8_t c = getclass(
p[x]);
421 uint32_t tag = gettag(
p, &x, ep -
p + x);
424 uint32_t
len = getlength(
p, &x, ep -
p + x);
428 der_class[c], der_type[t],
432 errx(EXIT_FAILURE,
"corrupt der");
433 printtag(tag, q,
len);
435 printdata(level + 1,
p, x,
len + x);
441main(
int argc,
char *argv[])
448 if ((
fd = open(argv[1], O_RDONLY)) == -1)
449 err(EXIT_FAILURE,
"open `%s'", argv[1]);
451 err(EXIT_FAILURE,
"stat `%s'", argv[1]);
452 l = (size_t)st.st_size;
454 err(EXIT_FAILURE,
"mmap `%s'", argv[1]);
456 printdata(0,
p, 0, l);
fprintf($stream, string $format, mixed ... $values)
printf(string $format, mixed ... $values)
#define DER_TYPE_PRIMITIVE
#define DER_TAG_UTF8_STRING
#define DER_TAG_PRINTABLE_STRING
int der_cmp(struct magic_set *ms, struct magic *m)
#define DER_TAG_IA5_STRING
int32_t der_offs(struct magic_set *ms, struct magic *m, size_t nbytes)
zend_ffi_ctype_name_buf buf
struct magic_set::@064260247024367202255202336305226346003333017071 search
strncmp(string $string1, string $string2, int $length)
strcmp(string $string1, string $string2)