1COAP_ENCRYPTION(3)              libcoap Manual              COAP_ENCRYPTION(3)
2
3
4

NAME

6       coap_encryption, coap_dtls_pki_t - Work with CoAP tls/dtls
7

SYNOPSIS

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

DESCRIPTION

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

EXAMPLES

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

SEE ALSO

568       coap_context(3), coap_resource(3), coap_session(3) and
569       coap_tls_library(3).
570

FURTHER INFORMATION

572       See "RFC7252: The Constrained Application Protocol (CoAP)" for further
573       information.
574

BUGS

576       Please report bugs on the mailing list for libcoap:
577       libcoap-developers@lists.sourceforge.net
578

AUTHORS

580       The libcoap project <libcoap-developers@lists.sourceforge.net>
581
582
583
584coap_encryption 4.2.1             01/26/2021                COAP_ENCRYPTION(3)
Impressum