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