1 /* coap_asn1.c -- ASN.1 handling functions
2 *
3 * Copyright (C) 2020 Jon Shallow <supjps-libcoap@jpshallow.com>
4 *
5 * SPDX-License-Identifier: BSD-2-Clause
6 *
7 * This file is part of the CoAP library libcoap. Please see
8 * README for terms of use.
9 */
10
11 #include "coap3/coap_internal.h"
12
13 size_t
asn1_len(const uint8_t ** ptr)14 asn1_len(const uint8_t **ptr)
15 {
16 size_t len = 0;
17
18 if ((**ptr) & 0x80) {
19 size_t octets = (**ptr) & 0x7f;
20 (*ptr)++;
21 while (octets) {
22 len = (len << 8) + (**ptr);
23 (*ptr)++;
24 octets--;
25 }
26 }
27 else {
28 len = (**ptr) & 0x7f;
29 (*ptr)++;
30 }
31 return len;
32 }
33
34 coap_asn1_tag_t
asn1_tag_c(const uint8_t ** ptr,int * constructed,int * class)35 asn1_tag_c(const uint8_t **ptr, int *constructed, int *class)
36 {
37 coap_asn1_tag_t tag = 0;
38 uint8_t byte;
39
40 byte = (**ptr);
41 *constructed = (byte & 0x20) ? 1 : 0;
42 *class = byte >> 6;
43 tag = byte & 0x1F;
44 (*ptr)++;
45 if (tag < 0x1F)
46 return tag;
47
48 /* Tag can be one byte or more based on B8 */
49 byte = (**ptr);
50 while (byte & 0x80) {
51 tag = (tag << 7) + (byte & 0x7F);
52 (*ptr)++;
53 byte = (**ptr);
54 }
55 /* Do the final one */
56 tag = (tag << 7) + (byte & 0x7F);
57 (*ptr)++;
58 return tag;
59 }
60
61 /* caller must free off returned coap_binary_t* */
62 coap_binary_t *
get_asn1_tag(coap_asn1_tag_t ltag,const uint8_t * ptr,size_t tlen,asn1_validate validate)63 get_asn1_tag(coap_asn1_tag_t ltag, const uint8_t *ptr, size_t tlen,
64 asn1_validate validate)
65 {
66 int constructed;
67 int class;
68 const uint8_t *acp = ptr;
69 uint8_t tag = asn1_tag_c(&acp, &constructed, &class);
70 size_t len = asn1_len(&acp);
71 coap_binary_t *tag_data;
72
73 while (tlen > 0 && len <= tlen) {
74 if (class == 2 && constructed == 1) {
75 /* Skip over element description */
76 tag = asn1_tag_c(&acp, &constructed, &class);
77 len = asn1_len(&acp);
78 }
79 if (tag == ltag) {
80 if (!validate || validate(acp, len)) {
81 tag_data = coap_new_binary(len);
82 if (tag_data == NULL)
83 return NULL;
84 tag_data->length = len;
85 memcpy(tag_data->s, acp, len);
86 return tag_data;
87 }
88 }
89 if (tag == 0x10 && constructed == 1) {
90 /* SEQUENCE or SEQUENCE OF */
91 tag_data = get_asn1_tag(ltag, acp, len, validate);
92 if (tag_data)
93 return tag_data;
94 }
95 acp += len;
96 tlen -= len;
97 tag = asn1_tag_c(&acp, &constructed, &class);
98 len = asn1_len(&acp);
99 }
100 return NULL;
101 }
102
103