• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * coap_tinydtls.c -- Datagram Transport Layer Support for libcoap with tinydtls
3  *
4  * Copyright (C) 2016-2020 Olaf Bergmann <bergmann@tzi.org>
5  * Copyright (C) 2020 Jon Shallow <supjps-libcoap@jpshallow.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 #include "coap3/coap_internal.h"
14 
15 #ifdef HAVE_LIBTINYDTLS
16 
17 /* We want TinyDTLS versions of these, not libcoap versions */
18 #undef PACKAGE_BUGREPORT
19 #undef PACKAGE_NAME
20 #undef PACKAGE_STRING
21 #undef PACKAGE_TARNAME
22 #undef PACKAGE_URL
23 #undef PACKAGE_VERSION
24 
25 #include <tinydtls.h>
26 #include <dtls.h>
27 #include <dtls_debug.h>
28 
29 typedef struct coap_tiny_context_t {
30   struct dtls_context_t *dtls_context;
31   coap_context_t *coap_context;
32 #ifdef DTLS_ECC
33   coap_dtls_pki_t setup_data;
34   coap_binary_t *priv_key;
35   coap_binary_t *pub_key;
36 #endif /* DTLS_ECC */
37 } coap_tiny_context_t;
38 
39 static dtls_tick_t dtls_tick_0 = 0;
40 static coap_tick_t coap_tick_0 = 0;
41 
42 int
coap_dtls_is_supported(void)43 coap_dtls_is_supported(void) {
44   return 1;
45 }
46 
coap_dtls_startup(void)47 void coap_dtls_startup(void) {
48   dtls_init();
49   dtls_ticks(&dtls_tick_0);
50   coap_ticks(&coap_tick_0);
51 }
52 
coap_dtls_shutdown(void)53 void coap_dtls_shutdown(void) {
54 }
55 
56 void *
coap_dtls_get_tls(const coap_session_t * c_session,coap_tls_library_t * tls_lib)57 coap_dtls_get_tls(const coap_session_t *c_session,
58                   coap_tls_library_t *tls_lib) {
59   if (tls_lib)
60     *tls_lib = COAP_TLS_LIBRARY_TINYDTLS;
61   if (c_session && c_session->context && c_session->context->dtls_context) {
62     const coap_tiny_context_t *t_context =
63                   (const coap_tiny_context_t *)c_session->context->dtls_context;
64 
65     return t_context->dtls_context;
66   }
67   return NULL;
68 }
69 
70 void
coap_dtls_set_log_level(int level)71 coap_dtls_set_log_level(int level) {
72   dtls_set_log_level(level);
73 }
74 
75 int
coap_dtls_get_log_level(void)76 coap_dtls_get_log_level(void) {
77   return dtls_get_log_level();
78 }
79 
get_session_addr(const session_t * s,coap_address_t * a)80 static void get_session_addr(const session_t *s, coap_address_t *a) {
81 #ifdef WITH_CONTIKI
82   a->addr = s->addr;
83   a->port = s->port;
84 #else
85   if (s->addr.sa.sa_family == AF_INET6) {
86     a->size = (socklen_t)sizeof(a->addr.sin6);
87     a->addr.sin6 = s->addr.sin6;
88   } else if (s->addr.sa.sa_family == AF_INET) {
89     a->size = (socklen_t)sizeof(a->addr.sin);
90     a->addr.sin = s->addr.sin;
91   } else {
92     a->size = (socklen_t)s->size;
93     a->addr.sa = s->addr.sa;
94   }
95 #endif
96 }
97 
put_session_addr(const coap_address_t * a,session_t * s)98 static void put_session_addr(const coap_address_t *a, session_t *s) {
99 #ifdef WITH_CONTIKI
100   s->size = (unsigned char)sizeof(s->addr);
101   s->addr = a->addr;
102   s->port = a->port;
103 #else
104   if (a->addr.sa.sa_family == AF_INET6) {
105     s->size = (socklen_t)sizeof(s->addr.sin6);
106     s->addr.sin6 = a->addr.sin6;
107   } else if (a->addr.sa.sa_family == AF_INET) {
108     s->size = (socklen_t)sizeof(s->addr.sin);
109     s->addr.sin = a->addr.sin;
110   } else {
111     s->size = (socklen_t)a->size;
112     s->addr.sa = a->addr.sa;
113   }
114 #endif
115 }
116 
117 static int
dtls_send_to_peer(struct dtls_context_t * dtls_context,session_t * dtls_session,uint8 * data,size_t len)118 dtls_send_to_peer(struct dtls_context_t *dtls_context,
119   session_t *dtls_session, uint8 *data, size_t len) {
120   coap_tiny_context_t *t_context =
121                   (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
122   coap_context_t *coap_context = t_context ? t_context->coap_context : NULL;
123   coap_session_t *coap_session;
124   coap_address_t remote_addr;
125 
126   assert(coap_context);
127   get_session_addr(dtls_session, &remote_addr);
128   coap_session = coap_session_get_by_peer(coap_context, &remote_addr, dtls_session->ifindex);
129   if (!coap_session) {
130     coap_log(LOG_WARNING, "dtls_send_to_peer: cannot find local interface\n");
131     return -3;
132   }
133   return (int)coap_session_send(coap_session, data, len);
134 }
135 
136 static int
dtls_application_data(struct dtls_context_t * dtls_context,session_t * dtls_session,uint8 * data,size_t len)137 dtls_application_data(struct dtls_context_t *dtls_context,
138   session_t *dtls_session, uint8 *data, size_t len) {
139   coap_tiny_context_t *t_context =
140                   (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
141   coap_context_t *coap_context = t_context ? t_context->coap_context : NULL;
142   coap_session_t *coap_session;
143   coap_address_t remote_addr;
144 
145   assert(coap_context);
146   get_session_addr(dtls_session, &remote_addr);
147   coap_session = coap_session_get_by_peer(coap_context, &remote_addr, dtls_session->ifindex);
148   if (!coap_session) {
149     coap_log(LOG_DEBUG,
150              "dropped message that was received on invalid interface\n");
151     return -1;
152   }
153 
154   return coap_handle_dgram(coap_context, coap_session, data, len);
155 }
156 
157 static int coap_event_dtls = 0;
158 
159 static int
dtls_event(struct dtls_context_t * dtls_context,session_t * dtls_session,dtls_alert_level_t level,uint16_t code)160 dtls_event(struct dtls_context_t *dtls_context,
161   session_t *dtls_session,
162   dtls_alert_level_t level,
163   uint16_t code) {
164   (void)dtls_context;
165   (void)dtls_session;
166 
167   if (level == DTLS_ALERT_LEVEL_FATAL)
168     coap_event_dtls = COAP_EVENT_DTLS_ERROR;
169 
170   /* handle DTLS events */
171   switch (code) {
172   case DTLS_ALERT_CLOSE_NOTIFY:
173   {
174     coap_event_dtls = COAP_EVENT_DTLS_CLOSED;
175     break;
176   }
177   case DTLS_EVENT_CONNECTED:
178   {
179     coap_event_dtls = COAP_EVENT_DTLS_CONNECTED;
180     break;
181   }
182   case DTLS_EVENT_RENEGOTIATE:
183   {
184     coap_event_dtls = COAP_EVENT_DTLS_RENEGOTIATE;
185     break;
186   }
187   default:
188     ;
189   }
190 
191   return 0;
192 }
193 
194 /* This function is the "key store" for tinyDTLS. It is called to
195  * retrieve a key for the given identity within this particular
196  * session. */
197 static int
get_psk_info(struct dtls_context_t * dtls_context,const session_t * dtls_session,dtls_credentials_type_t type,const uint8_t * id,size_t id_len,unsigned char * result,size_t result_length)198 get_psk_info(struct dtls_context_t *dtls_context,
199   const session_t *dtls_session,
200   dtls_credentials_type_t type,
201   const uint8_t *id, size_t id_len,
202   unsigned char *result, size_t result_length) {
203 
204   coap_tiny_context_t *t_context =
205                   (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
206   coap_context_t *coap_context = t_context ? t_context->coap_context : NULL;
207   coap_session_t *coap_session;
208   int fatal_error = DTLS_ALERT_INTERNAL_ERROR;
209   size_t identity_length;
210   uint8_t psk[128];
211   size_t psk_len = 0;
212   coap_address_t remote_addr;
213   coap_dtls_cpsk_t *setup_cdata;
214   coap_dtls_spsk_t *setup_sdata;
215   coap_bin_const_t temp;
216 
217   assert(coap_context);
218   get_session_addr(dtls_session, &remote_addr);
219   coap_session = coap_session_get_by_peer(coap_context, &remote_addr, dtls_session->ifindex);
220   if (!coap_session) {
221     coap_log(LOG_DEBUG, "cannot get PSK, session not found\n");
222     goto error;
223   }
224 
225   switch (type) {
226   case DTLS_PSK_IDENTITY:
227 
228     if (!coap_context || !coap_context->get_client_psk ||
229         coap_session->type != COAP_SESSION_TYPE_CLIENT)
230       goto error;
231 
232     setup_cdata = &coap_session->cpsk_setup_data;
233 
234     temp.s = id;
235     temp.length = id_len;
236     coap_session_refresh_psk_hint(coap_session, &temp);
237 
238     coap_log(LOG_DEBUG, "got psk_identity_hint: '%.*s'\n", (int)id_len, id ? (const char*)id : "");
239 
240     if (setup_cdata->validate_ih_call_back) {
241       coap_str_const_t lhint;
242       lhint.length = id_len;
243       lhint.s = id;
244       const coap_dtls_cpsk_info_t *psk_info =
245                setup_cdata->validate_ih_call_back(&lhint,
246                                                   coap_session,
247                                                   setup_cdata->ih_call_back_arg);
248 
249       if (psk_info == NULL)
250         return 0;
251       if (psk_info->identity.length >= result_length)
252         return 0;
253       if (psk_info->key.length > sizeof(psk))
254         return 0;
255 
256       if (coap_session->psk_identity) {
257         coap_delete_bin_const(coap_session->psk_identity);
258       }
259       identity_length = psk_info->identity.length;
260       coap_session->psk_identity = coap_new_bin_const(psk_info->identity.s, identity_length);
261       memcpy(result, psk_info->identity.s, identity_length);
262       result[identity_length] = '\000';
263 
264       coap_session_refresh_psk_key(coap_session, &psk_info->key);
265 
266       return identity_length;
267     }
268 
269     identity_length = 0;
270     /* result_length is max size of the returned identity */
271     psk_len = coap_context->get_client_psk(coap_session, (const uint8_t*)id, id_len, (uint8_t*)result, &identity_length, result_length, psk, sizeof(psk));
272     if (!psk_len) {
273       coap_log(LOG_WARNING, "no PSK identity for given realm or buffer too small\n");
274       fatal_error = DTLS_ALERT_CLOSE_NOTIFY;
275       goto error;
276     }
277     return (int)identity_length;
278 
279   case DTLS_PSK_KEY:
280     if (coap_session->type == COAP_SESSION_TYPE_CLIENT) {
281       if (!coap_context || !coap_context->get_client_psk)
282         goto error;
283       identity_length = 0;
284       /* Use psk[] as a scratch area for returning the unused identity */
285       psk_len = coap_context->get_client_psk(coap_session, (const uint8_t*)id, id_len, psk, &identity_length, sizeof(psk), result, result_length);
286       if (!psk_len) {
287         coap_log(LOG_WARNING, "no pre-shared key for given realm or buffer too small\n");
288         fatal_error = DTLS_ALERT_CLOSE_NOTIFY;
289         goto error;
290       }
291       return (int)psk_len;
292     }
293     if (coap_context->get_server_psk) {
294       setup_sdata = &coap_session->context->spsk_setup_data;
295 
296       if (!id)
297         id = (const uint8_t *)"";
298 
299       /* Track the Identity being used */
300       if (coap_session->psk_identity)
301         coap_delete_bin_const(coap_session->psk_identity);
302       coap_session->psk_identity = coap_new_bin_const(id, id_len);
303 
304       coap_log(LOG_DEBUG, "got psk_identity: '%.*s'\n",
305                (int)id_len, id);
306 
307       if (setup_sdata->validate_id_call_back) {
308         coap_bin_const_t lidentity;
309         lidentity.length = id_len;
310         lidentity.s = (const uint8_t*)id;
311         const coap_bin_const_t *psk_key =
312                  setup_sdata->validate_id_call_back(&lidentity,
313                                                     coap_session,
314                                                     setup_sdata->id_call_back_arg);
315 
316         if (psk_key == NULL)
317           return 0;
318         if (psk_key->length > result_length)
319           return 0;
320         memcpy(result, psk_key->s, psk_key->length);
321         coap_session_refresh_psk_key(coap_session, psk_key);
322         return psk_key->length;
323       }
324 
325       return (int)coap_context->get_server_psk(coap_session, (const uint8_t*)id, id_len, (uint8_t*)result, result_length);
326     }
327     return 0;
328 
329   case DTLS_PSK_HINT:
330     if (coap_context->get_server_hint)
331       return (int)coap_context->get_server_hint(coap_session, (uint8_t *)result, result_length);
332     return 0;
333 
334   default:
335     coap_log(LOG_WARNING, "unsupported request type: %d\n", type);
336   }
337 
338 error:
339   return dtls_alert_fatal_create(fatal_error);
340 }
341 
342 #ifdef DTLS_ECC
343 static int
get_ecdsa_key(struct dtls_context_t * dtls_context,const session_t * dtls_session COAP_UNUSED,const dtls_ecdsa_key_t ** result)344 get_ecdsa_key(struct dtls_context_t *dtls_context,
345               const session_t *dtls_session COAP_UNUSED,
346               const dtls_ecdsa_key_t **result) {
347   static dtls_ecdsa_key_t ecdsa_key;
348   coap_tiny_context_t *t_context =
349                   (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
350 
351   ecdsa_key.curve = DTLS_ECDH_CURVE_SECP256R1;
352   ecdsa_key.priv_key = t_context->priv_key->s;
353   ecdsa_key.pub_key_x = t_context->pub_key->s;
354   ecdsa_key.pub_key_y = &t_context->pub_key->s[DTLS_EC_KEY_SIZE];
355 
356   *result = &ecdsa_key;
357   return 0;
358 }
359 
360 /* first part of Raw public key, the is the start of the Subject Public Key */
361 static const unsigned char cert_asn1_header[] = {
362   0x30, 0x59, /* SEQUENCE, length 89 bytes */
363     0x30, 0x13, /* SEQUENCE, length 19 bytes */
364       0x06, 0x07, /* OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1) */
365         0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01,
366       0x06, 0x08, /* OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7) */
367         0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07,
368       0x03, 0x42, 0x00, /* BIT STRING, length 66 bytes, 0 bits unused */
369          0x04 /* uncompressed, followed by the r and s values of the public key */
370 };
371 #define DTLS_CE_LENGTH (sizeof(cert_asn1_header) + key_size + key_size)
372 
373 static int
verify_ecdsa_key(struct dtls_context_t * dtls_context COAP_UNUSED,const session_t * dtls_session COAP_UNUSED,const uint8_t * other_pub_x,const uint8_t * other_pub_y,size_t key_size)374 verify_ecdsa_key(struct dtls_context_t *dtls_context COAP_UNUSED,
375                  const session_t *dtls_session COAP_UNUSED,
376                  const uint8_t *other_pub_x,
377                  const uint8_t *other_pub_y,
378                  size_t key_size) {
379   coap_tiny_context_t *t_context =
380                   (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
381   if (t_context && t_context->setup_data.validate_cn_call_back) {
382     /* Need to build asn.1 certificate - code taken from tinydtls */
383     uint8 *p;
384     uint8 buf[DTLS_CE_LENGTH];
385     coap_session_t *c_session;
386     coap_address_t remote_addr;
387 
388     /* Certificate
389      *
390      * Start message construction at beginning of buffer. */
391     p = buf;
392 
393     memcpy(p, &cert_asn1_header, sizeof(cert_asn1_header));
394     p += sizeof(cert_asn1_header);
395 
396     memcpy(p, other_pub_x, key_size);
397     p += key_size;
398 
399     memcpy(p, other_pub_y, key_size);
400     p += key_size;
401 
402     assert(p <= (buf + sizeof(buf)));
403 
404     get_session_addr(dtls_session, &remote_addr);
405     c_session = coap_session_get_by_peer(t_context->coap_context,
406                                          &remote_addr, dtls_session->ifindex);
407     if (!c_session)
408       return -3;
409     if (!t_context->setup_data.validate_cn_call_back(COAP_DTLS_RPK_CERT_CN,
410         buf, p-buf, c_session, 0, 1, t_context->setup_data.cn_call_back_arg)) {
411       return -1;
412     }
413   }
414   return 0;
415 }
416 static dtls_handler_t ec_cb = {
417   .write = dtls_send_to_peer,
418   .read = dtls_application_data,
419   .event = dtls_event,
420   .get_psk_info = NULL,
421   .get_ecdsa_key = get_ecdsa_key,
422   .verify_ecdsa_key = verify_ecdsa_key
423 };
424 #endif /* DTLS_ECC */
425 
426 static dtls_handler_t psk_cb = {
427   .write = dtls_send_to_peer,
428   .read = dtls_application_data,
429   .event = dtls_event,
430   .get_psk_info = get_psk_info,
431 #ifdef DTLS_ECC
432   .get_ecdsa_key = NULL,
433   .verify_ecdsa_key = NULL
434 #endif
435 };
436 
437 void *
coap_dtls_new_context(coap_context_t * coap_context)438 coap_dtls_new_context(coap_context_t *coap_context) {
439   coap_tiny_context_t *t_context = coap_malloc(sizeof(coap_tiny_context_t));
440   struct dtls_context_t *dtls_context = t_context ? dtls_new_context(t_context) : NULL;
441   if (!dtls_context)
442     goto error;
443   memset(t_context, 0, sizeof(coap_tiny_context_t));
444   t_context->coap_context = coap_context;
445   t_context->dtls_context = dtls_context;
446   dtls_set_handler(dtls_context, &psk_cb);
447   return t_context;
448 error:
449   if (t_context)
450     coap_free(t_context);
451   if (dtls_context)
452     coap_dtls_free_context(dtls_context);
453   return NULL;
454 }
455 
456 void
coap_dtls_free_context(void * handle)457 coap_dtls_free_context(void *handle) {
458   if (handle) {
459     coap_tiny_context_t *t_context = (coap_tiny_context_t *)handle;
460 #ifdef DTLS_ECC
461     if (t_context->priv_key) {
462       coap_delete_binary(t_context->priv_key);
463       t_context->priv_key = NULL;
464     }
465     if (t_context->pub_key) {
466       coap_delete_binary(t_context->pub_key);
467       t_context->pub_key = NULL;
468     }
469 #endif /* DTLS_ECC */
470     if (t_context->dtls_context)
471       dtls_free_context(t_context->dtls_context);
472     coap_free(t_context);
473   }
474 }
475 
476 static session_t *
coap_dtls_new_session(coap_session_t * session)477 coap_dtls_new_session(coap_session_t *session) {
478   session_t *dtls_session = coap_malloc_type(COAP_DTLS_SESSION, sizeof(session_t));
479 
480   if (dtls_session) {
481     /* create tinydtls session object from remote address and local
482     * endpoint handle */
483     dtls_session_init(dtls_session);
484     put_session_addr(&session->addr_info.remote, dtls_session);
485     dtls_session->ifindex = session->ifindex;
486     coap_log(LOG_DEBUG, "***new session %p\n", (void *)dtls_session);
487   }
488 
489   return dtls_session;
490 }
491 
coap_dtls_new_server_session(coap_session_t * session)492 void *coap_dtls_new_server_session(coap_session_t *session) {
493   return coap_dtls_new_session(session);
494 }
495 
coap_dtls_new_client_session(coap_session_t * session)496 void *coap_dtls_new_client_session(coap_session_t *session) {
497   dtls_peer_t *peer;
498   coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
499   dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
500   session_t *dtls_session = dtls_context ? coap_dtls_new_session(session) : NULL;
501 
502   if (!dtls_session)
503     return NULL;
504   peer =
505     dtls_get_peer(dtls_context, dtls_session);
506 
507   if (!peer) {
508     /* The peer connection does not yet exist. */
509     /* dtls_connect() returns a value greater than zero if a new
510     * connection attempt is made, 0 for session reuse. */
511     if (dtls_connect(dtls_context, dtls_session) >= 0) {
512       peer =
513         dtls_get_peer(dtls_context, dtls_session);
514     }
515   }
516 
517   if (!peer) {
518     /* delete existing session because the peer object has been invalidated */
519     coap_free_type(COAP_DTLS_SESSION, dtls_session);
520     dtls_session = NULL;
521   }
522 
523   return dtls_session;
524 }
525 
526 void
coap_dtls_session_update_mtu(coap_session_t * session)527 coap_dtls_session_update_mtu(coap_session_t *session) {
528   (void)session;
529 }
530 
531 void
coap_dtls_free_session(coap_session_t * coap_session)532 coap_dtls_free_session(coap_session_t *coap_session) {
533   coap_tiny_context_t *t_context =
534                  (coap_tiny_context_t *)coap_session->context->dtls_context;
535   dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
536 
537   if (dtls_context == NULL)
538     return;
539   if (coap_session->tls && dtls_context) {
540     dtls_peer_t *peer = dtls_get_peer(dtls_context, (session_t *)coap_session->tls);
541     if ( peer )
542       dtls_reset_peer(dtls_context, peer);
543     else
544       dtls_close(dtls_context, (session_t *)coap_session->tls);
545     coap_log(LOG_DEBUG, "***removed session %p\n", coap_session->tls);
546     coap_free_type(COAP_DTLS_SESSION, coap_session->tls);
547     coap_session->tls = NULL;
548     coap_handle_event(coap_session->context, COAP_EVENT_DTLS_CLOSED, coap_session);
549   }
550 }
551 
552 int
coap_dtls_send(coap_session_t * session,const uint8_t * data,size_t data_len)553 coap_dtls_send(coap_session_t *session,
554   const uint8_t *data,
555   size_t data_len
556 ) {
557   int res;
558   uint8_t *data_rw;
559   coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
560   dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
561 
562   assert(dtls_context);
563   coap_log(LOG_DEBUG, "call dtls_write\n");
564 
565   coap_event_dtls = -1;
566   /* Need to do this to not get a compiler warning about const parameters */
567   memcpy (&data_rw, &data, sizeof(data_rw));
568   res = dtls_write(dtls_context,
569     (session_t *)session->tls, data_rw, data_len);
570 
571   if (res < 0)
572     coap_log(LOG_WARNING, "coap_dtls_send: cannot send PDU\n");
573 
574   if (coap_event_dtls >= 0) {
575     /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */
576     if (coap_event_dtls != COAP_EVENT_DTLS_CLOSED)
577       coap_handle_event(session->context, coap_event_dtls, session);
578     if (coap_event_dtls == COAP_EVENT_DTLS_CONNECTED)
579       coap_session_connected(session);
580     else if (coap_event_dtls == COAP_EVENT_DTLS_CLOSED || coap_event_dtls == COAP_EVENT_DTLS_ERROR)
581       coap_session_disconnected(session, COAP_NACK_TLS_FAILED);
582   }
583 
584   return res;
585 }
586 
coap_dtls_is_context_timeout(void)587 int coap_dtls_is_context_timeout(void) {
588   return 1;
589 }
590 
coap_dtls_get_context_timeout(void * tiny_context)591 coap_tick_t coap_dtls_get_context_timeout(void *tiny_context) {
592   clock_time_t next = 0;
593   coap_tiny_context_t *t_context = (coap_tiny_context_t *)tiny_context;
594   dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
595   if (tiny_context)
596     dtls_check_retransmit(dtls_context, &next);
597   if (next > 0)
598     return ((coap_tick_t)(next - dtls_tick_0)) * COAP_TICKS_PER_SECOND / DTLS_TICKS_PER_SECOND + coap_tick_0;
599   return 0;
600 }
601 
coap_dtls_get_timeout(coap_session_t * session,coap_tick_t now)602 coap_tick_t coap_dtls_get_timeout(coap_session_t *session, coap_tick_t now) {
603   (void)session;
604   (void)now;
605   return 0;
606 }
607 
coap_dtls_handle_timeout(coap_session_t * session)608 void coap_dtls_handle_timeout(coap_session_t *session) {
609   (void)session;
610   return;
611 }
612 
613 int
coap_dtls_receive(coap_session_t * session,const uint8_t * data,size_t data_len)614 coap_dtls_receive(coap_session_t *session,
615   const uint8_t *data,
616   size_t data_len
617 ) {
618   session_t *dtls_session = (session_t *)session->tls;
619   int err;
620   uint8_t *data_rw;
621   coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
622   dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
623 
624   assert(dtls_context);
625   coap_event_dtls = -1;
626   /* Need to do this to not get a compiler warning about const parameters */
627   memcpy (&data_rw, &data, sizeof(data_rw));
628   err = dtls_handle_message(dtls_context, dtls_session, data_rw, (int)data_len);
629 
630   if (err){
631     coap_event_dtls = COAP_EVENT_DTLS_ERROR;
632   }
633 
634   if (coap_event_dtls >= 0) {
635     /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */
636     if (coap_event_dtls != COAP_EVENT_DTLS_CLOSED)
637       coap_handle_event(session->context, coap_event_dtls, session);
638     if (coap_event_dtls == COAP_EVENT_DTLS_CONNECTED)
639       coap_session_connected(session);
640     else if (coap_event_dtls == COAP_EVENT_DTLS_CLOSED || coap_event_dtls == COAP_EVENT_DTLS_ERROR)
641       coap_session_disconnected(session, COAP_NACK_TLS_FAILED);
642   }
643 
644   return err;
645 }
646 
647 int
coap_dtls_hello(coap_session_t * session,const uint8_t * data,size_t data_len)648 coap_dtls_hello(coap_session_t *session,
649   const uint8_t *data,
650   size_t data_len
651 ) {
652   session_t dtls_session;
653   coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
654   dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
655   uint8_t *data_rw;
656 
657   assert(dtls_context);
658   dtls_session_init(&dtls_session);
659   put_session_addr(&session->addr_info.remote, &dtls_session);
660   dtls_session.ifindex = session->ifindex;
661   /* Need to do this to not get a compiler warning about const parameters */
662   memcpy (&data_rw, &data, sizeof(data_rw));
663   int res = dtls_handle_message(dtls_context, &dtls_session,
664     data_rw, (int)data_len);
665   if (res >= 0) {
666     if (dtls_get_peer(dtls_context, &dtls_session))
667       res = 1;
668     else
669       res = 0;
670   }
671   return res;
672 }
673 
coap_dtls_get_overhead(coap_session_t * session)674 unsigned int coap_dtls_get_overhead(coap_session_t *session) {
675   (void)session;
676   return 13 + 8 + 8;
677 }
678 
coap_tls_is_supported(void)679 int coap_tls_is_supported(void) {
680   return 0;
681 }
682 
683 coap_tls_version_t *
coap_get_tls_library_version(void)684 coap_get_tls_library_version(void) {
685   static coap_tls_version_t version;
686   const char *vers = dtls_package_version();
687 
688   version.version = 0;
689   if (vers) {
690     long int p1, p2 = 0, p3 = 0;
691     char* endptr;
692 
693     p1 = strtol(vers, &endptr, 10);
694     if (*endptr == '.') {
695       p2 = strtol(endptr+1, &endptr, 10);
696       if (*endptr == '.') {
697         p3 = strtol(endptr+1, &endptr, 10);
698       }
699     }
700     version.version = (p1 << 16) | (p2 << 8) | p3;
701   }
702   version.built_version = version.version;
703   version.type = COAP_TLS_LIBRARY_TINYDTLS;
704   return &version;
705 }
706 
707 #ifdef DTLS_ECC
708 static const uint8_t b64_6[256] =
709   {
710   64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
711   64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
712 /*                                             +               / */
713   64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
714 /* 0   1   2   3   4   5   6   7   8   9               =         */
715   52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
716 /*     A   B   C   D   E   F   G   H   I   J   K   L   M   N   O */
717   64,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
718 /* P   Q   R   S   T   U   V   W   X   Y   Z                     */
719   15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
720 /*     a   b   c   d   e   f   g   h   i   j   k   l   m   n   o */
721   64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
722 /* p   q   r   s   t   u   v   w   x   y   z                     */
723   41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
724   64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
725   64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
726   64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
727   64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
728   64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
729   64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
730   64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
731   64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
732   };
733 
734 /* caller must free off returned coap_binary_t* */
735 static coap_binary_t *
pem_base64_decode(const uint8_t * data,size_t size)736 pem_base64_decode (const uint8_t *data, size_t size)
737 {
738   uint8_t *tbuf = coap_malloc(size);
739   size_t nbytesdecoded;
740   size_t i;
741   coap_binary_t *decoded;
742   uint8_t *ptr;
743   uint8_t *out;
744   size_t nb64bytes = 0;
745 
746   for (i = 0; i < size; i++) {
747     switch (data[i]) {
748     case ' ':
749     case '\r':
750     case '\n':
751     case '\t':
752       break;
753     default:
754       if (b64_6[data[i]] == 64)
755         goto end;
756       tbuf[nb64bytes++] = data[i];
757       break;
758     }
759   }
760 
761 end:
762   nbytesdecoded = ((nb64bytes + 3) / 4) * 3;
763   decoded = coap_new_binary(nbytesdecoded + 1);
764   if (!decoded)
765     return NULL;
766 
767   out = decoded->s;
768   ptr = tbuf;
769 
770   while (nb64bytes > 4) {
771     *(out++) = b64_6[ptr[0]] << 2 | b64_6[ptr[1]] >> 4;
772     *(out++) = b64_6[ptr[1]] << 4 | b64_6[ptr[2]] >> 2;
773     *(out++) = b64_6[ptr[2]] << 6 | b64_6[ptr[3]];
774     ptr += 4;
775     nb64bytes -= 4;
776   }
777 
778   /* Note: (nb64bytes == 1) is an error */
779   if (nb64bytes > 1) {
780     *(out++) = b64_6[ptr[0]] << 2 | b64_6[ptr[1]] >> 4;
781   }
782   if (nb64bytes > 2) {
783     *(out++) = b64_6[ptr[1]] << 4 | b64_6[ptr[2]] >> 2;
784   }
785   if (nb64bytes > 3) {
786     *(out++) = b64_6[ptr[2]] << 6 | b64_6[ptr[3]];
787   }
788 
789   decoded->length = nbytesdecoded - ((4 - nb64bytes) & 3);
790   coap_free(tbuf);
791   return decoded;
792 }
793 
794 typedef coap_binary_t * (*asn1_callback)(const uint8_t *data, size_t size);
795 
796 static int
asn1_verify_privkey(const uint8_t * data,size_t size)797 asn1_verify_privkey(const uint8_t *data, size_t size)
798 {
799   /* Check if we have the private key (with optional leading 0x00) */
800   /* skip leading 0x00 */
801   if (size - 1 == DTLS_EC_KEY_SIZE && *data == '\000') {
802         --size;
803         ++data;
804   }
805 
806   /* Check if we have the private key */
807   if (size != DTLS_EC_KEY_SIZE)
808     return 0;
809 
810   return 1;
811 }
812 
813 static int
asn1_verify_pubkey(const uint8_t * data,size_t size)814 asn1_verify_pubkey(const uint8_t *data, size_t size)
815 {
816   (void)data;
817 
818   /* We have the public key
819      (with a leading 0x00 (no unused bits) 0x04 (not compressed() */
820   if (size - 2 != 2 * DTLS_EC_KEY_SIZE)
821     return 0;
822 
823   return 1;
824 }
825 
826 static int
asn1_verify_curve(const uint8_t * data,size_t size)827 asn1_verify_curve(const uint8_t *data, size_t size)
828 {
829   static uint8_t prime256v1_oid[] =
830          /* OID 1.2.840.10045.3.1.7 */
831          { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 };
832 
833   /* Check that we have the correct EC (only one supported) */
834   if (size != sizeof(prime256v1_oid) ||
835       memcmp(data, prime256v1_oid, size) != 0)
836     return 0;
837 
838   return 1;
839 }
840 
841 static int
asn1_verify_pkcs8_version(const uint8_t * data,size_t size)842 asn1_verify_pkcs8_version(const uint8_t *data, size_t size)
843 {
844   /* Check that we have the version */
845   if (size != 1 || *data != 0)
846     return 0;
847 
848   return 1;
849 }
850 
851 static int
asn1_verify_ec_identifier(const uint8_t * data,size_t size)852 asn1_verify_ec_identifier(const uint8_t *data, size_t size)
853 {
854   static uint8_t ec_public_key_oid[] =
855          /* OID 1.2.840.10045.2.1 */
856          { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01 };
857 
858   /* Check that we have the correct ecPublicKey */
859   if (size != sizeof(ec_public_key_oid) ||
860       memcmp(data, ec_public_key_oid, size) != 0)
861     return 0;
862 
863   return 1;
864 }
865 
866 static int
asn1_verify_ec_key(const uint8_t * data,size_t size)867 asn1_verify_ec_key(const uint8_t *data, size_t size)
868 {
869   (void)data;
870 
871   if (size == 0)
872     return 0;
873 
874   return 1;
875 }
876 
877 static int
asn1_derive_keys(coap_tiny_context_t * t_context,const uint8_t * priv_data,size_t priv_len,const uint8_t * pub_data,size_t pub_len,int is_pkcs8)878 asn1_derive_keys(coap_tiny_context_t *t_context,
879                  const uint8_t *priv_data, size_t priv_len,
880                  const uint8_t *pub_data, size_t pub_len,
881                  int is_pkcs8)
882 {
883   coap_binary_t *test;
884 
885   t_context->priv_key = get_asn1_tag(COAP_ASN1_OCTETSTRING, priv_data,
886                                      priv_len, asn1_verify_privkey);
887   if (!t_context->priv_key) {
888     coap_log(LOG_INFO, "EC Private Key (RPK) invalid\n");
889     return 0;
890   }
891   /* skip leading 0x00 */
892   if (t_context->priv_key->length - 1 == DTLS_EC_KEY_SIZE &&
893       t_context->priv_key->s[0] == '\000') {
894         t_context->priv_key->length--;
895         t_context->priv_key->s++;
896   }
897 
898   if (!is_pkcs8) {
899     /* pkcs8 abstraction tested for valid eliptic curve */
900     test = get_asn1_tag(COAP_ASN1_IDENTIFIER, priv_data, priv_len,
901                                     asn1_verify_curve);
902     if (!test) {
903       coap_log(LOG_INFO, "EC Private Key (RPK) invalid elliptic curve\n");
904       coap_delete_binary(t_context->priv_key);
905       t_context->priv_key = NULL;
906       return 0;
907     }
908     coap_delete_binary(test);
909   }
910 
911   t_context->pub_key = get_asn1_tag(COAP_ASN1_BITSTRING, pub_data, pub_len,
912                                               asn1_verify_pubkey);
913   if (!t_context->pub_key) {
914     coap_log(LOG_INFO, "EC Public Key (RPK) invalid\n");
915     coap_delete_binary(t_context->priv_key);
916     t_context->priv_key = NULL;
917     return 0;
918   }
919   /* Drop leading 0x00 and 0x04 */
920   t_context->pub_key->s += 2;
921   t_context->pub_key->length -= 2;
922   dtls_set_handler(t_context->dtls_context, &ec_cb);
923   return 1;
924 }
925 
926 static coap_binary_t *
ec_abstract_pkcs8_asn1(const uint8_t * asn1_ptr,size_t asn1_length)927 ec_abstract_pkcs8_asn1(const uint8_t *asn1_ptr, size_t asn1_length)
928 {
929   coap_binary_t *test;
930 
931   test = get_asn1_tag(COAP_ASN1_INTEGER, asn1_ptr, asn1_length,
932                                asn1_verify_pkcs8_version);
933   if (!test)
934     return 0;
935 
936   coap_delete_binary(test);
937 
938   test = get_asn1_tag(COAP_ASN1_IDENTIFIER, asn1_ptr, asn1_length,
939                                asn1_verify_ec_identifier);
940   if (!test)
941     return 0;
942   coap_delete_binary(test);
943 
944   test = get_asn1_tag(COAP_ASN1_IDENTIFIER, asn1_ptr, asn1_length,
945                                asn1_verify_curve);
946   if (!test) {
947     coap_log(LOG_INFO, "EC Private Key (RPK) invalid elliptic curve\n");
948     return 0;
949   }
950   coap_delete_binary(test);
951 
952   test = get_asn1_tag(COAP_ASN1_OCTETSTRING, asn1_ptr, asn1_length,
953                                asn1_verify_ec_key);
954   return test;
955 }
956 
957 static coap_binary_t *
pem_decode_mem_asn1(const char * begstr,const uint8_t * str)958 pem_decode_mem_asn1(const char *begstr, const uint8_t *str)
959 {
960   char *bcp = str ? strstr((const char*)str, begstr) : NULL;
961   char *tcp = bcp ? strstr(bcp, "-----END ") : NULL;
962 
963   if (bcp && tcp) {
964     bcp += strlen(begstr);
965     return pem_base64_decode ((const uint8_t *)bcp, tcp - bcp);
966   }
967   return NULL;
968 }
969 
970 #endif /* DTLS_ECC */
971 
972 int
coap_dtls_context_set_pki(coap_context_t * ctx,const coap_dtls_pki_t * setup_data,const coap_dtls_role_t role COAP_UNUSED)973 coap_dtls_context_set_pki(coap_context_t *ctx,
974                           const coap_dtls_pki_t* setup_data,
975                           const coap_dtls_role_t role COAP_UNUSED
976 ) {
977 #ifdef DTLS_ECC
978   coap_tiny_context_t *t_context;
979   coap_binary_t *asn1_priv;
980   coap_binary_t *asn1_pub;
981   coap_binary_t *asn1_temp;
982   int is_pkcs8 = 0;
983 
984   if (!setup_data)
985     return 0;
986   if (setup_data->version != COAP_DTLS_PKI_SETUP_VERSION)
987     return 0;
988   if (!setup_data->is_rpk_not_cert) {
989     coap_log(LOG_WARNING, "Only RPK, not full PKI is supported\n");
990     return 0;
991   }
992   if (!ctx)
993     return 0;
994   t_context = (coap_tiny_context_t *)ctx->dtls_context;
995   if (!t_context)
996     return 0;
997   if (t_context->priv_key) {
998     coap_delete_binary(t_context->priv_key);
999     t_context->priv_key = NULL;
1000   }
1001   if (t_context->pub_key) {
1002     coap_delete_binary(t_context->pub_key);
1003     t_context->pub_key = NULL;
1004   }
1005   t_context->setup_data = *setup_data;
1006 
1007   /* All should be RPK only now */
1008   switch (setup_data->pki_key.key_type) {
1009   case COAP_PKI_KEY_PEM:
1010     coap_log(LOG_WARNING, "RPK keys cannot be in COAP_PKI_KEY_PEM format\n");
1011     break;
1012   case COAP_PKI_KEY_PEM_BUF:
1013     if (setup_data->pki_key.key.pem_buf.public_cert &&
1014         setup_data->pki_key.key.pem_buf.public_cert[0] &&
1015         setup_data->pki_key.key.pem_buf.private_key &&
1016         setup_data->pki_key.key.pem_buf.private_key[0]) {
1017       /* Need to take PEM memory information and convert to binary */
1018       asn1_priv = pem_decode_mem_asn1("-----BEGIN EC PRIVATE KEY-----",
1019                                  setup_data->pki_key.key.pem_buf.private_key);
1020       if (!asn1_priv) {
1021         asn1_priv = pem_decode_mem_asn1("-----BEGIN PRIVATE KEY-----",
1022                                  setup_data->pki_key.key.pem_buf.private_key);
1023         if (!asn1_priv) {
1024           coap_log(LOG_INFO, "Private Key (RPK) invalid\n");
1025           return 0;
1026         }
1027         asn1_temp = ec_abstract_pkcs8_asn1(asn1_priv->s, asn1_priv->length);
1028         if (!asn1_temp) {
1029           coap_log(LOG_INFO, "PKCS#8 Private Key (RPK) invalid\n");
1030           coap_delete_binary(asn1_priv);
1031           return 0;
1032         }
1033         coap_delete_binary(asn1_priv);
1034         asn1_priv = asn1_temp;
1035         is_pkcs8 = 1;
1036       }
1037       asn1_pub = pem_decode_mem_asn1(
1038                                 "-----BEGIN PUBLIC KEY-----",
1039                                  setup_data->pki_key.key.pem_buf.public_cert);
1040       if (!asn1_pub) {
1041         asn1_pub = pem_decode_mem_asn1("-----BEGIN EC PRIVATE KEY-----",
1042                                  setup_data->pki_key.key.pem_buf.private_key);
1043         if (!asn1_pub) {
1044           asn1_pub = pem_decode_mem_asn1("-----BEGIN PRIVATE KEY-----",
1045                                  setup_data->pki_key.key.pem_buf.private_key);
1046           if (!asn1_pub) {
1047             coap_log(LOG_INFO, "Public Key (RPK) invalid\n");
1048             coap_delete_binary(asn1_priv);
1049             return 0;
1050           }
1051           asn1_temp = ec_abstract_pkcs8_asn1(asn1_pub->s, asn1_pub->length);
1052           if (!asn1_temp) {
1053             coap_log(LOG_INFO, "PKCS#8 Private Key (RPK) invalid\n");
1054             coap_delete_binary(asn1_priv);
1055             coap_delete_binary(asn1_pub);
1056             return 0;
1057           }
1058           coap_delete_binary(asn1_pub);
1059           asn1_pub = asn1_temp;
1060           is_pkcs8 = 1;
1061         }
1062       }
1063       if (!asn1_derive_keys(t_context, asn1_priv->s, asn1_priv->length,
1064                             asn1_pub->s, asn1_pub->length, is_pkcs8)) {
1065         coap_log(LOG_INFO, "Unable to derive Public/Private Keys\n");
1066         coap_delete_binary(asn1_priv);
1067         coap_delete_binary(asn1_pub);
1068         return 0;
1069       }
1070       coap_delete_binary(asn1_priv);
1071       coap_delete_binary(asn1_pub);
1072       return 1;
1073     }
1074     break;
1075   case COAP_PKI_KEY_ASN1:
1076     if (setup_data->pki_key.key.asn1.private_key &&
1077         setup_data->pki_key.key.asn1.private_key_len &&
1078          setup_data->pki_key.key.asn1.private_key_type == COAP_ASN1_PKEY_EC) {
1079       const uint8_t* private_key = setup_data->pki_key.key.asn1.private_key;
1080       size_t private_key_len = setup_data->pki_key.key.asn1.private_key_len;
1081 
1082       /* Check to see whether this is in pkcs8 format or not */
1083       asn1_temp = ec_abstract_pkcs8_asn1(
1084                        setup_data->pki_key.key.asn1.private_key,
1085                        setup_data->pki_key.key.asn1.private_key_len);
1086       if (asn1_temp) {
1087         private_key = asn1_temp->s;
1088         private_key_len = asn1_temp->length;
1089         is_pkcs8 = 1;
1090       }
1091       /* Need to take ASN1 memory information and convert to binary */
1092       if (setup_data->pki_key.key.asn1.public_cert &&
1093           setup_data->pki_key.key.asn1.public_cert_len) {
1094         if (!asn1_derive_keys(t_context,
1095                               private_key,
1096                               private_key_len,
1097                               setup_data->pki_key.key.asn1.public_cert,
1098                               setup_data->pki_key.key.asn1.public_cert_len,
1099                               is_pkcs8)) {
1100           coap_log(LOG_INFO, "Unable to derive Public/Private Keys\n");
1101           if (asn1_temp) coap_delete_binary(asn1_temp);
1102           return 0;
1103         }
1104       }
1105       else {
1106         if (!asn1_derive_keys(t_context,
1107                               private_key,
1108                               private_key_len,
1109                               private_key,
1110                               private_key_len,
1111                               is_pkcs8)) {
1112           coap_log(LOG_INFO, "Unable to derive Public/Private Keys\n");
1113           if (asn1_temp) coap_delete_binary(asn1_temp);
1114           return 0;
1115         }
1116       }
1117       return 1;
1118     }
1119     break;
1120   case COAP_PKI_KEY_PKCS11:
1121     coap_log(LOG_WARNING, "RPK keys cannot be in COAP_PKI_KEY_PCKS11 format\n");
1122     break;
1123   default:
1124     break;
1125   }
1126 #else /* ! DTLS_ECC */
1127   (void)ctx;
1128   (void)setup_data;
1129 #endif /* ! DTLS_ECC */
1130   return 0;
1131 }
1132 
1133 int
coap_dtls_context_set_pki_root_cas(coap_context_t * ctx COAP_UNUSED,const char * ca_file COAP_UNUSED,const char * ca_path COAP_UNUSED)1134 coap_dtls_context_set_pki_root_cas(coap_context_t *ctx COAP_UNUSED,
1135   const char *ca_file COAP_UNUSED,
1136   const char *ca_path COAP_UNUSED
1137 ) {
1138   coap_log(LOG_WARNING, "Root CAs PKI not supported\n");
1139   return 0;
1140 }
1141 
1142 int
coap_dtls_context_set_cpsk(coap_context_t * coap_context COAP_UNUSED,coap_dtls_cpsk_t * setup_data)1143 coap_dtls_context_set_cpsk(coap_context_t *coap_context COAP_UNUSED,
1144   coap_dtls_cpsk_t *setup_data
1145 ) {
1146   if (!setup_data)
1147     return 0;
1148 
1149   return 1;
1150 }
1151 
1152 int
coap_dtls_context_set_spsk(coap_context_t * coap_context COAP_UNUSED,coap_dtls_spsk_t * setup_data)1153 coap_dtls_context_set_spsk(coap_context_t *coap_context COAP_UNUSED,
1154   coap_dtls_spsk_t *setup_data
1155 ) {
1156   if (!setup_data)
1157     return 0;
1158 
1159   if (setup_data->validate_sni_call_back) {
1160     coap_log(LOG_WARNING,
1161         "CoAP Server with TinyDTLS does not support SNI selection\n");
1162   }
1163 
1164   return 1;
1165 }
1166 
1167 int
coap_dtls_context_check_keys_enabled(coap_context_t * ctx COAP_UNUSED)1168 coap_dtls_context_check_keys_enabled(coap_context_t *ctx COAP_UNUSED)
1169 {
1170   return 1;
1171 }
1172 
1173 #if !COAP_DISABLE_TCP
coap_tls_new_client_session(coap_session_t * session COAP_UNUSED,int * connected COAP_UNUSED)1174 void *coap_tls_new_client_session(coap_session_t *session COAP_UNUSED, int *connected COAP_UNUSED) {
1175   return NULL;
1176 }
1177 
coap_tls_new_server_session(coap_session_t * session COAP_UNUSED,int * connected COAP_UNUSED)1178 void *coap_tls_new_server_session(coap_session_t *session COAP_UNUSED, int *connected COAP_UNUSED) {
1179   return NULL;
1180 }
1181 
coap_tls_free_session(coap_session_t * coap_session COAP_UNUSED)1182 void coap_tls_free_session(coap_session_t *coap_session COAP_UNUSED) {
1183 }
1184 
coap_tls_write(coap_session_t * session COAP_UNUSED,const uint8_t * data COAP_UNUSED,size_t data_len COAP_UNUSED)1185 ssize_t coap_tls_write(coap_session_t *session COAP_UNUSED,
1186                        const uint8_t *data COAP_UNUSED,
1187                        size_t data_len COAP_UNUSED
1188 ) {
1189   return -1;
1190 }
1191 
coap_tls_read(coap_session_t * session COAP_UNUSED,uint8_t * data COAP_UNUSED,size_t data_len COAP_UNUSED)1192 ssize_t coap_tls_read(coap_session_t *session COAP_UNUSED,
1193                       uint8_t *data COAP_UNUSED,
1194                       size_t data_len COAP_UNUSED
1195 ) {
1196   return -1;
1197 }
1198 #endif /* !COAP_DISABLE_TCP */
1199 
1200 coap_digest_ctx_t *
coap_digest_setup(void)1201 coap_digest_setup(void) {
1202   dtls_sha256_ctx *digest_ctx = coap_malloc(sizeof(dtls_sha256_ctx));
1203 
1204   if (digest_ctx) {
1205     dtls_sha256_init(digest_ctx);
1206   }
1207 
1208   return digest_ctx;
1209 }
1210 
1211 void
coap_digest_free(coap_digest_ctx_t * digest_ctx)1212 coap_digest_free(coap_digest_ctx_t *digest_ctx) {
1213   coap_free(digest_ctx);
1214 }
1215 
1216 int
coap_digest_update(coap_digest_ctx_t * digest_ctx,const uint8_t * data,size_t data_len)1217 coap_digest_update(coap_digest_ctx_t *digest_ctx,
1218                    const uint8_t *data,
1219                    size_t data_len) {
1220   dtls_sha256_update(digest_ctx, data, data_len);
1221 
1222   return 1;
1223 }
1224 
1225 int
coap_digest_final(coap_digest_ctx_t * digest_ctx,coap_digest_t * digest_buffer)1226 coap_digest_final(coap_digest_ctx_t *digest_ctx,
1227                   coap_digest_t *digest_buffer) {
1228   dtls_sha256_final((uint8_t*)digest_buffer, digest_ctx);
1229 
1230   coap_digest_free(digest_ctx);
1231   return 1;
1232 }
1233 
1234 #else /* !HAVE_LIBTINYDTLS */
1235 
1236 #ifdef __clang__
1237 /* Make compilers happy that do not like empty modules. As this function is
1238  * never used, we ignore -Wunused-function at the end of compiling this file
1239  */
1240 #pragma GCC diagnostic ignored "-Wunused-function"
1241 #endif
dummy(void)1242 static inline void dummy(void) {
1243 }
1244 
1245 #endif /* HAVE_LIBTINYDTLS */
1246