libcoap 4.3.4-develop-c081bb6
coap_asn1.c
Go to the documentation of this file.
1/* coap_asn1.c -- ASN.1 handling functions
2*
3* Copyright (C) 2020-2024 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
16#include "coap3/coap_internal.h"
17
18size_t
19asn1_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
38asn1_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* */
65get_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
104/* first part of Raw public key, this is the start of the Subject Public Key */
105static const unsigned char cert_asn1_header1[] = {
106 0x30, 0x59, /* SEQUENCE, length 89 bytes */
107 0x30, 0x13, /* SEQUENCE, length 19 bytes */
108 0x06, 0x07, /* OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1) */
109 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01,
110};
111/* PrimeX will get inserted */
112#if 0
1130x06, 0x08, /* OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7) */
114 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07,
115#endif
116static const unsigned char cert_asn1_header2[] = {
117 0x03, 0x42, /* BIT STRING, length 66 bytes */
118 /* Note: 0 bits (0x00) and no compression (0x04) are already in the certificate */
119};
120
122get_asn1_spki(const uint8_t *data, size_t size) {
123 coap_binary_t *pub_key = get_asn1_tag(COAP_ASN1_BITSTRING, data, size, NULL);
124 coap_binary_t *prime = get_asn1_tag(COAP_ASN1_IDENTIFIER, data, size, NULL);
125 coap_binary_t *spki = NULL;
126
127 if (pub_key && prime) {
128 size_t header_size = sizeof(cert_asn1_header1) +
129 2 +
130 prime->length +
131 sizeof(cert_asn1_header2);
132 spki = coap_new_binary(header_size + pub_key->length);
133 if (spki) {
134 memcpy(&spki->s[header_size], pub_key->s, pub_key->length);
135 memcpy(spki->s, cert_asn1_header1, sizeof(cert_asn1_header1));
137 spki->s[sizeof(cert_asn1_header1)+1] = (uint8_t)prime->length;
138 memcpy(&spki->s[sizeof(cert_asn1_header1)+2],
139 prime->s, prime->length);
140 memcpy(&spki->s[sizeof(cert_asn1_header1)+2+prime->length],
142 spki->length = header_size + pub_key->length;
143 }
144 }
145 if (pub_key)
146 coap_delete_binary(pub_key);
147 if (prime)
148 coap_delete_binary(prime);
149 return spki;
150}
static const unsigned char cert_asn1_header2[]
Definition: coap_asn1.c:116
static const unsigned char cert_asn1_header1[]
Definition: coap_asn1.c:105
Pulls together all the internal only header files.
coap_binary_t * get_asn1_tag(coap_asn1_tag_t ltag, const uint8_t *ptr, size_t tlen, asn1_validate validate)
Get the asn1 tag and data from the current ptr.
Definition: coap_asn1.c:65
coap_asn1_tag_t asn1_tag_c(const uint8_t **ptr, int *constructed, int *cls)
Get the asn1 tag from the current ptr.
Definition: coap_asn1.c:38
size_t asn1_len(const uint8_t **ptr)
Get the asn1 length from the current ptr.
Definition: coap_asn1.c:19
coap_asn1_tag_t
coap_binary_t * get_asn1_spki(const uint8_t *data, size_t size)
Abstract SPKI public key from the ASN1.
Definition: coap_asn1.c:122
int(* asn1_validate)(const uint8_t *data, size_t size)
Callback to validate the asn1 tag and data.
@ COAP_ASN1_BITSTRING
@ COAP_ASN1_IDENTIFIER
coap_binary_t * coap_new_binary(size_t size)
Returns a new binary object with at least size bytes storage allocated.
Definition: coap_str.c:77
void coap_delete_binary(coap_binary_t *s)
Deletes the given coap_binary_t object and releases any memory allocated.
Definition: coap_str.c:105
CoAP binary data definition.
Definition: coap_str.h:56
size_t length
length of binary data
Definition: coap_str.h:57
uint8_t * s
binary data
Definition: coap_str.h:58