![]() |
![]()
| ![]() |
![]()
NAMEcoap_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. DESCRIPTIONThis man page focuses on setting up CoAP to use encryption. When the libcoap library was built, it will have been compiled using a specific underlying TLS implementation type (e.g. OpenSSL, GnuTLS, Mbed TLS, wolfSSL, TinyDTLS or noTLS). When the libcoap library is linked into an application, it is possible that the application needs to dynamically determine whether DTLS or TLS is supported, what type of TLS implementation libcoap was compiled with, as well as detect what is the version of the currently 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 revision of GnuTLS 3.5.5 which supports CCM algorithms is required by TinyDTLS 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 supports 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 libcoap 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 possible, the CoAP layer handles all this automatically based on different configuration 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 INFORMATIONFor Client PSK setup, the required information needs to be provided in the setup calls with optional application callbacks defined to update the Identity 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 { More detailed explanation of the coap_dtls_cpsk_t structure follows. WARNING: For all the parameter definitions that are pointers to other locations, these locations must remain valid during the lifetime of all the underlying TLS sessions that are, or will get created based on this PSK definition. 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 support for different versions of the coap_dtls_cpsk_t structure in the future. 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 /** validate_ih_call_back points to an application provided Identity Hint callback 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 success, 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) Definition 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 { identity defines the Identity to use. key defines the Pre-Shared Key to use PSK SERVER INFORMATIONFor 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 (optional) 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 { More detailed explanation of the coap_dtls_spsk_t structure follows. WARNING: For all the parameter definitions that are pointers to other locations, these locations must remain valid during the lifetime of all the underlying TLS sessions that are, or will get created based on this PSK definition. 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 support for different versions of the coap_dtls_spsk_t structure in the future. SECTION: PSK Server: coap_dtls_spsk_t: ec_jpake ec_jpake Set to 1 if EC-JPAKE negotiation can be used. Currently only supported 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 /** WARNING: If both validate_id_call_back and validate_sni_call_back are defined, 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(), validate_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 function. 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) Callback /** validate_sni_call_back points to an application provided SNI callback checking function or NULL. The application can make use of this SNI information 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 multiple 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 rejected. Libcoap remembers the association between a specific SNI and Hint Pre-Shared Key set and will only invoke this callback if the SNI is unknown. 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 function. An example would be a set of SNIs that are allowed with their matching Hint + Pre-Shared Key sets. SECTION: PSK Server: coap_dtls_spsk_t: PSK Information Definitions typedef struct 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 INFORMATIONFor 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 { More detailed explanation of the coap_dtls_pki_t structure follows. WARNING: For all the parameter definitions that are pointers to other locations, these locations must remain valid during the lifetime of all the underlying 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_expired_certs, cert_chain_validation, cert_chain_verify_depth, check_cert_revocation, allow_no_crl, allow_expired_crl, allow_bad_md_hash and allow_short_rsa_length settings are all ignored. check_common_ca Set to 1 to check that the CA that signed the peer’s certificate 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_common_ca is set, then a self-signed certificate will not be allowed. allow_expired_certs Set to 1 to allow certificates that have either expired, 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_common_ca, allow_self_signed, allow_expired_certs, cert_chain_validation, cert_chain_verify_depth, check_cert_revocation, allow_no_crl, allow_expired_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" /** validate_cn_call_back points to an application provided CN callback checking 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 function. 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 { validate_sni_call_back points to an application provided SNI callback checking function or NULL. The application can make use of this SNI information 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 multiple domains with different certificates allocated to each domain. The Callback returns a pointer to the certificates to use for this SNI, or NULL if the connection it to get rejected. libcoap remembers the association between 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 function. An example would be a set of SNIs that are allowed with their matching certificate sets. SECTION: PKI/RPK: coap_dtls_pki_t: Application Additional Setup Callback /** 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 { 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 { 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 { 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 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. SECTION: PKI/RPK: coap_dtls_pki_t: ASN1 Key Definitions typedef struct coap_pki_key_asn1_t { key.asn1.ca_cert points to a DER encoded ASN.1 definition of the CA Certificate, 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 definition of the private key. This will be one of the COAP_ASN1_PKEY_* definitions. SECTION: PKI: coap_dtls_pki_t: PKCS11 Key Definitions typedef struct 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 certificate 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%20Token;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 { key.define.ca.[su]_char and possibly key.define.ca_len points to the CA location 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 certificate 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.public_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.private_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 definition if required by key.define.private_key_def. key.define.ca_def defines the type of the CA entry, one of coap_pki_define_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_* definitions. 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%20Token;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. EXAMPLESCoAP Server DTLS PKI Setup #include <coap3/coap.h> typedef struct valid_cns_t { CoAP Server DTLS PSK Setup #include <coap3/coap.h> typedef struct id_def_t { 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, SEE ALSOcoap_block(3), coap_context(3), coap_resource(3), coap_session(3) and coap_tls_library(3) FURTHER INFORMATIONSee "RFC7252: The Constrained Application Protocol (CoAP)" for further information. BUGSPlease 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. AUTHORSThe libcoap project <libcoap-developers@lists.sourceforge.net>
|