Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
COAP_ENCRYPTION(3)		 libcoap Manual 	      COAP_ENCRYPTION(3)

NAME
     coap_encryption, coap_dtls_cpsk_t, coap_dtls_spsk_t, coap_dtls_pki_t - Work
     with CoAP TLS/DTLS

SYNOPSIS
     #include <coap3/coap.h>

     struct coap_dtls_cpsk_t;

     struct coap_dtls_spsk_t;

     struct coap_dtls_pki_t;

     For   specific   (D)TLS   library	 support,   link   with  -lcoap-3-notls,
     -lcoap-3-gnutls, -lcoap-3-openssl,  -lcoap-3-mbedtls,  -lcoap-3-wolfssl  or
     -lcoap-3-tinydtls.  Otherwise, link with -lcoap-3 to get the default (D)TLS
     library support.

DESCRIPTION
     This man page focuses on setting up CoAP to use encryption.

     When the libcoap library was built, it will have been compiled using a spe-
     cific underlying TLS implementation type (e.g. OpenSSL, GnuTLS,  Mbed  TLS,
     wolfSSL, TinyDTLS or noTLS). When the libcoap library is linked into an ap-
     plication,  it is possible that the application needs to dynamically deter-
     mine whether DTLS or TLS is supported, what type of TLS implementation lib-
     coap was compiled with, as well as detect what is the version of  the  cur-
     rently loaded TLS library.

     NOTE:  If OpenSSL is being used, then the minimum supported OpenSSL library
     version is 1.1.0.

     NOTE: If GnuTLS is being used, then the minimum GnuTLS library  version  is
     3.3.0.

     NOTE:  If Mbed TLS is being used, then the minimum Mbed TLS library version
     is 2.7.10.

     NOTE: If wolfSSL is being used, then the minimum wolfSSL library version is
     5.2.0.

     NOTE: If GnuTLS is going to interoperate with TinyDTLS, then a minimum  re-
     vision  of  GnuTLS 3.5.5 which supports CCM algorithms is required by Tiny-
     DTLS as TinyDTLS currently only supports CCM.

     NOTE: If wolfSSL is going to interoperate with TinyDTLS, then  the  library
     needs	    to	       be	  build 	with	     ./configure
     CFLAGS="-DBUILD_TLS_PSK_WITH_AES_128_CCM" as TinyDTLS currently  only  sup-
     ports CCM.

     NOTE:  For  Raw Public Key support, GnuTLS library version must be 3.6.6 or
     later. For Raw Public Key support, wolfSSL library version must be 5.6.4 or
     later. TinyDTLS  only  supports  TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,  curve
     secp256r1	and  hash SHA-256. There currently is no OpenSSL or Mbed TLS RPK
     support (respective library limitations).

     Network traffic can be un-encrypted or encrypted with libcoap if  there  is
     an underlying TLS library.

     If TLS is going to be used for encrypting the network traffic, then the TLS
     information  for  Pre-Shared Keys (PSK), Public Key Infrastructure (PKI) or
     Raw Public Key (RPK) needs to be  configured  before  any	network  traffic
     starts  to  flow.	For  Servers, this has to be done before the Endpoint is
     created, for Clients, this is done during the Client Session set up.

     For Servers, all the encryption information is held internally by	the  TLS
     Context level and the CoAP Context level as the Server is listening for new
     incoming traffic based on the Endpoint definition. The TLS and CoAP session
     will  not get built until the new traffic starts, which is done by the lib-
     coap library, with the session having a reference count of 1.

     For Clients, all the encryption information will be held internally by  the
     TLS  Context  and/or  TLS	Session level and internally by the CoAP Session
     level.

     In principle the set-up sequence for CoAP Servers looks like

	 coap_new_context()
	 coap_context_set_pki_root_cas() - if the root CAs need to be updated and PKI
	 coap_context_set_pki() and/or coap_context_set_psk2() - if encryption is required
	 coap_new_endpoint()

     Multiple endpoints can be set up per Context,  each  listening  for  a  new
     traffic  flow with different TCP/UDP protocols, TLS protocols, port numbers
     etc. When a new traffic flow is started, then the CoAP library will  create
     and start a new server session.

     In principle the set-up sequence for CoAP Clients looks like

	 coap_new_context()
	 coap_context_set_pki_root_cas() - if the root CAs need to be updated and PKI
	 coap_new_client_session(), coap_new_client_session_pki() or coap_new_client_session_psk2()

     Multiple client sessions are supported per Context.

     Due  to  the nature of TLS, there are Callbacks that are invoked as the TLS
     session negotiates encryption algorithms, encryption keys etc. Where possi-
     ble, the CoAP layer handles all this automatically based on different  con-
     figuration    options    passed	in    by   the	 coap_context_set_pki(),
     coap_new_client_session_pki(),	    coap_context_set_psk2()	     and
     coap_new_client_session_psk2() functions.

