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  * This file is part of the CoAP library libcoap. Please see README for terms
8  * of use.
9  */
10 
11 #ifndef COAP_DTLS_H_
12 #define COAP_DTLS_H_
13 
14 #include "coap_time.h"
15 #include "str.h"
16 
17 struct coap_context_t;
18 struct coap_session_t;
19 struct coap_dtls_pki_t;
20 
21 /**
22  * @defgroup dtls DTLS Support
23  * API functions for interfacing with DTLS libraries.
24  * @{
25  */
26 
27 /**
28  * Check whether DTLS is available.
29  *
30  * @return @c 1 if support for DTLS is enabled, or @c 0 otherwise.
31  */
32 int coap_dtls_is_supported(void);
33 
34 /**
35  * Check whether TLS is available.
36  *
37  * @return @c 1 if support for TLS is enabled, or @c 0 otherwise.
38  */
39 int coap_tls_is_supported(void);
40 
41 typedef enum coap_tls_library_t {
42   COAP_TLS_LIBRARY_NOTLS = 0, /**< No DTLS library */
43   COAP_TLS_LIBRARY_TINYDTLS,  /**< Using TinyDTLS library */
44   COAP_TLS_LIBRARY_OPENSSL,   /**< Using OpenSSL library */
45   COAP_TLS_LIBRARY_GNUTLS,    /**< Using GnuTLS library */
46   COAP_TLS_LIBRARY_MBEDTLS,   /**< Using MbedTLS library */
47 } coap_tls_library_t;
48 
49 /**
50  * The structure used for returning the underlying (D)TLS library
51  * information.
52  */
53 typedef struct coap_tls_version_t {
54   uint64_t version; /**< (D)TLS runtime Library Version */
55   coap_tls_library_t type; /**< Library type. One of COAP_TLS_LIBRARY_* */
56   uint64_t built_version; /**< (D)TLS Built against Library Version */
57 } coap_tls_version_t;
58 
59 /**
60  * Determine the type and version of the underlying (D)TLS library.
61  *
62  * @return The version and type of library libcoap was compiled against.
63  */
64 coap_tls_version_t *coap_get_tls_library_version(void);
65 
66 /**
67  * Additional Security setup handler that can be set up by
68  * coap_context_set_pki().
69  * Invoked when libcoap has done the validation checks at the TLS level,
70  * but the application needs to do some additional checks/changes/updates.
71  *
72  * @param tls_session The security session definition - e.g. SSL * for OpenSSL.
73  *                    NULL if server call-back.
74  *                    This will be dependent on the underlying TLS library -
75  *                    see coap_get_tls_library_version()
76  * @param setup_data A structure containing setup data originally passed into
77  *                   coap_context_set_pki() or coap_new_client_session_pki().
78  *
79  * @return @c 1 if successful, else @c 0.
80  */
81 typedef int (*coap_dtls_security_setup_t)(void* tls_session,
82                                         struct coap_dtls_pki_t *setup_data);
83 
84 /**
85  * CN Validation call-back that can be set up by coap_context_set_pki().
86  * Invoked when libcoap has done the validation checks at the TLS level,
87  * but the application needs to check that the CN is allowed.
88  * CN is the SubjectAltName in the cert, if not present, then the leftmost
89  * Common Name (CN) component of the subject name.
90  *
91  * @param cn  The determined CN from the certificate
92  * @param asn1_public_cert  The ASN.1 DER encoded X.509 certificate
93  * @param asn1_length  The ASN.1 length
94  * @param coap_session  The CoAP session associated with the certificate update
95  * @param depth  Depth in cert chain.  If 0, then client cert, else a CA
96  * @param validated  TLS layer can find no issues if 1
97  * @param arg  The same as was passed into coap_context_set_pki()
98  *             in setup_data->cn_call_back_arg
99  *
100  * @return @c 1 if accepted, else @c 0 if to be rejected.
101  */
102 typedef int (*coap_dtls_cn_callback_t)(const char *cn,
103              const uint8_t *asn1_public_cert,
104              size_t asn1_length,
105              struct coap_session_t *coap_session,
106              unsigned depth,
107              int validated,
108              void *arg);
109 
110 /**
111  * The enum used for determining the provided PKI ASN.1 (DER) Private Key
112  * formats.
113  */
114 typedef enum coap_asn1_privatekey_type_t {
115   COAP_ASN1_PKEY_NONE,     /**< NONE */
116   COAP_ASN1_PKEY_RSA,      /**< RSA type */
117   COAP_ASN1_PKEY_RSA2,     /**< RSA2 type */
118   COAP_ASN1_PKEY_DSA,      /**< DSA type */
119   COAP_ASN1_PKEY_DSA1,     /**< DSA1 type */
120   COAP_ASN1_PKEY_DSA2,     /**< DSA2 type */
121   COAP_ASN1_PKEY_DSA3,     /**< DSA3 type */
122   COAP_ASN1_PKEY_DSA4,     /**< DSA4 type */
123   COAP_ASN1_PKEY_DH,       /**< DH type */
124   COAP_ASN1_PKEY_DHX,      /**< DHX type */
125   COAP_ASN1_PKEY_EC,       /**< EC type */
126   COAP_ASN1_PKEY_HMAC,     /**< HMAC type */
127   COAP_ASN1_PKEY_CMAC,     /**< CMAC type */
128   COAP_ASN1_PKEY_TLS1_PRF, /**< TLS1_PRF type */
129   COAP_ASN1_PKEY_HKDF      /**< HKDF type */
130 } coap_asn1_privatekey_type_t;
131 
132 /**
133  * The enum used for determining the PKI key formats.
134  */
135 typedef enum coap_pki_key_t {
136   COAP_PKI_KEY_PEM = 0,        /**< The PKI key type is PEM file */
137   COAP_PKI_KEY_ASN1,           /**< The PKI key type is ASN.1 (DER) */
138   COAP_PKI_KEY_PEM_BUF,        /**< The PKI key type is PEM buffer */
139 } coap_pki_key_t;
140 
141 /**
142  * The structure that holds the PKI PEM definitions.
143  */
144 typedef struct coap_pki_key_pem_t {
145   const char *ca_file;       /**< File location of Common CA in PEM format */
146   const char *public_cert;   /**< File location of Public Cert in PEM format */
147   const char *private_key;   /**< File location of Private Key in PEM format */
148 } coap_pki_key_pem_t;
149 
150 /**
151  * The structure that holds the PKI PEM buffer definitions.
152  */
153 typedef struct coap_pki_key_pem_buf_t {
154   const uint8_t *ca_cert;     /**< PEM buffer Common CA Cert */
155   const uint8_t *public_cert; /**< PEM buffer Public Cert */
156   const uint8_t *private_key; /**< PEM buffer Private Key */
157   size_t ca_cert_len;         /**< PEM buffer CA Cert length */
158   size_t public_cert_len;     /**< PEM buffer Public Cert length */
159   size_t private_key_len;     /**< PEM buffer Private Key length */
160 } coap_pki_key_pem_buf_t;
161 
162 /**
163  * The structure that holds the PKI ASN.1 (DER) definitions.
164  */
165 typedef struct coap_pki_key_asn1_t {
166   const uint8_t *ca_cert;     /**< ASN1 (DER) Common CA Cert */
167   const uint8_t *public_cert; /**< ASN1 (DER) Public Cert */
168   const uint8_t *private_key; /**< ASN1 (DER) Private Key */
169   size_t ca_cert_len;         /**< ASN1 CA Cert length */
170   size_t public_cert_len;     /**< ASN1 Public Cert length */
171   size_t private_key_len;     /**< ASN1 Private Key length */
172   coap_asn1_privatekey_type_t private_key_type; /**< Private Key Type */
173 } coap_pki_key_asn1_t;
174 
175 /**
176  * The structure that holds the PKI key information.
177  */
178 typedef struct coap_dtls_key_t {
179   coap_pki_key_t key_type;          /**< key format type */
180   union {
181     coap_pki_key_pem_t pem;          /**< for PEM file keys */
182     coap_pki_key_pem_buf_t pem_buf;  /**< for PEM memory keys */
183     coap_pki_key_asn1_t asn1;        /**< for ASN.1 (DER) file keys */
184   } key;
185 } coap_dtls_key_t;
186 
187 /**
188  * Server Name Indication (SNI) Validation call-back that can be set up by
189  * coap_context_set_pki().
190  * Invoked if the SNI is not previously seen and prior to sending a certificate
191  * set back to the client so that the appropriate certificate set can be used
192  * based on the requesting SNI.
193  *
194  * @param sni  The requested SNI
195  * @param arg  The same as was passed into coap_context_set_pki()
196  *             in setup_data->sni_call_back_arg
197  *
198  * @return New set of certificates to use, or @c NULL if SNI is to be rejected.
199  */
200 typedef coap_dtls_key_t *(*coap_dtls_sni_callback_t)(const char *sni,
201              void* arg);
202 
203 
204 #define COAP_DTLS_PKI_SETUP_VERSION 1 /**< Latest PKI setup version */
205 
206 /**
207  * The structure used for defining the PKI setup data to be used.
208  */
209 typedef struct coap_dtls_pki_t {
210   uint8_t version; /** Set to 1 to support this version of the struct */
211 
212   /* Options to enable different TLS functionality in libcoap */
213   uint8_t verify_peer_cert;        /**< 1 if peer cert is to be verified */
214   uint8_t require_peer_cert;       /**< 1 if peer cert is required */
215   uint8_t allow_self_signed;       /**< 1 if self signed certs are allowed */
216   uint8_t allow_expired_certs;     /**< 1 if expired certs are allowed */
217   uint8_t cert_chain_validation;   /**< 1 if to check cert_chain_verify_depth */
218   uint8_t cert_chain_verify_depth; /**< recommended depth is 3 */
219   uint8_t check_cert_revocation;   /**< 1 if revocation checks wanted */
220   uint8_t allow_no_crl;            /**< 1 ignore if CRL not there */
221   uint8_t allow_expired_crl;       /**< 1 if expired crl is allowed */
222   uint8_t allow_bad_md_hash;       /**< 1 if expired certs are allowed */
223   uint8_t allow_short_rsa_length;  /**< 1 if expired certs are allowed */
224   uint8_t reserved[4];             /**< Reserved - must be set to 0 for
225                                         future compatibility */
226                                    /* Size of 4 chosen to align to next
227                                     * parameter, so if newly defined option
228                                     * it can use one of the reserverd slot so
229                                     * no need to change
230                                     * COAP_DTLS_PKI_SETUP_VERSION and just
231                                     * decrement the reserved[] count.
232                                     */
233 
234   /** CN check call-back function.
235    * If not NULL, is called when the TLS connection has passed the configured
236    * TLS options above for the application to verify if the CN is valid.
237    */
238   coap_dtls_cn_callback_t validate_cn_call_back;
239   void *cn_call_back_arg;  /**< Passed in to the CN call-back function */
240 
241   /** SNI check call-back function.
242    * If not @p NULL, called if the SNI is not previously seen and prior to
243    * sending a certificate set back to the client so that the appropriate
244    * certificate set can be used based on the requesting SNI.
245    */
246   coap_dtls_sni_callback_t validate_sni_call_back;
247   void *sni_call_back_arg;  /**< Passed in to the sni call-back function */
248 
249   /** Additional Security call-back handler that is invoked when libcoap has
250    * done the standerd, defined validation checks at the TLS level,
251    * If not @p NULL, called from within the TLS Client Hello connection
252    * setup.
253    */
254   coap_dtls_security_setup_t additional_tls_setup_call_back;
255 
256   char* client_sni;    /**<  If not NULL, SNI to use in client TLS setup.
257                              Owned by the client app and must remain valid
258                              during the call to coap_new_client_session_pki() */
259 
260   coap_dtls_key_t pki_key;  /**< PKI key definition */
261 } coap_dtls_pki_t;
262 
263 /** @} */
264 
265 /**
266  * @defgroup dtls_internal DTLS Support (Internal)
267  * Internal API functions for interfacing with DTLS libraries.
268  * @{
269  */
270 
271 /**
272  * Creates a new DTLS context for the given @p coap_context. This function
273  * returns a pointer to a new DTLS context object or @c NULL on error.
274  *
275  * Internal function.
276  *
277  * @param coap_context The CoAP context where the DTLS object shall be used.
278  *
279  * @return A DTLS context object or @c NULL on error.
280  */
281 void *
282 coap_dtls_new_context(struct coap_context_t *coap_context);
283 
284 typedef enum coap_dtls_role_t {
285   COAP_DTLS_ROLE_CLIENT, /**< Internal function invoked for client */
286   COAP_DTLS_ROLE_SERVER  /**< Internal function invoked for server */
287 } coap_dtls_role_t;
288 
289 /**
290  * Set the DTLS context's default PSK information.
291  * This does the PSK specifics following coap_dtls_new_context().
292  * If @p COAP_DTLS_ROLE_SERVER, then identity hint will also get set.
293  * If @p COAP_DTLS_ROLE_SERVER, then the information will get put into the
294  * TLS library's context (from which sessions are derived).
295  * If @p COAP_DTLS_ROLE_CLIENT, then the information will get put into the
296  * TLS library's session.
297  *
298  * Internal function.
299  *
300  * @param coap_context The CoAP context.
301  * @param identity_hint The default PSK server identity hint sent to a client.
302  *                      Required parameter.  If @p NULL, will be set to "".
303  *                      Empty string is a valid hint.
304  *                      This parameter is ignored if COAP_DTLS_ROLE_CLIENT
305  * @param role  One of @p COAP_DTLS_ROLE_CLIENT or @p COAP_DTLS_ROLE_SERVER
306  *
307  * @return @c 1 if successful, else @c 0.
308  */
309 
310 int
311 coap_dtls_context_set_psk(struct coap_context_t *coap_context,
312                           const char *identity_hint,
313                           coap_dtls_role_t role);
314 
315 /**
316  * Set the DTLS context's default server PKI information.
317  * This does the PKI specifics following coap_dtls_new_context().
318  * If @p COAP_DTLS_ROLE_SERVER, then the information will get put into the
319  * TLS library's context (from which sessions are derived).
320  * If @p COAP_DTLS_ROLE_CLIENT, then the information will get put into the
321  * TLS library's session.
322  *
323  * Internal function.
324  *
325  * @param coap_context The CoAP context.
326  * @param setup_data     Setup information defining how PKI is to be setup.
327  *                       Required parameter.  If @p NULL, PKI will not be
328  *                       set up.
329  * @param role  One of @p COAP_DTLS_ROLE_CLIENT or @p COAP_DTLS_ROLE_SERVER
330  *
331  * @return @c 1 if successful, else @c 0.
332  */
333 
334 int
335 coap_dtls_context_set_pki(struct coap_context_t *coap_context,
336                           coap_dtls_pki_t *setup_data,
337                           coap_dtls_role_t role);
338 
339 /**
340  * Set the dtls context's default Root CA information for a client or server.
341  *
342  * Internal function.
343  *
344  * @param coap_context   The current coap_context_t object.
345  * @param ca_file        If not @p NULL, is the full path name of a PEM encoded
346  *                       file containing all the Root CAs to be used.
347  * @param ca_dir         If not @p NULL, points to a directory containing PEM
348  *                       encoded files containing all the Root CAs to be used.
349  *
350  * @return @c 1 if successful, else @c 0.
351  */
352 
353 int
354 coap_dtls_context_set_pki_root_cas(struct coap_context_t *coap_context,
355                                    const char *ca_file,
356                                    const char *ca_dir);
357 
358 /**
359  * Check whether one of the coap_dtls_context_set_{psk|pki}() functions have
360  * been called.
361  *
362  * Internal function.
363  *
364  * @param coap_context The current coap_context_t object.
365  *
366  * @return @c 1 if coap_dtls_context_set_{psk|pki}() called, else @c 0.
367  */
368 
369 int coap_dtls_context_check_keys_enabled(struct coap_context_t *coap_context);
370 
371 /**
372  * Releases the storage allocated for @p dtls_context.
373  *
374  * Internal function.
375  *
376  * @param dtls_context The DTLS context as returned by coap_dtls_new_context().
377  */
378 void coap_dtls_free_context(void *dtls_context);
379 
380 /**
381  * Create a new client-side session. This should send a HELLO to the server.
382  *
383  * Internal function.
384  *
385  * @param coap_session   The CoAP session.
386  *
387  * @return Opaque handle to underlying TLS library object containing security
388  *         parameters for the session.
389 */
390 void *coap_dtls_new_client_session(struct coap_session_t *coap_session);
391 
392 /**
393  * Create a new DTLS server-side session.
394  * Called after coap_dtls_hello() has returned @c 1, signalling that a validated
395  * HELLO was received from a client.
396  * This should send a HELLO to the server.
397  *
398  * Internal function.
399  *
400  * @param coap_session   The CoAP session.
401  *
402  * @return Opaque handle to underlying TLS library object containing security
403  *         parameters for the DTLS session.
404  */
405 void *coap_dtls_new_server_session(struct coap_session_t *coap_session);
406 
407 /**
408  * Terminates the DTLS session (may send an ALERT if necessary) then frees the
409  * underlying TLS library object containing security parameters for the session.
410  *
411  * Internal function.
412  *
413  * @param coap_session   The CoAP session.
414  */
415 void coap_dtls_free_session(struct coap_session_t *coap_session);
416 
417 /**
418  * Notify of a change in the CoAP session's MTU, for example after
419  * a PMTU update.
420  *
421  * Internal function.
422  *
423  * @param coap_session   The CoAP session.
424  */
425 void coap_dtls_session_update_mtu(struct coap_session_t *coap_session);
426 
427 /**
428  * Send data to a DTLS peer.
429  *
430  * Internal function.
431  *
432  * @param coap_session The CoAP session.
433  * @param data      pointer to data.
434  * @param data_len  Number of bytes to send.
435  *
436  * @return @c 0 if this would be blocking, @c -1 if there is an error or the
437  *         number of cleartext bytes sent.
438  */
439 int coap_dtls_send(struct coap_session_t *coap_session,
440                    const uint8_t *data,
441                    size_t data_len);
442 
443 /**
444  * Check if timeout is handled per CoAP session or per CoAP context.
445  *
446  * Internal function.
447  *
448  * @return @c 1 of timeout and retransmit is per context, @c 0 if it is
449  *         per session.
450  */
451 int coap_dtls_is_context_timeout(void);
452 
453 /**
454  * Do all pending retransmits and get next timeout
455  *
456  * Internal function.
457  *
458  * @param dtls_context The DTLS context.
459  *
460  * @return @c 0 if no event is pending or date of the next retransmit.
461  */
462 coap_tick_t coap_dtls_get_context_timeout(void *dtls_context);
463 
464 /**
465  * Get next timeout for this session.
466  *
467  * Internal function.
468  *
469  * @param coap_session The CoAP session.
470  * @param now The current time in ticks.
471  *
472  * @return @c 0 If no event is pending or ticks time of the next retransmit.
473  */
474 coap_tick_t coap_dtls_get_timeout(struct coap_session_t *coap_session,
475                                   coap_tick_t now);
476 
477 /**
478  * Handle a DTLS timeout expiration.
479  *
480  * Internal function.
481  *
482  * @param coap_session The CoAP session.
483  */
484 void coap_dtls_handle_timeout(struct coap_session_t *coap_session);
485 
486 /**
487  * Handling incoming data from a DTLS peer.
488  *
489  * Internal function.
490  *
491  * @param coap_session The CoAP session.
492  * @param data      Encrypted datagram.
493  * @param data_len  Encrypted datagram size.
494  *
495  * @return Result of coap_handle_dgram on the decrypted CoAP PDU
496  *         or @c -1 for error.
497  */
498 int coap_dtls_receive(struct coap_session_t *coap_session,
499                       const uint8_t *data,
500                       size_t data_len);
501 
502 /**
503  * Handling client HELLO messages from a new candiate peer.
504  * Note that session->tls is empty.
505  *
506  * Internal function.
507  *
508  * @param coap_session The CoAP session.
509  * @param data      Encrypted datagram.
510  * @param data_len  Encrypted datagram size.
511  *
512  * @return @c 0 if a cookie verification message has been sent, @c 1 if the
513  *        HELLO contains a valid cookie and a server session should be created,
514  *        @c -1 if the message is invalid.
515  */
516 int coap_dtls_hello(struct coap_session_t *coap_session,
517                     const uint8_t *data,
518                     size_t data_len);
519 
520 /**
521  * Get DTLS overhead over cleartext PDUs.
522  *
523  * Internal function.
524  *
525  * @param coap_session The CoAP session.
526  *
527  * @return Maximum number of bytes added by DTLS layer.
528  */
529 unsigned int coap_dtls_get_overhead(struct coap_session_t *coap_session);
530 
531 /**
532  * Create a new TLS client-side session.
533  *
534  * Internal function.
535  *
536  * @param coap_session The CoAP session.
537  * @param connected Updated with whether the connection is connected yet or not.
538  *                  @c 0 is not connected, @c 1 is connected.
539  *
540  * @return Opaque handle to underlying TLS library object containing security
541  *         parameters for the session.
542 */
543 void *coap_tls_new_client_session(struct coap_session_t *coap_session, int *connected);
544 
545 /**
546  * Create a TLS new server-side session.
547  *
548  * Internal function.
549  *
550  * @param coap_session The CoAP session.
551  * @param connected Updated with whether the connection is connected yet or not.
552  *                  @c 0 is not connected, @c 1 is connected.
553  *
554  * @return Opaque handle to underlying TLS library object containing security
555  *         parameters for the session.
556  */
557 void *coap_tls_new_server_session(struct coap_session_t *coap_session, int *connected);
558 
559 /**
560  * Terminates the TLS session (may send an ALERT if necessary) then frees the
561  * underlying TLS library object containing security parameters for the session.
562  *
563  * Internal function.
564  *
565  * @param coap_session The CoAP session.
566  */
567 void coap_tls_free_session( struct coap_session_t *coap_session );
568 
569 /**
570  * Send data to a TLS peer, with implicit flush.
571  *
572  * Internal function.
573  *
574  * @param coap_session The CoAP session.
575  * @param data      Pointer to data.
576  * @param data_len  Number of bytes to send.
577  *
578  * @return          @c 0 if this should be retried, @c -1 if there is an error
579  *                  or the number of cleartext bytes sent.
580  */
581 ssize_t coap_tls_write(struct coap_session_t *coap_session,
582                        const uint8_t *data,
583                        size_t data_len
584                        );
585 
586 /**
587  * Read some data from a TLS peer.
588  *
589  * Internal function.
590  *
591  * @param coap_session The CoAP session.
592  * @param data      Pointer to data.
593  * @param data_len  Maximum number of bytes to read.
594  *
595  * @return          @c 0 if this should be retried, @c -1 if there is an error
596  *                  or the number of cleartext bytes read.
597  */
598 ssize_t coap_tls_read(struct coap_session_t *coap_session,
599                       uint8_t *data,
600                       size_t data_len
601                       );
602 
603 /**
604  * Initialize the underlying (D)TLS Library layer.
605  *
606  * Internal function.
607  *
608  */
609 void coap_dtls_startup(void);
610 
611 /** @} */
612 
613 /**
614  * @ingroup logging
615  * Sets the (D)TLS logging level to the specified @p level.
616  * Note: coap_log_level() will influence output if at a specified level.
617  *
618  * @param level The logging level to use - LOG_*
619  */
620 void coap_dtls_set_log_level(int level);
621 
622 /**
623  * @ingroup logging
624  * Get the current (D)TLS logging.
625  *
626  * @return The current log level (one of LOG_*).
627  */
628 int coap_dtls_get_log_level(void);
629 
630 
631 #endif /* COAP_DTLS_H */
632