1COAP_ENCRYPTION(3) libcoap Manual COAP_ENCRYPTION(3)
2
3
4
6 coap_encryption, coap_dtls_pki_t - Work with CoAP tls/dtls
7
9 #include <coap2/coap.h>
10
11 struct coap_dtls_pki_t
12
13 Link with -lcoap-2, -lcoap-2-gnutls, -lcoap-2-openssl or
14 -lcoap-2-tinydtls depending on your (D)TLS library type.
15
17 This man page focuses on setting up CoAP to use encryption.
18
19 When the libcoap library was built, it will have been compiled using a
20 specific underlying TLS implementation type (e.g. OpenSSL, GnuTLS,
21 TinyDTLS or noTLS). When the libcoap library is linked into an
22 application, it is possible that the application needs to dynamically
23 determine whether DTLS or TLS is supported, what type of TLS
24 implementation libcoap was compiled with, as well as detect what is the
25 version of the currently loaded TLS library.
26
27 NOTE: If OpenSSL is being used, then the minimum supported OpenSSL
28 library version is 1.1.0.
29
30 NOTE: If GnuTLS is being used, then the minimum GnuTLS library version
31 is 3.3.0.
32
33 NOTE: If GnuTLS is going to interoperate with TinyDTLS, then a minimum
34 revision of GnuTLS 3.5.5 which supports CCM algorithms is required by
35 TinyDTLS as TinyDTLS currently only supports CCM.
36
37 Network traffic can be un-encrypted or encrypted with libcoap if there
38 is an underlying TLS library.
39
40 If TLS is going to be used for encrypting the network traffic, then the
41 TLS information for Pre-Shared Keys (PSK) or Public Key Infrastructure
42 (PKI) needs to be configured before any network traffic starts to flow.
43 For Servers, this has to be done before the Endpoint is created, for
44 Clients, this is done during the Client Session set up.
45
46 For Servers, all the encryption information is held internally by the
47 TLS Context level and the CoAP Context level as the Server is listening
48 for new incoming traffic based on the Endpoint definition. The TLS and
49 CoAP session will not get built until the new traffic starts, which is
50 done by the libcoap library, with the session having a reference count
51 of 1.
52
53 For Clients, all the encryption information can be held at the TLS
54 Context and CoAP Context levels, or usually at the TLS Session and CoAP
55 Session levels. If defined at the Context level, then when Sessions are
56 created, they will inherit the Context definitions, unless they have
57 separately been defined for the Session level, in which case the
58 Session version will get used. Typically the information will be
59 configured at the Session level for Clients.
60
61 In principle the set-up sequence for CoAP Servers looks like
62
63 coap_new_context()
64 coap_context_set_pki_root_cas() - if the root CAs need to be updated and PKI
65 coap_context_set_pki() and/or coap_context_set_psk() - if encryption is required
66 coap_new_endpoint()
67
68 Multiple endpoints can be set up per Context, each listening for a new
69 traffic flow with different TCP/UDP protocols, TLS protocols, port
70 numbers etc. When a new traffic flow is started, then the CoAP library
71 will create and start a new server session.
72
73 In principle the set-up sequence for CoAP Clients looks like
74
75 coap_new_context()
76 coap_context_set_pki_root_cas() - if the root CAs need to be updated and PKI
77 coap_new_client_session(), coap_new_client_session_pki() or coap_new_client_session_psk()
78
79 Multiple client sessions are supported per Context.
80
81 Due to the nature of TLS, there are Callbacks that are invoked as the
82 TLS session negotiates encryption algorithms, encryption keys etc.
83 Where possible, the CoAP layer handles all this automatically based on
84 different configuration options passed in by the coap_*_pki()
85 functions.
86
87 For PSK setup, the required information needs to be provided in the
88 setup calls with no application Callbacks required. Both the Client and
89 Server have to provide a PSK. The Server must have a Hint defined and
90 the Client must have an Identity defined.
91
92 For PKI setup, if the libcoap PKI configuration options do not handle a
93 specific requirement as defined by the available options, then an
94 application defined Callback can called to do the additional specific
95 checks.
96
97 The information passed to this Application Callback will be the TLS
98 session (as well the configuration information), but the structures
99 containing this information will be different as they will be based on
100 the underlying TLS library type. coap_get_tls_library_version() is
101 provided to help here.
102
103 Libcoap will add in the defined Certificate, Private Key and CA
104 Certificate into the TLS environment. The CA Certificate is also added
105 in to the list of valid CAs for Certificate checking.
106
107 The internal Callbacks (and optionally the Application Callback) will
108 then check the required information as defined in the coap_dtls_pki_t
109 described below.
110
111 typedef struct coap_dtls_pki_t {
112 uint8_t version; /* COAP_DTLS_PKI_SETUP_VERSION */
113
114 /* Options to enable different TLS functionality in libcoap */
115 uint8_t verify_peer_cert; /* 1 if peer cert is to be verified */
116 uint8_t require_peer_cert; /* 1 if peer cert is required */
117 uint8_t allow_self_signed; /* 1 if self signed certs are allowed */
118 uint8_t allow_expired_certs; /* 1 if expired certs are allowed */
119 uint8_t cert_chain_validation; /* 1 if to check cert_chain_verify_depth */
120 uint8_t cert_chain_verify_depth; /* recommended depth is 3 */
121 uint8_t check_cert_revocation; /* 1 if revocation checks wanted */
122 uint8_t allow_no_crl; /* 1 ignore if CRL not there */
123 uint8_t allow_expired_crl; /* 1 if expired crl is allowed */
124 uint8_t reserved[6]; /* Reserved - must be set to 0 for
125 future compatibility */
126
127 /** CN check call-back function
128 * If not NULL, is called when the TLS connection has passed the configured
129 * TLS options above for the application to verify if the CN is valid.
130 */
131 coap_dtls_cn_callback_t validate_cn_call_back;
132 void *cn_call_back_arg; /* Passed in to the CN call-back function */
133
134 /** SNI check call-back function
135 * If not NULL, called if the SNI is not previously seen and prior to sending
136 * a certificate set back to the client so that the appropriate certificate set
137 * can be used based on the requesting SNI.
138 */
139 coap_dtls_sni_callback_t validate_sni_call_back;
140 void *sni_call_back_arg; /* Passed in to the sni call-back function */
141
142 /** Additional Security call-back handler that is invoked when libcoap has
143 * done the standerd, defined validation checks at the TLS level,
144 * If not NULL, called from within the TLS Client Hello connection
145 * setup.
146 */
147 coap_dtls_security_setup_t additional_tls_setup_call_back;
148
149 char* client_sni; /* If not NULL, SNI to use in client TLS setup.
150 Owned by the client app and must remain valid
151 during the call to coap_new_client_session_pki() */
152
153 coap_dtls_key_t pki_key; /* PKI key definition */
154 } coap_dtls_pki_t;
155
156 More detailed explanation of the coap_dtls_pki_t structure follows.
157
158 WARNING: All the parameter definitions that are pointers to other
159 locations, these locations must remain valid during the lifetime of all
160 the underlying TLS sessions that are, or will get created based on this
161 PKI definition.
162
163 The first parameter in each subsection enables/disables the
164 functionality, the remaining parameter(s) control control what happens
165 when the functionality is enabled.
166
167 SECTION: coap_dtls_pki_t Version
168
169 #define COAP_DTLS_PKI_SETUP_VERSION 1
170
171 version is set to COAP_DTLS_PKI_SETUP_VERSION. This will then allow
172 support for different versions of the coap_dtls_pki_t structure in the
173 future.
174
175 SECTION: Peer Certificate Checking
176
177 verify_peer_cert Set to 1 to check that the peer’s certificate is valid
178 if provided, else 0.
179
180 require_peer_cert Set to 1 to enforce that the peer provides a
181 certificate, else 0. If the Server, this initates a request for the
182 peer certificate.
183
184 allow_self_signed Set to 1 to allow the peer (or any certificate in the
185 certificate chain) to be a self-signed certificate, else 0.
186
187 allow_expired_certs Set to 1 to allow certificates that have either
188 expired, or are not yet valid to be allowed, else 0.
189
190 SECTION: Certificate Chain Validation
191
192 cert_chain_validation Set to 1 to check that the certificate chain is
193 valid, else 0.
194
195 cert_chain_verify_depth Set to the chain depth that is to be checked.
196 This is the number of intermediate CAs in the chain. If set to 0, then
197 there can be no intermediate CA in the chain.
198
199 SECTION: Certificate Revocation
200
201 check_cert_revocation Set to 1 to check whether any certificate in the
202 chain has been revoked, else 0.
203
204 allow_no_crl Set to 1 to not check any certificate that does not have a
205 CRL.
206
207 allow_expired_crl Set to 1 to allow an certificate that has an expired
208 CRL definition to be valid, else 0.
209
210 SECTION: Reserved
211
212 reserved Must be set to 0. Future functionality updates will make use
213 of these reserved definitions.
214
215 SECTION: Common Name (CN) Callback
216
217 /**
218 * CN Validation call-back that can be set up by coap_context_set_pki().
219 * Invoked when libcoap has done the validation checks at the TLS level,
220 * but the application needs to check that the CN is allowed.
221 * CN is the SubjectAltName in the cert, if not present, then the leftmost
222 * Common Name (CN) component of the subject name
223 *
224 * @param cn The determined CN from the certificate
225 * @param asn1_public_cert The ASN.1 encoded (DER) X.509 certificate
226 * @param asn1_length The ASN.1 length
227 * @param session The coap session associated with the certificate update
228 * @param depth Depth in cert chain. If 0, then client cert, else a CA
229 * @param validated TLS can find no issues if 1
230 * @param arg The same as was passed into coap_context_set_pki()
231 * in setup_data->cn_call_back_arg
232 *
233 * @return 1 if accepted, else 0 if to be rejected
234 */
235 typedef int (*coap_dtls_cn_callback_t)(const char *cn,
236 const uint8_t *asn1_public_cert,
237 size_t asn1_length,
238 coap_session_t *session,
239 unsigned depth,
240 int validated,
241 void *arg);
242
243 validate_cn_call_back points to an application provided CN callback
244 checking function or NULL. The application can make use of this CN
245 information to decide, for example, that the CN is valid coming from a
246 particular peer. The Callback returns 1 on success, 0 if the TLS
247 connection is to be aborted.
248
249 cn_call_back_arg points to a user defined set of data that will get
250 passed in to the validate_cn_call_back() function and can be used by
251 that function. An example would be a set of CNs that are allowed.
252
253 SECTION: Subject Name Identifier (SNI) Callback
254
255 typedef struct coap_dtls_key_t {
256 coap_pki_key_t key_type; /* key format type */
257 union {
258 coap_pki_key_pem_t pem; /* for PEM keys */
259 coap_pki_key_asn1_t asn1; /* for ASN.1 (DER) keys */
260 } key;
261 } coap_dtls_key_t;
262
263 /**
264 * SNI Validation call-back that can be set up by coap_context_set_pki().
265 * Invoked if the SNI is not previously seen and prior to sending a certificate
266 * set back to the client so that the appropriate certificate set can be used
267 * based on the requesting SNI.
268 *
269 * @param sni The requested SNI
270 * @param arg The same as was passed into coap_context_set_pki()
271 * in setup_data->sni_call_back_arg
272 *
273 * @return new set of certificates to use, or NULL if SNI is to be rejected.
274 */
275 typedef coap_dtls_key_t *(*coap_dtls_sni_callback_t)(const char *sni,
276 void* arg);
277
278 validate_sni_call_back points to an application provided SNI callback
279 checking function or NULL. The application can make use of this SNI
280 information to decide whether the SNI is valid, and what set of
281 certificates to give to the client. Thus it is possible for the coap
282 server to host multiple domains with different certificates allocated
283 to each domain. The Callback returns a pointer to the certificates to
284 use for this SNI, or NULL if the connection it to get rejected. libcoap
285 remembers the association between the SNI and Certificate set and will
286 only invoke this callback if the SNI is unknown.
287
288 sni_call_back_arg points to a user defined set of data that will get
289 passed in to the validate_sni_call_back() function and can be used by
290 that function. An example would be a set of SNIs that are allowed with
291 their matching certificate sets.
292
293 SECTION: Application Additional Setup Callback
294
295 /**
296 * Additional Security setup handler that can be set up by
297 * coap_context_set_pki().
298 * Invoked when libcoap has done the validation checks at the TLS level,
299 * but the application needs to do some additional checks/changes/updates.
300 *
301 * @param session The security session definition - e.g. SSL * for OpenSSL.
302 * This will be dependent on the underlying TLS library
303 * - see coap_get_tls_library_version()
304 * @param setup_data A structure containing setup data originally passed into
305 * coap_context_set_pki() or coap_new_client_session_pki().
306 * @return 1 if successful, else 0
307 */
308 typedef int (*coap_dtls_security_setup_t)(void *context, void* session,
309 struct coap_dtls_pki_t *setup_data);
310
311 additional_tls_setup_call_back points to an application provided
312 callback function that will do additional checking/changes/updates
313 after libcoap has done all of the configured TLS setup checking, or
314 NULL to do no additional checking.
315
316 SECTION: Subject Name Indicator (SNI) Definition
317
318 client_sni points to the SNI name that will be added in as a TLS
319 extension, or set NULL. This typically is the DNS name of the server
320 that the client is trying to contact. This is only used by a client
321 application and the server is then able to decide, based on the name in
322 the SNI extension, whether, for example, a different certificate should
323 be provided.
324
325 SECTION: Key Type Definition
326
327 typedef enum coap_pki_key_t {
328 COAP_PKI_KEY_PEM, /* PEM type informaiton */
329 COAP_PKI_KEY_ASN1, /* ASN1 type information */
330 } coap_pki_key_t;
331
332 key_type defines the format that the certificates / keys are provided
333 in. This can be COAP_PKI_KEY_PEM or COAP_PKI_KEY_ASN1.
334
335 SECTION: PEM Key Definitions
336
337 typedef struct coap_pki_key_pem_t {
338 const char *ca_file; /* File location of Common CA in PEM format */
339 const char *public_cert; /* File location of Public Cert in PEM format */
340 const char *private_key; /* File location of Private Key in PEM format */
341 } coap_pki_key_pem_t;
342
343 key.pem.ca_file points to the CA File location on disk which will be in
344 PEM format, or NULL. This file should only contain 1 CA (who signed the
345 Public Certificate) as this is passed from the server to the client
346 when requesting the client’s certificate. This certificate is also
347 added into the valid root CAs list if not already present.
348
349 key.pem.public_cert points to the Public Certificate location on disk
350 which will be in PEM format.
351
352 key.pem.private_key points to the Private Key location on disk which
353 will be in PEM format. This file cannot be password protected.
354
355 SECTION: ASN1 Key Definitions
356
357 typedef struct coap_pki_key_asn1_t {
358 const uint8_t *ca_cert; /* ASN1 Common CA Certificate */
359 const uint8_t *public_cert; /* ASN1 Public Certificate */
360 const uint8_t *private_key; /* ASN1 Private Key */
361 int ca_cert_len; /* ASN1 CA Certificate length */
362 int public_cert_len; /* ASN1 Public Certificate length */
363 int private_key_len; /* ASN1 Private Key length */
364 coap_asn1_privatekey_type_t private_key_type; /* Private Key Type
365 COAP_ASN1_PKEY_* */
366 } coap_pki_key_asn1_t;
367
368 typedef enum coap_asn1_privatekey_type_t {
369 COAP_ASN1_PKEY_NONE,
370 COAP_ASN1_PKEY_RSA,
371 COAP_ASN1_PKEY_RSA2,
372 COAP_ASN1_PKEY_DSA,
373 COAP_ASN1_PKEY_DSA1,
374 COAP_ASN1_PKEY_DSA2,
375 COAP_ASN1_PKEY_DSA3,
376 COAP_ASN1_PKEY_DSA4,
377 COAP_ASN1_PKEY_DH,
378 COAP_ASN1_PKEY_DHX,
379 COAP_ASN1_PKEY_EC,
380 COAP_ASN1_PKEY_HMAC,
381 COAP_ASN1_PKEY_CMAC,
382 COAP_ASN1_PKEY_TLS1_PRF,
383 COAP_ASN1_PKEY_HKDF
384 } coap_asn1_privatekey_type_t;
385
386 key.asn1.ca_cert points to a DER encoded ASN.1 definition of the CA
387 Certificate, or NULL. This certificate is passed from the server to the
388 client when requesting the client’s certificate. This certificate is
389 also added into the valid root CAs list if not already present.
390
391 key.asn1.public_cert points to a DER encoded ASN.1 definition of the
392 Public Certificate.
393
394 key.asn1.private_key points to DER encoded ASN.1 definition of the
395 Private Key.
396
397 key.asn1.ca_cert_len is the length of the DER encoded ASN.1 definition
398 of the CA Certificate.
399
400 key.asn1.public_cert_len is the length of the DER encoded ASN.1
401 definition of the Public Certificate.
402
403 key.asn1.private_key_len is the length of the DER encoded ASN.1
404 definition of the Private Key.
405
406 key.asn1.private_key_type is the encoding type of the DER encoded ASN.1
407 definition of the Private Key. This will be one of the COAP_ASN1_PKEY_*
408 definitions.
409
411 CoAP Server DTLS PKI Setup
412
413 #include <coap2/coap.h>
414
415 typedef struct valid_cns_t {
416 int count;
417 char **cn_list;
418 } valid_cns_t;
419
420 /**
421 * CN Validation call-back that is set up by coap_context_set_pki().
422 * Invoked when libcoap has done the validation checks at the TLS level,
423 * but the application needs to check that the CN is allowed.
424 * CN is the SubjectAltName in the cert, if not present, then the leftmost
425 * Common Name (CN) component of the subject name
426 *
427 * @param cn The determined CN from the certificate
428 * @param asn1_public_cert The ASN.1 encoded (DER) X.509 certificate
429 * @param asn1_length The ASN.1 length
430 * @param session The coap session associated with the certificate update
431 * @param depth Depth in cert chain. If 0, then client cert, else a CA
432 * @param validated TLS can find no issues if 1
433 * @param arg The same as was passed into coap_context_set_pki()
434 * in setup_data->cn_call_back_arg
435 *
436 * @return 1 if accepted, else 0 if to be rejected
437 */
438 static int
439 verify_cn_callback(const char *cn,
440 const uint8_t *asn1_public_cert,
441 size_t asn1_length,
442 coap_session_t *session,
443 unsigned depth,
444 int validated,
445 void *arg
446 ) {
447 valid_cns_t *valid_cn_list = ( valid_cns_t*)arg;
448 int i;
449
450 /* Check that the CN is valid */
451 for (i = 0; i < valid_cn_list->count; i++) {
452 if (!strcasecmp(cn, valid_cn_list->cn_list[i])) {
453 return 1;
454 }
455 }
456 return 0;
457 }
458
459 typedef struct sni_def_t {
460 char* sni;
461 coap_dtls_key_t key;
462 } sni_def_t;
463
464 typedef struct valid_snis_t {
465 int count;
466 sni_def_t *sni_list;
467 } valid_snis_t;
468
469 /**
470 * SNI Validation call-back that is set up by coap_context_set_pki().
471 * Invoked if the SNI is not previously seen and prior to sending a certificate
472 * set back to the client so that the appropriate certificate set can be used
473 * based on the requesting SNI.
474 *
475 * @param sni The requested SNI
476 * @param arg The same as was passed into coap_context_set_pki()
477 * in setup_data->sni_call_back_arg
478 *
479 * @return new set of certificates to use, or NULL if SNI is to be rejected.
480 */
481 static coap_dtls_key_t *
482 verify_sni_callback(const char *sni,
483 void *arg
484 ) {
485 valid_snis_t *valid_sni_list = (valid_snis_t *)arg;
486 int i;
487
488 /* Check that the SNI is valid */
489 for (i = 0; i < valid_sni_list->count; i++) {
490 if (!strcasecmp(sni, valid_sni_list->sni_list[i].sni)) {
491 return &valid_sni_list->sni_list[i].key;
492 }
493 }
494 return NULL;
495 }
496
497 /*
498 * Set up PKI encryption information
499 */
500 static coap_context_t *
501 setup_server_context_pki (const char *public_cert_file,
502 const char *private_key_file,
503 const char *ca_file,
504 valid_cns_t *valid_cn_list,
505 valid_snis_t *valid_sni_list
506 ) {
507 coap_endpoint_t *endpoint;
508 coap_address_t listen_addr;
509 coap_dtls_pki_t dtls_pki;
510 coap_context_t *context;
511
512 /* See coap_tls_library(3) */
513 if (!coap_dtls_is_supported())
514 return NULL;
515
516 /* See coap_context(3) */
517 context = coap_new_context(NULL);
518 if (!context)
519 return NULL;
520
521 memset (&dtls_pki, 0, sizeof (dtls_pki));
522
523 dtls_pki.version = COAP_DTLS_PKI_SETUP_VERSION;
524 dtls_pki.verify_peer_cert = 1;
525 dtls_pki.require_peer_cert = 1;
526 dtls_pki.allow_self_signed = 1;
527 dtls_pki.allow_expired_certs = 1;
528 dtls_pki.cert_chain_validation = 1;
529 dtls_pki.cert_chain_verify_depth = 1;
530 dtls_pki.check_cert_revocation = 1;
531 dtls_pki.allow_no_crl = 1;
532 dtls_pki.allow_expired_crl = 1;
533 dtls_pki.validate_cn_call_back = verify_cn_callback;
534 dtls_pki.cn_call_back_arg = valid_cn_list;
535 dtls_pki.validate_sni_call_back = verify_sni_callback;
536 dtls_pki.sni_call_back_arg = valid_sni_list;
537 dtls_pki.additional_tls_setup_call_back = NULL;
538 dtls_pki.sni = NULL;
539 dtls_pki.pki_key.key_type = COAP_PKI_KEY_PEM;
540 dtls_pki.pki_key.key.pem.ca_file = ca_file;
541 dtls_pki.pki_key.key.pem.public_cert = public_cert_file;
542 dtls_pki.pki_key.key.pem.private_key = private_key_file;
543
544 /* See coap_context(3) */
545 if (coap_context_set_pki(context, &dtls_pki)) {
546 coap_free_context(context);
547 return NULL;
548 }
549
550 coap_address_init(&listen_addr);
551 listen_addr.addr.sa.sa_family = AF_INET;
552 listen_addr.addr.sin.sin_port = htons (5684);
553
554 /* See coap_context(3) */
555 endpoint = coap_new_endpoint(context, &listen_addr, COAP_PROTO_DTLS);
556 if (!endpoint) {
557 coap_free_context(context);
558 return NULL;
559 }
560
561 /* See coap_resource(3) */
562 init_resources(context);
563
564 return context;
565 }
566
568 coap_context(3), coap_resource(3), coap_session(3) and
569 coap_tls_library(3).
570
572 See "RFC7252: The Constrained Application Protocol (CoAP)" for further
573 information.
574
576 Please report bugs on the mailing list for libcoap:
577 libcoap-developers@lists.sourceforge.net
578
580 The libcoap project <libcoap-developers@lists.sourceforge.net>
581
582
583
584coap_encryption 4.2.1 07/28/2020 COAP_ENCRYPTION(3)