PSK CLIENT INFORMATION
     For  Client PSK setup, the required information needs to be provided in the
     setup calls with optional application callbacks defined to update the Iden-
     tity and PSK. Initially, the Client  has  to  provide  an	Identity  and  a
     Pre-Shared Key.

     Libcoap  will  put  the Identity and Pre-Shared Key as appropriate into the
     TLS environment.

     SECTION: PSK Client: coap_dtls_cpsk_t

	 typedef struct coap_dtls_cpsk_t {
	   uint8_t version; /** Set to COAP_DTLS_CPSK_SETUP_VERSION
				to support the version of the struct */

	   /* Options to enable different TLS functionality in libcoap */
	   uint8_t ec_jpake;	    /* Set to 1 if DC-JPAKE is to be used.
				       Currently Mbed TLS only */

	   uint8_t use_cid;	    /* Set to 1 if DTLS Connection ID is to be used.
				       Currently Mbed TLS only */

	   /* Options to enable different TLS functionality in libcoap */
	   uint8_t reserved[5]; 	    /* Reserved - must be set to 0 for
					       future compatibility */

	   /** Identity Hint check callback function.
	    * If not NULL, is called when the Identity Hint (TLS1.2 or earlier) is
	    * provided by the server.
	    * The appropriate Identity and Pre-Shared Key to use can then be returned.
	    */
	   coap_dtls_ih_callback_t validate_ih_call_back;
	   void *ih_call_back_arg;  /* Passed in to the Identity Hint callback
				       function */

	   char* client_sni;	/*  If not NULL, SNI to use in client TLS setup.
				    Owned by the client app and must remain valid
				    during the call to coap_new_client_session_pki().
				    Note: Ignored if literal IPv4 or IPv6 address.
				    Note: Not supported by TinyDTLS. */

	   coap_dtls_cpsk_info_t psk_info;  /* Client PSK definition */
	 } coap_dtls_cpsk_t;

     More detailed explanation of the coap_dtls_cpsk_t structure follows.

     WARNING: For all the parameter definitions that are pointers to other loca-
     tions, these locations must remain valid during the lifetime of all the un-
     derlying TLS sessions that are, or will get created based on this PSK defi-
     nition.

     SECTION: PSK Client: coap_dtls_cpsk_t: Version

	 #define COAP_DTLS_CPSK_SETUP_VERSION 1 /**< Latest CPSK setup version */

     version is set to COAP_DTLS_CPSK_SETUP_VERSION. This will then  allow  sup-
     port  for	different  versions of the coap_dtls_cpsk_t structure in the fu-
     ture.

     SECTION: PSK Client: coap_dtls_cpsk_t: ec_jpake

     ec_jpake Set to 1 if EC-JPAKE negotiation is to  be  used.  Currently  only
     supported by suitably compiled Mbed TLS library.

     SECTION: PSK Client: coap_dtls_cpsk_t: use_cid

     use_cid Set to 1 if the DTLS Client is to try to used Connection-ID. Server
     is alwys enabled if support available.

     SECTION: PSK Client: coap_dtls_cpsk_t: Reserved

     reserved  All  must be set to 0. Future functionality updates will make use
     of these reserved definitions.

     SECTION: PSK Client: coap_dtls_cpsk_t: Identity Hint Callback

	 /**
	  * Identity Hint Validation callback that can be set up by
	  * coap_new_client_session_psk2().
	  * Invoked when libcoap has done the validation checks at the TLS level,
	  * but the application needs to check that the Identity Hint is allowed, and
	  * needs to use the appropriate PSK information for the (D)TLS session.
	  * Note: Identity Hint is not supported in (D)TLS1.3.
	  *
	  * @param hint  The server provided Identity Hint
	  * @param coap_session  The CoAP session associated with the Identity Hint
	  * @param arg	The same as was passed into coap_new_client_session_psk2()
	  *		in setup_data->ih_call_back_arg
	  *
	  * @return New coap_dtls_cpsk_info_t object or @c NULL on error.
	  */
	 typedef const coap_dtls_cpsk_info_t *(*coap_dtls_ih_callback_t)(
					 coap_str_const_t *hint,
					 coap_session_t *coap_session,
					 void *arg);

     validate_ih_call_back points to an application provided Identity Hint call-
     back function or NULL. The application can make use of this  Identity  Hint
     information  to  decide what Identity and Pre-Shared Key should be used for
     this session. The Callback returns the new  coap_dtls_cpsk_info_t	on  suc-
     cess, or NULL if the Identity Hint is unacceptable.

     NOTE:  The Server may not provide a hint, or a zero length hint to indicate
     there is no  hint.  In  this  case  the  initially  provided  Identity  and
     Pre-Shared Key should be used.

     ih_call_back_arg  points to a user defined set of data that will get passed
     in to the validate_ih_call_back() function's arg parameter and can be  used
     by that function. An example would be a set of Identity Hints that map into
     new Identity / Pre-Shared Key to use.

     SECTION: PSK Client: coap_dtls_cpsk_t: Subject Name Indicator (SNI) Defini-
     tion

     client_sni points to the SNI name that will be added in as a TLS extension,
     if  not  NULL. This typically is the DNS name of the server that the client
     is trying to contact. The server is then able to decide, based on the  name
     in  the  SNI  extension,  whether,  for  example,	a  different Hint and/or
     Pre-Shared Key is to be used.

     NOTE: Ignored if literal IPv4 or IPv6 address.

     NOTE: Not supported by TinyDTLS.

     SECTION: PSK Client: coap_dtls_cpsk_t: PSK Client Definitions

	 typedef struct coap_dtls_cpsk_info_t {
	   coap_bin_const_t identity; /* The Identity */
	   coap_bin_const_t key;      /* The Pre-Shared Key */
	 } coap_dtls_cpsk_info_t;

     identity defines the Identity to use.

     key defines the Pre-Shared Key to use

PSK SERVER INFORMATION
     For PSK setup, the required information needs to be provided in  the  setup
     calls  with  optional  application Callbacks defined to update the Identity
     Hint and Pre-SHared Key. Initially, the Server has to provided with an (op-
     tional) Identity Hint and a (required) Pre-Shared Key.

     Libcoap will put the Hint and Pre-Shared Key as appropriate  into	the  TLS
     environment.

     SECTION: PSK Server: coap_dtls_spsk_t

	 typedef struct coap_dtls_spsk_t {
	   uint8_t version; /* Set to COAP_DTLS_SPSK_SETUP_VERSION
				to support the version of the struct */

	   /* Options to enable different TLS functionality in libcoap */
	   uint8_t ec_jpake;	    /* Set to 1 if DC-JPAKE can be used.
				       Currently Mbed TLS only */

	   /* Options to enable different TLS functionality in libcoap */
	   uint8_t reserved[6]; 	    /* Reserved - must be set to 0 for
					       future compatibility */

	   /** Identity check callback function.
	    * If not @p NULL, is called when the Identity is provided by the client.
	    *  The appropriate Pre-Shared Key to use can then be returned.
	    */
	   coap_dtls_id_callback_t validate_id_call_back;
	   void *id_call_back_arg;  /* Passed in to the Identity callback function */

	   /** SNI check callback function.
	    * If not @p NULL, called if the SNI is not previously seen and exexuted
	    * prior to sending an Identity Hint back to the client so that the
	    * appropriate PSK information can be used based on the requesting SNI.
	    */
	   coap_dtls_psk_sni_callback_t validate_sni_call_back;
	   void *sni_call_back_arg;  /* Passed in to the SNI callback function */

	   coap_dtls_spsk_info_t psk_info;  /* Server PSK definition */
	 } coap_dtls_spsk_t;

     More detailed explanation of the coap_dtls_spsk_t structure follows.

     WARNING: For all the parameter definitions that are pointers to other loca-
     tions, these locations must remain valid during the lifetime of all the un-
     derlying TLS sessions that are, or will get created based on this PSK defi-
     nition.

     SECTION: PSK Server: coap_dtls_spsk_t: Version

	 #define COAP_DTLS_SPSK_SETUP_VERSION 1 /**< Latest SPSK setup version */

     version  is  set to COAP_DTLS_SPSK_SETUP_VERSION. This will then allow sup-
     port for different versions of the coap_dtls_spsk_t structure  in	the  fu-
     ture.

     SECTION: PSK Server: coap_dtls_spsk_t: ec_jpake

     ec_jpake  Set to 1 if EC-JPAKE negotiation can be used. Currently only sup-
     ported by suitably compiled Mbed TLS library.

     SECTION: PSK Server: coap_dtls_spsk_t: Reserved

     reserved All must be set to 0. Future functionality updates will  make  use
     of these reserved definitions.

     SECTION: PSK Server: coap_dtls_spsk_t: Identity Validation Callback

	 /**
	  * Identity Validation callback that can be set up by
	  * coap_context_set_psk2().
	  * Invoked when libcoap has done the validation checks at the TLS level,
	  * but the application needs to check that the Identity is allowed, and
	  * needs to use the appropriate Pre-Shared Key for the (D)TLS session.
	  *
	  * @param identity  The client provided Identity (should be NULL terminated)
	  * @param coap_session  The CoAP session associated with the Identity Hint
	  * @param arg	The same as was passed into coap_context_set_psk2()
	  *		in setup_data->id_call_back_arg
	  *
	  * @return New coap_bin_const_t Pre-Shared Key object or @c NULL on error.
	  */
	 typedef const coap_bin_const_t *(*coap_dtls_id_callback_t)(
					  coap_bin_const_t *identity,
					  coap_session_t *coap_session,
					  void *arg);

     WARNING:  If  both validate_id_call_back and validate_sni_call_back are de-
     fined, validate_id_call_back() is invoked	after  validate_sni_call_back(),
     and  so if the Pre-Shared Key is changed in validate_sni_call_back(), vali-
     date_id_call_back() needs to be sure that the appropriate Pre-Shared Key is
     provided.

     validate_id_call_back points to an application provided  Identity	callback
     function or NULL. The application can make use of this Identity information
     to  decide  what  PSK should be used for this session. The Callback returns
     the new coap_bin_const_t Pre-Shared Key on success, or NULL if the Identity
     is unacceptable.

     NOTE: The Client may be using a binary Identity that contains  an	embedded
     zero. However OpenSSL and GnuTLS do not currently support this.

     id_call_back_arg  points to a user defined set of data that will get passed
     in to the validate_id_call_back() function and can be used  by  that  func-
     tion.  An example would be a set of Identities that map into new Pre-Shared
     Keys to use.

     SECTION: PSK Server: coap_dtls_spsk_t: Subject Name Identifier (SNI)  Call-
     back

	 /**
	  * PSK SNI callback that can be set up by coap_context_set_psk2().
	  * Invoked when libcoap has done the validation checks at the TLS level,
	  * but the application needs to check that the SNI is allowed, and needs
	  * to use the appropriate PSK information for the (D)TLS session.
	  *
	  * @param sni	The client provided SNI
	  * @param coap_session  The CoAP session associated with the SNI
	  * @param arg	The same as was passed into coap_new_client_session_psk2()
	  *		in setup_data->sni_call_back_arg
	  *
	  * @return New coap_dtls_spsk_info_t object or @c NULL on error.
	  */
	 typedef const coap_dtls_spsk_info_t *(*coap_dtls_psk_sni_callback_t)(
					  const char *sni,
					  coap_session_t *coap_session,
					  void *arg);

     validate_sni_call_back  points  to  an  application  provided  SNI callback
     checking function or NULL. The application can make use of this SNI  infor-
     mation  to  decide  whether  the  SNI is valid, and hence what new Hint and
     Pre-Shared Key to use. Thus it is possible for the coap server to host mul-
     tiple domains with different Hints and PSKs allocated to each  SNI  domain.
     The  Callback  returns  a	coap_dtls_spsk_info_t  pointer	to  the Hint and
     Pre-Shared Key to use for this SNI, or NULL if the connection is to get re-
     jected. Libcoap remembers the association between a specific SNI  and  Hint
     Pre-Shared  Key  set  and	will only invoke this callback if the SNI is un-
     known.

     NOTE: Not supported by TinyDTLS.

     sni_call_back_arg points to a user defined set of data that will get passed
     in to the validate_sni_call_back() function and can be used by  that  func-
     tion.  An example would be a set of SNIs that are allowed with their match-
     ing Hint + Pre-Shared Key sets.

     SECTION: PSK Server: coap_dtls_spsk_t: PSK Information Definitions

	 typedef struct coap_dtls_spsk_info_t {
	   coap_bin_const_t hint; /* The identity hint to use */
	   coap_bin_const_t key;  /* The Pre-Shared Key to use */
	 } coap_dtls_spsk_info_t;

     identity defines the Identity Hint to use.

     key defines the Pre-Shared Key to use

