• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * coap_dtls.h -- (Datagram) Transport Layer Support for libcoap
3  *
4  * Copyright (C) 2016 Olaf Bergmann <bergmann@tzi.org>
5  * Copyright (C) 2017 Jean-Claude Michelou <jcm@spinetix.com>
6  *
7  * SPDX-License-Identifier: BSD-2-Clause
8  *
9  * This file is part of the CoAP library libcoap. Please see README for terms
10  * of use.
11  */
12 
13 #ifndef COAP_DTLS_H_
14 #define COAP_DTLS_H_
15 
16 #include "coap_time.h"
17 #include "str.h"
18 
19 /**
20  * @defgroup dtls DTLS Support
21  * API functions for interfacing with DTLS libraries.
22  * @{
23  */
24 
25 typedef struct coap_dtls_pki_t coap_dtls_pki_t;
26 
27 #ifndef COAP_DTLS_HINT_LENGTH
28 #define COAP_DTLS_HINT_LENGTH 128
29 #endif
30 
31 typedef enum coap_dtls_role_t {
32   COAP_DTLS_ROLE_CLIENT, /**< Internal function invoked for client */
33   COAP_DTLS_ROLE_SERVER  /**< Internal function invoked for server */
34 } coap_dtls_role_t;
35 
36 #define COAP_DTLS_RPK_CERT_CN "RPK"
37 
38 /**
39  * Check whether DTLS is available.
40  *
41  * @return @c 1 if support for DTLS is enabled, or @c 0 otherwise.
42  */
43 int coap_dtls_is_supported(void);
44 
45 /**
46  * Check whether TLS is available.
47  *
48  * @return @c 1 if support for TLS is enabled, or @c 0 otherwise.
49  */
50 int coap_tls_is_supported(void);
51 
52 typedef enum coap_tls_library_t {
53   COAP_TLS_LIBRARY_NOTLS = 0, /**< No DTLS library */
54   COAP_TLS_LIBRARY_TINYDTLS,  /**< Using TinyDTLS library */
55   COAP_TLS_LIBRARY_OPENSSL,   /**< Using OpenSSL library */
56   COAP_TLS_LIBRARY_GNUTLS,    /**< Using GnuTLS library */
57   COAP_TLS_LIBRARY_MBEDTLS,   /**< Using Mbed TLS library */
58 } coap_tls_library_t;
59 
60 /**
61  * The structure used for returning the underlying (D)TLS library
62  * information.
63  */
64 typedef struct coap_tls_version_t {
65   uint64_t version; /**< (D)TLS runtime Library Version */
66   coap_tls_library_t type; /**< Library type. One of COAP_TLS_LIBRARY_* */
67   uint64_t built_version; /**< (D)TLS Built against Library Version */
68 } coap_tls_version_t;
69 
70 /**
71  * Determine the type and version of the underlying (D)TLS library.
72  *
73  * @return The version and type of library libcoap was compiled against.
74  */
75 coap_tls_version_t *coap_get_tls_library_version(void);
76 
77 /**
78  * Additional Security setup handler that can be set up by
79  * coap_context_set_pki().
80  * Invoked when libcoap has done the validation checks at the TLS level,
81  * but the application needs to do some additional checks/changes/updates.
82  *
83  * @param tls_session The security session definition - e.g. SSL * for OpenSSL.
84  *                    NULL if server callback.
85  *                    This will be dependent on the underlying TLS library -
86  *                    see coap_get_tls_library_version()
87  * @param setup_data A structure containing setup data originally passed into
88  *                   coap_context_set_pki() or coap_new_client_session_pki().
89  *
90  * @return @c 1 if successful, else @c 0.
91  */
92 typedef int (*coap_dtls_security_setup_t)(void* tls_session,
93                                           coap_dtls_pki_t *setup_data);
94 
95 /**
96  * CN Validation callback that can be set up by coap_context_set_pki().
97  * Invoked when libcoap has done the validation checks at the TLS level,
98  * but the application needs to check that the CN is allowed.
99  * CN is the SubjectAltName in the cert, if not present, then the leftmost
100  * Common Name (CN) component of the subject name.
101  * NOTE: If using RPK, then the Public Key does not contain a CN, but the
102  * content of COAP_DTLS_RPK_CERT_CN is presented for the @p cn parameter.
103  *
104  * @param cn  The determined CN from the certificate
105  * @param asn1_public_cert  The ASN.1 DER encoded X.509 certificate
106  * @param asn1_length  The ASN.1 length
107  * @param coap_session  The CoAP session associated with the certificate update
108  * @param depth  Depth in cert chain.  If 0, then client cert, else a CA
109  * @param validated  TLS layer can find no issues if 1
110  * @param arg  The same as was passed into coap_context_set_pki()
111  *             in setup_data->cn_call_back_arg
112  *
113  * @return @c 1 if accepted, else @c 0 if to be rejected.
114  */
115 typedef int (*coap_dtls_cn_callback_t)(const char *cn,
116              const uint8_t *asn1_public_cert,
117              size_t asn1_length,
118              coap_session_t *coap_session,
119              unsigned int depth,
120              int validated,
121              void *arg);
122 
123 /**
124  * The enum used for determining the provided PKI ASN.1 (DER) Private Key
125  * formats.
126  */
127 typedef enum coap_asn1_privatekey_type_t {
128   COAP_ASN1_PKEY_NONE,     /**< NONE */
129   COAP_ASN1_PKEY_RSA,      /**< RSA type */
130   COAP_ASN1_PKEY_RSA2,     /**< RSA2 type */
131   COAP_ASN1_PKEY_DSA,      /**< DSA type */
132   COAP_ASN1_PKEY_DSA1,     /**< DSA1 type */
133   COAP_ASN1_PKEY_DSA2,     /**< DSA2 type */
134   COAP_ASN1_PKEY_DSA3,     /**< DSA3 type */
135   COAP_ASN1_PKEY_DSA4,     /**< DSA4 type */
136   COAP_ASN1_PKEY_DH,       /**< DH type */
137   COAP_ASN1_PKEY_DHX,      /**< DHX type */
138   COAP_ASN1_PKEY_EC,       /**< EC type */
139   COAP_ASN1_PKEY_HMAC,     /**< HMAC type */
140   COAP_ASN1_PKEY_CMAC,     /**< CMAC type */
141   COAP_ASN1_PKEY_TLS1_PRF, /**< TLS1_PRF type */
142   COAP_ASN1_PKEY_HKDF      /**< HKDF type */
143 } coap_asn1_privatekey_type_t;
144 
145 /**
146  * The enum used for determining the PKI key formats.
147  */
148 typedef enum coap_pki_key_t {
149   COAP_PKI_KEY_PEM = 0,        /**< The PKI key type is PEM file */
150   COAP_PKI_KEY_ASN1,           /**< The PKI key type is ASN.1 (DER) buffer */
151   COAP_PKI_KEY_PEM_BUF,        /**< The PKI key type is PEM buffer */
152   COAP_PKI_KEY_PKCS11,         /**< The PKI key type is PKCS11 (DER) */
153 } coap_pki_key_t;
154 
155 /**
156  * The structure that holds the PKI PEM definitions.
157  */
158 typedef struct coap_pki_key_pem_t {
159   const char *ca_file;       /**< File location of Common CA in PEM format */
160   const char *public_cert;   /**< File location of Public Cert */
161   const char *private_key;   /**< File location of Private Key in PEM format */
162 } coap_pki_key_pem_t;
163 
164 /**
165  * The structure that holds the PKI PEM buffer definitions.
166  * The certificates and private key data must be in PEM format.
167  *
168  * Note:  The Certs and Key should be NULL terminated strings for
169  * performance reasons (to save a potential buffer copy) and the length include
170  * this NULL terminator. It is not a requirement to have the NULL terminator
171  * though and the length must then reflect the actual data size.
172  */
173 typedef struct coap_pki_key_pem_buf_t {
174   const uint8_t *ca_cert;     /**< PEM buffer Common CA Cert */
175   const uint8_t *public_cert; /**< PEM buffer Public Cert, or Public Key if RPK */
176   const uint8_t *private_key; /**< PEM buffer Private Key
177                                   If RPK and 'EC PRIVATE KEY' this can be used
178                                   for both the public_cert and private_key */
179   size_t ca_cert_len;         /**< PEM buffer CA Cert length */
180   size_t public_cert_len;     /**< PEM buffer Public Cert length */
181   size_t private_key_len;     /**< PEM buffer Private Key length */
182 } coap_pki_key_pem_buf_t;
183 
184 /**
185  * The structure that holds the PKI ASN.1 (DER) definitions.
186  */
187 typedef struct coap_pki_key_asn1_t {
188   const uint8_t *ca_cert;     /**< ASN1 (DER) Common CA Cert */
189   const uint8_t *public_cert; /**< ASN1 (DER) Public Cert, or Public Key if RPK */
190   const uint8_t *private_key; /**< ASN1 (DER) Private Key */
191   size_t ca_cert_len;         /**< ASN1 CA Cert length */
192   size_t public_cert_len;     /**< ASN1 Public Cert length */
193   size_t private_key_len;     /**< ASN1 Private Key length */
194   coap_asn1_privatekey_type_t private_key_type; /**< Private Key Type */
195 } coap_pki_key_asn1_t;
196 
197 /**
198  * The structure that holds the PKI PKCS11 definitions.
199  */
200 typedef struct coap_pki_key_pkcs11_t {
201   const char *ca;            /**< pkcs11: URI for Common CA Certificate */
202   const char *public_cert;   /**< pkcs11: URI for Public Cert */
203   const char *private_key;   /**< pkcs11: URI for Private Key */
204   const char *user_pin;      /**< User pin to access PKCS11.  If NULL, then
205                                   pin-value= parameter must be set in
206                                   pkcs11: URI as a query. */
207 } coap_pki_key_pkcs11_t;
208 
209 /**
210  * The structure that holds the PKI key information.
211  */
212 typedef struct coap_dtls_key_t {
213   coap_pki_key_t key_type;          /**< key format type */
214   union {
215     coap_pki_key_pem_t pem;          /**< for PEM file keys */
216     coap_pki_key_pem_buf_t pem_buf;  /**< for PEM memory keys */
217     coap_pki_key_asn1_t asn1;        /**< for ASN.1 (DER) memory keys */
218     coap_pki_key_pkcs11_t pkcs11;    /**< for PKCS11 keys */
219   } key;
220 } coap_dtls_key_t;
221 
222 /**
223  * Server Name Indication (SNI) Validation callback that can be set up by
224  * coap_context_set_pki().
225  * Invoked if the SNI is not previously seen and prior to sending a certificate
226  * set back to the client so that the appropriate certificate set can be used
227  * based on the requesting SNI.
228  *
229  * @param sni  The requested SNI
230  * @param arg  The same as was passed into coap_context_set_pki()
231  *             in setup_data->sni_call_back_arg
232  *
233  * @return New set of certificates to use, or @c NULL if SNI is to be rejected.
234  */
235 typedef coap_dtls_key_t *(*coap_dtls_pki_sni_callback_t)(const char *sni,
236              void* arg);
237 
238 
239 #define COAP_DTLS_PKI_SETUP_VERSION 1 /**< Latest PKI setup version */
240 
241 /**
242  * The structure used for defining the PKI setup data to be used.
243  */
244 struct coap_dtls_pki_t {
245   uint8_t version; /** Set to COAP_DTLS_PKI_SETUP_VERSION
246                        to support this version of the struct */
247 
248   /* Options to enable different TLS functionality in libcoap */
249   uint8_t verify_peer_cert;        /**< 1 if peer cert is to be verified */
250   uint8_t check_common_ca;         /**< 1 if peer cert is to be signed by
251                                     * the same CA as the local cert */
252   uint8_t allow_self_signed;       /**< 1 if self-signed certs are allowed.
253                                     *     Ignored if check_common_ca set */
254   uint8_t allow_expired_certs;     /**< 1 if expired certs are allowed */
255   uint8_t cert_chain_validation;   /**< 1 if to check cert_chain_verify_depth */
256   uint8_t cert_chain_verify_depth; /**< recommended depth is 3 */
257   uint8_t check_cert_revocation;   /**< 1 if revocation checks wanted */
258   uint8_t allow_no_crl;            /**< 1 ignore if CRL not there */
259   uint8_t allow_expired_crl;       /**< 1 if expired crl is allowed */
260   uint8_t allow_bad_md_hash;      /**< 1 if unsupported MD hashes are allowed */
261   uint8_t allow_short_rsa_length; /**< 1 if small RSA keysizes are allowed */
262   uint8_t is_rpk_not_cert;        /**< 1 is RPK instead of Public Certificate.
263                                    *     If set, PKI key format type cannot be
264                                    *     COAP_PKI_KEY_PEM */
265   uint8_t reserved[3];             /**< Reserved - must be set to 0 for
266                                         future compatibility */
267                                    /* Size of 3 chosen to align to next
268                                     * parameter, so if newly defined option
269                                     * it can use one of the reserverd slot so
270                                     * no need to change
271                                     * COAP_DTLS_PKI_SETUP_VERSION and just
272                                     * decrement the reserved[] count.
273                                     */
274 
275   /** CN check callback function.
276    * If not NULL, is called when the TLS connection has passed the configured
277    * TLS options above for the application to verify if the CN is valid.
278    */
279   coap_dtls_cn_callback_t validate_cn_call_back;
280   void *cn_call_back_arg;  /**< Passed in to the CN callback function */
281 
282   /** SNI check callback function.
283    * If not @p NULL, called if the SNI is not previously seen and prior to
284    * sending a certificate set back to the client so that the appropriate
285    * certificate set can be used based on the requesting SNI.
286    */
287   coap_dtls_pki_sni_callback_t validate_sni_call_back;
288   void *sni_call_back_arg;  /**< Passed in to the sni callback function */
289 
290   /** Additional Security callback handler that is invoked when libcoap has
291    * done the standard, defined validation checks at the TLS level,
292    * If not @p NULL, called from within the TLS Client Hello connection
293    * setup.
294    */
295   coap_dtls_security_setup_t additional_tls_setup_call_back;
296 
297   char* client_sni;    /**<  If not NULL, SNI to use in client TLS setup.
298                              Owned by the client app and must remain valid
299                              during the call to coap_new_client_session_pki() */
300 
301   coap_dtls_key_t pki_key;  /**< PKI key definition */
302 };
303 
304 /**
305  * The structure that holds the Client PSK information.
306  */
307 typedef struct coap_dtls_cpsk_info_t {
308   coap_bin_const_t identity;
309   coap_bin_const_t key;
310 } coap_dtls_cpsk_info_t;
311 
312 /**
313  * Identity Hint Validation callback that can be set up by
314  * coap_new_client_session_psk2().
315  * Invoked when libcoap has done the validation checks at the TLS level,
316  * but the application needs to check that the Identity Hint is allowed,
317  * and thus needs to use the appropriate PSK information for the Identity
318  * Hint for the (D)TLS session.
319  * Note: Identity Hint is not supported in (D)TLS1.3.
320  *
321  * @param hint  The server provided Identity Hint
322  * @param coap_session  The CoAP session associated with the Identity Hint
323  * @param arg  The same as was passed into coap_new_client_session_psk2()
324  *             in setup_data->ih_call_back_arg
325  *
326  * @return New coap_dtls_cpsk_info_t object or @c NULL on error.
327  */
328 typedef const coap_dtls_cpsk_info_t *(*coap_dtls_ih_callback_t)(
329                                       coap_str_const_t *hint,
330                                       coap_session_t *coap_session,
331                                       void *arg);
332 
333 #define COAP_DTLS_CPSK_SETUP_VERSION 1 /**< Latest CPSK setup version */
334 
335 /**
336  * The structure used for defining the Client PSK setup data to be used.
337  */
338 typedef struct coap_dtls_cpsk_t {
339   uint8_t version; /** Set to COAP_DTLS_CPSK_SETUP_VERSION
340                        to support this version of the struct */
341 
342   /* Options to enable different TLS functionality in libcoap */
343   uint8_t reserved[7];             /**< Reserved - must be set to 0 for
344                                         future compatibility */
345                                    /* Size of 7 chosen to align to next
346                                     * parameter, so if newly defined option
347                                     * it can use one of the reserverd slot so
348                                     * no need to change
349                                     * COAP_DTLS_CPSK_SETUP_VERSION and just
350                                     * decrement the reserved[] count.
351                                     */
352 
353   /** Identity Hint check callback function.
354    * If not NULL, is called when the Identity Hint (TLS1.2 or earlier) is
355    * provided by the server.
356    * The appropriate Identity and Pre-shared Key to use can then be returned.
357    */
358   coap_dtls_ih_callback_t validate_ih_call_back;
359   void *ih_call_back_arg;  /**< Passed in to the Identity Hint callback
360                                 function */
361 
362   char* client_sni;    /**< If not NULL, SNI to use in client TLS setup.
363                             Owned by the client app and must remain valid
364                             during the call to coap_new_client_session_psk2()
365                             Note: Not supported by TinyDTLS. */
366 
367   coap_dtls_cpsk_info_t psk_info;  /**< Client PSK definition */
368 } coap_dtls_cpsk_t;
369 
370 /**
371  * The structure that holds the Server Pre-Shared Key and Identity
372  * Hint information.
373  */
374 typedef struct coap_dtls_spsk_info_t {
375   coap_bin_const_t hint;
376   coap_bin_const_t key;
377 } coap_dtls_spsk_info_t;
378 
379 
380 /**
381  * Identity Validation callback that can be set up by
382  * coap_context_set_psk2().
383  * Invoked when libcoap has done the validation checks at the TLS level,
384  * but the application needs to check that the Identity is allowed,
385  * and needs to use the appropriate Pre-Shared Key for the (D)TLS session.
386  *
387  * @param identity  The client provided Identity
388  * @param coap_session  The CoAP session associated with the Identity Hint
389  * @param arg  The value as passed into coap_context_set_psk2()
390  *             in setup_data->id_call_back_arg
391  *
392  * @return New coap_bin_const_t object containing the Pre-Shared Key or
393            @c NULL on error.
394  *         Note: This information will be duplicated into an internal
395  *               structure.
396  */
397 typedef const coap_bin_const_t *(*coap_dtls_id_callback_t)(
398                                  coap_bin_const_t *identity,
399                                  coap_session_t *coap_session,
400                                  void *arg);
401 /**
402  * PSK SNI callback that can be set up by coap_context_set_psk2().
403  * Invoked when libcoap has done the validation checks at the TLS level
404  * and the application needs to:-
405  * a) check that the SNI is allowed
406  * b) provide the appropriate PSK information for the (D)TLS session.
407  *
408  * @param sni  The client provided SNI
409  * @param coap_session  The CoAP session associated with the SNI
410  * @param arg  The same as was passed into coap_context_set_psk2()
411  *             in setup_data->sni_call_back_arg
412  *
413  * @return New coap_dtls_spsk_info_t object or @c NULL on error.
414  */
415 typedef const coap_dtls_spsk_info_t *(*coap_dtls_psk_sni_callback_t)(
416                                  const char *sni,
417                                  coap_session_t *coap_session,
418                                  void *arg);
419 
420 #define COAP_DTLS_SPSK_SETUP_VERSION 1 /**< Latest SPSK setup version */
421 
422 /**
423  * The structure used for defining the Server PSK setup data to be used.
424  */
425 typedef struct coap_dtls_spsk_t {
426   uint8_t version; /** Set to COAP_DTLS_SPSK_SETUP_VERSION
427                        to support this version of the struct */
428 
429   /* Options to enable different TLS functionality in libcoap */
430   uint8_t reserved[7];             /**< Reserved - must be set to 0 for
431                                         future compatibility */
432                                    /* Size of 7 chosen to align to next
433                                     * parameter, so if newly defined option
434                                     * it can use one of the reserverd slot so
435                                     * no need to change
436                                     * COAP_DTLS_SPSK_SETUP_VERSION and just
437                                     * decrement the reserved[] count.
438                                     */
439 
440   /** Identity check callback function.
441    * If not @p NULL, is called when the Identity is provided by the client.
442    * The appropriate Pre-Shared Key to use can then be returned.
443    */
444   coap_dtls_id_callback_t validate_id_call_back;
445   void *id_call_back_arg;  /**< Passed in to the Identity callback function */
446 
447   /** SNI check callback function.
448    * If not @p NULL, called if the SNI is not previously seen and prior to
449    * sending PSK information back to the client so that the appropriate
450    * PSK information can be used based on the requesting SNI.
451    */
452   coap_dtls_psk_sni_callback_t validate_sni_call_back;
453   void *sni_call_back_arg;  /**< Passed in to the SNI callback function */
454 
455   coap_dtls_spsk_info_t psk_info;  /**< Server PSK definition */
456 } coap_dtls_spsk_t;
457 
458 
459 /** @} */
460 
461 /**
462  * @ingroup logging
463  * Sets the (D)TLS logging level to the specified @p level.
464  * Note: coap_log_level() will influence output if at a specified level.
465  *
466  * @param level The logging level to use - LOG_*
467  */
468 void coap_dtls_set_log_level(int level);
469 
470 /**
471  * @ingroup logging
472  * Get the current (D)TLS logging.
473  *
474  * @return The current log level (one of LOG_*).
475  */
476 int coap_dtls_get_log_level(void);
477 
478 
479 #endif /* COAP_DTLS_H */
480