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