PKI/RPK CLIENT AND SERVER INFORMATION
     For PKI or RPK setup, if the libcoap PKI/RPK configuration options  do  not
     handle  a specific requirement as defined by the available options, then an
     application defined Callback can  called  to  do  the  additional	specific
     checks.

     The information passed to this Application Callback will be the TLS session
     (as well the configuration information), but the structures containing this
     information  will	be different as they will be based on the underlying TLS
     library type. coap_get_tls_library_version() is provided to help here.

     Libcoap will add in the defined Certificate (or Public  Key),  Private  Key
     and  CA  Certificate  into  the TLS environment. The CA Certificate is also
     added in to the list of valid CAs for Certificate checking.

     The internal Callbacks (and optionally the Application Callback) will  then
     check  the required information as defined in the coap_dtls_pki_t described
     below.

     SECTION: PKI/RPK: coap_dtls_pki_t

	 typedef struct coap_dtls_pki_t {
	   uint8_t version;	       /* COAP_DTLS_PKI_SETUP_VERSION */

	   /* Options to enable different TLS functionality in libcoap */
	   uint8_t verify_peer_cert;	     /* 1 if peer cert is to be verified */
	   uint8_t check_common_ca;	     /* 1 if peer cert is to be signed by
					      * the same CA as the local cert */
	   uint8_t allow_self_signed;	     /* 1 if self-signed certs are allowed */
	   uint8_t allow_self_signed;	     /* 1 if self-signed certs are allowed.
					      * Ignored if check_common_ca set */
	   uint8_t allow_expired_certs;      /* 1 if expired certs are allowed */
	   uint8_t cert_chain_validation;    /* 1 if to check cert_chain_verify_depth */
	   uint8_t cert_chain_verify_depth;  /* recommended depth is 3 */
	   uint8_t check_cert_revocation;    /* 1 if revocation checks wanted */
	   uint8_t allow_no_crl;	     /* 1 ignore if CRL not there */
	   uint8_t allow_expired_crl;	     /* 1 if expired crl is allowed */
	   uint8_t allow_bad_md_hash;	     /* 1 if unsupported MD hashes are allowed */
	   uint8_t allow_short_rsa_length;   /* 1 if small RSA keysizes are allowed */
	   uint8_t is_rpk_not_cert;	     /* 1 is RPK instead of Public Certificate.
					      *   If set, PKI key format type cannot be
					      *   COAP_PKI_KEY_PEM */
	   uint8_t use_cid;		     /* 1 if DTLS Connection ID is to be
					      *   used (Client only, server always enabled)
					      *   if supported */
	   uint8_t reserved[2]; 	     /* Reserved - must be set to 0 for
						future compatibility */

	   /** CN check callback function
	    * If not NULL, is called when the TLS connection has passed the configured
	    * TLS options above for the application to verify if the CN is valid.
	    */
	   coap_dtls_cn_callback_t validate_cn_call_back;
	   void *cn_call_back_arg;  /* Passed in to the CN callback function */

	   /** SNI check callback function
	    * If not NULL, called if the SNI is not previously seen and prior to sending
	    * a certificate set back to the client so that the appropriate certificate
	    * set can be used based on the requesting SNI.
	    */
	   coap_dtls_sni_callback_t validate_sni_call_back;
	   void *sni_call_back_arg;  /* Passed in to the SNI callback function */

	   /** Additional Security callback handler that is invoked when libcoap has
	    * done the standard, defined validation checks at the TLS level,
	    * If not NULL, called from within the TLS Client Hello connection
	    * setup.
	    */
	   coap_dtls_security_setup_t additional_tls_setup_call_back;

	   char* client_sni;	   /* If not NULL, SNI to use in client TLS setup.
				      Owned by the client app and must remain valid
				      during the call to coap_new_client_session_pki().
				      Note: Ignored if literal IPv4 or IPv6 address. */

	   coap_dtls_key_t pki_key; /* PKI key definition */
	 } coap_dtls_pki_t;

     More detailed explanation of the coap_dtls_pki_t structure follows.

     WARNING: For all the parameter definitions that are pointers to other loca-
     tions, these locations must remain valid during the lifetime of all the un-
     derlying TLS sessions that are, or will get created based on  this  PKI/RPK
     definition.

     The  first parameter in each subsection enables/disables the functionality,
     the remaining parameter(s) control what happens when the  functionality  is
     enabled.

     SECTION: PKI/RPK: coap_dtls_pki_t: Version

	 #define COAP_DTLS_PKI_SETUP_VERSION 1

     version is set to COAP_DTLS_PKI_SETUP_VERSION. This will then allow support
     for different versions of the coap_dtls_pki_t structure in the future.

     SECTION: PKI/RPK: coap_dtls_pki_t: Peer Certificate Checking

     verify_peer_cert  Set to 1 to check that the peer's certificate is valid if
     provided, else 0. If not set, check_common_ca, allow_self_signed, allow_ex-
     pired_certs, cert_chain_validation, cert_chain_verify_depth, check_cert_re-
     vocation,	allow_no_crl,  allow_expired_crl,  allow_bad_md_hash   and   al-
     low_short_rsa_length settings are all ignored.

     check_common_ca  Set  to 1 to check that the CA that signed the peer's cer-
     tificate is the same CA that signed the local certificate else 0. If set to
     1 and verify_peer_cert is set to 1, then for the server, a  list  of  valid
     CAs  are sent to client. For the client, the logic will check that both the
     client and server certificates are signed by the same CA.

     allow_self_signed Set to 1 to allow the peer (or  any  certificate  in  the
     certificate  chain)  to be a self-signed certificate, else 0. If check_com-
     mon_ca is set, then a self-signed certificate will not be allowed.

     allow_expired_certs Set to 1 to allow certificates  that  have  either  ex-
     pired, or are not yet valid to be allowed, else 0.

     SECTION: PKI/RPK: coap_dtls_pki_t: Certificate Chain Validation

     cert_chain_validation  Set  to  1	to  check  that the certificate chain is
     valid, else 0.

     cert_chain_verify_depth Set to the chain depth that is to be checked.  This
     is the number of intermediate CAs in the chain. If set to 0, then there can
     be no intermediate CA in the chain.

     SECTION: PKI/RPK: coap_dtls_pki_t: Certificate Revocation

     check_cert_revocation  Set  to  1	to  check whether any certificate in the
     chain has been revoked, else 0.

     allow_no_crl Set to 1 to not check any certificate that  does  not  have  a
     CRL, else 0.

     allow_expired_crl	Set to 1 to allow an certificate that has an expired CRL
     definition to be valid, else 0.

     SECTION: PKI/RPK: coap_dtls_pki_t: Other

     allow_bad_md_hash Set to 1 if unsupported MD hashes are allowed, else 0.

     allow_short_rsa_length Set to 1 if small RSA keysizes are allowed, else 0.

     is_rpk_not_cert Set to 1 if the Certificate is actually a Raw  Public  Key.
     If  set, PKI key format type cannot be COAP_PKI_KEY_PEM. If set, check_com-
     mon_ca,  allow_self_signed,   allow_expired_certs,   cert_chain_validation,
     cert_chain_verify_depth,	check_cert_revocation,	allow_no_crl,  allow_ex-
     pired_crl, allow_bad_md_hash and allow_short_rsa_length  settings	are  all
     ignored.

     use_cid Set to 1 if the DTLS Client is to try to used Connection-ID. Server
     is alwys enabled if support available.

     SECTION: PKI/RPK: coap_dtls_pki_t: Reserved

     reserved  All  must be set to 0. Future functionality updates will make use
     of these reserved definitions.

     SECTION: PKI/RPK: coap_dtls_pki_t: Common Name (CN) Callback

	 #define COAP_DTLS_RPK_CERT_CN "RPK"

	 /**
	  * CN Validation callback that can be set up by coap_context_set_pki().
	  * Invoked when libcoap has done the validation checks at the TLS level,
	  * but the application needs to check that the CN is allowed.
	  * CN is the SubjectAltName in the cert, if not present, then the leftmost
	  * Common Name (CN) component of the subject name.
	  * NOTE: If using RPK, then the Public Key does not contain a CN, but the
	  * content of COAP_DTLS_RPK_CERT_CN is presented for the @p cn parameter.
	  *
	  * @param cn  The determined CN from the certificate
	  * @param asn1_public_cert  The ASN.1 encoded (DER) X.509 certificate
	  * @param asn1_length	The ASN.1 length
	  * @param session  The coap session associated with the certificate update
	  * @param depth  Depth in cert chain.	If 0, then client cert, else a CA
	  * @param validated  TLS can find no issues if 1
	  * @param arg	The same as was passed into coap_context_set_pki()
	  *		in setup_data->cn_call_back_arg
	  *
	  * @return 1 if accepted, else 0 if to be rejected
	  */
	 typedef int (*coap_dtls_cn_callback_t)(const char *cn,
		      const uint8_t *asn1_public_cert,
		      size_t asn1_length,
		      coap_session_t *session,
		      unsigned int depth,
		      int validated,
		      void *arg);

     validate_cn_call_back points to an application provided CN callback  check-
     ing  function  or NULL. The application can make use of this CN information
     to decide, for example, that the CN is valid coming from a particular peer.
     The Callback returns 1 on success,  0  if	the  TLS  connection  is  to  be
     aborted.

     cn_call_back_arg  points to a user defined set of data that will get passed
     in to the validate_cn_call_back() function and can be used  by  that  func-
     tion. An example would be a set of CNs that are allowed.

     SECTION: PKI/RPK: coap_dtls_pki_t: Subject Name Identifier (SNI) Callback

	 typedef struct coap_dtls_key_t {
	   coap_pki_key_t key_type;	     /* key format type */
	   union {
	     coap_pki_key_pem_t pem;	     /* for PEM file keys */
	     coap_pki_key_pem_buf_t pem_buf; /* for PEM memory keys */
	     coap_pki_key_asn1_t asn1;	     /* for ASN.1 (DER) memory keys */
	     coap_pki_key_pkcs11_t pkcs11;   /* for PKCS11 keys */
	     coap_pki_key_define_t define;   /* definable type keys */
	   } key;
	 } coap_dtls_key_t;

	 /**
	  * SNI Validation callback that can be set up by coap_context_set_pki().
	  * Invoked if the SNI is not previously seen and prior to sending a certificate
	  * set back to the client so that the appropriate certificate set can be used
	  * based on the requesting SNI.
	  *
	  * @param sni	The requested SNI
	  * @param arg	The same as was passed into coap_context_set_pki()
	  *		in setup_data->sni_call_back_arg
	  *
	  * @return new set of certificates to use, or NULL if SNI is to be rejected.
	  */
	 typedef coap_dtls_key_t *(*coap_dtls_sni_callback_t)(const char *sni,
		      void* arg);

     validate_sni_call_back  points  to  an  application  provided  SNI callback
     checking function or NULL. The application can make use of this SNI  infor-
     mation  to decide whether the SNI is valid, and what set of certificates to
     give to the client. Thus it is possible for the coap server to host  multi-
     ple domains with different certificates allocated to each domain. The Call-
     back  returns a pointer to the certificates to use for this SNI, or NULL if
     the connection it to get rejected. libcoap remembers  the	association  be-
     tween the SNI and Certificate set and will only invoke this callback if the
     SNI is unknown.

     sni_call_back_arg points to a user defined set of data that will get passed
     in  to  the validate_sni_call_back() function and can be used by that func-
     tion. An example would be a set of SNIs that are allowed with their  match-
     ing certificate sets.

     SECTION: PKI/RPK: coap_dtls_pki_t: Application Additional Setup Callback

	 /**
	  * Additional Security setup handler that can be set up by
	  * coap_context_set_pki().
	  * Invoked when libcoap has done the validation checks at the TLS level,
	  * but the application needs to do some additional checks/changes/updates.
	  *
	  * @param session The security session definition - e.g. SSL * for OpenSSL.
	  *		   This will be dependent on the underlying TLS library
	  *		   - see coap_get_tls_library_version()
	  * @param setup_data A structure containing setup data originally passed into
	  *		      coap_context_set_pki() or coap_new_client_session_pki().
	  * @return 1 if successful, else 0
	  */
	 typedef int (*coap_dtls_security_setup_t)(void *context, void* session,
						   coap_dtls_pki_t *setup_data);

     additional_tls_setup_call_back  points  to an application provided callback
     function that will do additional checking/changes/updates after libcoap has
     done all of the configured TLS setup checking, or NULL to do no  additional
     checking.

     SECTION: PKI/RPK: coap_dtls_pki_t: Subject Name Indicator (SNI) Definition

     client_sni points to the SNI name that will be added in as a TLS extension,
     or  set  NULL. This typically is the DNS name of the server that the client
     is trying to contact. This is only used by a  client  application	and  the
     server  is  then  able  to  decide, based on the name in the SNI extension,
     whether, for example, a different certificate should be provided.

     NOTE: Ignored if literal IPv4 or IPv6 address.

     SECTION: PKI/RPK: coap_dtls_pki_t: Key Type Definition

	 typedef enum coap_pki_key_t {
	   COAP_PKI_KEY_PEM,	 /* The PKI key type is PEM file */
	   COAP_PKI_KEY_ASN1,	 /* The PKI key type is ASN.1 (DER) buffer */
	   COAP_PKI_KEY_PEM_BUF, /* The PKI key type is PEM buffer */
	   COAP_PKI_KEY_PKCS11,  /* The PKI key type is PKCS11 (DER) */
	   COAP_PKI_KEY_DEFINE,  /* The individual PKI key types are Definable */
	 } coap_pki_key_t;

     key_type defines the format that the certificates / keys are  provided  in.
     This   can  be  COAP_PKI_KEY_PEM,	COAP_PKI_KEY_PEM_BUF,  COAP_PKI_KEY_ASN1
     COAP_PKI_KEY_PKCS11 or COAP_PKI_KEY_DEFINE.

     SECTION: PKI: coap_dtls_pki_t: PEM Key Definitions

	 typedef struct coap_pki_key_pem_t {
	   const char *ca_file;       /* File location of Common CA (and any
					 intermediates) in PEM format */
	   const char *public_cert;   /* File location of Public Cert */
	   const char *private_key;   /* File location of Private Key in PEM format */
	 } coap_pki_key_pem_t;

     key.pem.ca_file points to the CA File location on disk which will be in PEM
     format, or NULL. This file should only contain one CA (that has signed  the
     public  certificate)  as  this is passed from the server to the client when
     requesting the client's certificate. This certificate is  also  added  into
     the valid root CAs list if not already present.

     key.pem.public_cert points to the public certificate location on disk which
     will  be  in PEM format. This can be the entire certificate chain including
     the CAs.

     key.pem.private_key points to the private key location on disk  which  will
     be in PEM format. This file cannot be password protected.

     SECTION: PKI/RPK: coap_dtls_pki_t: PEM Memory Key Definitions

	 typedef struct coap_pki_key_pem_buf_t {
	   const uint8_t *ca_cert;     /* PEM buffer Common CA Cert */
	   const uint8_t *public_cert; /* PEM buffer Public Cert, or Public Key if RPK */
	   const uint8_t *private_key; /* PEM buffer Private Key */
					  If RPK and 'EC PRIVATE KEY' this can be used
					  for both the public_cert and private_key */
	   size_t ca_cert_len;	       /* PEM buffer CA Cert length */
	   size_t public_cert_len;     /* PEM buffer Public Cert length */
	   size_t private_key_len;     /* PEM buffer Private Key length */
	 } coap_pki_key_pem_buf_t;

     key.pem_buf.ca_cert  points  to  the CA location in memory which will be in
     PEM format, or NULL. This file should only contain one CA (that has  signed
     the  public  certificate)	as  this is passed from the server to the client
     when requesting the client's certificate. This certificate  is  also  added
     into the valid root CAs list if not already present.

     key.pem_buf.ca_cert_len is the length of the CA.

     key.pem_buf.public_cert  points to the public certificate (or public key if
     RPK) location in memory which will be in PEM format.

     key.pem_buf.public_cert_len is the length of the public certificate.

     key.pem_buf.private_key points to the private key location in memory  which
     will  be  in PEM format. This data cannot be password protected. If RPK and
     EC PRIVATE KEY this can be used for both the public_cert and private_key.

     key.pem_buf.private_key is the length of the private key.

     NOTE: The PEM buffer Certs and Key should be be NULL terminated strings for
     performance reasons (to save a potential buffer copy) and	the  length  in-
     clude this NULL terminator. It is not a requirement to have the NULL termi-
     nator though and the length must then reflect the actual data size.

     SECTION: PKI/RPK: coap_dtls_pki_t: ASN1 Key Definitions

	 typedef struct coap_pki_key_asn1_t {
	   const uint8_t *ca_cert;     /* ASN1 Common CA Certificate */
	   const uint8_t *public_cert; /* ASN1 (DER) Public Cert, or Public Key if RPK */
	   const uint8_t *private_key; /* ASN1 Private Key */
	   int ca_cert_len;	       /* ASN1 CA Certificate length */
	   int public_cert_len;        /* ASN1 Public Certificate length */
	   int private_key_len;        /* ASN1 Private Key length */
	   coap_asn1_privatekey_type_t private_key_type; /* Private Key Type
							    COAP_ASN1_PKEY_* */
	 } coap_pki_key_asn1_t;

	 typedef enum coap_asn1_privatekey_type_t {
	   COAP_ASN1_PKEY_NONE,
	   COAP_ASN1_PKEY_RSA,
	   COAP_ASN1_PKEY_RSA2,
	   COAP_ASN1_PKEY_DSA,
	   COAP_ASN1_PKEY_DSA1,
	   COAP_ASN1_PKEY_DSA2,
	   COAP_ASN1_PKEY_DSA3,
	   COAP_ASN1_PKEY_DSA4,
	   COAP_ASN1_PKEY_DH,
	   COAP_ASN1_PKEY_DHX,
	   COAP_ASN1_PKEY_EC,
	   COAP_ASN1_PKEY_HMAC,
	   COAP_ASN1_PKEY_CMAC,
	   COAP_ASN1_PKEY_TLS1_PRF,
	   COAP_ASN1_PKEY_HKDF
	 } coap_asn1_privatekey_type_t;

     key.asn1.ca_cert  points  to  a DER encoded ASN.1 definition of the CA Cer-
     tificate, or NULL. This certificate is passed from the server to the client
     when requesting the client's certificate. This certificate  is  also  added
     into the valid root CAs list if not already present.

     key.asn1.public_cert points to a DER encoded ASN.1 definition of the public
     certificate (or public key if RPK).

     key.asn1.private_key  points to DER encoded ASN.1 definition of the private
     key.

     key.asn1.ca_cert_len is the length of the DER encoded ASN.1  definition  of
     the CA Certificate.

     key.asn1.public_cert_len  is the length of the DER encoded ASN.1 definition
     of the public certificate.

     key.asn1.private_key_len is the length of the DER encoded ASN.1  definition
     of the private key.

     key.asn1.private_key_type is the encoding type of the DER encoded ASN.1 de-
     finition of the private key. This will be one of the COAP_ASN1_PKEY_* defi-
     nitions.

     SECTION: PKI: coap_dtls_pki_t: PKCS11 Key Definitions

	 typedef struct coap_pki_key_pkcs11_t {
	   const char *ca;	      /* pkcs11: URI for Common CA Certificate */
	   const char *public_cert;   /* pkcs11: URI for Public Cert */
	   const char *private_key;   /* pkcs11: URI for Private Key */
	   const char *user_pin;      /* User pin to access PKCS11.  If NULL, then
					 pin-value= parameter must be set in
					 pkcs11: URI as a query. */
	 } coap_pki_key_pkcs11_t;

     key.pkcs11.ca  is a pkcs11: URI for the CA certificate or NULL. This is for
     the CA (that has signed the public certificate) as this is passed from  the
     server  to  the  client when requesting the client's certificate. This cer-
     tificate is also added into the valid root CAs list if not already present.
     An example URI is pkcs11:pkcs11:token=My%20Token;id=%aa%bb%cc%dd  which  is
     for token My Token and (hex) id of aabbccdd.

     key.pkcs11.public_cert  is  a  pkcs11: URI for the Public Certificate which
     was signed by key.pkcs11.ca or NULL.

     key.pkcs11.private_key is a pkcs11: URI for the Private Key for the  public
     certificate defined by key.pkcs11.public_cert or NULL.

     key.pkcs11.user_pin  is  the  user pin used to unlock the token or NULL. If
     NULL, the pin can be defined on the other	pkcs11:  URI  entries  by  using
     pin-value=XXX    as    a	 query	 -   e.g.   pkcs11:pkcs11:token=My%20To-
     ken;id=%aa%bb%cc%dd?pin-value=XXX where XXX is the user pin.

     SECTION: PKI/RPK: coap_dtls_pki_t: Individual Cert/Key type Definitions

	 typedef struct coap_pki_key_define_t {
	   coap_const_char_ptr_t ca;	      /* define: Common CA Certificate */
	   coap_const_char_ptr_t public_cert; /* define: Public Cert */
	   coap_const_char_ptr_t private_key; /* define: Private Key */
	   size_t ca_len;	      /* define CA Cert length (if needed)*/
	   size_t public_cert_len;    /* define Public Cert length (if needed)*/
	   size_t private_key_len;    /* define Private Key length (if needed)*/
	   coap_pki_define_t ca_def;  /* define: Common CA type definition*/
	   coap_pki_define_t public_cert_def;  /* define: Public Cert type definition*/
	   coap_pki_define_t private_key_def;  /* define: Private Key type definition*/
	   coap_asn1_privatekey_type_t private_key_type; /* define: ASN1 Private Key
							    Type (if needed) */
	   const char *user_pin;      /* define: User pin to access type PKCS11.
					 If PKCS11 and NULL, then pin-value= parameter
					 must be set in pkcs11: URI as a query. */
	 } coap_pki_key_define_t;

	 typedef union {
	   const char *s_byte;	  /* signed char ptr */
	   const uint8_t *u_byte; /* unsigned char ptr */
	 } coap_const_char_ptr_t;

	 typedef enum coap_pki_define_t {
	   COAP_PKI_KEY_DEF_PEM = 0, /* The PKI key type is PEM file.
					Length ignored, NULL terminated. */
	   COAP_PKI_KEY_DEF_PEM_BUF, /* The PKI key type is PEM buffer.
					Length required. */
	   COAP_PKI_KEY_DEF_RPK_BUF, /* The PKI key type is RPK in buffer.
					Length required. */
	   COAP_PKI_KEY_DEF_DER,     /* The PKI key type is DER file.
					Length ignored, NULL terminated. */
	   COAP_PKI_KEY_DEF_DER_BUF, /* The PKI key type is DER buffer (ASN.1).
					Length required.
					Private Key Type required. */
	   COAP_PKI_KEY_DEF_PKCS11,  /* The PKI key type is PKCS11 (pkcs11:...).
					Length ignored, NULL terminated.
					User Pin optional. */
	   COAP_PKI_KEY_DEF_PKCS11_RPK, /* The PKI key type is PKCS11 w/ RPK (pkcs11:...).
					Length ignored, NULL terminated.
					User Pin optional. */
	   COAP_PKI_KEY_DEF_ENGINE,  /* The PKI key type is to be passed to ENGINE.
					Length ignored, NULL terminated.
					Supported by OpenSSL only */
	 } coap_pki_define_t;

     key.define.ca.[su]_char and possibly key.define.ca_len points to the CA lo-
     cation as defined by key.define.ca_def. key.define.ca.[su]_char can be NULL
     if there is no CA explicitely defined. This definition should only  contain
     one  CA (that has signed the public certificate) as this is passed from the
     server to the client when requesting the client's	certificate.  This  cer-
     tificate is also added into the valid root CAs list if not already present.

     key.define.public_cert.[su]_char  and  possibly  key.define.public_cert_len
     points to the public certificate location	as  defined  by  key.define.pub-
     lic_cert_def.

     key.define.private_key.[su]_char  and  possibly  key.define.privatr_key_len
     points  to  the  private  key  location  as  defined   by	 key.define.pri-
     vate_key_def.  This  information cannot be password protected, but for type
     PKCS11 key.define.user_pin can be defined. If type RPK and EC  PRIVATE  KEY
     this can be used for both the public_cert and private_key.

     key.define.ca_len	is  the optional length of the CA definition if required
     by key.define.ca_def.

     key.define.public_cert_len is the optional length of the public certificate
     definition if required by key.define.public_cert_def

     key.define.private_key_len is the optional length of the private key defin-
     ition if required by key.define.private_key_def.

     key.define.ca_def defines the type of the CA  entry,  one	of  coap_pki_de-
     fine_t.

     key.define.public_cert_def  defines  the type of the Public Cert/Key entry,
     one of coap_pki_define_t.

     key.define.private_key_def defines the type of the Private Key  entry,  one
     of coap_pki_define_t.

     key.define.private_key_type  is  the encoding type of the DER encoded ASN.1
     definition of the private key. This will be one of the COAP_ASN1_PKEY_* de-
     finitions.

     key.define.user_pin is the user pin used to unlock the  token  or	NULL  if
     type is PKCS11. If NULL, the pin can be defined on the pkcs11: URI entry by
     using   pin-value=XXX   as  a  query  -  e.g.  pkcs11:pkcs11:token=My%20To-
     ken;id=%aa%bb%cc%dd?pin-value=XXX where XXX is the user pin.

     NOTE: The PEM/ASN1/RPK buffer Certs and Key should be  be	NULL  terminated
     strings  for  performance reasons (to save a potential buffer copy) and the
     length include this NULL terminator. It is not a requirement  to  have  the
     NULL  terminator  though  and  the length must then reflect the actual data
     size.

