• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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