1c87c5fbaSopenharmony_ci// -*- mode:doc; -*-
2c87c5fbaSopenharmony_ci// vim: set syntax=asciidoc tw=0
3c87c5fbaSopenharmony_ci
4c87c5fbaSopenharmony_cicoap_encryption(3)
5c87c5fbaSopenharmony_ci===================
6c87c5fbaSopenharmony_ci:doctype: manpage
7c87c5fbaSopenharmony_ci:man source:   coap_encryption
8c87c5fbaSopenharmony_ci:man version:  @PACKAGE_VERSION@
9c87c5fbaSopenharmony_ci:man manual:   libcoap Manual
10c87c5fbaSopenharmony_ci
11c87c5fbaSopenharmony_ciNAME
12c87c5fbaSopenharmony_ci----
13c87c5fbaSopenharmony_cicoap_encryption,
14c87c5fbaSopenharmony_cicoap_dtls_cpsk_t,
15c87c5fbaSopenharmony_cicoap_dtls_spsk_t,
16c87c5fbaSopenharmony_cicoap_dtls_pki_t
17c87c5fbaSopenharmony_ci- Work with CoAP TLS/DTLS
18c87c5fbaSopenharmony_ci
19c87c5fbaSopenharmony_ciSYNOPSIS
20c87c5fbaSopenharmony_ci--------
21c87c5fbaSopenharmony_ci*#include <coap@LIBCOAP_API_VERSION@/coap.h>*
22c87c5fbaSopenharmony_ci
23c87c5fbaSopenharmony_ci*struct coap_dtls_cpsk_t;*
24c87c5fbaSopenharmony_ci
25c87c5fbaSopenharmony_ci*struct coap_dtls_spsk_t;*
26c87c5fbaSopenharmony_ci
27c87c5fbaSopenharmony_ci*struct coap_dtls_pki_t;*
28c87c5fbaSopenharmony_ci
29c87c5fbaSopenharmony_ciFor specific (D)TLS library support, link with
30c87c5fbaSopenharmony_ci*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*,
31c87c5fbaSopenharmony_ci*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls*
32c87c5fbaSopenharmony_cior *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*.   Otherwise, link with
33c87c5fbaSopenharmony_ci*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support.
34c87c5fbaSopenharmony_ci
35c87c5fbaSopenharmony_ciDESCRIPTION
36c87c5fbaSopenharmony_ci-----------
37c87c5fbaSopenharmony_ciThis man page focuses on setting up CoAP to use encryption.
38c87c5fbaSopenharmony_ci
39c87c5fbaSopenharmony_ciWhen the libcoap library was built, it will have been compiled using a
40c87c5fbaSopenharmony_cispecific underlying TLS implementation type (e.g. https://www.openssl.org[OpenSSL],
41c87c5fbaSopenharmony_cihttps://www.gnutls.org[GnuTLS],
42c87c5fbaSopenharmony_cihttps://www.trustedfirmware.org/projects/mbed-tls/[Mbed TLS],
43c87c5fbaSopenharmony_cihttps://github.com/eclipse/tinydtls[TinyDTLS] or noTLS).
44c87c5fbaSopenharmony_ciWhen the libcoap library is linked into an application, it is possible
45c87c5fbaSopenharmony_cithat the application needs to dynamically determine whether DTLS or TLS is
46c87c5fbaSopenharmony_cisupported, what type of TLS implementation libcoap was compiled with, as well
47c87c5fbaSopenharmony_cias detect what is the version of the currently loaded TLS library.
48c87c5fbaSopenharmony_ci
49c87c5fbaSopenharmony_ci*NOTE:* If OpenSSL is being used, then the minimum supported OpenSSL library
50c87c5fbaSopenharmony_civersion is 1.1.0.
51c87c5fbaSopenharmony_ci
52c87c5fbaSopenharmony_ci*NOTE:* If GnuTLS is being used, then the minimum GnuTLS library version is
53c87c5fbaSopenharmony_ci3.3.0.
54c87c5fbaSopenharmony_ci
55c87c5fbaSopenharmony_ci*NOTE:* If Mbed TLS is being used, then the minimum Mbed TLS library version is
56c87c5fbaSopenharmony_ci2.7.10.
57c87c5fbaSopenharmony_ci
58c87c5fbaSopenharmony_ci*NOTE:* If GnuTLS is going to interoperate with TinyDTLS, then a minimum
59c87c5fbaSopenharmony_cirevision of GnuTLS 3.5.5 which supports CCM algorithms is required
60c87c5fbaSopenharmony_ciby TinyDTLS as TinyDTLS currently only supports CCM.
61c87c5fbaSopenharmony_ci
62c87c5fbaSopenharmony_ci*NOTE:* For Raw Public Key support, GnuTLS library version must be 3.6.6 or
63c87c5fbaSopenharmony_cilater. TinyDTLS only supports TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, curve
64c87c5fbaSopenharmony_cisecp256r1 and hash SHA-256.  There currently is no OpenSSL or Mbed TLS RPK support
65c87c5fbaSopenharmony_ci(respective library limitations).
66c87c5fbaSopenharmony_ci
67c87c5fbaSopenharmony_ciNetwork traffic can be un-encrypted or encrypted with libcoap if there is an
68c87c5fbaSopenharmony_ciunderlying TLS library.
69c87c5fbaSopenharmony_ci
70c87c5fbaSopenharmony_ciIf TLS is going to be used for encrypting the network traffic, then the TLS
71c87c5fbaSopenharmony_ciinformation for Pre-Shared Keys (PSK), Public Key Infrastructure (PKI) or
72c87c5fbaSopenharmony_ciRaw Public Key (RPK) needs to be configured before any network traffic starts
73c87c5fbaSopenharmony_cito flow. For Servers, this has to be done before the Endpoint is created,
74c87c5fbaSopenharmony_cifor Clients, this is done during the Client Session set up.
75c87c5fbaSopenharmony_ci
76c87c5fbaSopenharmony_ciFor Servers, all the encryption information is held internally by the TLS
77c87c5fbaSopenharmony_ciContext level and the CoAP Context level as the Server is listening for new
78c87c5fbaSopenharmony_ciincoming traffic based on the Endpoint definition.  The TLS and CoAP session
79c87c5fbaSopenharmony_ciwill not get built until the new traffic starts, which is done by the libcoap
80c87c5fbaSopenharmony_cilibrary, with the session having a reference count of 1.
81c87c5fbaSopenharmony_ci
82c87c5fbaSopenharmony_ciFor Clients, all the encryption information will be held internally by the TLS
83c87c5fbaSopenharmony_ciContext and/or TLS Session level and internally by the CoAP Session level.
84c87c5fbaSopenharmony_ci
85c87c5fbaSopenharmony_ciIn principle the set-up sequence for CoAP Servers looks like
86c87c5fbaSopenharmony_ci----
87c87c5fbaSopenharmony_cicoap_new_context()
88c87c5fbaSopenharmony_cicoap_context_set_pki_root_cas() - if the root CAs need to be updated and PKI
89c87c5fbaSopenharmony_cicoap_context_set_pki() and/or coap_context_set_psk2() - if encryption is required
90c87c5fbaSopenharmony_cicoap_new_endpoint()
91c87c5fbaSopenharmony_ci----
92c87c5fbaSopenharmony_ci
93c87c5fbaSopenharmony_ciMultiple endpoints can be set up per Context, each listening for a new traffic
94c87c5fbaSopenharmony_ciflow with different TCP/UDP protocols, TLS protocols, port numbers etc. When a
95c87c5fbaSopenharmony_cinew traffic flow is started, then the CoAP library will create and start a new
96c87c5fbaSopenharmony_ciserver session.
97c87c5fbaSopenharmony_ci
98c87c5fbaSopenharmony_ciIn principle the set-up sequence for CoAP Clients looks like
99c87c5fbaSopenharmony_ci----
100c87c5fbaSopenharmony_cicoap_new_context()
101c87c5fbaSopenharmony_cicoap_context_set_pki_root_cas() - if the root CAs need to be updated and PKI
102c87c5fbaSopenharmony_cicoap_new_client_session(), coap_new_client_session_pki() or coap_new_client_session_psk2()
103c87c5fbaSopenharmony_ci----
104c87c5fbaSopenharmony_ci
105c87c5fbaSopenharmony_ciMultiple client sessions are supported per Context.
106c87c5fbaSopenharmony_ci
107c87c5fbaSopenharmony_ciDue to the nature of TLS, there are Callbacks that are invoked as the TLS
108c87c5fbaSopenharmony_cisession negotiates encryption algorithms, encryption keys etc.
109c87c5fbaSopenharmony_ciWhere possible, the CoAP layer handles all this automatically based on
110c87c5fbaSopenharmony_cidifferent configuration options passed in by the *coap_context_set_pki*(),
111c87c5fbaSopenharmony_ci*coap_new_client_session_pki*(), *coap_context_set_psk2*() and
112c87c5fbaSopenharmony_ci*coap_new_client_session_psk2*() functions.
113c87c5fbaSopenharmony_ci
114c87c5fbaSopenharmony_ciPSK CLIENT INFORMATION
115c87c5fbaSopenharmony_ci----------------------
116c87c5fbaSopenharmony_ci
117c87c5fbaSopenharmony_ciFor Client PSK setup, the required information needs to be provided in the setup
118c87c5fbaSopenharmony_cicalls with optional application callbacks defined to update the Identity and
119c87c5fbaSopenharmony_ciPSK. Initially, the Client has to provide an Identity and a Pre-Shared Key.
120c87c5fbaSopenharmony_ci
121c87c5fbaSopenharmony_ciLibcoap will put the Identity and Pre-Shared Key as appropriate into the TLS
122c87c5fbaSopenharmony_cienvironment.
123c87c5fbaSopenharmony_ci
124c87c5fbaSopenharmony_ci*SECTION: PSK Client: coap_dtls_cpsk_t*
125c87c5fbaSopenharmony_ci[source, c]
126c87c5fbaSopenharmony_ci----
127c87c5fbaSopenharmony_citypedef struct coap_dtls_cpsk_t {
128c87c5fbaSopenharmony_ci  uint8_t version; /** Set to COAP_DTLS_CPSK_SETUP_VERSION
129c87c5fbaSopenharmony_ci                       to support the version of the struct */
130c87c5fbaSopenharmony_ci
131c87c5fbaSopenharmony_ci  /* Options to enable different TLS functionality in libcoap */
132c87c5fbaSopenharmony_ci  uint8_t reserved[7];             /* Reserved - must be set to 0 for
133c87c5fbaSopenharmony_ci                                      future compatibility */
134c87c5fbaSopenharmony_ci
135c87c5fbaSopenharmony_ci  /** Identity Hint check callback function.
136c87c5fbaSopenharmony_ci   * If not NULL, is called when the Identity Hint (TLS1.2 or earlier) is
137c87c5fbaSopenharmony_ci   * provided by the server.
138c87c5fbaSopenharmony_ci   * The appropriate Identity and Pre-Shared Key to use can then be returned.
139c87c5fbaSopenharmony_ci   */
140c87c5fbaSopenharmony_ci  coap_dtls_ih_callback_t validate_ih_call_back;
141c87c5fbaSopenharmony_ci  void *ih_call_back_arg;  /* Passed in to the Identity Hint callback
142c87c5fbaSopenharmony_ci                              function */
143c87c5fbaSopenharmony_ci
144c87c5fbaSopenharmony_ci  char* client_sni;    /*  If not NULL, SNI to use in client TLS setup.
145c87c5fbaSopenharmony_ci                           Owned by the client app and must remain valid
146c87c5fbaSopenharmony_ci                           during the call to coap_new_client_session_pki().
147c87c5fbaSopenharmony_ci                           Note: Not supported by TinyDTLS. */
148c87c5fbaSopenharmony_ci
149c87c5fbaSopenharmony_ci  coap_dtls_cpsk_info_t psk_info;  /* Client PSK definition */
150c87c5fbaSopenharmony_ci} coap_dtls_cpsk_t;
151c87c5fbaSopenharmony_ci----
152c87c5fbaSopenharmony_ci
153c87c5fbaSopenharmony_ciMore detailed explanation of the coap_dtls_cpsk_t structure follows.
154c87c5fbaSopenharmony_ci
155c87c5fbaSopenharmony_ci*WARNING*: For all the parameter definitions that are pointers to other
156c87c5fbaSopenharmony_cilocations, these locations must remain valid during the lifetime of all the
157c87c5fbaSopenharmony_ciunderlying TLS sessions that are, or will get created based on this PSK
158c87c5fbaSopenharmony_cidefinition.
159c87c5fbaSopenharmony_ci
160c87c5fbaSopenharmony_ci*SECTION: PSK Client: coap_dtls_cpsk_t: Version*
161c87c5fbaSopenharmony_ci[source, c]
162c87c5fbaSopenharmony_ci----
163c87c5fbaSopenharmony_ci#define COAP_DTLS_CPSK_SETUP_VERSION 1 /**< Latest CPSK setup version */
164c87c5fbaSopenharmony_ci----
165c87c5fbaSopenharmony_ci
166c87c5fbaSopenharmony_ci*version* is set to COAP_DTLS_CPSK_SETUP_VERSION.  This will then allow
167c87c5fbaSopenharmony_cisupport for different versions of the coap_dtls_cpsk_t structure in the future.
168c87c5fbaSopenharmony_ci
169c87c5fbaSopenharmony_ci*SECTION: PSK Client: coap_dtls_cpsk_t: Reserved*
170c87c5fbaSopenharmony_ci
171c87c5fbaSopenharmony_ci*reserved* All must be set to 0.  Future functionality updates will make use of
172c87c5fbaSopenharmony_cithese reserved definitions.
173c87c5fbaSopenharmony_ci
174c87c5fbaSopenharmony_ci*SECTION: PSK Client: coap_dtls_cpsk_t: Identity Hint Callback*
175c87c5fbaSopenharmony_ci[source, c]
176c87c5fbaSopenharmony_ci----
177c87c5fbaSopenharmony_ci/**
178c87c5fbaSopenharmony_ci * Identity Hint Validation callback that can be set up by
179c87c5fbaSopenharmony_ci * coap_new_client_session_psk2().
180c87c5fbaSopenharmony_ci * Invoked when libcoap has done the validation checks at the TLS level,
181c87c5fbaSopenharmony_ci * but the application needs to check that the Identity Hint is allowed, and
182c87c5fbaSopenharmony_ci * needs to use the appropriate PSK information for the (D)TLS session.
183c87c5fbaSopenharmony_ci * Note: Identity Hint is not supported in (D)TLS1.3.
184c87c5fbaSopenharmony_ci *
185c87c5fbaSopenharmony_ci * @param hint  The server provided Identity Hint
186c87c5fbaSopenharmony_ci * @param coap_session  The CoAP session associated with the Identity Hint
187c87c5fbaSopenharmony_ci * @param arg  The same as was passed into coap_new_client_session_psk2()
188c87c5fbaSopenharmony_ci *             in setup_data->ih_call_back_arg
189c87c5fbaSopenharmony_ci *
190c87c5fbaSopenharmony_ci * @return New coap_dtls_cpsk_info_t object or @c NULL on error.
191c87c5fbaSopenharmony_ci */
192c87c5fbaSopenharmony_citypedef const coap_dtls_cpsk_info_t *(*coap_dtls_ih_callback_t)(
193c87c5fbaSopenharmony_ci                                coap_str_const_t *hint,
194c87c5fbaSopenharmony_ci                                coap_session_t *coap_session,
195c87c5fbaSopenharmony_ci                                void *arg);
196c87c5fbaSopenharmony_ci----
197c87c5fbaSopenharmony_ci
198c87c5fbaSopenharmony_ci*validate_ih_call_back* points to an application provided Identity Hint callback
199c87c5fbaSopenharmony_cifunction or NULL. The application can make use of this Identity Hint information
200c87c5fbaSopenharmony_cito decide what Identity and Pre-Shared Key should be used for this session.
201c87c5fbaSopenharmony_ciThe Callback returns the new coap_dtls_cpsk_info_t on success,
202c87c5fbaSopenharmony_cior NULL if the Identity Hint is unacceptable.
203c87c5fbaSopenharmony_ci
204c87c5fbaSopenharmony_ci*NOTE:* The Server may not provide a hint, or a zero length hint to indicate
205c87c5fbaSopenharmony_cithere is no hint.  In this case the initially provided Identity and
206c87c5fbaSopenharmony_ciPre-Shared Key should be used.
207c87c5fbaSopenharmony_ci
208c87c5fbaSopenharmony_ci*ih_call_back_arg* points to a user defined set of data that will get passed
209c87c5fbaSopenharmony_ciin to the validate_ih_call_back() function's arg parameter and can be used by
210c87c5fbaSopenharmony_cithat function.  An example would be a set of Identity Hints that map into new
211c87c5fbaSopenharmony_ciIdentity / Pre-Shared Key to use.
212c87c5fbaSopenharmony_ci
213c87c5fbaSopenharmony_ci*SECTION: PSK Client: coap_dtls_cpsk_t: Subject Name Indicator (SNI) Definition*
214c87c5fbaSopenharmony_ci
215c87c5fbaSopenharmony_ci*client_sni* points to the SNI name that will be added in as a TLS extension,
216c87c5fbaSopenharmony_ciif not NULL.  This typically is the DNS name of the server that the client is
217c87c5fbaSopenharmony_citrying to contact.  The server is then able to decide, based on the name in the
218c87c5fbaSopenharmony_ciSNI extension, whether, for example, a different Hint and/or Pre-Shared Key is
219c87c5fbaSopenharmony_cito be used.
220c87c5fbaSopenharmony_ci
221c87c5fbaSopenharmony_ci*NOTE:* Not supported by TinyDTLS.
222c87c5fbaSopenharmony_ci
223c87c5fbaSopenharmony_ci*SECTION: PSK Client: coap_dtls_cpsk_t: PSK Client Definitions*
224c87c5fbaSopenharmony_ci[source, c]
225c87c5fbaSopenharmony_ci----
226c87c5fbaSopenharmony_citypedef struct coap_dtls_cpsk_info_t {
227c87c5fbaSopenharmony_ci  coap_bin_const_t identity; /* The Identity */
228c87c5fbaSopenharmony_ci  coap_bin_const_t key;      /* The Pre-Shared Key */
229c87c5fbaSopenharmony_ci} coap_dtls_cpsk_info_t;
230c87c5fbaSopenharmony_ci----
231c87c5fbaSopenharmony_ci
232c87c5fbaSopenharmony_ci*identity* defines the Identity to use.
233c87c5fbaSopenharmony_ci
234c87c5fbaSopenharmony_ci*key* defines the Pre-Shared Key to use
235c87c5fbaSopenharmony_ci
236c87c5fbaSopenharmony_ciPSK SERVER INFORMATION
237c87c5fbaSopenharmony_ci----------------------
238c87c5fbaSopenharmony_ci
239c87c5fbaSopenharmony_ciFor PSK setup, the required information needs to be provided in the setup
240c87c5fbaSopenharmony_cicalls with optional application Callbacks defined to update the Identity Hint
241c87c5fbaSopenharmony_ciand Pre-SHared Key. Initially, the Server has to provided with an (optional)
242c87c5fbaSopenharmony_ciIdentity Hint and a (required) Pre-Shared Key.
243c87c5fbaSopenharmony_ci
244c87c5fbaSopenharmony_ciLibcoap will put the Hint and Pre-Shared Key as appropriate into the TLS
245c87c5fbaSopenharmony_cienvironment.
246c87c5fbaSopenharmony_ci
247c87c5fbaSopenharmony_ci*SECTION: PSK Server: coap_dtls_spsk_t*
248c87c5fbaSopenharmony_ci[source, c]
249c87c5fbaSopenharmony_ci----
250c87c5fbaSopenharmony_citypedef struct coap_dtls_spsk_t {
251c87c5fbaSopenharmony_ci  uint8_t version; /** Set to COAP_DTLS_SPSK_SETUP_VERSION
252c87c5fbaSopenharmony_ci                       to support the version of the struct */
253c87c5fbaSopenharmony_ci
254c87c5fbaSopenharmony_ci  /* Options to enable different TLS functionality in libcoap */
255c87c5fbaSopenharmony_ci  uint8_t reserved[7];             /* Reserved - must be set to 0 for
256c87c5fbaSopenharmony_ci                                      future compatibility */
257c87c5fbaSopenharmony_ci
258c87c5fbaSopenharmony_ci  /** Identity check callback function.
259c87c5fbaSopenharmony_ci   * If not @p NULL, is called when the Identity is provided by the client.
260c87c5fbaSopenharmony_ci   *  The appropriate Pre-Shared Key to use can then be returned.
261c87c5fbaSopenharmony_ci   */
262c87c5fbaSopenharmony_ci  coap_dtls_id_callback_t validate_id_call_back;
263c87c5fbaSopenharmony_ci  void *id_call_back_arg;  /* Passed in to the Identity callback function */
264c87c5fbaSopenharmony_ci
265c87c5fbaSopenharmony_ci  /** SNI check callback function.
266c87c5fbaSopenharmony_ci   * If not @p NULL, called if the SNI is not previously seen and exexuted
267c87c5fbaSopenharmony_ci   * prior to sending an Identity Hint back to the client so that the
268c87c5fbaSopenharmony_ci   * appropriate PSK information can be used based on the requesting SNI.
269c87c5fbaSopenharmony_ci   */
270c87c5fbaSopenharmony_ci  coap_dtls_psk_sni_callback_t validate_sni_call_back;
271c87c5fbaSopenharmony_ci  void *sni_call_back_arg;  /* Passed in to the SNI callback function */
272c87c5fbaSopenharmony_ci
273c87c5fbaSopenharmony_ci  coap_dtls_spsk_info_t psk_info;  /* Server PSK definition */
274c87c5fbaSopenharmony_ci} coap_dtls_spsk_t;
275c87c5fbaSopenharmony_ci----
276c87c5fbaSopenharmony_ci
277c87c5fbaSopenharmony_ciMore detailed explanation of the coap_dtls_spsk_t structure follows.
278c87c5fbaSopenharmony_ci
279c87c5fbaSopenharmony_ci*WARNING*: For all the parameter definitions that are pointers to other
280c87c5fbaSopenharmony_cilocations, these locations must remain valid during the lifetime of all the
281c87c5fbaSopenharmony_ciunderlying TLS sessions that are, or will get created based on this PSK
282c87c5fbaSopenharmony_cidefinition.
283c87c5fbaSopenharmony_ci
284c87c5fbaSopenharmony_ci*SECTION: PSK Server: coap_dtls_spsk_t: Version*
285c87c5fbaSopenharmony_ci[source, c]
286c87c5fbaSopenharmony_ci----
287c87c5fbaSopenharmony_ci#define COAP_DTLS_SPSK_SETUP_VERSION 1 /**< Latest SPSK setup version */
288c87c5fbaSopenharmony_ci----
289c87c5fbaSopenharmony_ci
290c87c5fbaSopenharmony_ci*version* is set to COAP_DTLS_SPSK_SETUP_VERSION.  This will then allow
291c87c5fbaSopenharmony_cisupport for different versions of the coap_dtls_spsk_t structure in the future.
292c87c5fbaSopenharmony_ci
293c87c5fbaSopenharmony_ci*SECTION: PSK Server: coap_dtls_spsk_t: Reserved*
294c87c5fbaSopenharmony_ci
295c87c5fbaSopenharmony_ci*reserved* All must be set to 0.  Future functionality updates will make use of
296c87c5fbaSopenharmony_cithese reserved definitions.
297c87c5fbaSopenharmony_ci
298c87c5fbaSopenharmony_ci*SECTION: PSK Server: coap_dtls_spsk_t: Identity Validation Callback*
299c87c5fbaSopenharmony_ci[source, c]
300c87c5fbaSopenharmony_ci----
301c87c5fbaSopenharmony_ci/**
302c87c5fbaSopenharmony_ci * Identity Validation callback that can be set up by
303c87c5fbaSopenharmony_ci * coap_context_set_psk2().
304c87c5fbaSopenharmony_ci * Invoked when libcoap has done the validation checks at the TLS level,
305c87c5fbaSopenharmony_ci * but the application needs to check that the Identity is allowed, and
306c87c5fbaSopenharmony_ci * needs to use the appropriate Pre-Shared Key for the (D)TLS session.
307c87c5fbaSopenharmony_ci *
308c87c5fbaSopenharmony_ci * @param identity  The client provided Identity (should be NULL terminated)
309c87c5fbaSopenharmony_ci * @param coap_session  The CoAP session associated with the Identity Hint
310c87c5fbaSopenharmony_ci * @param arg  The same as was passed into coap_context_set_psk2()
311c87c5fbaSopenharmony_ci *             in setup_data->id_call_back_arg
312c87c5fbaSopenharmony_ci *
313c87c5fbaSopenharmony_ci * @return New coap_bin_const_t Pre-Shared Key object or @c NULL on error.
314c87c5fbaSopenharmony_ci */
315c87c5fbaSopenharmony_citypedef const coap_bin_const_t *(*coap_dtls_id_callback_t)(
316c87c5fbaSopenharmony_ci                                 coap_bin_const_t *identity,
317c87c5fbaSopenharmony_ci                                 coap_session_t *coap_session,
318c87c5fbaSopenharmony_ci                                 void *arg);
319c87c5fbaSopenharmony_ci----
320c87c5fbaSopenharmony_ci
321c87c5fbaSopenharmony_ci*WARNING:* If both *validate_id_call_back* and *validate_sni_call_back* are
322c87c5fbaSopenharmony_cidefined, validate_id_call_back() is invoked after validate_sni_call_back(),
323c87c5fbaSopenharmony_ciand so if the Pre-Shared Key is changed in validate_sni_call_back(),
324c87c5fbaSopenharmony_civalidate_id_call_back() needs to be sure that the appropriate Pre-Shared Key
325c87c5fbaSopenharmony_ciis provided.
326c87c5fbaSopenharmony_ci
327c87c5fbaSopenharmony_ci*validate_id_call_back* points to an application provided Identity callback
328c87c5fbaSopenharmony_cifunction or NULL. The application can make use of this Identity information
329c87c5fbaSopenharmony_cito decide what PSK should be used for this session.
330c87c5fbaSopenharmony_ciThe Callback returns the new coap_bin_const_t Pre-Shared Key on success,
331c87c5fbaSopenharmony_cior NULL if the Identity is unacceptable.
332c87c5fbaSopenharmony_ci
333c87c5fbaSopenharmony_ci*NOTE:* The Client may be using a binary Identity that contains an embedded
334c87c5fbaSopenharmony_cizero. However OpenSSL and GnuTLS do not currently support this.
335c87c5fbaSopenharmony_ci
336c87c5fbaSopenharmony_ci*id_call_back_arg* points to a user defined set of data that will get passed
337c87c5fbaSopenharmony_ciin to the validate_id_call_back() function and can be used by that function.
338c87c5fbaSopenharmony_ciAn example would be a set of Identities that map into new Pre-Shared Keys
339c87c5fbaSopenharmony_cito use.
340c87c5fbaSopenharmony_ci
341c87c5fbaSopenharmony_ci*SECTION: PSK Server: coap_dtls_spsk_t: Subject Name Identifier (SNI) Callback*
342c87c5fbaSopenharmony_ci[source, c]
343c87c5fbaSopenharmony_ci----
344c87c5fbaSopenharmony_ci/**
345c87c5fbaSopenharmony_ci * PSK SNI callback that can be set up by coap_context_set_psk2().
346c87c5fbaSopenharmony_ci * Invoked when libcoap has done the validation checks at the TLS level,
347c87c5fbaSopenharmony_ci * but the application needs to check that the SNI is allowed, and needs
348c87c5fbaSopenharmony_ci * to use the appropriate PSK information for the (D)TLS session.
349c87c5fbaSopenharmony_ci *
350c87c5fbaSopenharmony_ci * @param sni  The client provided SNI
351c87c5fbaSopenharmony_ci * @param coap_session  The CoAP session associated with the SNI
352c87c5fbaSopenharmony_ci * @param arg  The same as was passed into coap_new_client_session_psk2()
353c87c5fbaSopenharmony_ci *             in setup_data->sni_call_back_arg
354c87c5fbaSopenharmony_ci *
355c87c5fbaSopenharmony_ci * @return New coap_dtls_spsk_info_t object or @c NULL on error.
356c87c5fbaSopenharmony_ci */
357c87c5fbaSopenharmony_citypedef const coap_dtls_spsk_info_t *(*coap_dtls_psk_sni_callback_t)(
358c87c5fbaSopenharmony_ci                                 const char *sni,
359c87c5fbaSopenharmony_ci                                 coap_session_t *coap_session,
360c87c5fbaSopenharmony_ci                                 void *arg);
361c87c5fbaSopenharmony_ci----
362c87c5fbaSopenharmony_ci
363c87c5fbaSopenharmony_ci*validate_sni_call_back* points to an application provided SNI callback
364c87c5fbaSopenharmony_cichecking function or NULL. The application can make use of this SNI information
365c87c5fbaSopenharmony_cito decide whether the SNI is valid, and hence what new Hint and Pre-Shared Key
366c87c5fbaSopenharmony_cito use.
367c87c5fbaSopenharmony_ciThus it is possible for the coap server to host multiple domains with
368c87c5fbaSopenharmony_cidifferent Hints and PSKs allocated to each SNI domain.
369c87c5fbaSopenharmony_ciThe Callback returns a coap_dtls_spsk_info_t pointer to the Hint and
370c87c5fbaSopenharmony_ciPre-Shared Key to use for this SNI, or NULL if the connection is to get
371c87c5fbaSopenharmony_cirejected.  Libcoap remembers the association between a specific SNI and Hint +
372c87c5fbaSopenharmony_ciPre-Shared Key set and will only invoke this callback if the SNI is unknown.
373c87c5fbaSopenharmony_ci
374c87c5fbaSopenharmony_ci*NOTE:* Not supported by TinyDTLS.
375c87c5fbaSopenharmony_ci
376c87c5fbaSopenharmony_ci*sni_call_back_arg* points to a user defined set of data that will get passed
377c87c5fbaSopenharmony_ciin to the validate_sni_call_back() function and can be used by that function.
378c87c5fbaSopenharmony_ciAn example would be a set of SNIs that are allowed with their matching
379c87c5fbaSopenharmony_ciHint + Pre-Shared Key sets.
380c87c5fbaSopenharmony_ci
381c87c5fbaSopenharmony_ci*SECTION: PSK Server: coap_dtls_spsk_t: PSK Information Definitions*
382c87c5fbaSopenharmony_ci[source, c]
383c87c5fbaSopenharmony_ci----
384c87c5fbaSopenharmony_citypedef struct coap_dtls_spsk_info_t {
385c87c5fbaSopenharmony_ci  coap_bin_const_t hint; /* The identity hint to use */
386c87c5fbaSopenharmony_ci  coap_bin_const_t key;  /* The Pre-Shared Key to use */
387c87c5fbaSopenharmony_ci} coap_dtls_spsk_info_t;
388c87c5fbaSopenharmony_ci----
389c87c5fbaSopenharmony_ci
390c87c5fbaSopenharmony_ci*identity* defines the Identity Hint to use.
391c87c5fbaSopenharmony_ci
392c87c5fbaSopenharmony_ci*key* defines the Pre-Shared Key to use
393c87c5fbaSopenharmony_ci
394c87c5fbaSopenharmony_ciPKI/RPK CLIENT AND SERVER INFORMATION
395c87c5fbaSopenharmony_ci-------------------------------------
396c87c5fbaSopenharmony_ci
397c87c5fbaSopenharmony_ciFor PKI or RPK setup, if the libcoap PKI/RPK configuration options do not
398c87c5fbaSopenharmony_cihandle a specific requirement as defined by the available options, then an
399c87c5fbaSopenharmony_ciapplication defined Callback can called to do the additional specific checks.
400c87c5fbaSopenharmony_ci
401c87c5fbaSopenharmony_ciThe information passed to this Application Callback will be the
402c87c5fbaSopenharmony_ciTLS session (as well the configuration information), but the structures
403c87c5fbaSopenharmony_cicontaining this information will be different as they will be based on the
404c87c5fbaSopenharmony_ciunderlying TLS library type. coap_get_tls_library_version() is provided to help
405c87c5fbaSopenharmony_cihere.
406c87c5fbaSopenharmony_ci
407c87c5fbaSopenharmony_ciLibcoap will add in the defined Certificate (or Public Key), Private Key and
408c87c5fbaSopenharmony_ciCA Certificate into the TLS environment.  The CA Certificate is also added
409c87c5fbaSopenharmony_ciin to the list of valid CAs for Certificate checking.
410c87c5fbaSopenharmony_ci
411c87c5fbaSopenharmony_ciThe internal Callbacks (and optionally the Application Callback) will then
412c87c5fbaSopenharmony_cicheck the required information as defined in the coap_dtls_pki_t described
413c87c5fbaSopenharmony_cibelow.
414c87c5fbaSopenharmony_ci
415c87c5fbaSopenharmony_ci*SECTION: PKI/RPK: coap_dtls_pki_t*
416c87c5fbaSopenharmony_ci[source, c]
417c87c5fbaSopenharmony_ci----
418c87c5fbaSopenharmony_citypedef struct coap_dtls_pki_t {
419c87c5fbaSopenharmony_ci  uint8_t version;            /* COAP_DTLS_PKI_SETUP_VERSION */
420c87c5fbaSopenharmony_ci
421c87c5fbaSopenharmony_ci  /* Options to enable different TLS functionality in libcoap */
422c87c5fbaSopenharmony_ci  uint8_t verify_peer_cert;         /* 1 if peer cert is to be verified */
423c87c5fbaSopenharmony_ci  uint8_t check_common_ca;          /* 1 if peer cert is to be signed by
424c87c5fbaSopenharmony_ci                                     * the same CA as the local cert */
425c87c5fbaSopenharmony_ci  uint8_t allow_self_signed;        /* 1 if self-signed certs are allowed */
426c87c5fbaSopenharmony_ci  uint8_t allow_self_signed;        /* 1 if self-signed certs are allowed.
427c87c5fbaSopenharmony_ci                                     * Ignored if check_common_ca set */
428c87c5fbaSopenharmony_ci  uint8_t allow_expired_certs;      /* 1 if expired certs are allowed */
429c87c5fbaSopenharmony_ci  uint8_t cert_chain_validation;    /* 1 if to check cert_chain_verify_depth */
430c87c5fbaSopenharmony_ci  uint8_t cert_chain_verify_depth;  /* recommended depth is 3 */
431c87c5fbaSopenharmony_ci  uint8_t check_cert_revocation;    /* 1 if revocation checks wanted */
432c87c5fbaSopenharmony_ci  uint8_t allow_no_crl;             /* 1 ignore if CRL not there */
433c87c5fbaSopenharmony_ci  uint8_t allow_expired_crl;        /* 1 if expired crl is allowed */
434c87c5fbaSopenharmony_ci  uint8_t allow_bad_md_hash;        /* 1 if unsupported MD hashes are allowed */
435c87c5fbaSopenharmony_ci  uint8_t allow_short_rsa_length;   /* 1 if small RSA keysizes are allowed */
436c87c5fbaSopenharmony_ci  uint8_t is_rpk_not_cert;          /* 1 is RPK instead of Public Certificate.
437c87c5fbaSopenharmony_ci                                     *   If set, PKI key format type cannot be
438c87c5fbaSopenharmony_ci                                     *   COAP_PKI_KEY_PEM */
439c87c5fbaSopenharmony_ci  uint8_t reserved[3];              /* Reserved - must be set to 0 for
440c87c5fbaSopenharmony_ci                                       future compatibility */
441c87c5fbaSopenharmony_ci
442c87c5fbaSopenharmony_ci  /** CN check callback function
443c87c5fbaSopenharmony_ci   * If not NULL, is called when the TLS connection has passed the configured
444c87c5fbaSopenharmony_ci   * TLS options above for the application to verify if the CN is valid.
445c87c5fbaSopenharmony_ci   */
446c87c5fbaSopenharmony_ci  coap_dtls_cn_callback_t validate_cn_call_back;
447c87c5fbaSopenharmony_ci  void *cn_call_back_arg;  /* Passed in to the CN callback function */
448c87c5fbaSopenharmony_ci
449c87c5fbaSopenharmony_ci  /** SNI check callback function
450c87c5fbaSopenharmony_ci   * If not NULL, called if the SNI is not previously seen and prior to sending
451c87c5fbaSopenharmony_ci   * a certificate set back to the client so that the appropriate certificate
452c87c5fbaSopenharmony_ci   * set can be used based on the requesting SNI.
453c87c5fbaSopenharmony_ci   */
454c87c5fbaSopenharmony_ci  coap_dtls_sni_callback_t validate_sni_call_back;
455c87c5fbaSopenharmony_ci  void *sni_call_back_arg;  /* Passed in to the SNI callback function */
456c87c5fbaSopenharmony_ci
457c87c5fbaSopenharmony_ci  /** Additional Security callback handler that is invoked when libcoap has
458c87c5fbaSopenharmony_ci   * done the standard, defined validation checks at the TLS level,
459c87c5fbaSopenharmony_ci   * If not NULL, called from within the TLS Client Hello connection
460c87c5fbaSopenharmony_ci   * setup.
461c87c5fbaSopenharmony_ci   */
462c87c5fbaSopenharmony_ci  coap_dtls_security_setup_t additional_tls_setup_call_back;
463c87c5fbaSopenharmony_ci
464c87c5fbaSopenharmony_ci  char* client_sni;       /* If not NULL, SNI to use in client TLS setup.
465c87c5fbaSopenharmony_ci                             Owned by the client app and must remain valid
466c87c5fbaSopenharmony_ci                             during the call to coap_new_client_session_pki() */
467c87c5fbaSopenharmony_ci
468c87c5fbaSopenharmony_ci  coap_dtls_key_t pki_key; /* PKI key definition */
469c87c5fbaSopenharmony_ci} coap_dtls_pki_t;
470c87c5fbaSopenharmony_ci----
471c87c5fbaSopenharmony_ci
472c87c5fbaSopenharmony_ciMore detailed explanation of the coap_dtls_pki_t structure follows.
473c87c5fbaSopenharmony_ci
474c87c5fbaSopenharmony_ci*WARNING*: For all the parameter definitions that are pointers to other
475c87c5fbaSopenharmony_cilocations, these locations must remain valid during the lifetime of all the
476c87c5fbaSopenharmony_ciunderlying TLS sessions that are, or will get created based on this PKI/RPK
477c87c5fbaSopenharmony_cidefinition.
478c87c5fbaSopenharmony_ci
479c87c5fbaSopenharmony_ciThe first parameter in each subsection enables/disables the functionality, the
480c87c5fbaSopenharmony_ciremaining parameter(s) control what happens when the functionality is
481c87c5fbaSopenharmony_cienabled.
482c87c5fbaSopenharmony_ci
483c87c5fbaSopenharmony_ci*SECTION: PKI/RPK: coap_dtls_pki_t: Version*
484c87c5fbaSopenharmony_ci[source, c]
485c87c5fbaSopenharmony_ci----
486c87c5fbaSopenharmony_ci#define COAP_DTLS_PKI_SETUP_VERSION 1
487c87c5fbaSopenharmony_ci----
488c87c5fbaSopenharmony_ci
489c87c5fbaSopenharmony_ci*version* is set to COAP_DTLS_PKI_SETUP_VERSION.  This will then allow support
490c87c5fbaSopenharmony_cifor different versions of the coap_dtls_pki_t structure in the future.
491c87c5fbaSopenharmony_ci
492c87c5fbaSopenharmony_ci*SECTION: PKI/RPK: coap_dtls_pki_t: Peer Certificate Checking*
493c87c5fbaSopenharmony_ci
494c87c5fbaSopenharmony_ci*verify_peer_cert* Set to 1 to check that the peer's certificate is valid if
495c87c5fbaSopenharmony_ciprovided, else 0. If not set, check_common_ca, allow_self_signed,
496c87c5fbaSopenharmony_ciallow_expired_certs, cert_chain_validation, cert_chain_verify_depth,
497c87c5fbaSopenharmony_cicheck_cert_revocation, allow_no_crl, allow_expired_crl, allow_bad_md_hash
498c87c5fbaSopenharmony_ciand allow_short_rsa_length settings are all ignored.
499c87c5fbaSopenharmony_ci
500c87c5fbaSopenharmony_ci*check_common_ca* Set to 1 to check that the CA that signed the peer's
501c87c5fbaSopenharmony_cicertificate is the same CA that signed the local certificate
502c87c5fbaSopenharmony_cielse 0.  If set to 1 and *verify_peer_cert* is set to 1, then for the server, a
503c87c5fbaSopenharmony_cilist of valid CAs are sent to client.  For the client, the logic will check
504c87c5fbaSopenharmony_cithat both the client and server certificates are signed by the same CA.
505c87c5fbaSopenharmony_ci
506c87c5fbaSopenharmony_ci*allow_self_signed* Set to 1 to allow the peer (or any certificate in the
507c87c5fbaSopenharmony_cicertificate chain) to be a self-signed certificate, else 0. If
508c87c5fbaSopenharmony_ci*check_common_ca* is set, then a self-signed certificate will not be allowed.
509c87c5fbaSopenharmony_ci
510c87c5fbaSopenharmony_ci*allow_expired_certs* Set to 1 to allow certificates that have either expired,
511c87c5fbaSopenharmony_cior are not yet valid to be allowed, else 0.
512c87c5fbaSopenharmony_ci
513c87c5fbaSopenharmony_ci*SECTION: PKI/RPK: coap_dtls_pki_t: Certificate Chain Validation*
514c87c5fbaSopenharmony_ci
515c87c5fbaSopenharmony_ci*cert_chain_validation* Set to 1 to check that the certificate chain is valid,
516c87c5fbaSopenharmony_cielse 0.
517c87c5fbaSopenharmony_ci
518c87c5fbaSopenharmony_ci*cert_chain_verify_depth* Set to the chain depth that is to be checked. This
519c87c5fbaSopenharmony_ciis the number of intermediate CAs in the chain. If set to 0, then there can be
520c87c5fbaSopenharmony_cino intermediate CA in the chain.
521c87c5fbaSopenharmony_ci
522c87c5fbaSopenharmony_ci*SECTION: PKI/RPK: coap_dtls_pki_t: Certificate Revocation*
523c87c5fbaSopenharmony_ci
524c87c5fbaSopenharmony_ci*check_cert_revocation* Set to 1 to check whether any certificate in the chain
525c87c5fbaSopenharmony_cihas been revoked, else 0.
526c87c5fbaSopenharmony_ci
527c87c5fbaSopenharmony_ci*allow_no_crl* Set to 1 to not check any certificate that does not have a CRL,
528c87c5fbaSopenharmony_cielse 0.
529c87c5fbaSopenharmony_ci
530c87c5fbaSopenharmony_ci*allow_expired_crl* Set to 1 to allow an certificate that has an expired CRL
531c87c5fbaSopenharmony_cidefinition to be valid, else 0.
532c87c5fbaSopenharmony_ci
533c87c5fbaSopenharmony_ci*SECTION: PKI/RPK: coap_dtls_pki_t: Other*
534c87c5fbaSopenharmony_ci
535c87c5fbaSopenharmony_ci*allow_bad_md_hash* Set to 1 if unsupported MD hashes are allowed, else 0.
536c87c5fbaSopenharmony_ci
537c87c5fbaSopenharmony_ci*allow_short_rsa_length* Set to 1 if small RSA keysizes are allowed, else 0.
538c87c5fbaSopenharmony_ci
539c87c5fbaSopenharmony_ci*is_rpk_not_cert* Set to 1 if the Certificate is actually a Raw Public Key.
540c87c5fbaSopenharmony_ciIf set, PKI key format type cannot be COAP_PKI_KEY_PEM.  If set,
541c87c5fbaSopenharmony_cicheck_common_ca, allow_self_signed, allow_expired_certs,
542c87c5fbaSopenharmony_cicert_chain_validation, cert_chain_verify_depth, check_cert_revocation,
543c87c5fbaSopenharmony_ciallow_no_crl, allow_expired_crl, allow_bad_md_hash and
544c87c5fbaSopenharmony_ciallow_short_rsa_length settings are all ignored.
545c87c5fbaSopenharmony_ci
546c87c5fbaSopenharmony_ci*SECTION: PKI/RPK: coap_dtls_pki_t: Reserved*
547c87c5fbaSopenharmony_ci
548c87c5fbaSopenharmony_ci*reserved* All must be set to 0.  Future functionality updates will make use of
549c87c5fbaSopenharmony_cithese reserved definitions.
550c87c5fbaSopenharmony_ci
551c87c5fbaSopenharmony_ci*SECTION: PKI/RPK: coap_dtls_pki_t: Common Name (CN) Callback*
552c87c5fbaSopenharmony_ci[source, c]
553c87c5fbaSopenharmony_ci----
554c87c5fbaSopenharmony_ci#define COAP_DTLS_RPK_CERT_CN "RPK"
555c87c5fbaSopenharmony_ci
556c87c5fbaSopenharmony_ci/**
557c87c5fbaSopenharmony_ci * CN Validation callback that can be set up by coap_context_set_pki().
558c87c5fbaSopenharmony_ci * Invoked when libcoap has done the validation checks at the TLS level,
559c87c5fbaSopenharmony_ci * but the application needs to check that the CN is allowed.
560c87c5fbaSopenharmony_ci * CN is the SubjectAltName in the cert, if not present, then the leftmost
561c87c5fbaSopenharmony_ci * Common Name (CN) component of the subject name.
562c87c5fbaSopenharmony_ci * NOTE: If using RPK, then the Public Key does not contain a CN, but the
563c87c5fbaSopenharmony_ci * content of COAP_DTLS_RPK_CERT_CN is presented for the @p cn parameter.
564c87c5fbaSopenharmony_ci *
565c87c5fbaSopenharmony_ci * @param cn  The determined CN from the certificate
566c87c5fbaSopenharmony_ci * @param asn1_public_cert  The ASN.1 encoded (DER) X.509 certificate
567c87c5fbaSopenharmony_ci * @param asn1_length  The ASN.1 length
568c87c5fbaSopenharmony_ci * @param session  The coap session associated with the certificate update
569c87c5fbaSopenharmony_ci * @param depth  Depth in cert chain.  If 0, then client cert, else a CA
570c87c5fbaSopenharmony_ci * @param validated  TLS can find no issues if 1
571c87c5fbaSopenharmony_ci * @param arg  The same as was passed into coap_context_set_pki()
572c87c5fbaSopenharmony_ci *             in setup_data->cn_call_back_arg
573c87c5fbaSopenharmony_ci *
574c87c5fbaSopenharmony_ci * @return 1 if accepted, else 0 if to be rejected
575c87c5fbaSopenharmony_ci */
576c87c5fbaSopenharmony_citypedef int (*coap_dtls_cn_callback_t)(const char *cn,
577c87c5fbaSopenharmony_ci             const uint8_t *asn1_public_cert,
578c87c5fbaSopenharmony_ci             size_t asn1_length,
579c87c5fbaSopenharmony_ci             coap_session_t *session,
580c87c5fbaSopenharmony_ci             unsigned int depth,
581c87c5fbaSopenharmony_ci             int validated,
582c87c5fbaSopenharmony_ci             void *arg);
583c87c5fbaSopenharmony_ci----
584c87c5fbaSopenharmony_ci
585c87c5fbaSopenharmony_ci*validate_cn_call_back* points to an application provided CN callback
586c87c5fbaSopenharmony_cichecking function or NULL. The application can make use of this CN information
587c87c5fbaSopenharmony_cito decide, for example, that the CN is valid coming from a particular peer.
588c87c5fbaSopenharmony_ciThe Callback returns 1 on success, 0 if the TLS connection is to be aborted.
589c87c5fbaSopenharmony_ci
590c87c5fbaSopenharmony_ci*cn_call_back_arg* points to a user defined set of data that will get passed
591c87c5fbaSopenharmony_ciin to the validate_cn_call_back() function and can be used by that function.
592c87c5fbaSopenharmony_ciAn example would be a set of CNs that are allowed.
593c87c5fbaSopenharmony_ci
594c87c5fbaSopenharmony_ci*SECTION: PKI/RPK: coap_dtls_pki_t: Subject Name Identifier (SNI) Callback*
595c87c5fbaSopenharmony_ci[source, c]
596c87c5fbaSopenharmony_ci----
597c87c5fbaSopenharmony_citypedef struct coap_dtls_key_t {
598c87c5fbaSopenharmony_ci  coap_pki_key_t key_type;          /* key format type */
599c87c5fbaSopenharmony_ci  union {
600c87c5fbaSopenharmony_ci    coap_pki_key_pem_t pem;         /* for PEM file keys */
601c87c5fbaSopenharmony_ci    coap_pki_key_pem_buf_t pem_buf; /* for PEM memory keys */
602c87c5fbaSopenharmony_ci    coap_pki_key_asn1_t asn1;       /* for ASN.1 (DER) memory keys */
603c87c5fbaSopenharmony_ci    coap_pki_key_pkcs11_t pkcs11;   /* for PKCS11 keys */
604c87c5fbaSopenharmony_ci  } key;
605c87c5fbaSopenharmony_ci} coap_dtls_key_t;
606c87c5fbaSopenharmony_ci
607c87c5fbaSopenharmony_ci/**
608c87c5fbaSopenharmony_ci * SNI Validation callback that can be set up by coap_context_set_pki().
609c87c5fbaSopenharmony_ci * Invoked if the SNI is not previously seen and prior to sending a certificate
610c87c5fbaSopenharmony_ci * set back to the client so that the appropriate certificate set can be used
611c87c5fbaSopenharmony_ci * based on the requesting SNI.
612c87c5fbaSopenharmony_ci *
613c87c5fbaSopenharmony_ci * @param sni  The requested SNI
614c87c5fbaSopenharmony_ci * @param arg  The same as was passed into coap_context_set_pki()
615c87c5fbaSopenharmony_ci *             in setup_data->sni_call_back_arg
616c87c5fbaSopenharmony_ci *
617c87c5fbaSopenharmony_ci * @return new set of certificates to use, or NULL if SNI is to be rejected.
618c87c5fbaSopenharmony_ci */
619c87c5fbaSopenharmony_citypedef coap_dtls_key_t *(*coap_dtls_sni_callback_t)(const char *sni,
620c87c5fbaSopenharmony_ci             void* arg);
621c87c5fbaSopenharmony_ci----
622c87c5fbaSopenharmony_ci
623c87c5fbaSopenharmony_ci*validate_sni_call_back* points to an application provided SNI callback
624c87c5fbaSopenharmony_cichecking function or NULL. The application can make use of this SNI information
625c87c5fbaSopenharmony_cito decide whether the SNI is valid, and what set of certificates to give to the
626c87c5fbaSopenharmony_ciclient.  Thus it is possible for the coap server to host multiple domains with
627c87c5fbaSopenharmony_cidifferent certificates allocated to each domain.
628c87c5fbaSopenharmony_ciThe Callback returns a pointer to the certificates to use for this SNI, or NULL
629c87c5fbaSopenharmony_ciif the connection it to get rejected.  libcoap remembers the association
630c87c5fbaSopenharmony_cibetween the SNI and Certificate set and will only invoke this callback if the
631c87c5fbaSopenharmony_ciSNI is unknown.
632c87c5fbaSopenharmony_ci
633c87c5fbaSopenharmony_ci*sni_call_back_arg* points to a user defined set of data that will get passed
634c87c5fbaSopenharmony_ciin to the validate_sni_call_back() function and can be used by that function.
635c87c5fbaSopenharmony_ciAn example would be a set of SNIs that are allowed with their matching
636c87c5fbaSopenharmony_cicertificate sets.
637c87c5fbaSopenharmony_ci
638c87c5fbaSopenharmony_ci*SECTION: PKI/RPK: coap_dtls_pki_t: Application Additional Setup Callback*
639c87c5fbaSopenharmony_ci[source, c]
640c87c5fbaSopenharmony_ci----
641c87c5fbaSopenharmony_ci/**
642c87c5fbaSopenharmony_ci * Additional Security setup handler that can be set up by
643c87c5fbaSopenharmony_ci * coap_context_set_pki().
644c87c5fbaSopenharmony_ci * Invoked when libcoap has done the validation checks at the TLS level,
645c87c5fbaSopenharmony_ci * but the application needs to do some additional checks/changes/updates.
646c87c5fbaSopenharmony_ci *
647c87c5fbaSopenharmony_ci * @param session The security session definition - e.g. SSL * for OpenSSL.
648c87c5fbaSopenharmony_ci *                This will be dependent on the underlying TLS library
649c87c5fbaSopenharmony_ci *                - see coap_get_tls_library_version()
650c87c5fbaSopenharmony_ci * @param setup_data A structure containing setup data originally passed into
651c87c5fbaSopenharmony_ci *                   coap_context_set_pki() or coap_new_client_session_pki().
652c87c5fbaSopenharmony_ci * @return 1 if successful, else 0
653c87c5fbaSopenharmony_ci */
654c87c5fbaSopenharmony_citypedef int (*coap_dtls_security_setup_t)(void *context, void* session,
655c87c5fbaSopenharmony_ci                                          coap_dtls_pki_t *setup_data);
656c87c5fbaSopenharmony_ci----
657c87c5fbaSopenharmony_ci
658c87c5fbaSopenharmony_ci*additional_tls_setup_call_back* points to an application provided callback
659c87c5fbaSopenharmony_cifunction that will do additional checking/changes/updates after libcoap has
660c87c5fbaSopenharmony_cidone all of the configured TLS setup checking, or NULL to do no additional
661c87c5fbaSopenharmony_cichecking.
662c87c5fbaSopenharmony_ci
663c87c5fbaSopenharmony_ci*SECTION: PKI/RPK: coap_dtls_pki_t: Subject Name Indicator (SNI) Definition*
664c87c5fbaSopenharmony_ci
665c87c5fbaSopenharmony_ci*client_sni* points to the SNI name that will be added in as a TLS extension,
666c87c5fbaSopenharmony_cior set NULL.  This typically is the DNS name of the server that the client is
667c87c5fbaSopenharmony_citrying to contact.  This is only used by a client application and the server
668c87c5fbaSopenharmony_ciis then able to decide, based on the name in the SNI extension, whether, for
669c87c5fbaSopenharmony_ciexample, a different certificate should be provided.
670c87c5fbaSopenharmony_ci
671c87c5fbaSopenharmony_ci*SECTION: PKI/RPK: coap_dtls_pki_t: Key Type Definition*
672c87c5fbaSopenharmony_ci[source, c]
673c87c5fbaSopenharmony_ci----
674c87c5fbaSopenharmony_citypedef enum coap_pki_key_t {
675c87c5fbaSopenharmony_ci  COAP_PKI_KEY_PEM,     /* The PKI key type is PEM file */
676c87c5fbaSopenharmony_ci  COAP_PKI_KEY_ASN1,    /* The PKI key type is ASN.1 (DER) buffer */
677c87c5fbaSopenharmony_ci  COAP_PKI_KEY_PEM_BUF, /* The PKI key type is PEM buffer */
678c87c5fbaSopenharmony_ci  COAP_PKI_KEY_PKCS11,  /* The PKI key type is PKCS11 (DER) */
679c87c5fbaSopenharmony_ci} coap_pki_key_t;
680c87c5fbaSopenharmony_ci----
681c87c5fbaSopenharmony_ci
682c87c5fbaSopenharmony_ci*key_type* defines the format that the certificates / keys are provided in.
683c87c5fbaSopenharmony_ciThis can be COAP_PKI_KEY_PEM, COAP_PKI_KEY_PEM_BUF, COAP_PKI_KEY_ASN1 or
684c87c5fbaSopenharmony_ciCOAP_PKI_KEY_PKCS11.
685c87c5fbaSopenharmony_ci
686c87c5fbaSopenharmony_ci*SECTION: PKI: coap_dtls_pki_t: PEM Key Definitions*
687c87c5fbaSopenharmony_ci[source, c]
688c87c5fbaSopenharmony_ci----
689c87c5fbaSopenharmony_citypedef struct coap_pki_key_pem_t {
690c87c5fbaSopenharmony_ci  const char *ca_file;       /* File location of Common CA in PEM format */
691c87c5fbaSopenharmony_ci  const char *public_cert;   /* File location of Public Cert */
692c87c5fbaSopenharmony_ci  const char *private_key;   /* File location of Private Key in PEM format */
693c87c5fbaSopenharmony_ci} coap_pki_key_pem_t;
694c87c5fbaSopenharmony_ci----
695c87c5fbaSopenharmony_ci
696c87c5fbaSopenharmony_ci*key.pem.ca_file* points to the CA File location on disk which will be in
697c87c5fbaSopenharmony_ciPEM format, or NULL. This file should only contain one CA (that has signed the
698c87c5fbaSopenharmony_cipublic certificate) as this is passed from the server to the client when
699c87c5fbaSopenharmony_cirequesting the client's certificate. This certificate is also added into
700c87c5fbaSopenharmony_cithe valid root CAs list if not already present.
701c87c5fbaSopenharmony_ci
702c87c5fbaSopenharmony_ci*key.pem.public_cert* points to the public certificate location on disk which
703c87c5fbaSopenharmony_ciwill be in PEM format.
704c87c5fbaSopenharmony_ci
705c87c5fbaSopenharmony_ci*key.pem.private_key* points to the private key location on disk which
706c87c5fbaSopenharmony_ciwill be in PEM format.  This file cannot be password protected.
707c87c5fbaSopenharmony_ci
708c87c5fbaSopenharmony_ci*SECTION: PKI/RPK: coap_dtls_pki_t: PEM Memory Key Definitions*
709c87c5fbaSopenharmony_ci[source, c]
710c87c5fbaSopenharmony_ci----
711c87c5fbaSopenharmony_citypedef struct coap_pki_key_pem_buf_t {
712c87c5fbaSopenharmony_ci  const uint8_t *ca_cert;     /* PEM buffer Common CA Cert */
713c87c5fbaSopenharmony_ci  const uint8_t *public_cert; /* PEM buffer Public Cert, or Public Key if RPK */
714c87c5fbaSopenharmony_ci  const uint8_t *private_key; /* PEM buffer Private Key */
715c87c5fbaSopenharmony_ci                                 If RPK and 'EC PRIVATE KEY' this can be used
716c87c5fbaSopenharmony_ci                                 for both the public_cert and private_key */
717c87c5fbaSopenharmony_ci  size_t ca_cert_len;         /* PEM buffer CA Cert length */
718c87c5fbaSopenharmony_ci  size_t public_cert_len;     /* PEM buffer Public Cert length */
719c87c5fbaSopenharmony_ci  size_t private_key_len;     /* PEM buffer Private Key length */
720c87c5fbaSopenharmony_ci} coap_pki_key_pem_buf_t;
721c87c5fbaSopenharmony_ci----
722c87c5fbaSopenharmony_ci
723c87c5fbaSopenharmony_ci*key.pem_buf.ca_cert* points to the CA location in memory which will be in
724c87c5fbaSopenharmony_ciPEM format, or NULL. This file should only contain one CA (that has signed the
725c87c5fbaSopenharmony_cipublic certificate) as this is passed from the server to the client when
726c87c5fbaSopenharmony_cirequesting the client's certificate. This certificate is also added into
727c87c5fbaSopenharmony_cithe valid root CAs list if not already present.
728c87c5fbaSopenharmony_ci
729c87c5fbaSopenharmony_ci*key.pem_buf.ca_cert_len* is the length of the CA.
730c87c5fbaSopenharmony_ci
731c87c5fbaSopenharmony_ci*key.pem_buf.public_cert* points to the public certificate (or public key if
732c87c5fbaSopenharmony_ciRPK) location in memory which will be in PEM format.
733c87c5fbaSopenharmony_ci
734c87c5fbaSopenharmony_ci*key.pem_buf.public_cert_len* is the length of the public certificate.
735c87c5fbaSopenharmony_ci
736c87c5fbaSopenharmony_ci*key.pem_buf.private_key* points to the private key location in memory which
737c87c5fbaSopenharmony_ciwill be in PEM format.  This data cannot be password protected. If RPK and
738c87c5fbaSopenharmony_ci'EC PRIVATE KEY' this can be used for both the public_cert and private_key.
739c87c5fbaSopenharmony_ci
740c87c5fbaSopenharmony_ci*key.pem_buf.private_key* is the length of the private key.
741c87c5fbaSopenharmony_ci
742c87c5fbaSopenharmony_ci*NOTE:* The PEM buffer Certs and Key should be be NULL terminated strings for
743c87c5fbaSopenharmony_ciperformance reasons (to save a potential buffer copy) and the length include
744c87c5fbaSopenharmony_cithis NULL terminator. It is not a requirement to have the NULL terminator
745c87c5fbaSopenharmony_cithough and the length must then reflect the actual data size.
746c87c5fbaSopenharmony_ci
747c87c5fbaSopenharmony_ci*SECTION: PKI/RPK: coap_dtls_pki_t: ASN1 Key Definitions*
748c87c5fbaSopenharmony_ci[source, c]
749c87c5fbaSopenharmony_ci----
750c87c5fbaSopenharmony_citypedef struct coap_pki_key_asn1_t {
751c87c5fbaSopenharmony_ci  const uint8_t *ca_cert;     /* ASN1 Common CA Certificate */
752c87c5fbaSopenharmony_ci  const uint8_t *public_cert; /* ASN1 (DER) Public Cert, or Public Key if RPK */
753c87c5fbaSopenharmony_ci  const uint8_t *private_key; /* ASN1 Private Key */
754c87c5fbaSopenharmony_ci  int ca_cert_len;            /* ASN1 CA Certificate length */
755c87c5fbaSopenharmony_ci  int public_cert_len;        /* ASN1 Public Certificate length */
756c87c5fbaSopenharmony_ci  int private_key_len;        /* ASN1 Private Key length */
757c87c5fbaSopenharmony_ci  coap_asn1_privatekey_type_t private_key_type; /* Private Key Type
758c87c5fbaSopenharmony_ci                                                   COAP_ASN1_PKEY_* */
759c87c5fbaSopenharmony_ci} coap_pki_key_asn1_t;
760c87c5fbaSopenharmony_ci
761c87c5fbaSopenharmony_citypedef enum coap_asn1_privatekey_type_t {
762c87c5fbaSopenharmony_ci  COAP_ASN1_PKEY_NONE,
763c87c5fbaSopenharmony_ci  COAP_ASN1_PKEY_RSA,
764c87c5fbaSopenharmony_ci  COAP_ASN1_PKEY_RSA2,
765c87c5fbaSopenharmony_ci  COAP_ASN1_PKEY_DSA,
766c87c5fbaSopenharmony_ci  COAP_ASN1_PKEY_DSA1,
767c87c5fbaSopenharmony_ci  COAP_ASN1_PKEY_DSA2,
768c87c5fbaSopenharmony_ci  COAP_ASN1_PKEY_DSA3,
769c87c5fbaSopenharmony_ci  COAP_ASN1_PKEY_DSA4,
770c87c5fbaSopenharmony_ci  COAP_ASN1_PKEY_DH,
771c87c5fbaSopenharmony_ci  COAP_ASN1_PKEY_DHX,
772c87c5fbaSopenharmony_ci  COAP_ASN1_PKEY_EC,
773c87c5fbaSopenharmony_ci  COAP_ASN1_PKEY_HMAC,
774c87c5fbaSopenharmony_ci  COAP_ASN1_PKEY_CMAC,
775c87c5fbaSopenharmony_ci  COAP_ASN1_PKEY_TLS1_PRF,
776c87c5fbaSopenharmony_ci  COAP_ASN1_PKEY_HKDF
777c87c5fbaSopenharmony_ci} coap_asn1_privatekey_type_t;
778c87c5fbaSopenharmony_ci----
779c87c5fbaSopenharmony_ci
780c87c5fbaSopenharmony_ci*key.asn1.ca_cert* points to a DER encoded ASN.1 definition of the CA
781c87c5fbaSopenharmony_ciCertificate, or NULL.  This certificate is passed from the server to the client
782c87c5fbaSopenharmony_ciwhen requesting the client's certificate. This certificate is also added into
783c87c5fbaSopenharmony_cithe valid root CAs list if not already present.
784c87c5fbaSopenharmony_ci
785c87c5fbaSopenharmony_ci*key.asn1.public_cert* points to a DER encoded ASN.1 definition of the
786c87c5fbaSopenharmony_cipublic certificate (or public key if RPK).
787c87c5fbaSopenharmony_ci
788c87c5fbaSopenharmony_ci*key.asn1.private_key* points to DER encoded ASN.1 definition of the
789c87c5fbaSopenharmony_ciprivate key.
790c87c5fbaSopenharmony_ci
791c87c5fbaSopenharmony_ci*key.asn1.ca_cert_len* is the length of the DER encoded ASN.1 definition of
792c87c5fbaSopenharmony_cithe CA Certificate.
793c87c5fbaSopenharmony_ci
794c87c5fbaSopenharmony_ci*key.asn1.public_cert_len* is the length of the DER encoded ASN.1 definition
795c87c5fbaSopenharmony_ciof the public certificate.
796c87c5fbaSopenharmony_ci
797c87c5fbaSopenharmony_ci*key.asn1.private_key_len* is the length of the DER encoded ASN.1 definition
798c87c5fbaSopenharmony_ciof the private key.
799c87c5fbaSopenharmony_ci
800c87c5fbaSopenharmony_ci*key.asn1.private_key_type* is the encoding type of the DER encoded ASN.1
801c87c5fbaSopenharmony_cidefinition of the private key.  This will be one of the COAP_ASN1_PKEY_*
802c87c5fbaSopenharmony_cidefinitions.
803c87c5fbaSopenharmony_ci
804c87c5fbaSopenharmony_ci*SECTION: PKI: coap_dtls_pki_t: PKCS11 Key Definitions*
805c87c5fbaSopenharmony_ci[source, c]
806c87c5fbaSopenharmony_ci----
807c87c5fbaSopenharmony_citypedef struct coap_pki_key_pkcs11_t {
808c87c5fbaSopenharmony_ci  const char *ca;            /* pkcs11: URI for Common CA Certificate */
809c87c5fbaSopenharmony_ci  const char *public_cert;   /* pkcs11: URI for Public Cert */
810c87c5fbaSopenharmony_ci  const char *private_key;   /* pkcs11: URI for Private Key */
811c87c5fbaSopenharmony_ci  const char *pin;           /* pin to access PKCS11.  If NULL, then
812c87c5fbaSopenharmony_ci                                pin-value= parameter must be set in
813c87c5fbaSopenharmony_ci                                pkcs11: URI as a query. */
814c87c5fbaSopenharmony_ci} coap_pki_key_pkcs11_t;
815c87c5fbaSopenharmony_ci----
816c87c5fbaSopenharmony_ci
817c87c5fbaSopenharmony_ci*key.pkcs11.ca* is a pkcs11: URI for the CA certificate or NULL.  This is for
818c87c5fbaSopenharmony_cithe CA (that has signed the public certificate) as this is passed from the
819c87c5fbaSopenharmony_ciserver to the client when requesting the client's certificate. This certificate
820c87c5fbaSopenharmony_ciis also added into the valid root CAs list if not already present.
821c87c5fbaSopenharmony_ciAn example URI is 'pkcs11:pkcs11:token=My%20Token;id=%aa%bb%cc%dd' which is
822c87c5fbaSopenharmony_cifor token 'My Token' and (hex) id of 'aabbccdd'.
823c87c5fbaSopenharmony_ci
824c87c5fbaSopenharmony_ci*key.pkcs11.public_cert* is a pkcs11: URI for the Public Certificate which
825c87c5fbaSopenharmony_ciwas signed by *key.pkcs11.ca* or NULL.
826c87c5fbaSopenharmony_ci
827c87c5fbaSopenharmony_ci*key.pkcs11.private_key* is a pkcs11: URI for the Private Key for the
828c87c5fbaSopenharmony_cipublic certificate defined by *key.pkcs11.public_cert* or NULL.
829c87c5fbaSopenharmony_ci
830c87c5fbaSopenharmony_ci*key.pkcs11.user_pin* is the user pin used to unlock the token or NULL.
831c87c5fbaSopenharmony_ciIf NULL, the pin can be defined on the other pkcs11: URI entries by using
832c87c5fbaSopenharmony_cipin-value=XXX as a query - e.g.
833c87c5fbaSopenharmony_ci'pkcs11:pkcs11:token=My%20Token;id=%aa%bb%cc%dd?pin-value=XXX' where XXX is
834c87c5fbaSopenharmony_cithe user pin.
835c87c5fbaSopenharmony_ci
836c87c5fbaSopenharmony_ciEXAMPLES
837c87c5fbaSopenharmony_ci--------
838c87c5fbaSopenharmony_ci*CoAP Server DTLS PKI Setup*
839c87c5fbaSopenharmony_ci[source, c]
840c87c5fbaSopenharmony_ci----
841c87c5fbaSopenharmony_ci#include <coap@LIBCOAP_API_VERSION@/coap.h>
842c87c5fbaSopenharmony_ci
843c87c5fbaSopenharmony_citypedef struct valid_cns_t {
844c87c5fbaSopenharmony_ci  int count;
845c87c5fbaSopenharmony_ci  char **cn_list;
846c87c5fbaSopenharmony_ci} valid_cns_t;
847c87c5fbaSopenharmony_ci
848c87c5fbaSopenharmony_ci/**
849c87c5fbaSopenharmony_ci * CN Validation callback that can be set up by coap_context_set_pki().
850c87c5fbaSopenharmony_ci * Invoked when libcoap has done the validation checks at the TLS level,
851c87c5fbaSopenharmony_ci * but the application needs to check that the CN is allowed.
852c87c5fbaSopenharmony_ci * CN is the SubjectAltName in the cert, if not present, then the leftmost
853c87c5fbaSopenharmony_ci * Common Name (CN) component of the subject name.
854c87c5fbaSopenharmony_ci * NOTE: If using RPK, then the Public Key does not contain a CN, but "RPK"
855c87c5fbaSopenharmony_ci * is presented for the cn parameter.
856c87c5fbaSopenharmony_ci *
857c87c5fbaSopenharmony_ci * @param cn  The determined CN from the certificate
858c87c5fbaSopenharmony_ci * @param asn1_public_cert  The ASN.1 encoded (DER) X.509 certificate
859c87c5fbaSopenharmony_ci * @param asn1_length  The ASN.1 length
860c87c5fbaSopenharmony_ci * @param session  The coap session associated with the certificate update
861c87c5fbaSopenharmony_ci * @param depth  Depth in cert chain.  If 0, then client cert, else a CA
862c87c5fbaSopenharmony_ci * @param validated  TLS can find no issues if 1
863c87c5fbaSopenharmony_ci * @param arg  The same as was passed into coap_context_set_pki()
864c87c5fbaSopenharmony_ci *             in setup_data->cn_call_back_arg
865c87c5fbaSopenharmony_ci *
866c87c5fbaSopenharmony_ci * @return 1 if accepted, else 0 if to be rejected
867c87c5fbaSopenharmony_ci */
868c87c5fbaSopenharmony_cistatic int
869c87c5fbaSopenharmony_civerify_cn_callback(const char *cn,
870c87c5fbaSopenharmony_ci                   const uint8_t *asn1_public_cert,
871c87c5fbaSopenharmony_ci                   size_t asn1_length,
872c87c5fbaSopenharmony_ci                   coap_session_t *c_session,
873c87c5fbaSopenharmony_ci                   unsigned depth,
874c87c5fbaSopenharmony_ci                   int validated,
875c87c5fbaSopenharmony_ci                   void *arg
876c87c5fbaSopenharmony_ci) {
877c87c5fbaSopenharmony_ci  valid_cns_t *valid_cn_list = (valid_cns_t*)arg;
878c87c5fbaSopenharmony_ci  int i;
879c87c5fbaSopenharmony_ci  /* Remove (void) definition if variable is used */
880c87c5fbaSopenharmony_ci  (void)asn1_public_cert;
881c87c5fbaSopenharmony_ci  (void)asn1_length;
882c87c5fbaSopenharmony_ci  (void)c_session;
883c87c5fbaSopenharmony_ci  (void)depth;
884c87c5fbaSopenharmony_ci  (void)validated;
885c87c5fbaSopenharmony_ci
886c87c5fbaSopenharmony_ci  /* Check that the CN is valid */
887c87c5fbaSopenharmony_ci  for (i = 0; i < valid_cn_list->count; i++) {
888c87c5fbaSopenharmony_ci    if (!strcasecmp(cn, valid_cn_list->cn_list[i])) {
889c87c5fbaSopenharmony_ci      return 1;
890c87c5fbaSopenharmony_ci    }
891c87c5fbaSopenharmony_ci  }
892c87c5fbaSopenharmony_ci  return 0;
893c87c5fbaSopenharmony_ci}
894c87c5fbaSopenharmony_ci
895c87c5fbaSopenharmony_citypedef struct sni_def_t {
896c87c5fbaSopenharmony_ci  char* sni;
897c87c5fbaSopenharmony_ci  coap_dtls_key_t key;
898c87c5fbaSopenharmony_ci} sni_def_t;
899c87c5fbaSopenharmony_ci
900c87c5fbaSopenharmony_citypedef struct valid_snis_t {
901c87c5fbaSopenharmony_ci  int count;
902c87c5fbaSopenharmony_ci  sni_def_t *sni_list;
903c87c5fbaSopenharmony_ci} valid_snis_t;
904c87c5fbaSopenharmony_ci
905c87c5fbaSopenharmony_ci/**
906c87c5fbaSopenharmony_ci * SNI Validation callback that is set up by coap_context_set_pki().
907c87c5fbaSopenharmony_ci * Invoked if the SNI is not previously seen and prior to sending a certificate
908c87c5fbaSopenharmony_ci * set back to the client so that the appropriate certificate set can be used
909c87c5fbaSopenharmony_ci * based on the requesting SNI.
910c87c5fbaSopenharmony_ci *
911c87c5fbaSopenharmony_ci * @param sni  The requested SNI
912c87c5fbaSopenharmony_ci * @param arg  The same as was passed into coap_context_set_pki()
913c87c5fbaSopenharmony_ci *             in setup_data->sni_call_back_arg
914c87c5fbaSopenharmony_ci *
915c87c5fbaSopenharmony_ci * @return new set of certificates to use, or NULL if SNI is to be rejected.
916c87c5fbaSopenharmony_ci */
917c87c5fbaSopenharmony_cistatic coap_dtls_key_t *
918c87c5fbaSopenharmony_civerify_pki_sni_callback(const char *sni,
919c87c5fbaSopenharmony_ci                        void *arg
920c87c5fbaSopenharmony_ci) {
921c87c5fbaSopenharmony_ci  valid_snis_t *valid_sni_list = (valid_snis_t *)arg;
922c87c5fbaSopenharmony_ci  int i;
923c87c5fbaSopenharmony_ci
924c87c5fbaSopenharmony_ci  /* Check that the SNI is valid */
925c87c5fbaSopenharmony_ci  for (i = 0; i < valid_sni_list->count; i++) {
926c87c5fbaSopenharmony_ci    if (!strcasecmp(sni, valid_sni_list->sni_list[i].sni)) {
927c87c5fbaSopenharmony_ci      return &valid_sni_list->sni_list[i].key;
928c87c5fbaSopenharmony_ci    }
929c87c5fbaSopenharmony_ci  }
930c87c5fbaSopenharmony_ci  return NULL;
931c87c5fbaSopenharmony_ci}
932c87c5fbaSopenharmony_ci
933c87c5fbaSopenharmony_ci/*
934c87c5fbaSopenharmony_ci * Set up PKI encryption information
935c87c5fbaSopenharmony_ci */
936c87c5fbaSopenharmony_cistatic coap_context_t *
937c87c5fbaSopenharmony_cisetup_server_context_pki (const char *public_cert_file,
938c87c5fbaSopenharmony_ci                          const char *private_key_file,
939c87c5fbaSopenharmony_ci                          const char *ca_file,
940c87c5fbaSopenharmony_ci                          valid_cns_t *valid_cn_list,
941c87c5fbaSopenharmony_ci                          valid_snis_t *valid_sni_list
942c87c5fbaSopenharmony_ci) {
943c87c5fbaSopenharmony_ci  coap_endpoint_t *endpoint;
944c87c5fbaSopenharmony_ci  coap_address_t listen_addr;
945c87c5fbaSopenharmony_ci  coap_dtls_pki_t dtls_pki;
946c87c5fbaSopenharmony_ci  coap_context_t *context;
947c87c5fbaSopenharmony_ci
948c87c5fbaSopenharmony_ci  /* See coap_tls_library(3) */
949c87c5fbaSopenharmony_ci  if (!coap_dtls_is_supported())
950c87c5fbaSopenharmony_ci    return NULL;
951c87c5fbaSopenharmony_ci
952c87c5fbaSopenharmony_ci  /* See coap_context(3) */
953c87c5fbaSopenharmony_ci  context = coap_new_context(NULL);
954c87c5fbaSopenharmony_ci  if (!context)
955c87c5fbaSopenharmony_ci    return NULL;
956c87c5fbaSopenharmony_ci  /* See coap_block(3) */
957c87c5fbaSopenharmony_ci  coap_context_set_block_mode(context,
958c87c5fbaSopenharmony_ci                              COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
959c87c5fbaSopenharmony_ci
960c87c5fbaSopenharmony_ci
961c87c5fbaSopenharmony_ci  memset (&dtls_pki, 0, sizeof (dtls_pki));
962c87c5fbaSopenharmony_ci
963c87c5fbaSopenharmony_ci  dtls_pki.version                 = COAP_DTLS_PKI_SETUP_VERSION;
964c87c5fbaSopenharmony_ci  dtls_pki.verify_peer_cert        = 1;
965c87c5fbaSopenharmony_ci  dtls_pki.check_common_ca         = 1;
966c87c5fbaSopenharmony_ci  dtls_pki.allow_self_signed       = 1;
967c87c5fbaSopenharmony_ci  dtls_pki.allow_expired_certs     = 1;
968c87c5fbaSopenharmony_ci  dtls_pki.cert_chain_validation   = 1;
969c87c5fbaSopenharmony_ci  dtls_pki.cert_chain_verify_depth = 1;
970c87c5fbaSopenharmony_ci  dtls_pki.check_cert_revocation   = 1;
971c87c5fbaSopenharmony_ci  dtls_pki.allow_no_crl            = 1;
972c87c5fbaSopenharmony_ci  dtls_pki.allow_expired_crl       = 1;
973c87c5fbaSopenharmony_ci  dtls_pki.allow_bad_md_hash       = 0;
974c87c5fbaSopenharmony_ci  dtls_pki.allow_short_rsa_length  = 0;
975c87c5fbaSopenharmony_ci  dtls_pki.is_rpk_not_cert         = 0; /* Set to 1 if RPK */
976c87c5fbaSopenharmony_ci  dtls_pki.validate_cn_call_back   = verify_cn_callback;
977c87c5fbaSopenharmony_ci  dtls_pki.cn_call_back_arg        = valid_cn_list;
978c87c5fbaSopenharmony_ci  dtls_pki.validate_sni_call_back  = verify_pki_sni_callback;
979c87c5fbaSopenharmony_ci  dtls_pki.sni_call_back_arg       = valid_sni_list;
980c87c5fbaSopenharmony_ci  dtls_pki.additional_tls_setup_call_back = NULL;
981c87c5fbaSopenharmony_ci  dtls_pki.client_sni              = NULL;
982c87c5fbaSopenharmony_ci  dtls_pki.pki_key.key_type        = COAP_PKI_KEY_PEM;
983c87c5fbaSopenharmony_ci  dtls_pki.pki_key.key.pem.ca_file = ca_file;
984c87c5fbaSopenharmony_ci  dtls_pki.pki_key.key.pem.public_cert = public_cert_file;
985c87c5fbaSopenharmony_ci  dtls_pki.pki_key.key.pem.private_key = private_key_file;
986c87c5fbaSopenharmony_ci
987c87c5fbaSopenharmony_ci  /* See coap_context(3) */
988c87c5fbaSopenharmony_ci  if (coap_context_set_pki(context, &dtls_pki)) {
989c87c5fbaSopenharmony_ci    coap_free_context(context);
990c87c5fbaSopenharmony_ci    return NULL;
991c87c5fbaSopenharmony_ci  }
992c87c5fbaSopenharmony_ci
993c87c5fbaSopenharmony_ci  coap_address_init(&listen_addr);
994c87c5fbaSopenharmony_ci  listen_addr.addr.sa.sa_family = AF_INET;
995c87c5fbaSopenharmony_ci  listen_addr.addr.sin.sin_port = htons (5684);
996c87c5fbaSopenharmony_ci
997c87c5fbaSopenharmony_ci  /* See coap_context(3) */
998c87c5fbaSopenharmony_ci  endpoint = coap_new_endpoint(context, &listen_addr, COAP_PROTO_DTLS);
999c87c5fbaSopenharmony_ci  if (!endpoint) {
1000c87c5fbaSopenharmony_ci    coap_free_context(context);
1001c87c5fbaSopenharmony_ci    return NULL;
1002c87c5fbaSopenharmony_ci  }
1003c87c5fbaSopenharmony_ci
1004c87c5fbaSopenharmony_ci  /* Initialize resources - See coap_resource(3) init_resources() example */
1005c87c5fbaSopenharmony_ci
1006c87c5fbaSopenharmony_ci  return context;
1007c87c5fbaSopenharmony_ci}
1008c87c5fbaSopenharmony_ci----
1009c87c5fbaSopenharmony_ci
1010c87c5fbaSopenharmony_ci*CoAP Server DTLS PSK Setup*
1011c87c5fbaSopenharmony_ci[source, c]
1012c87c5fbaSopenharmony_ci----
1013c87c5fbaSopenharmony_ci#include <coap@LIBCOAP_API_VERSION@/coap.h>
1014c87c5fbaSopenharmony_ci
1015c87c5fbaSopenharmony_citypedef struct id_def_t {
1016c87c5fbaSopenharmony_ci  char *hint_match;
1017c87c5fbaSopenharmony_ci  coap_bin_const_t id;
1018c87c5fbaSopenharmony_ci  coap_bin_const_t key;
1019c87c5fbaSopenharmony_ci} id_def_t;
1020c87c5fbaSopenharmony_ci
1021c87c5fbaSopenharmony_citypedef struct valid_ids_t {
1022c87c5fbaSopenharmony_ci  size_t count;
1023c87c5fbaSopenharmony_ci  id_def_t *id_list;
1024c87c5fbaSopenharmony_ci} valid_ids_t;
1025c87c5fbaSopenharmony_ci
1026c87c5fbaSopenharmony_ci/*
1027c87c5fbaSopenharmony_ci * PSK Identity Pre-Shared Key selection Callback function
1028c87c5fbaSopenharmony_ci */
1029c87c5fbaSopenharmony_cistatic const coap_bin_const_t *
1030c87c5fbaSopenharmony_civerify_id_callback(coap_bin_const_t *identity,
1031c87c5fbaSopenharmony_ci                   coap_session_t *c_session,
1032c87c5fbaSopenharmony_ci                   void *arg
1033c87c5fbaSopenharmony_ci) {
1034c87c5fbaSopenharmony_ci  valid_ids_t *valid_id_list = (valid_ids_t*)arg;
1035c87c5fbaSopenharmony_ci  const coap_bin_const_t *s_psk_hint = coap_session_get_psk_hint(c_session);
1036c87c5fbaSopenharmony_ci  size_t i;
1037c87c5fbaSopenharmony_ci
1038c87c5fbaSopenharmony_ci  /* Check that the Identity is valid */
1039c87c5fbaSopenharmony_ci  for (i = 0; i < valid_id_list->count; i++) {
1040c87c5fbaSopenharmony_ci    if (s_psk_hint &&
1041c87c5fbaSopenharmony_ci        strcmp((const char *)s_psk_hint->s,
1042c87c5fbaSopenharmony_ci               valid_id_list->id_list[i].hint_match)) {
1043c87c5fbaSopenharmony_ci      continue;
1044c87c5fbaSopenharmony_ci    }
1045c87c5fbaSopenharmony_ci    if (coap_binary_equal(identity, &valid_id_list->id_list[i].id)) {
1046c87c5fbaSopenharmony_ci      return &valid_id_list->id_list[i].key;
1047c87c5fbaSopenharmony_ci    }
1048c87c5fbaSopenharmony_ci  }
1049c87c5fbaSopenharmony_ci  return NULL;
1050c87c5fbaSopenharmony_ci}
1051c87c5fbaSopenharmony_ci
1052c87c5fbaSopenharmony_citypedef struct sni_psk_def_t {
1053c87c5fbaSopenharmony_ci  char* sni;
1054c87c5fbaSopenharmony_ci  coap_dtls_spsk_info_t psk_info;
1055c87c5fbaSopenharmony_ci} sni_psk_def_t;
1056c87c5fbaSopenharmony_ci
1057c87c5fbaSopenharmony_citypedef struct valid_psk_snis_t {
1058c87c5fbaSopenharmony_ci  int count;
1059c87c5fbaSopenharmony_ci  sni_psk_def_t *sni_list;
1060c87c5fbaSopenharmony_ci} valid_psk_snis_t;
1061c87c5fbaSopenharmony_ci
1062c87c5fbaSopenharmony_ci/*
1063c87c5fbaSopenharmony_ci * PSK Subject Name Identifier (SNI) callback verifier
1064c87c5fbaSopenharmony_ci */
1065c87c5fbaSopenharmony_cistatic const coap_dtls_spsk_info_t *
1066c87c5fbaSopenharmony_civerify_psk_sni_callback(const char *sni,
1067c87c5fbaSopenharmony_ci                        coap_session_t *c_session,
1068c87c5fbaSopenharmony_ci                        void *arg
1069c87c5fbaSopenharmony_ci) {
1070c87c5fbaSopenharmony_ci  valid_psk_snis_t *valid_sni_list = (valid_psk_snis_t *)arg;
1071c87c5fbaSopenharmony_ci  int i;
1072c87c5fbaSopenharmony_ci  /* Remove (void) definition if variable is used */
1073c87c5fbaSopenharmony_ci  (void)c_session;
1074c87c5fbaSopenharmony_ci
1075c87c5fbaSopenharmony_ci  /* Check that the SNI is valid */
1076c87c5fbaSopenharmony_ci  for (i = 0; i < valid_sni_list->count; i++) {
1077c87c5fbaSopenharmony_ci    if (!strcasecmp(sni, valid_sni_list->sni_list[i].sni)) {
1078c87c5fbaSopenharmony_ci      return &valid_sni_list->sni_list[i].psk_info;
1079c87c5fbaSopenharmony_ci    }
1080c87c5fbaSopenharmony_ci  }
1081c87c5fbaSopenharmony_ci  return NULL;
1082c87c5fbaSopenharmony_ci}
1083c87c5fbaSopenharmony_ci
1084c87c5fbaSopenharmony_cistatic coap_context_t *
1085c87c5fbaSopenharmony_cisetup_server_context_psk (const char *hint,
1086c87c5fbaSopenharmony_ci                          const uint8_t *key,
1087c87c5fbaSopenharmony_ci                          unsigned int key_len,
1088c87c5fbaSopenharmony_ci                          valid_ids_t *valid_id_list,
1089c87c5fbaSopenharmony_ci                          valid_psk_snis_t *valid_sni_list
1090c87c5fbaSopenharmony_ci) {
1091c87c5fbaSopenharmony_ci  coap_endpoint_t *endpoint;
1092c87c5fbaSopenharmony_ci  coap_address_t listen_addr;
1093c87c5fbaSopenharmony_ci  coap_context_t *context;
1094c87c5fbaSopenharmony_ci  coap_dtls_spsk_t dtls_psk;
1095c87c5fbaSopenharmony_ci
1096c87c5fbaSopenharmony_ci  /* See coap_tls_library(3) */
1097c87c5fbaSopenharmony_ci  if (!coap_dtls_is_supported())
1098c87c5fbaSopenharmony_ci    return NULL;
1099c87c5fbaSopenharmony_ci
1100c87c5fbaSopenharmony_ci  context = coap_new_context(NULL);
1101c87c5fbaSopenharmony_ci  if (!context)
1102c87c5fbaSopenharmony_ci    return NULL;
1103c87c5fbaSopenharmony_ci  /* See coap_block(3) */
1104c87c5fbaSopenharmony_ci  coap_context_set_block_mode(context,
1105c87c5fbaSopenharmony_ci                              COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
1106c87c5fbaSopenharmony_ci
1107c87c5fbaSopenharmony_ci
1108c87c5fbaSopenharmony_ci  memset (&dtls_psk, 0, sizeof (dtls_psk));
1109c87c5fbaSopenharmony_ci
1110c87c5fbaSopenharmony_ci  /* see coap_encryption(3) */
1111c87c5fbaSopenharmony_ci  dtls_psk.version                 = COAP_DTLS_SPSK_SETUP_VERSION;
1112c87c5fbaSopenharmony_ci  dtls_psk.validate_id_call_back   = verify_id_callback;
1113c87c5fbaSopenharmony_ci  dtls_psk.id_call_back_arg        = valid_id_list;
1114c87c5fbaSopenharmony_ci  dtls_psk.validate_sni_call_back  = verify_psk_sni_callback;
1115c87c5fbaSopenharmony_ci  dtls_psk.sni_call_back_arg       = valid_sni_list;
1116c87c5fbaSopenharmony_ci  dtls_psk.psk_info.hint.s         = (const uint8_t*)hint;
1117c87c5fbaSopenharmony_ci  dtls_psk.psk_info.hint.length    = hint ? strlen(hint) : 0;
1118c87c5fbaSopenharmony_ci  dtls_psk.psk_info.key.s          = key;
1119c87c5fbaSopenharmony_ci  dtls_psk.psk_info.key.length     = key_len;
1120c87c5fbaSopenharmony_ci
1121c87c5fbaSopenharmony_ci  if (coap_context_set_psk2(context, &dtls_psk)) {
1122c87c5fbaSopenharmony_ci    coap_free_context(context);
1123c87c5fbaSopenharmony_ci    return NULL;
1124c87c5fbaSopenharmony_ci  }
1125c87c5fbaSopenharmony_ci
1126c87c5fbaSopenharmony_ci  coap_address_init(&listen_addr);
1127c87c5fbaSopenharmony_ci  listen_addr.addr.sa.sa_family = AF_INET;
1128c87c5fbaSopenharmony_ci  listen_addr.addr.sin.sin_port = htons (5684);
1129c87c5fbaSopenharmony_ci
1130c87c5fbaSopenharmony_ci  endpoint = coap_new_endpoint(context, &listen_addr, COAP_PROTO_DTLS);
1131c87c5fbaSopenharmony_ci  if (!endpoint) {
1132c87c5fbaSopenharmony_ci    coap_free_context(context);
1133c87c5fbaSopenharmony_ci    return NULL;
1134c87c5fbaSopenharmony_ci  }
1135c87c5fbaSopenharmony_ci
1136c87c5fbaSopenharmony_ci  /* Initialize resources - See coap_resource(3) init_resources() example */
1137c87c5fbaSopenharmony_ci
1138c87c5fbaSopenharmony_ci  return context;
1139c87c5fbaSopenharmony_ci}
1140c87c5fbaSopenharmony_ci----
1141c87c5fbaSopenharmony_ci
1142c87c5fbaSopenharmony_ci*CoAP Client DTLS PSK Setup*
1143c87c5fbaSopenharmony_ci[source, c]
1144c87c5fbaSopenharmony_ci----
1145c87c5fbaSopenharmony_ci#include <coap@LIBCOAP_API_VERSION@/coap.h>
1146c87c5fbaSopenharmony_ci
1147c87c5fbaSopenharmony_ci#include <stdio.h>
1148c87c5fbaSopenharmony_ci
1149c87c5fbaSopenharmony_ci#ifndef min
1150c87c5fbaSopenharmony_ci#define min(a,b) ((a) < (b) ? (a) : (b))
1151c87c5fbaSopenharmony_ci#endif
1152c87c5fbaSopenharmony_ci
1153c87c5fbaSopenharmony_cistatic const coap_dtls_cpsk_info_t *
1154c87c5fbaSopenharmony_civerify_ih_callback(coap_str_const_t *hint,
1155c87c5fbaSopenharmony_ci                   coap_session_t *c_session,
1156c87c5fbaSopenharmony_ci                   void *arg
1157c87c5fbaSopenharmony_ci) {
1158c87c5fbaSopenharmony_ci  coap_dtls_cpsk_info_t *psk_info = (coap_dtls_cpsk_info_t *)arg;
1159c87c5fbaSopenharmony_ci  /* Remove (void) definition if variable is used */
1160c87c5fbaSopenharmony_ci  (void)c_session;
1161c87c5fbaSopenharmony_ci
1162c87c5fbaSopenharmony_ci  coap_log_info("Identity Hint '%.*s' provided\n", (int)hint->length, hint->s);
1163c87c5fbaSopenharmony_ci
1164c87c5fbaSopenharmony_ci  /* Just use the defined information for now as passed in by arg */
1165c87c5fbaSopenharmony_ci  return psk_info;
1166c87c5fbaSopenharmony_ci}
1167c87c5fbaSopenharmony_ci
1168c87c5fbaSopenharmony_cistatic coap_dtls_cpsk_t dtls_psk;
1169c87c5fbaSopenharmony_cistatic char client_sni[256];
1170c87c5fbaSopenharmony_ci
1171c87c5fbaSopenharmony_cistatic coap_session_t *
1172c87c5fbaSopenharmony_cisetup_client_session_psk (const char *uri,
1173c87c5fbaSopenharmony_ci                          struct in_addr ip_address,
1174c87c5fbaSopenharmony_ci                          const uint8_t *identity,
1175c87c5fbaSopenharmony_ci                          unsigned int identity_len,
1176c87c5fbaSopenharmony_ci                          const uint8_t *key,
1177c87c5fbaSopenharmony_ci                          unsigned int key_len
1178c87c5fbaSopenharmony_ci) {
1179c87c5fbaSopenharmony_ci  coap_session_t *session;
1180c87c5fbaSopenharmony_ci  coap_address_t server;
1181c87c5fbaSopenharmony_ci  /* See coap_context(3) */
1182c87c5fbaSopenharmony_ci  coap_context_t *context = coap_new_context(NULL);
1183c87c5fbaSopenharmony_ci
1184c87c5fbaSopenharmony_ci  if (!context)
1185c87c5fbaSopenharmony_ci    return NULL;
1186c87c5fbaSopenharmony_ci  /* See coap_block(3) */
1187c87c5fbaSopenharmony_ci  coap_context_set_block_mode(context,
1188c87c5fbaSopenharmony_ci                              COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
1189c87c5fbaSopenharmony_ci
1190c87c5fbaSopenharmony_ci
1191c87c5fbaSopenharmony_ci  coap_address_init(&server);
1192c87c5fbaSopenharmony_ci  server.addr.sa.sa_family = AF_INET;
1193c87c5fbaSopenharmony_ci  server.addr.sin.sin_addr = ip_address;
1194c87c5fbaSopenharmony_ci  server.addr.sin.sin_port = htons (5684);
1195c87c5fbaSopenharmony_ci
1196c87c5fbaSopenharmony_ci  /* See coap_encryption(3) */
1197c87c5fbaSopenharmony_ci  memset (&dtls_psk, 0, sizeof(dtls_psk));
1198c87c5fbaSopenharmony_ci  dtls_psk.version = COAP_DTLS_CPSK_SETUP_VERSION;
1199c87c5fbaSopenharmony_ci  dtls_psk.validate_ih_call_back = verify_ih_callback;
1200c87c5fbaSopenharmony_ci  dtls_psk.ih_call_back_arg = &dtls_psk.psk_info;
1201c87c5fbaSopenharmony_ci  if (uri)
1202c87c5fbaSopenharmony_ci    memcpy(client_sni, uri, min(strlen(uri), sizeof(client_sni)-1));
1203c87c5fbaSopenharmony_ci  else
1204c87c5fbaSopenharmony_ci    memcpy(client_sni, "localhost", 9);
1205c87c5fbaSopenharmony_ci  dtls_psk.client_sni = client_sni;
1206c87c5fbaSopenharmony_ci  dtls_psk.psk_info.identity.s = identity;
1207c87c5fbaSopenharmony_ci  dtls_psk.psk_info.identity.length = identity_len;
1208c87c5fbaSopenharmony_ci  dtls_psk.psk_info.key.s = key;
1209c87c5fbaSopenharmony_ci  dtls_psk.psk_info.key.length = key_len;
1210c87c5fbaSopenharmony_ci  session = coap_new_client_session_psk2(context, NULL, &server,
1211c87c5fbaSopenharmony_ci                                        COAP_PROTO_DTLS, &dtls_psk);
1212c87c5fbaSopenharmony_ci  if (!session) {
1213c87c5fbaSopenharmony_ci    coap_free_context(context);
1214c87c5fbaSopenharmony_ci    return NULL;
1215c87c5fbaSopenharmony_ci  }
1216c87c5fbaSopenharmony_ci  /* The context is in session->context */
1217c87c5fbaSopenharmony_ci  return session;
1218c87c5fbaSopenharmony_ci}
1219c87c5fbaSopenharmony_ci----
1220c87c5fbaSopenharmony_ci
1221c87c5fbaSopenharmony_ciSEE ALSO
1222c87c5fbaSopenharmony_ci--------
1223c87c5fbaSopenharmony_ci*coap_block*(3), *coap_context*(3), *coap_resource*(3), *coap_session*(3) and
1224c87c5fbaSopenharmony_ci*coap_tls_library*(3)
1225c87c5fbaSopenharmony_ci
1226c87c5fbaSopenharmony_ciFURTHER INFORMATION
1227c87c5fbaSopenharmony_ci-------------------
1228c87c5fbaSopenharmony_ciSee
1229c87c5fbaSopenharmony_ci
1230c87c5fbaSopenharmony_ci"https://rfc-editor.org/rfc/rfc7252[RFC7252: The Constrained Application Protocol (CoAP)]"
1231c87c5fbaSopenharmony_ci
1232c87c5fbaSopenharmony_cifor further information.
1233c87c5fbaSopenharmony_ci
1234c87c5fbaSopenharmony_ciBUGS
1235c87c5fbaSopenharmony_ci----
1236c87c5fbaSopenharmony_ciPlease report bugs on the mailing list for libcoap:
1237c87c5fbaSopenharmony_cilibcoap-developers@lists.sourceforge.net or raise an issue on GitHub at
1238c87c5fbaSopenharmony_cihttps://github.com/obgm/libcoap/issues
1239c87c5fbaSopenharmony_ci
1240c87c5fbaSopenharmony_ciAUTHORS
1241c87c5fbaSopenharmony_ci-------
1242c87c5fbaSopenharmony_ciThe libcoap project <libcoap-developers@lists.sourceforge.net>
1243