EXAMPLES
     CoAP Server DTLS PKI Setup

	 #include <coap3/coap.h>

	 typedef struct valid_cns_t {
	   int count;
	   char **cn_list;
	 } valid_cns_t;

	 /**
	  * CN Validation callback that can be set up by coap_context_set_pki().
	  * Invoked when libcoap has done the validation checks at the TLS level,
	  * but the application needs to check that the CN is allowed.
	  * CN is the SubjectAltName in the cert, if not present, then the leftmost
	  * Common Name (CN) component of the subject name.
	  * NOTE: If using RPK, then the Public Key does not contain a CN, but "RPK"
	  * is presented for the cn parameter.
	  *
	  * @param cn  The determined CN from the certificate
	  * @param asn1_public_cert  The ASN.1 encoded (DER) X.509 certificate
	  * @param asn1_length	The ASN.1 length
	  * @param session  The coap session associated with the certificate update
	  * @param depth  Depth in cert chain.	If 0, then client cert, else a CA
	  * @param validated  TLS can find no issues if 1
	  * @param arg	The same as was passed into coap_context_set_pki()
	  *		in setup_data->cn_call_back_arg
	  *
	  * @return 1 if accepted, else 0 if to be rejected
	  */
	 static int
	 verify_cn_callback(const char *cn,
			    const uint8_t *asn1_public_cert,
			    size_t asn1_length,
			    coap_session_t *c_session,
			    unsigned depth,
			    int validated,
			    void *arg) {
	   valid_cns_t *valid_cn_list = (valid_cns_t *)arg;
	   int i;
	   /* Remove (void) definition if variable is used */
	   (void)asn1_public_cert;
	   (void)asn1_length;
	   (void)c_session;
	   (void)depth;
	   (void)validated;

	   /* Check that the CN is valid */
	   for (i = 0; i < valid_cn_list->count; i++) {
	     if (!strcasecmp(cn, valid_cn_list->cn_list[i])) {
	       return 1;
	     }
	   }
	   return 0;
	 }

	 typedef struct sni_def_t {
	   char *sni;
	   coap_dtls_key_t key;
	 } sni_def_t;

	 typedef struct valid_snis_t {
	   int count;
	   sni_def_t *sni_list;
	 } valid_snis_t;

	 /**
	  * SNI Validation callback that is set up by coap_context_set_pki().
	  * Invoked if the SNI is not previously seen and prior to sending a certificate
	  * set back to the client so that the appropriate certificate set can be used
	  * based on the requesting SNI.
	  *
	  * @param sni	The requested SNI
	  * @param arg	The same as was passed into coap_context_set_pki()
	  *		in setup_data->sni_call_back_arg
	  *
	  * @return new set of certificates to use, or NULL if SNI is to be rejected.
	  */
	 static coap_dtls_key_t *
	 verify_pki_sni_callback(const char *sni,
				 void *arg) {
	   valid_snis_t *valid_sni_list = (valid_snis_t *)arg;
	   int i;

	   /* Check that the SNI is valid */
	   for (i = 0; i < valid_sni_list->count; i++) {
	     if (!strcasecmp(sni, valid_sni_list->sni_list[i].sni)) {
	       return &valid_sni_list->sni_list[i].key;
	     }
	   }
	   return NULL;
	 }

	 /*
	  * Set up PKI encryption information
	  */
	 static coap_context_t *
	 setup_server_context_pki(const char *public_cert_file,
				  const char *private_key_file,
				  const char *ca_file,
				  valid_cns_t *valid_cn_list,
				  valid_snis_t *valid_sni_list) {
	   coap_endpoint_t *endpoint;
	   coap_address_t listen_addr;
	   coap_dtls_pki_t dtls_pki;
	   coap_context_t *context;

	   /* See coap_tls_library(3) */
	   if (!coap_dtls_is_supported())
	     return NULL;

	   /* See coap_context(3) */
	   context = coap_new_context(NULL);
	   if (!context)
	     return NULL;
	   /* See coap_block(3) */
	   coap_context_set_block_mode(context,
				       COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);

	   memset(&dtls_pki, 0, sizeof(dtls_pki));

	   dtls_pki.version		    = COAP_DTLS_PKI_SETUP_VERSION;
	   dtls_pki.verify_peer_cert	    = 1;
	   dtls_pki.check_common_ca	    = 1;
	   dtls_pki.allow_self_signed	    = 1;
	   dtls_pki.allow_expired_certs     = 1;
	   dtls_pki.cert_chain_validation   = 1;
	   dtls_pki.cert_chain_verify_depth = 1;
	   dtls_pki.check_cert_revocation   = 1;
	   dtls_pki.allow_no_crl	    = 1;
	   dtls_pki.allow_expired_crl	    = 1;
	   dtls_pki.allow_bad_md_hash	    = 0;
	   dtls_pki.allow_short_rsa_length  = 0;
	   dtls_pki.is_rpk_not_cert	    = 0; /* Set to 1 if RPK */
	   dtls_pki.validate_cn_call_back   = verify_cn_callback;
	   dtls_pki.cn_call_back_arg	    = valid_cn_list;
	   dtls_pki.validate_sni_call_back  = verify_pki_sni_callback;
	   dtls_pki.sni_call_back_arg	    = valid_sni_list;
	   dtls_pki.additional_tls_setup_call_back = NULL;
	   dtls_pki.client_sni		    = NULL;
	   dtls_pki.pki_key.key_type	    = COAP_PKI_KEY_PEM;
	   dtls_pki.pki_key.key.pem.ca_file = ca_file;
	   dtls_pki.pki_key.key.pem.public_cert = public_cert_file;
	   dtls_pki.pki_key.key.pem.private_key = private_key_file;

	   /* Alternative definition for dtls_pki.pki_key that does the
	    * same thing as above.
	    *
	    * dtls_pki.pki_key.key_type 		     = COAP_PKI_KEY_DEFINE;
	    * dtls_pki.pki_key.key.define.ca.s_byte	     = ca_file;
	    * dtls_pki.pki_key.key.define.public_cert.s_byte = public_cert_file;
	    * dtls_pki.pki_key.key.define.private_key.s_byte = private_key_file;
	    * dtls_pki.pki_key.key.define.ca_def	     = COAP_PKI_KEY_DEF_PEM;
	    * dtls_pki.pki_key.key.define.public_cert_def    = COAP_PKI_KEY_DEF_PEM;
	    * dtls_pki.pki_key.key.define.private_key_def    = COAP_PKI_KEY_DEF_PEM;
	    */

	   /* See coap_context(3) */
	   if (coap_context_set_pki(context, &dtls_pki)) {
	     coap_free_context(context);
	     return NULL;
	   }

	   coap_address_init(&listen_addr);
	   listen_addr.addr.sa.sa_family = AF_INET;
	   listen_addr.addr.sin.sin_port = htons(5684);

	   /* See coap_context(3) */
	   endpoint = coap_new_endpoint(context, &listen_addr, COAP_PROTO_DTLS);
	   if (!endpoint) {
	     coap_free_context(context);
	     return NULL;
	   }

	   /* Initialize resources - See coap_resource(3) init_resources() example */

	   return context;
	 }

     CoAP Server DTLS PSK Setup

	 #include <coap3/coap.h>

	 typedef struct id_def_t {
	   char *hint_match;
	   coap_bin_const_t id;
	   coap_bin_const_t key;
	 } id_def_t;

	 typedef struct valid_ids_t {
	   size_t count;
	   id_def_t *id_list;
	 } valid_ids_t;

	 /*
	  * PSK Identity Pre-Shared Key selection Callback function
	  */
	 static const coap_bin_const_t *
	 verify_id_callback(coap_bin_const_t *identity,
			    coap_session_t *c_session,
			    void *arg) {
	   valid_ids_t *valid_id_list = (valid_ids_t *)arg;
	   const coap_bin_const_t *s_psk_hint = coap_session_get_psk_hint(c_session);
	   size_t i;

	   /* Check that the Identity is valid */
	   for (i = 0; i < valid_id_list->count; i++) {
	     if (s_psk_hint &&
		 strcmp((const char *)s_psk_hint->s,
			valid_id_list->id_list[i].hint_match)) {
	       continue;
	     }
	     if (coap_binary_equal(identity, &valid_id_list->id_list[i].id)) {
	       return &valid_id_list->id_list[i].key;
	     }
	   }
	   return NULL;
	 }

	 typedef struct sni_psk_def_t {
	   char *sni;
	   coap_dtls_spsk_info_t psk_info;
	 } sni_psk_def_t;

	 typedef struct valid_psk_snis_t {
	   int count;
	   sni_psk_def_t *sni_list;
	 } valid_psk_snis_t;

	 /*
	  * PSK Subject Name Identifier (SNI) callback verifier
	  */
	 static const coap_dtls_spsk_info_t *
	 verify_psk_sni_callback(const char *sni,
				 coap_session_t *c_session,
				 void *arg) {
	   valid_psk_snis_t *valid_sni_list = (valid_psk_snis_t *)arg;
	   int i;
	   /* Remove (void) definition if variable is used */
	   (void)c_session;

	   /* Check that the SNI is valid */
	   for (i = 0; i < valid_sni_list->count; i++) {
	     if (!strcasecmp(sni, valid_sni_list->sni_list[i].sni)) {
	       return &valid_sni_list->sni_list[i].psk_info;
	     }
	   }
	   return NULL;
	 }

	 static coap_context_t *
	 setup_server_context_psk(const char *hint,
				  const uint8_t *key,
				  unsigned int key_len,
				  valid_ids_t *valid_id_list,
				  valid_psk_snis_t *valid_sni_list) {
	   coap_endpoint_t *endpoint;
	   coap_address_t listen_addr;
	   coap_context_t *context;
	   coap_dtls_spsk_t dtls_psk;

	   /* See coap_tls_library(3) */
	   if (!coap_dtls_is_supported())
	     return NULL;

	   context = coap_new_context(NULL);
	   if (!context)
	     return NULL;
	   /* See coap_block(3) */
	   coap_context_set_block_mode(context,
				       COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);

	   memset(&dtls_psk, 0, sizeof(dtls_psk));

	   /* see coap_encryption(3) */
	   dtls_psk.version		    = COAP_DTLS_SPSK_SETUP_VERSION;
	   dtls_psk.validate_id_call_back   = verify_id_callback;
	   dtls_psk.id_call_back_arg	    = valid_id_list;
	   dtls_psk.validate_sni_call_back  = verify_psk_sni_callback;
	   dtls_psk.sni_call_back_arg	    = valid_sni_list;
	   dtls_psk.psk_info.hint.s	    = (const uint8_t *)hint;
	   dtls_psk.psk_info.hint.length    = hint ? strlen(hint) : 0;
	   dtls_psk.psk_info.key.s	    = key;
	   dtls_psk.psk_info.key.length     = key_len;

	   if (coap_context_set_psk2(context, &dtls_psk)) {
	     coap_free_context(context);
	     return NULL;
	   }

	   coap_address_init(&listen_addr);
	   listen_addr.addr.sa.sa_family = AF_INET;
	   listen_addr.addr.sin.sin_port = htons(5684);

	   endpoint = coap_new_endpoint(context, &listen_addr, COAP_PROTO_DTLS);
	   if (!endpoint) {
	     coap_free_context(context);
	     return NULL;
	   }

	   /* Initialize resources - See coap_resource(3) init_resources() example */

	   return context;
	 }

     CoAP Client DTLS PSK Setup

	 #include <coap3/coap.h>

	 #include <stdio.h>

	 #ifndef min
	 #define min(a,b) ((a) < (b) ? (a) : (b))
	 #endif

	 static const coap_dtls_cpsk_info_t *
	 verify_ih_callback(coap_str_const_t *hint,
			    coap_session_t *c_session,
			    void *arg) {
	   coap_dtls_cpsk_info_t *psk_info = (coap_dtls_cpsk_info_t *)arg;
	   /* Remove (void) definition if variable is used */
	   (void)c_session;

	   coap_log_info("Identity Hint '%.*s' provided\n", (int)hint->length, hint->s);

	   /* Just use the defined information for now as passed in by arg */
	   return psk_info;
	 }

	 static coap_dtls_cpsk_t dtls_psk;
	 static char client_sni[256];

	 static coap_session_t *
	 setup_client_session_psk(const char *host,
				  struct in_addr ip_address,
				  const uint8_t *identity,
				  unsigned int identity_len,
				  const uint8_t *key,
				  unsigned int key_len) {
	   coap_session_t *session;
	   coap_address_t server;
	   /* See coap_context(3) */
	   coap_context_t *context = coap_new_context(NULL);

	   if (!context)
	     return NULL;
	   /* See coap_block(3) */
	   coap_context_set_block_mode(context,
				       COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);

	   coap_address_init(&server);
	   server.addr.sa.sa_family = AF_INET;
	   server.addr.sin.sin_addr = ip_address;
	   server.addr.sin.sin_port = htons(5684);

	   /* See coap_encryption(3) */
	   memset(&dtls_psk, 0, sizeof(dtls_psk));
	   dtls_psk.version = COAP_DTLS_CPSK_SETUP_VERSION;
	   dtls_psk.validate_ih_call_back = verify_ih_callback;
	   dtls_psk.ih_call_back_arg = &dtls_psk.psk_info;
	   snprintf(client_sni, sizeof(client_sni), "%s", host);
	   dtls_psk.client_sni = client_sni;
	   dtls_psk.psk_info.identity.s = identity;
	   dtls_psk.psk_info.identity.length = identity_len;
	   dtls_psk.psk_info.key.s = key;
	   dtls_psk.psk_info.key.length = key_len;
	   session = coap_new_client_session_psk2(context, NULL, &server,
						  COAP_PROTO_DTLS, &dtls_psk);
	   if (!session) {
	     coap_free_context(context);
	     return NULL;
	   }
	   /* The context is in session->context */
	   return session;
	 }

SEE ALSO
     coap_block(3),  coap_context(3),  coap_resource(3),   coap_session(3)   and
     coap_tls_library(3)

FURTHER INFORMATION
     See

     "RFC7252: The Constrained Application Protocol (CoAP)"

     for further information.

BUGS
     Please  raise  an issue on GitHub at https://github.com/obgm/libcoap/issues
     to report any bugs.

     Please raise a Pull Request  at  https://github.com/obgm/libcoap/pulls  for
     any fixes.

AUTHORS
     The libcoap project <libcoap-developers@lists.sourceforge.net>

coap_encryption 4.3.5		   08/02/2026		      COAP_ENCRYPTION(3)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=coap_encryption&sektion=3&manpath=FreeBSD+Ports+15.1.quarterly>

home | help