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