1c87c5fbaSopenharmony_ci/*
2c87c5fbaSopenharmony_ci * coap_tinydtls.c -- Datagram Transport Layer Support for libcoap with tinydtls
3c87c5fbaSopenharmony_ci *
4c87c5fbaSopenharmony_ci * Copyright (C) 2016-2020 Olaf Bergmann <bergmann@tzi.org>
5c87c5fbaSopenharmony_ci * Copyright (C) 2020-2023 Jon Shallow <supjps-libcoap@jpshallow.com>
6c87c5fbaSopenharmony_ci *
7c87c5fbaSopenharmony_ci * SPDX-License-Identifier: BSD-2-Clause
8c87c5fbaSopenharmony_ci *
9c87c5fbaSopenharmony_ci * This file is part of the CoAP library libcoap. Please see README for terms
10c87c5fbaSopenharmony_ci * of use.
11c87c5fbaSopenharmony_ci */
12c87c5fbaSopenharmony_ci
13c87c5fbaSopenharmony_ci/**
14c87c5fbaSopenharmony_ci * @file coap_tinydtls.c
15c87c5fbaSopenharmony_ci * @brief TinyDTLS specific handling functions
16c87c5fbaSopenharmony_ci */
17c87c5fbaSopenharmony_ci
18c87c5fbaSopenharmony_ci#include "coap3/coap_internal.h"
19c87c5fbaSopenharmony_ci
20c87c5fbaSopenharmony_ci#ifdef COAP_WITH_LIBTINYDTLS
21c87c5fbaSopenharmony_ci
22c87c5fbaSopenharmony_ci/* We want TinyDTLS versions of these, not libcoap versions */
23c87c5fbaSopenharmony_ci#undef PACKAGE_BUGREPORT
24c87c5fbaSopenharmony_ci#undef PACKAGE_NAME
25c87c5fbaSopenharmony_ci#undef PACKAGE_STRING
26c87c5fbaSopenharmony_ci#undef PACKAGE_TARNAME
27c87c5fbaSopenharmony_ci#undef PACKAGE_URL
28c87c5fbaSopenharmony_ci#undef PACKAGE_VERSION
29c87c5fbaSopenharmony_ci
30c87c5fbaSopenharmony_ci#ifndef  RIOT_VERSION
31c87c5fbaSopenharmony_ci#include <tinydtls/tinydtls.h>
32c87c5fbaSopenharmony_ci#include <tinydtls/dtls.h>
33c87c5fbaSopenharmony_ci#include <tinydtls/dtls_debug.h>
34c87c5fbaSopenharmony_ci#include <tinydtls/dtls_time.h>
35c87c5fbaSopenharmony_ci#else /* RIOT_VERSION */
36c87c5fbaSopenharmony_ci#include <tinydtls.h>
37c87c5fbaSopenharmony_ci#include <dtls.h>
38c87c5fbaSopenharmony_ci#include <dtls_debug.h>
39c87c5fbaSopenharmony_ci#include <dtls_time.h>
40c87c5fbaSopenharmony_ci#endif /* RIOT_VERSION */
41c87c5fbaSopenharmony_ci
42c87c5fbaSopenharmony_citypedef struct coap_tiny_context_t {
43c87c5fbaSopenharmony_ci  struct dtls_context_t *dtls_context;
44c87c5fbaSopenharmony_ci  coap_context_t *coap_context;
45c87c5fbaSopenharmony_ci#ifdef DTLS_ECC
46c87c5fbaSopenharmony_ci  coap_dtls_pki_t setup_data;
47c87c5fbaSopenharmony_ci  coap_binary_t *priv_key;
48c87c5fbaSopenharmony_ci  coap_binary_t *pub_key;
49c87c5fbaSopenharmony_ci#endif /* DTLS_ECC */
50c87c5fbaSopenharmony_ci} coap_tiny_context_t;
51c87c5fbaSopenharmony_ci
52c87c5fbaSopenharmony_ci#if ! defined(DTLS_PSK) && ! defined(DTLS_ECC)
53c87c5fbaSopenharmony_ci#error Neither DTLS_PSK or DTLS_ECC defined
54c87c5fbaSopenharmony_ci#endif /* ! DTLS_PSK && ! DTLS_ECC */
55c87c5fbaSopenharmony_ci
56c87c5fbaSopenharmony_cistatic dtls_tick_t dtls_tick_0 = 0;
57c87c5fbaSopenharmony_cistatic coap_tick_t coap_tick_0 = 0;
58c87c5fbaSopenharmony_ci
59c87c5fbaSopenharmony_ciint
60c87c5fbaSopenharmony_cicoap_dtls_is_supported(void) {
61c87c5fbaSopenharmony_ci  return 1;
62c87c5fbaSopenharmony_ci}
63c87c5fbaSopenharmony_ci
64c87c5fbaSopenharmony_ci/*
65c87c5fbaSopenharmony_ci * return 0 failed
66c87c5fbaSopenharmony_ci *        1 passed
67c87c5fbaSopenharmony_ci */
68c87c5fbaSopenharmony_ciint
69c87c5fbaSopenharmony_cicoap_dtls_psk_is_supported(void) {
70c87c5fbaSopenharmony_ci#ifdef DTLS_PSK
71c87c5fbaSopenharmony_ci  return 1;
72c87c5fbaSopenharmony_ci#else /* ! DTLS_PSK */
73c87c5fbaSopenharmony_ci  return 0;
74c87c5fbaSopenharmony_ci#endif /* ! DTLS_PSK */
75c87c5fbaSopenharmony_ci}
76c87c5fbaSopenharmony_ci
77c87c5fbaSopenharmony_ci/*
78c87c5fbaSopenharmony_ci * return 0 failed
79c87c5fbaSopenharmony_ci *        1 passed
80c87c5fbaSopenharmony_ci */
81c87c5fbaSopenharmony_ciint
82c87c5fbaSopenharmony_cicoap_dtls_pki_is_supported(void) {
83c87c5fbaSopenharmony_ci  return 0;
84c87c5fbaSopenharmony_ci}
85c87c5fbaSopenharmony_ci
86c87c5fbaSopenharmony_ci/*
87c87c5fbaSopenharmony_ci * return 0 failed
88c87c5fbaSopenharmony_ci *        1 passed
89c87c5fbaSopenharmony_ci */
90c87c5fbaSopenharmony_ciint
91c87c5fbaSopenharmony_cicoap_dtls_pkcs11_is_supported(void) {
92c87c5fbaSopenharmony_ci  return 0;
93c87c5fbaSopenharmony_ci}
94c87c5fbaSopenharmony_ci
95c87c5fbaSopenharmony_ci/*
96c87c5fbaSopenharmony_ci * return 0 failed
97c87c5fbaSopenharmony_ci *        1 passed
98c87c5fbaSopenharmony_ci */
99c87c5fbaSopenharmony_ciint
100c87c5fbaSopenharmony_cicoap_dtls_rpk_is_supported(void) {
101c87c5fbaSopenharmony_ci#ifdef DTLS_ECC
102c87c5fbaSopenharmony_ci  return 1;
103c87c5fbaSopenharmony_ci#else /* ! DTLS_ECC */
104c87c5fbaSopenharmony_ci  return 0;
105c87c5fbaSopenharmony_ci#endif /* ! DTLS_ECC */
106c87c5fbaSopenharmony_ci}
107c87c5fbaSopenharmony_ci
108c87c5fbaSopenharmony_cistatic coap_log_t
109c87c5fbaSopenharmony_cidtls_map_logging(log_t d_level) {
110c87c5fbaSopenharmony_ci  /* DTLS_LOG_ERR is missing, so account for the gap */
111c87c5fbaSopenharmony_ci  switch (d_level) {
112c87c5fbaSopenharmony_ci  case DTLS_LOG_EMERG:
113c87c5fbaSopenharmony_ci    return COAP_LOG_EMERG;
114c87c5fbaSopenharmony_ci    break;
115c87c5fbaSopenharmony_ci  case DTLS_LOG_ALERT:
116c87c5fbaSopenharmony_ci    return COAP_LOG_ALERT;
117c87c5fbaSopenharmony_ci    break;
118c87c5fbaSopenharmony_ci  case DTLS_LOG_CRIT:
119c87c5fbaSopenharmony_ci    return COAP_LOG_CRIT;
120c87c5fbaSopenharmony_ci    break;
121c87c5fbaSopenharmony_ci  case DTLS_LOG_WARN:
122c87c5fbaSopenharmony_ci    return COAP_LOG_WARN;
123c87c5fbaSopenharmony_ci    break;
124c87c5fbaSopenharmony_ci  case DTLS_LOG_NOTICE:
125c87c5fbaSopenharmony_ci    return COAP_LOG_NOTICE;
126c87c5fbaSopenharmony_ci    break;
127c87c5fbaSopenharmony_ci  case DTLS_LOG_INFO:
128c87c5fbaSopenharmony_ci    return COAP_LOG_INFO;
129c87c5fbaSopenharmony_ci    break;
130c87c5fbaSopenharmony_ci  case DTLS_LOG_DEBUG:
131c87c5fbaSopenharmony_ci  default:
132c87c5fbaSopenharmony_ci    return COAP_LOG_DEBUG;
133c87c5fbaSopenharmony_ci    break;
134c87c5fbaSopenharmony_ci  }
135c87c5fbaSopenharmony_ci  return COAP_LOG_DEBUG;
136c87c5fbaSopenharmony_ci}
137c87c5fbaSopenharmony_ci#ifdef HAVE_DTLS_SET_LOG_HANDLER
138c87c5fbaSopenharmony_ci/* Valid after TinyDTLS submodule has been updated */
139c87c5fbaSopenharmony_cistatic void
140c87c5fbaSopenharmony_cidtls_logging(log_t d_level, const char *message) {
141c87c5fbaSopenharmony_ci  coap_log_t c_level = dtls_map_logging(d_level);
142c87c5fbaSopenharmony_ci
143c87c5fbaSopenharmony_ci  coap_dtls_log(c_level, "%s", message);
144c87c5fbaSopenharmony_ci}
145c87c5fbaSopenharmony_ci#endif /* HAVE_DTLS_SET_LOG_HANDLER */
146c87c5fbaSopenharmony_ci
147c87c5fbaSopenharmony_civoid
148c87c5fbaSopenharmony_cicoap_dtls_startup(void) {
149c87c5fbaSopenharmony_ci  dtls_init();
150c87c5fbaSopenharmony_ci  dtls_ticks(&dtls_tick_0);
151c87c5fbaSopenharmony_ci  coap_ticks(&coap_tick_0);
152c87c5fbaSopenharmony_ci#ifdef HAVE_DTLS_SET_LOG_HANDLER
153c87c5fbaSopenharmony_ci  /* Valid after TinyDTLS submodule has been updated */
154c87c5fbaSopenharmony_ci  dtls_set_log_handler(dtls_logging);
155c87c5fbaSopenharmony_ci#endif /* HAVE_DTLS_SET_LOG_HANDLER */
156c87c5fbaSopenharmony_ci  coap_dtls_set_log_level(COAP_LOG_EMERG);
157c87c5fbaSopenharmony_ci}
158c87c5fbaSopenharmony_ci
159c87c5fbaSopenharmony_civoid
160c87c5fbaSopenharmony_cicoap_dtls_shutdown(void) {
161c87c5fbaSopenharmony_ci  coap_dtls_set_log_level(COAP_LOG_EMERG);
162c87c5fbaSopenharmony_ci}
163c87c5fbaSopenharmony_ci
164c87c5fbaSopenharmony_civoid *
165c87c5fbaSopenharmony_cicoap_dtls_get_tls(const coap_session_t *c_session,
166c87c5fbaSopenharmony_ci                  coap_tls_library_t *tls_lib) {
167c87c5fbaSopenharmony_ci  if (tls_lib)
168c87c5fbaSopenharmony_ci    *tls_lib = COAP_TLS_LIBRARY_TINYDTLS;
169c87c5fbaSopenharmony_ci  if (c_session && c_session->context && c_session->context->dtls_context) {
170c87c5fbaSopenharmony_ci    const coap_tiny_context_t *t_context =
171c87c5fbaSopenharmony_ci        (const coap_tiny_context_t *)c_session->context->dtls_context;
172c87c5fbaSopenharmony_ci
173c87c5fbaSopenharmony_ci    return t_context->dtls_context;
174c87c5fbaSopenharmony_ci  }
175c87c5fbaSopenharmony_ci  return NULL;
176c87c5fbaSopenharmony_ci}
177c87c5fbaSopenharmony_ci
178c87c5fbaSopenharmony_civoid
179c87c5fbaSopenharmony_cicoap_dtls_set_log_level(coap_log_t c_level) {
180c87c5fbaSopenharmony_ci  log_t d_level;
181c87c5fbaSopenharmony_ci
182c87c5fbaSopenharmony_ci  /* DTLS_LOG_ERR is missing, so account for the gap */
183c87c5fbaSopenharmony_ci  switch (c_level) {
184c87c5fbaSopenharmony_ci  case COAP_LOG_EMERG:
185c87c5fbaSopenharmony_ci    d_level = DTLS_LOG_EMERG;
186c87c5fbaSopenharmony_ci    break;
187c87c5fbaSopenharmony_ci  case COAP_LOG_ALERT:
188c87c5fbaSopenharmony_ci    d_level = DTLS_LOG_ALERT;
189c87c5fbaSopenharmony_ci    break;
190c87c5fbaSopenharmony_ci  case COAP_LOG_CRIT:
191c87c5fbaSopenharmony_ci  case COAP_LOG_ERR:
192c87c5fbaSopenharmony_ci    d_level = DTLS_LOG_CRIT;
193c87c5fbaSopenharmony_ci    break;
194c87c5fbaSopenharmony_ci  case COAP_LOG_WARN:
195c87c5fbaSopenharmony_ci    d_level = DTLS_LOG_WARN;
196c87c5fbaSopenharmony_ci    break;
197c87c5fbaSopenharmony_ci  case COAP_LOG_NOTICE:
198c87c5fbaSopenharmony_ci    d_level = DTLS_LOG_NOTICE;
199c87c5fbaSopenharmony_ci    break;
200c87c5fbaSopenharmony_ci  case COAP_LOG_INFO:
201c87c5fbaSopenharmony_ci    d_level = DTLS_LOG_INFO;
202c87c5fbaSopenharmony_ci    break;
203c87c5fbaSopenharmony_ci  case COAP_LOG_DEBUG:
204c87c5fbaSopenharmony_ci  case COAP_LOG_OSCORE:
205c87c5fbaSopenharmony_ci  case COAP_LOG_DTLS_BASE:
206c87c5fbaSopenharmony_ci  default:
207c87c5fbaSopenharmony_ci    d_level = DTLS_LOG_DEBUG;
208c87c5fbaSopenharmony_ci    break;
209c87c5fbaSopenharmony_ci  }
210c87c5fbaSopenharmony_ci  dtls_set_log_level(d_level);
211c87c5fbaSopenharmony_ci}
212c87c5fbaSopenharmony_ci
213c87c5fbaSopenharmony_cicoap_log_t
214c87c5fbaSopenharmony_cicoap_dtls_get_log_level(void) {
215c87c5fbaSopenharmony_ci  log_t d_level = dtls_get_log_level();
216c87c5fbaSopenharmony_ci
217c87c5fbaSopenharmony_ci  return dtls_map_logging(d_level);
218c87c5fbaSopenharmony_ci}
219c87c5fbaSopenharmony_ci
220c87c5fbaSopenharmony_cistatic void
221c87c5fbaSopenharmony_ciget_session_addr(const session_t *s, coap_address_t *a) {
222c87c5fbaSopenharmony_ci#if defined(WITH_CONTIKI) || defined(WITH_LWIP)
223c87c5fbaSopenharmony_ci  a->addr = s->addr;
224c87c5fbaSopenharmony_ci  a->port = s->port;
225c87c5fbaSopenharmony_ci#elif defined(WITH_RIOT_SOCK)
226c87c5fbaSopenharmony_ci  if (s->addr.family == AF_INET6) {
227c87c5fbaSopenharmony_ci    a->size = (socklen_t)sizeof(a->addr.sin6);
228c87c5fbaSopenharmony_ci    a->addr.sa.sa_family = s->addr.family;
229c87c5fbaSopenharmony_ci    memcpy(&a->addr.sin6.sin6_addr, &s->addr.ipv6,
230c87c5fbaSopenharmony_ci           sizeof(a->addr.sin6.sin6_addr));
231c87c5fbaSopenharmony_ci    a->addr.sin6.sin6_port = s->addr.port;
232c87c5fbaSopenharmony_ci#ifdef SOCK_HAS_IPV4
233c87c5fbaSopenharmony_ci  } else if (s->addr.family == AF_INET) {
234c87c5fbaSopenharmony_ci    a->addr.sa.sa_family = s->addr.family;
235c87c5fbaSopenharmony_ci    a->size = (socklen_t)sizeof(a->addr.sin);
236c87c5fbaSopenharmony_ci    memcpy(&a->addr.sin.sin_addr, &s->addr.ipv4, sizeof(a->addr.sin.sin_addr));
237c87c5fbaSopenharmony_ci    a->addr.sin.sin_port = s->addr.port;
238c87c5fbaSopenharmony_ci#endif /* SOCK_HAS_IPV4 */
239c87c5fbaSopenharmony_ci  }
240c87c5fbaSopenharmony_ci#else /* ! WITH_CONTIKI && ! WITH_LWIP && ! WITH_RIOT_SOCK */
241c87c5fbaSopenharmony_ci  if (s->addr.sa.sa_family == AF_INET6) {
242c87c5fbaSopenharmony_ci    a->size = (socklen_t)sizeof(a->addr.sin6);
243c87c5fbaSopenharmony_ci    a->addr.sin6 = s->addr.sin6;
244c87c5fbaSopenharmony_ci  } else if (s->addr.sa.sa_family == AF_INET) {
245c87c5fbaSopenharmony_ci    a->size = (socklen_t)sizeof(a->addr.sin);
246c87c5fbaSopenharmony_ci    a->addr.sin = s->addr.sin;
247c87c5fbaSopenharmony_ci  } else {
248c87c5fbaSopenharmony_ci    a->size = (socklen_t)s->size;
249c87c5fbaSopenharmony_ci    a->addr.sa = s->addr.sa;
250c87c5fbaSopenharmony_ci  }
251c87c5fbaSopenharmony_ci#endif /* ! WITH_CONTIKI && ! WITH_LWIP && ! WITH_RIOT_SOCK */
252c87c5fbaSopenharmony_ci}
253c87c5fbaSopenharmony_ci
254c87c5fbaSopenharmony_cistatic void
255c87c5fbaSopenharmony_ciput_session_addr(const coap_address_t *a, session_t *s) {
256c87c5fbaSopenharmony_ci#if defined(WITH_CONTIKI) || defined(WITH_LWIP)
257c87c5fbaSopenharmony_ci  s->size = (unsigned char)sizeof(s->addr);
258c87c5fbaSopenharmony_ci  s->addr = a->addr;
259c87c5fbaSopenharmony_ci  s->port = a->port;
260c87c5fbaSopenharmony_ci#elif defined(WITH_RIOT_SOCK)
261c87c5fbaSopenharmony_ci  if (a->addr.sa.sa_family == AF_INET6) {
262c87c5fbaSopenharmony_ci    s->size = (socklen_t)sizeof(s->addr.ipv6);
263c87c5fbaSopenharmony_ci    s->addr.family = a->addr.sa.sa_family;
264c87c5fbaSopenharmony_ci    memcpy(&s->addr.ipv6, &a->addr.sin6.sin6_addr,
265c87c5fbaSopenharmony_ci           sizeof(s->addr.ipv6));
266c87c5fbaSopenharmony_ci    s->addr.port = a->addr.sin6.sin6_port;
267c87c5fbaSopenharmony_ci#ifdef SOCK_HAS_IPV4
268c87c5fbaSopenharmony_ci  } else if (a->addr.sa.sa_family == AF_INET) {
269c87c5fbaSopenharmony_ci    s->size = (socklen_t)sizeof(s->addr.ipv4);
270c87c5fbaSopenharmony_ci    s->addr.family = a->addr.sa.sa_family;
271c87c5fbaSopenharmony_ci    memcpy(&a->addr.ipv4, &s->addr.sin.sin_addr, sizeof(a->addr.ipv4));
272c87c5fbaSopenharmony_ci    s->addr.port = a->addr.sin.sin_port;
273c87c5fbaSopenharmony_ci#endif /* SOCK_HAS_IPV4 */
274c87c5fbaSopenharmony_ci  }
275c87c5fbaSopenharmony_ci#else /* ! WITH_CONTIKI && ! WITH_LWIP && ! WITH_RIOT_SOCK */
276c87c5fbaSopenharmony_ci  if (a->addr.sa.sa_family == AF_INET6) {
277c87c5fbaSopenharmony_ci    s->size = (socklen_t)sizeof(s->addr.sin6);
278c87c5fbaSopenharmony_ci    s->addr.sin6 = a->addr.sin6;
279c87c5fbaSopenharmony_ci  } else if (a->addr.sa.sa_family == AF_INET) {
280c87c5fbaSopenharmony_ci    s->size = (socklen_t)sizeof(s->addr.sin);
281c87c5fbaSopenharmony_ci    s->addr.sin = a->addr.sin;
282c87c5fbaSopenharmony_ci  } else {
283c87c5fbaSopenharmony_ci    s->size = (socklen_t)a->size;
284c87c5fbaSopenharmony_ci    s->addr.sa = a->addr.sa;
285c87c5fbaSopenharmony_ci  }
286c87c5fbaSopenharmony_ci#endif /* ! WITH_CONTIKI && ! WITH_LWIP && ! WITH_RIOT_SOCK */
287c87c5fbaSopenharmony_ci}
288c87c5fbaSopenharmony_ci
289c87c5fbaSopenharmony_cistatic int
290c87c5fbaSopenharmony_cidtls_send_to_peer(struct dtls_context_t *dtls_context,
291c87c5fbaSopenharmony_ci                  session_t *dtls_session, uint8 *data, size_t len) {
292c87c5fbaSopenharmony_ci  coap_tiny_context_t *t_context =
293c87c5fbaSopenharmony_ci      (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
294c87c5fbaSopenharmony_ci  coap_context_t *coap_context = t_context ? t_context->coap_context : NULL;
295c87c5fbaSopenharmony_ci  coap_session_t *coap_session;
296c87c5fbaSopenharmony_ci  coap_address_t remote_addr;
297c87c5fbaSopenharmony_ci
298c87c5fbaSopenharmony_ci  assert(coap_context);
299c87c5fbaSopenharmony_ci  get_session_addr(dtls_session, &remote_addr);
300c87c5fbaSopenharmony_ci  coap_session = coap_session_get_by_peer(coap_context, &remote_addr, dtls_session->ifindex);
301c87c5fbaSopenharmony_ci  if (!coap_session) {
302c87c5fbaSopenharmony_ci    coap_log_warn("dtls_send_to_peer: cannot find local interface\n");
303c87c5fbaSopenharmony_ci    return -3;
304c87c5fbaSopenharmony_ci  }
305c87c5fbaSopenharmony_ci  return (int)coap_session->sock.lfunc[COAP_LAYER_TLS].l_write(coap_session,
306c87c5fbaSopenharmony_ci         data, len);
307c87c5fbaSopenharmony_ci}
308c87c5fbaSopenharmony_ci
309c87c5fbaSopenharmony_cistatic int
310c87c5fbaSopenharmony_cidtls_application_data(struct dtls_context_t *dtls_context,
311c87c5fbaSopenharmony_ci                      session_t *dtls_session, uint8 *data, size_t len) {
312c87c5fbaSopenharmony_ci  coap_tiny_context_t *t_context =
313c87c5fbaSopenharmony_ci      (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
314c87c5fbaSopenharmony_ci  coap_context_t *coap_context = t_context ? t_context->coap_context : NULL;
315c87c5fbaSopenharmony_ci  coap_session_t *coap_session;
316c87c5fbaSopenharmony_ci  coap_address_t remote_addr;
317c87c5fbaSopenharmony_ci
318c87c5fbaSopenharmony_ci  assert(coap_context);
319c87c5fbaSopenharmony_ci  get_session_addr(dtls_session, &remote_addr);
320c87c5fbaSopenharmony_ci  coap_session = coap_session_get_by_peer(coap_context, &remote_addr, dtls_session->ifindex);
321c87c5fbaSopenharmony_ci  if (!coap_session) {
322c87c5fbaSopenharmony_ci    coap_log_debug("dropped message that was received on invalid interface\n");
323c87c5fbaSopenharmony_ci    return -1;
324c87c5fbaSopenharmony_ci  }
325c87c5fbaSopenharmony_ci
326c87c5fbaSopenharmony_ci  return coap_handle_dgram(coap_context, coap_session, data, len);
327c87c5fbaSopenharmony_ci}
328c87c5fbaSopenharmony_ci
329c87c5fbaSopenharmony_cistatic int coap_event_dtls = 0;
330c87c5fbaSopenharmony_ci
331c87c5fbaSopenharmony_cistatic int
332c87c5fbaSopenharmony_cidtls_event(struct dtls_context_t *dtls_context,
333c87c5fbaSopenharmony_ci           session_t *dtls_session,
334c87c5fbaSopenharmony_ci           dtls_alert_level_t level,
335c87c5fbaSopenharmony_ci           uint16_t code) {
336c87c5fbaSopenharmony_ci  (void)dtls_context;
337c87c5fbaSopenharmony_ci  (void)dtls_session;
338c87c5fbaSopenharmony_ci
339c87c5fbaSopenharmony_ci  if (level == DTLS_ALERT_LEVEL_FATAL)
340c87c5fbaSopenharmony_ci    coap_event_dtls = COAP_EVENT_DTLS_ERROR;
341c87c5fbaSopenharmony_ci
342c87c5fbaSopenharmony_ci  /* handle DTLS events */
343c87c5fbaSopenharmony_ci  switch (code) {
344c87c5fbaSopenharmony_ci  case DTLS_ALERT_CLOSE_NOTIFY: {
345c87c5fbaSopenharmony_ci    coap_event_dtls = COAP_EVENT_DTLS_CLOSED;
346c87c5fbaSopenharmony_ci    break;
347c87c5fbaSopenharmony_ci  }
348c87c5fbaSopenharmony_ci  case DTLS_EVENT_CONNECTED: {
349c87c5fbaSopenharmony_ci    coap_event_dtls = COAP_EVENT_DTLS_CONNECTED;
350c87c5fbaSopenharmony_ci    break;
351c87c5fbaSopenharmony_ci  }
352c87c5fbaSopenharmony_ci#ifdef DTLS_EVENT_RENEGOTIATE
353c87c5fbaSopenharmony_ci  case DTLS_EVENT_RENEGOTIATE: {
354c87c5fbaSopenharmony_ci    coap_event_dtls = COAP_EVENT_DTLS_RENEGOTIATE;
355c87c5fbaSopenharmony_ci    break;
356c87c5fbaSopenharmony_ci  }
357c87c5fbaSopenharmony_ci#endif
358c87c5fbaSopenharmony_ci  default:
359c87c5fbaSopenharmony_ci    ;
360c87c5fbaSopenharmony_ci  }
361c87c5fbaSopenharmony_ci
362c87c5fbaSopenharmony_ci  return 0;
363c87c5fbaSopenharmony_ci}
364c87c5fbaSopenharmony_ci
365c87c5fbaSopenharmony_ci#ifdef DTLS_PSK
366c87c5fbaSopenharmony_ci/* This function is the "key store" for tinyDTLS. It is called to
367c87c5fbaSopenharmony_ci * retrieve a key for the given identity within this particular
368c87c5fbaSopenharmony_ci * session. */
369c87c5fbaSopenharmony_cistatic int
370c87c5fbaSopenharmony_ciget_psk_info(struct dtls_context_t *dtls_context,
371c87c5fbaSopenharmony_ci             const session_t *dtls_session,
372c87c5fbaSopenharmony_ci             dtls_credentials_type_t type,
373c87c5fbaSopenharmony_ci             const uint8_t *id, size_t id_len,
374c87c5fbaSopenharmony_ci             unsigned char *result, size_t result_length) {
375c87c5fbaSopenharmony_ci
376c87c5fbaSopenharmony_ci  coap_tiny_context_t *t_context =
377c87c5fbaSopenharmony_ci      (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
378c87c5fbaSopenharmony_ci  coap_context_t *coap_context = t_context ? t_context->coap_context : NULL;
379c87c5fbaSopenharmony_ci  coap_session_t *coap_session;
380c87c5fbaSopenharmony_ci  int fatal_error = DTLS_ALERT_INTERNAL_ERROR;
381c87c5fbaSopenharmony_ci  coap_address_t remote_addr;
382c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT
383c87c5fbaSopenharmony_ci  coap_dtls_cpsk_t *setup_cdata;
384c87c5fbaSopenharmony_ci  const coap_bin_const_t *psk_identity;
385c87c5fbaSopenharmony_ci  const coap_dtls_cpsk_info_t *cpsk_info;
386c87c5fbaSopenharmony_ci#endif /* COAP_CLIENT_SUPPORT */
387c87c5fbaSopenharmony_ci  const coap_bin_const_t *psk_key;
388c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT
389c87c5fbaSopenharmony_ci  coap_dtls_spsk_t *setup_sdata;
390c87c5fbaSopenharmony_ci  const coap_bin_const_t *psk_hint;
391c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */
392c87c5fbaSopenharmony_ci
393c87c5fbaSopenharmony_ci  assert(coap_context);
394c87c5fbaSopenharmony_ci  get_session_addr(dtls_session, &remote_addr);
395c87c5fbaSopenharmony_ci  coap_session = coap_session_get_by_peer(coap_context, &remote_addr, dtls_session->ifindex);
396c87c5fbaSopenharmony_ci  if (!coap_session) {
397c87c5fbaSopenharmony_ci    coap_log_debug("cannot get PSK, session not found\n");
398c87c5fbaSopenharmony_ci    goto error;
399c87c5fbaSopenharmony_ci  }
400c87c5fbaSopenharmony_ci
401c87c5fbaSopenharmony_ci  switch (type) {
402c87c5fbaSopenharmony_ci  case DTLS_PSK_IDENTITY:
403c87c5fbaSopenharmony_ci
404c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT
405c87c5fbaSopenharmony_ci    if (coap_session->type != COAP_SESSION_TYPE_CLIENT)
406c87c5fbaSopenharmony_ci      goto error;
407c87c5fbaSopenharmony_ci
408c87c5fbaSopenharmony_ci    setup_cdata = &coap_session->cpsk_setup_data;
409c87c5fbaSopenharmony_ci
410c87c5fbaSopenharmony_ci    coap_bin_const_t temp;
411c87c5fbaSopenharmony_ci    temp.s = id;
412c87c5fbaSopenharmony_ci    temp.length = id_len;
413c87c5fbaSopenharmony_ci    coap_session_refresh_psk_hint(coap_session, &temp);
414c87c5fbaSopenharmony_ci
415c87c5fbaSopenharmony_ci    coap_log_debug("got psk_identity_hint: '%.*s'\n", (int)id_len,
416c87c5fbaSopenharmony_ci                   id ? (const char *)id : "");
417c87c5fbaSopenharmony_ci
418c87c5fbaSopenharmony_ci    if (setup_cdata->validate_ih_call_back) {
419c87c5fbaSopenharmony_ci      coap_str_const_t lhint;
420c87c5fbaSopenharmony_ci
421c87c5fbaSopenharmony_ci      lhint.length = id_len;
422c87c5fbaSopenharmony_ci      lhint.s = id;
423c87c5fbaSopenharmony_ci      cpsk_info =
424c87c5fbaSopenharmony_ci          setup_cdata->validate_ih_call_back(&lhint,
425c87c5fbaSopenharmony_ci                                             coap_session,
426c87c5fbaSopenharmony_ci                                             setup_cdata->ih_call_back_arg);
427c87c5fbaSopenharmony_ci      if (cpsk_info) {
428c87c5fbaSopenharmony_ci        psk_identity = &cpsk_info->identity;
429c87c5fbaSopenharmony_ci        coap_session_refresh_psk_identity(coap_session, &cpsk_info->identity);
430c87c5fbaSopenharmony_ci        coap_session_refresh_psk_key(coap_session, &cpsk_info->key);
431c87c5fbaSopenharmony_ci      } else {
432c87c5fbaSopenharmony_ci        psk_identity = NULL;
433c87c5fbaSopenharmony_ci      }
434c87c5fbaSopenharmony_ci    } else {
435c87c5fbaSopenharmony_ci      psk_identity = coap_get_session_client_psk_identity(coap_session);
436c87c5fbaSopenharmony_ci    }
437c87c5fbaSopenharmony_ci    if (psk_identity == NULL) {
438c87c5fbaSopenharmony_ci      coap_log_warn("no PSK identity given\n");
439c87c5fbaSopenharmony_ci      fatal_error = DTLS_ALERT_CLOSE_NOTIFY;
440c87c5fbaSopenharmony_ci      goto error;
441c87c5fbaSopenharmony_ci    }
442c87c5fbaSopenharmony_ci    if (psk_identity->length > result_length) {
443c87c5fbaSopenharmony_ci      coap_log_warn("psk_identity too large, truncated to %zd bytes\n",
444c87c5fbaSopenharmony_ci                    result_length);
445c87c5fbaSopenharmony_ci    } else {
446c87c5fbaSopenharmony_ci      /* Reduce to match */
447c87c5fbaSopenharmony_ci      result_length = psk_identity->length;
448c87c5fbaSopenharmony_ci    }
449c87c5fbaSopenharmony_ci    memcpy(result, psk_identity->s, result_length);
450c87c5fbaSopenharmony_ci    return result_length;
451c87c5fbaSopenharmony_ci#else /* ! COAP_CLIENT_SUPPORT */
452c87c5fbaSopenharmony_ci    return 0;
453c87c5fbaSopenharmony_ci#endif /* ! COAP_CLIENT_SUPPORT */
454c87c5fbaSopenharmony_ci
455c87c5fbaSopenharmony_ci  case DTLS_PSK_KEY:
456c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT
457c87c5fbaSopenharmony_ci    if (coap_session->type == COAP_SESSION_TYPE_CLIENT) {
458c87c5fbaSopenharmony_ci      psk_key = coap_get_session_client_psk_key(coap_session);
459c87c5fbaSopenharmony_ci      if (psk_key == NULL) {
460c87c5fbaSopenharmony_ci        coap_log_warn("no PSK key given\n");
461c87c5fbaSopenharmony_ci        fatal_error = DTLS_ALERT_CLOSE_NOTIFY;
462c87c5fbaSopenharmony_ci        goto error;
463c87c5fbaSopenharmony_ci      }
464c87c5fbaSopenharmony_ci      if (psk_key->length > result_length) {
465c87c5fbaSopenharmony_ci        coap_log_warn("psk_key too large, truncated to %zd bytes\n",
466c87c5fbaSopenharmony_ci                      result_length);
467c87c5fbaSopenharmony_ci      } else {
468c87c5fbaSopenharmony_ci        /* Reduce to match */
469c87c5fbaSopenharmony_ci        result_length = psk_key->length;
470c87c5fbaSopenharmony_ci      }
471c87c5fbaSopenharmony_ci      memcpy(result, psk_key->s, result_length);
472c87c5fbaSopenharmony_ci      return result_length;
473c87c5fbaSopenharmony_ci    }
474c87c5fbaSopenharmony_ci#endif /* COAP_CLIENT_SUPPORT */
475c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT
476c87c5fbaSopenharmony_ci    if (coap_session->type != COAP_SESSION_TYPE_CLIENT) {
477c87c5fbaSopenharmony_ci      coap_bin_const_t lidentity;
478c87c5fbaSopenharmony_ci
479c87c5fbaSopenharmony_ci      lidentity.length = id ? id_len : 0;
480c87c5fbaSopenharmony_ci      lidentity.s = id ? (const uint8_t *)id : (const uint8_t *)"";
481c87c5fbaSopenharmony_ci      setup_sdata = &coap_session->context->spsk_setup_data;
482c87c5fbaSopenharmony_ci
483c87c5fbaSopenharmony_ci      /* Track the Identity being used */
484c87c5fbaSopenharmony_ci      coap_session_refresh_psk_identity(coap_session, &lidentity);
485c87c5fbaSopenharmony_ci
486c87c5fbaSopenharmony_ci      coap_log_debug("got psk_identity: '%.*s'\n",
487c87c5fbaSopenharmony_ci                     (int)lidentity.length, lidentity.s);
488c87c5fbaSopenharmony_ci
489c87c5fbaSopenharmony_ci      if (setup_sdata->validate_id_call_back) {
490c87c5fbaSopenharmony_ci        psk_key =
491c87c5fbaSopenharmony_ci            setup_sdata->validate_id_call_back(&lidentity,
492c87c5fbaSopenharmony_ci                                               coap_session,
493c87c5fbaSopenharmony_ci                                               setup_sdata->id_call_back_arg);
494c87c5fbaSopenharmony_ci      } else {
495c87c5fbaSopenharmony_ci        psk_key = coap_get_session_server_psk_key(coap_session);
496c87c5fbaSopenharmony_ci      }
497c87c5fbaSopenharmony_ci
498c87c5fbaSopenharmony_ci      if (psk_key == NULL) {
499c87c5fbaSopenharmony_ci        coap_log_warn("no PSK key given\n");
500c87c5fbaSopenharmony_ci        return 0;
501c87c5fbaSopenharmony_ci      }
502c87c5fbaSopenharmony_ci      if (setup_sdata->validate_id_call_back)
503c87c5fbaSopenharmony_ci        coap_session_refresh_psk_key(coap_session, psk_key);
504c87c5fbaSopenharmony_ci      if (psk_key->length > result_length) {
505c87c5fbaSopenharmony_ci        coap_log_warn("psk_key too large, truncated to %zd bytes\n",
506c87c5fbaSopenharmony_ci                      result_length);
507c87c5fbaSopenharmony_ci      } else {
508c87c5fbaSopenharmony_ci        /* Reduce to match */
509c87c5fbaSopenharmony_ci        result_length = psk_key->length;
510c87c5fbaSopenharmony_ci      }
511c87c5fbaSopenharmony_ci      memcpy(result, psk_key->s, result_length);
512c87c5fbaSopenharmony_ci      return result_length;
513c87c5fbaSopenharmony_ci    }
514c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */
515c87c5fbaSopenharmony_ci    return 0;
516c87c5fbaSopenharmony_ci
517c87c5fbaSopenharmony_ci  case DTLS_PSK_HINT:
518c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT
519c87c5fbaSopenharmony_ci    psk_hint = coap_get_session_server_psk_hint(coap_session);
520c87c5fbaSopenharmony_ci    if (psk_hint == NULL)
521c87c5fbaSopenharmony_ci      return 0;
522c87c5fbaSopenharmony_ci    if (psk_hint->length > result_length) {
523c87c5fbaSopenharmony_ci      coap_log_warn("psk_hint too large, truncated to %zd bytes\n",
524c87c5fbaSopenharmony_ci                    result_length);
525c87c5fbaSopenharmony_ci    } else {
526c87c5fbaSopenharmony_ci      /* Reduce to match */
527c87c5fbaSopenharmony_ci      result_length = psk_hint->length;
528c87c5fbaSopenharmony_ci    }
529c87c5fbaSopenharmony_ci    memcpy(result, psk_hint->s, result_length);
530c87c5fbaSopenharmony_ci    return result_length;
531c87c5fbaSopenharmony_ci#else /* COAP_SERVER_SUPPORT */
532c87c5fbaSopenharmony_ci    return 0;
533c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */
534c87c5fbaSopenharmony_ci
535c87c5fbaSopenharmony_ci  default:
536c87c5fbaSopenharmony_ci    coap_log_warn("unsupported request type: %d\n", type);
537c87c5fbaSopenharmony_ci  }
538c87c5fbaSopenharmony_ci
539c87c5fbaSopenharmony_cierror:
540c87c5fbaSopenharmony_ci  return dtls_alert_fatal_create(fatal_error);
541c87c5fbaSopenharmony_ci}
542c87c5fbaSopenharmony_ci#endif /* DTLS_PSK */
543c87c5fbaSopenharmony_ci
544c87c5fbaSopenharmony_ci#ifdef DTLS_ECC
545c87c5fbaSopenharmony_cistatic int
546c87c5fbaSopenharmony_ciget_ecdsa_key(struct dtls_context_t *dtls_context,
547c87c5fbaSopenharmony_ci              const session_t *dtls_session COAP_UNUSED,
548c87c5fbaSopenharmony_ci              const dtls_ecdsa_key_t **result) {
549c87c5fbaSopenharmony_ci  static dtls_ecdsa_key_t ecdsa_key;
550c87c5fbaSopenharmony_ci  coap_tiny_context_t *t_context =
551c87c5fbaSopenharmony_ci      (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
552c87c5fbaSopenharmony_ci
553c87c5fbaSopenharmony_ci  ecdsa_key.curve = DTLS_ECDH_CURVE_SECP256R1;
554c87c5fbaSopenharmony_ci  ecdsa_key.priv_key = t_context->priv_key->s;
555c87c5fbaSopenharmony_ci  ecdsa_key.pub_key_x = t_context->pub_key->s;
556c87c5fbaSopenharmony_ci  ecdsa_key.pub_key_y = &t_context->pub_key->s[DTLS_EC_KEY_SIZE];
557c87c5fbaSopenharmony_ci
558c87c5fbaSopenharmony_ci  *result = &ecdsa_key;
559c87c5fbaSopenharmony_ci  return 0;
560c87c5fbaSopenharmony_ci}
561c87c5fbaSopenharmony_ci
562c87c5fbaSopenharmony_ci/* first part of Raw public key, the is the start of the Subject Public Key */
563c87c5fbaSopenharmony_cistatic const unsigned char cert_asn1_header[] = {
564c87c5fbaSopenharmony_ci  0x30, 0x59, /* SEQUENCE, length 89 bytes */
565c87c5fbaSopenharmony_ci  0x30, 0x13, /* SEQUENCE, length 19 bytes */
566c87c5fbaSopenharmony_ci  0x06, 0x07, /* OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1) */
567c87c5fbaSopenharmony_ci  0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01,
568c87c5fbaSopenharmony_ci  0x06, 0x08, /* OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7) */
569c87c5fbaSopenharmony_ci  0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07,
570c87c5fbaSopenharmony_ci  0x03, 0x42, 0x00, /* BIT STRING, length 66 bytes, 0 bits unused */
571c87c5fbaSopenharmony_ci  0x04 /* uncompressed, followed by the r and s values of the public key */
572c87c5fbaSopenharmony_ci};
573c87c5fbaSopenharmony_ci#define DTLS_CE_LENGTH (sizeof(cert_asn1_header) + key_size + key_size)
574c87c5fbaSopenharmony_ci
575c87c5fbaSopenharmony_cistatic int
576c87c5fbaSopenharmony_civerify_ecdsa_key(struct dtls_context_t *dtls_context COAP_UNUSED,
577c87c5fbaSopenharmony_ci                 const session_t *dtls_session COAP_UNUSED,
578c87c5fbaSopenharmony_ci                 const uint8_t *other_pub_x,
579c87c5fbaSopenharmony_ci                 const uint8_t *other_pub_y,
580c87c5fbaSopenharmony_ci                 size_t key_size) {
581c87c5fbaSopenharmony_ci  coap_tiny_context_t *t_context =
582c87c5fbaSopenharmony_ci      (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
583c87c5fbaSopenharmony_ci  if (t_context && t_context->setup_data.validate_cn_call_back) {
584c87c5fbaSopenharmony_ci    /* Need to build asn.1 certificate - code taken from tinydtls */
585c87c5fbaSopenharmony_ci    uint8 *p;
586c87c5fbaSopenharmony_ci    uint8 buf[DTLS_CE_LENGTH];
587c87c5fbaSopenharmony_ci    coap_session_t *c_session;
588c87c5fbaSopenharmony_ci    coap_address_t remote_addr;
589c87c5fbaSopenharmony_ci
590c87c5fbaSopenharmony_ci    /* Certificate
591c87c5fbaSopenharmony_ci     *
592c87c5fbaSopenharmony_ci     * Start message construction at beginning of buffer. */
593c87c5fbaSopenharmony_ci    p = buf;
594c87c5fbaSopenharmony_ci
595c87c5fbaSopenharmony_ci    memcpy(p, &cert_asn1_header, sizeof(cert_asn1_header));
596c87c5fbaSopenharmony_ci    p += sizeof(cert_asn1_header);
597c87c5fbaSopenharmony_ci
598c87c5fbaSopenharmony_ci    memcpy(p, other_pub_x, key_size);
599c87c5fbaSopenharmony_ci    p += key_size;
600c87c5fbaSopenharmony_ci
601c87c5fbaSopenharmony_ci    memcpy(p, other_pub_y, key_size);
602c87c5fbaSopenharmony_ci    p += key_size;
603c87c5fbaSopenharmony_ci
604c87c5fbaSopenharmony_ci    assert(p <= (buf + sizeof(buf)));
605c87c5fbaSopenharmony_ci
606c87c5fbaSopenharmony_ci    get_session_addr(dtls_session, &remote_addr);
607c87c5fbaSopenharmony_ci    c_session = coap_session_get_by_peer(t_context->coap_context,
608c87c5fbaSopenharmony_ci                                         &remote_addr, dtls_session->ifindex);
609c87c5fbaSopenharmony_ci    if (!c_session)
610c87c5fbaSopenharmony_ci      return -3;
611c87c5fbaSopenharmony_ci    if (!t_context->setup_data.validate_cn_call_back(COAP_DTLS_RPK_CERT_CN,
612c87c5fbaSopenharmony_ci                                                     buf, p-buf, c_session, 0, 1, t_context->setup_data.cn_call_back_arg)) {
613c87c5fbaSopenharmony_ci      return -1;
614c87c5fbaSopenharmony_ci    }
615c87c5fbaSopenharmony_ci  }
616c87c5fbaSopenharmony_ci  return 0;
617c87c5fbaSopenharmony_ci}
618c87c5fbaSopenharmony_cistatic dtls_handler_t ec_cb = {
619c87c5fbaSopenharmony_ci  .write = dtls_send_to_peer,
620c87c5fbaSopenharmony_ci  .read = dtls_application_data,
621c87c5fbaSopenharmony_ci  .event = dtls_event,
622c87c5fbaSopenharmony_ci#ifdef DTLS_PSK
623c87c5fbaSopenharmony_ci  .get_psk_info = NULL,
624c87c5fbaSopenharmony_ci#endif /* DTLS_PSK */
625c87c5fbaSopenharmony_ci  .get_ecdsa_key = get_ecdsa_key,
626c87c5fbaSopenharmony_ci  .verify_ecdsa_key = verify_ecdsa_key
627c87c5fbaSopenharmony_ci};
628c87c5fbaSopenharmony_ci#endif /* DTLS_ECC */
629c87c5fbaSopenharmony_ci
630c87c5fbaSopenharmony_cistatic dtls_handler_t psk_cb = {
631c87c5fbaSopenharmony_ci  .write = dtls_send_to_peer,
632c87c5fbaSopenharmony_ci  .read = dtls_application_data,
633c87c5fbaSopenharmony_ci  .event = dtls_event,
634c87c5fbaSopenharmony_ci#ifdef DTLS_PSK
635c87c5fbaSopenharmony_ci  .get_psk_info = get_psk_info,
636c87c5fbaSopenharmony_ci#endif /* DTLS_PSK */
637c87c5fbaSopenharmony_ci#ifdef DTLS_ECC
638c87c5fbaSopenharmony_ci  .get_ecdsa_key = NULL,
639c87c5fbaSopenharmony_ci  .verify_ecdsa_key = NULL
640c87c5fbaSopenharmony_ci#endif /* DTLS_ECC */
641c87c5fbaSopenharmony_ci};
642c87c5fbaSopenharmony_ci
643c87c5fbaSopenharmony_civoid *
644c87c5fbaSopenharmony_cicoap_dtls_new_context(coap_context_t *coap_context) {
645c87c5fbaSopenharmony_ci  coap_tiny_context_t *t_context = coap_malloc_type(COAP_DTLS_CONTEXT, sizeof(coap_tiny_context_t));
646c87c5fbaSopenharmony_ci  struct dtls_context_t *dtls_context = t_context ? dtls_new_context(t_context) : NULL;
647c87c5fbaSopenharmony_ci  if (!dtls_context)
648c87c5fbaSopenharmony_ci    goto error;
649c87c5fbaSopenharmony_ci  memset(t_context, 0, sizeof(coap_tiny_context_t));
650c87c5fbaSopenharmony_ci  t_context->coap_context = coap_context;
651c87c5fbaSopenharmony_ci  t_context->dtls_context = dtls_context;
652c87c5fbaSopenharmony_ci  dtls_set_handler(dtls_context, &psk_cb);
653c87c5fbaSopenharmony_ci  return t_context;
654c87c5fbaSopenharmony_cierror:
655c87c5fbaSopenharmony_ci  if (t_context)
656c87c5fbaSopenharmony_ci    coap_free_type(COAP_DTLS_CONTEXT, t_context);
657c87c5fbaSopenharmony_ci  if (dtls_context)
658c87c5fbaSopenharmony_ci    coap_dtls_free_context(dtls_context);
659c87c5fbaSopenharmony_ci  return NULL;
660c87c5fbaSopenharmony_ci}
661c87c5fbaSopenharmony_ci
662c87c5fbaSopenharmony_civoid
663c87c5fbaSopenharmony_cicoap_dtls_free_context(void *handle) {
664c87c5fbaSopenharmony_ci  if (handle) {
665c87c5fbaSopenharmony_ci    coap_tiny_context_t *t_context = (coap_tiny_context_t *)handle;
666c87c5fbaSopenharmony_ci#ifdef DTLS_ECC
667c87c5fbaSopenharmony_ci    if (t_context->priv_key) {
668c87c5fbaSopenharmony_ci      coap_delete_binary(t_context->priv_key);
669c87c5fbaSopenharmony_ci      t_context->priv_key = NULL;
670c87c5fbaSopenharmony_ci    }
671c87c5fbaSopenharmony_ci    if (t_context->pub_key) {
672c87c5fbaSopenharmony_ci      coap_delete_binary(t_context->pub_key);
673c87c5fbaSopenharmony_ci      t_context->pub_key = NULL;
674c87c5fbaSopenharmony_ci    }
675c87c5fbaSopenharmony_ci#endif /* DTLS_ECC */
676c87c5fbaSopenharmony_ci    if (t_context->dtls_context)
677c87c5fbaSopenharmony_ci      dtls_free_context(t_context->dtls_context);
678c87c5fbaSopenharmony_ci    coap_free_type(COAP_DTLS_CONTEXT, t_context);
679c87c5fbaSopenharmony_ci  }
680c87c5fbaSopenharmony_ci}
681c87c5fbaSopenharmony_ci
682c87c5fbaSopenharmony_cistatic session_t *
683c87c5fbaSopenharmony_cicoap_dtls_new_session(coap_session_t *session) {
684c87c5fbaSopenharmony_ci  session_t *dtls_session = coap_malloc_type(COAP_DTLS_SESSION, sizeof(session_t));
685c87c5fbaSopenharmony_ci
686c87c5fbaSopenharmony_ci  if (dtls_session) {
687c87c5fbaSopenharmony_ci    /* create tinydtls session object from remote address and local
688c87c5fbaSopenharmony_ci    * endpoint handle */
689c87c5fbaSopenharmony_ci    dtls_session_init(dtls_session);
690c87c5fbaSopenharmony_ci    put_session_addr(&session->addr_info.remote, dtls_session);
691c87c5fbaSopenharmony_ci    dtls_session->ifindex = session->ifindex;
692c87c5fbaSopenharmony_ci    coap_log_debug("***new session %p\n", (void *)dtls_session);
693c87c5fbaSopenharmony_ci  }
694c87c5fbaSopenharmony_ci
695c87c5fbaSopenharmony_ci  return dtls_session;
696c87c5fbaSopenharmony_ci}
697c87c5fbaSopenharmony_ci
698c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT
699c87c5fbaSopenharmony_civoid *
700c87c5fbaSopenharmony_cicoap_dtls_new_server_session(coap_session_t *session) {
701c87c5fbaSopenharmony_ci  return coap_dtls_new_session(session);
702c87c5fbaSopenharmony_ci}
703c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */
704c87c5fbaSopenharmony_ci
705c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT
706c87c5fbaSopenharmony_civoid *
707c87c5fbaSopenharmony_cicoap_dtls_new_client_session(coap_session_t *session) {
708c87c5fbaSopenharmony_ci  dtls_peer_t *peer;
709c87c5fbaSopenharmony_ci  coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
710c87c5fbaSopenharmony_ci  dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
711c87c5fbaSopenharmony_ci  session_t *dtls_session = dtls_context ? coap_dtls_new_session(session) : NULL;
712c87c5fbaSopenharmony_ci
713c87c5fbaSopenharmony_ci  if (!dtls_session)
714c87c5fbaSopenharmony_ci    return NULL;
715c87c5fbaSopenharmony_ci  peer =
716c87c5fbaSopenharmony_ci      dtls_get_peer(dtls_context, dtls_session);
717c87c5fbaSopenharmony_ci
718c87c5fbaSopenharmony_ci  if (!peer) {
719c87c5fbaSopenharmony_ci    /* The peer connection does not yet exist. */
720c87c5fbaSopenharmony_ci    /* dtls_connect() returns a value greater than zero if a new
721c87c5fbaSopenharmony_ci    * connection attempt is made, 0 for session reuse. */
722c87c5fbaSopenharmony_ci    if (dtls_connect(dtls_context, dtls_session) >= 0) {
723c87c5fbaSopenharmony_ci      peer =
724c87c5fbaSopenharmony_ci          dtls_get_peer(dtls_context, dtls_session);
725c87c5fbaSopenharmony_ci    }
726c87c5fbaSopenharmony_ci  }
727c87c5fbaSopenharmony_ci
728c87c5fbaSopenharmony_ci  if (!peer) {
729c87c5fbaSopenharmony_ci    /* delete existing session because the peer object has been invalidated */
730c87c5fbaSopenharmony_ci    coap_free_type(COAP_DTLS_SESSION, dtls_session);
731c87c5fbaSopenharmony_ci    dtls_session = NULL;
732c87c5fbaSopenharmony_ci  }
733c87c5fbaSopenharmony_ci
734c87c5fbaSopenharmony_ci  return dtls_session;
735c87c5fbaSopenharmony_ci}
736c87c5fbaSopenharmony_ci#endif /* COAP_CLIENT_SUPPORT */
737c87c5fbaSopenharmony_ci
738c87c5fbaSopenharmony_civoid
739c87c5fbaSopenharmony_cicoap_dtls_session_update_mtu(coap_session_t *session) {
740c87c5fbaSopenharmony_ci  (void)session;
741c87c5fbaSopenharmony_ci}
742c87c5fbaSopenharmony_ci
743c87c5fbaSopenharmony_civoid
744c87c5fbaSopenharmony_cicoap_dtls_free_session(coap_session_t *coap_session) {
745c87c5fbaSopenharmony_ci  coap_tiny_context_t *t_context =
746c87c5fbaSopenharmony_ci      (coap_tiny_context_t *)coap_session->context->dtls_context;
747c87c5fbaSopenharmony_ci  dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
748c87c5fbaSopenharmony_ci
749c87c5fbaSopenharmony_ci  if (dtls_context == NULL)
750c87c5fbaSopenharmony_ci    return;
751c87c5fbaSopenharmony_ci  if (coap_session->tls && dtls_context) {
752c87c5fbaSopenharmony_ci    dtls_peer_t *peer = dtls_get_peer(dtls_context, (session_t *)coap_session->tls);
753c87c5fbaSopenharmony_ci    if (peer)
754c87c5fbaSopenharmony_ci      dtls_reset_peer(dtls_context, peer);
755c87c5fbaSopenharmony_ci    else
756c87c5fbaSopenharmony_ci      dtls_close(dtls_context, (session_t *)coap_session->tls);
757c87c5fbaSopenharmony_ci    coap_log_debug("***removed session %p\n", coap_session->tls);
758c87c5fbaSopenharmony_ci    coap_free_type(COAP_DTLS_SESSION, coap_session->tls);
759c87c5fbaSopenharmony_ci    coap_session->tls = NULL;
760c87c5fbaSopenharmony_ci    coap_handle_event(coap_session->context, COAP_EVENT_DTLS_CLOSED, coap_session);
761c87c5fbaSopenharmony_ci  }
762c87c5fbaSopenharmony_ci}
763c87c5fbaSopenharmony_ci
764c87c5fbaSopenharmony_cissize_t
765c87c5fbaSopenharmony_cicoap_dtls_send(coap_session_t *session,
766c87c5fbaSopenharmony_ci               const uint8_t *data,
767c87c5fbaSopenharmony_ci               size_t data_len) {
768c87c5fbaSopenharmony_ci  int res;
769c87c5fbaSopenharmony_ci  uint8_t *data_rw;
770c87c5fbaSopenharmony_ci  coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
771c87c5fbaSopenharmony_ci  dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
772c87c5fbaSopenharmony_ci
773c87c5fbaSopenharmony_ci  assert(dtls_context);
774c87c5fbaSopenharmony_ci
775c87c5fbaSopenharmony_ci  coap_event_dtls = -1;
776c87c5fbaSopenharmony_ci  /* Need to do this to not get a compiler warning about const parameters */
777c87c5fbaSopenharmony_ci  memcpy(&data_rw, &data, sizeof(data_rw));
778c87c5fbaSopenharmony_ci  res = dtls_write(dtls_context,
779c87c5fbaSopenharmony_ci                   (session_t *)session->tls, data_rw, data_len);
780c87c5fbaSopenharmony_ci
781c87c5fbaSopenharmony_ci  if (res < 0)
782c87c5fbaSopenharmony_ci    coap_log_warn("coap_dtls_send: cannot send PDU\n");
783c87c5fbaSopenharmony_ci
784c87c5fbaSopenharmony_ci  if (coap_event_dtls >= 0) {
785c87c5fbaSopenharmony_ci    /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */
786c87c5fbaSopenharmony_ci    if (coap_event_dtls != COAP_EVENT_DTLS_CLOSED)
787c87c5fbaSopenharmony_ci      coap_handle_event(session->context, coap_event_dtls, session);
788c87c5fbaSopenharmony_ci    if (coap_event_dtls == COAP_EVENT_DTLS_CONNECTED)
789c87c5fbaSopenharmony_ci      coap_session_connected(session);
790c87c5fbaSopenharmony_ci    else if (coap_event_dtls == COAP_EVENT_DTLS_CLOSED || coap_event_dtls == COAP_EVENT_DTLS_ERROR)
791c87c5fbaSopenharmony_ci      coap_session_disconnected(session, COAP_NACK_TLS_FAILED);
792c87c5fbaSopenharmony_ci  }
793c87c5fbaSopenharmony_ci
794c87c5fbaSopenharmony_ci  if (res > 0) {
795c87c5fbaSopenharmony_ci    if (res == (ssize_t)data_len)
796c87c5fbaSopenharmony_ci      coap_log_debug("*  %s: dtls:  sent %4d bytes\n",
797c87c5fbaSopenharmony_ci                     coap_session_str(session), res);
798c87c5fbaSopenharmony_ci    else
799c87c5fbaSopenharmony_ci      coap_log_debug("*  %s: dtls:  sent %4d of %4zd bytes\n",
800c87c5fbaSopenharmony_ci                     coap_session_str(session), res, data_len);
801c87c5fbaSopenharmony_ci  }
802c87c5fbaSopenharmony_ci  return res;
803c87c5fbaSopenharmony_ci}
804c87c5fbaSopenharmony_ci
805c87c5fbaSopenharmony_ciint
806c87c5fbaSopenharmony_cicoap_dtls_is_context_timeout(void) {
807c87c5fbaSopenharmony_ci  return 1;
808c87c5fbaSopenharmony_ci}
809c87c5fbaSopenharmony_ci
810c87c5fbaSopenharmony_cicoap_tick_t
811c87c5fbaSopenharmony_cicoap_dtls_get_context_timeout(void *tiny_context) {
812c87c5fbaSopenharmony_ci  clock_time_t next = 0;
813c87c5fbaSopenharmony_ci  coap_tiny_context_t *t_context = (coap_tiny_context_t *)tiny_context;
814c87c5fbaSopenharmony_ci  dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
815c87c5fbaSopenharmony_ci  if (tiny_context)
816c87c5fbaSopenharmony_ci    dtls_check_retransmit(dtls_context, &next);
817c87c5fbaSopenharmony_ci  if (next > 0)
818c87c5fbaSopenharmony_ci    return ((coap_tick_t)(next - dtls_tick_0)) * COAP_TICKS_PER_SECOND / DTLS_TICKS_PER_SECOND +
819c87c5fbaSopenharmony_ci           coap_tick_0;
820c87c5fbaSopenharmony_ci  return 0;
821c87c5fbaSopenharmony_ci}
822c87c5fbaSopenharmony_ci
823c87c5fbaSopenharmony_cicoap_tick_t
824c87c5fbaSopenharmony_cicoap_dtls_get_timeout(coap_session_t *session, coap_tick_t now) {
825c87c5fbaSopenharmony_ci  (void)session;
826c87c5fbaSopenharmony_ci  (void)now;
827c87c5fbaSopenharmony_ci  return 0;
828c87c5fbaSopenharmony_ci}
829c87c5fbaSopenharmony_ci
830c87c5fbaSopenharmony_ci/*
831c87c5fbaSopenharmony_ci * return 1 timed out
832c87c5fbaSopenharmony_ci *        0 still timing out
833c87c5fbaSopenharmony_ci */
834c87c5fbaSopenharmony_ciint
835c87c5fbaSopenharmony_cicoap_dtls_handle_timeout(coap_session_t *session) {
836c87c5fbaSopenharmony_ci  (void)session;
837c87c5fbaSopenharmony_ci  return 0;
838c87c5fbaSopenharmony_ci}
839c87c5fbaSopenharmony_ci
840c87c5fbaSopenharmony_ciint
841c87c5fbaSopenharmony_cicoap_dtls_receive(coap_session_t *session,
842c87c5fbaSopenharmony_ci                  const uint8_t *data,
843c87c5fbaSopenharmony_ci                  size_t data_len
844c87c5fbaSopenharmony_ci                 ) {
845c87c5fbaSopenharmony_ci  session_t *dtls_session = (session_t *)session->tls;
846c87c5fbaSopenharmony_ci  int err;
847c87c5fbaSopenharmony_ci  uint8_t *data_rw;
848c87c5fbaSopenharmony_ci  coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
849c87c5fbaSopenharmony_ci  dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
850c87c5fbaSopenharmony_ci
851c87c5fbaSopenharmony_ci  assert(dtls_context);
852c87c5fbaSopenharmony_ci  coap_event_dtls = -1;
853c87c5fbaSopenharmony_ci  /* Need to do this to not get a compiler warning about const parameters */
854c87c5fbaSopenharmony_ci  memcpy(&data_rw, &data, sizeof(data_rw));
855c87c5fbaSopenharmony_ci  err = dtls_handle_message(dtls_context, dtls_session, data_rw, (int)data_len);
856c87c5fbaSopenharmony_ci
857c87c5fbaSopenharmony_ci  if (err) {
858c87c5fbaSopenharmony_ci    coap_event_dtls = COAP_EVENT_DTLS_ERROR;
859c87c5fbaSopenharmony_ci  }
860c87c5fbaSopenharmony_ci
861c87c5fbaSopenharmony_ci  if (coap_event_dtls >= 0) {
862c87c5fbaSopenharmony_ci    /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */
863c87c5fbaSopenharmony_ci    if (coap_event_dtls != COAP_EVENT_DTLS_CLOSED)
864c87c5fbaSopenharmony_ci      coap_handle_event(session->context, coap_event_dtls, session);
865c87c5fbaSopenharmony_ci    if (coap_event_dtls == COAP_EVENT_DTLS_CONNECTED)
866c87c5fbaSopenharmony_ci      coap_session_connected(session);
867c87c5fbaSopenharmony_ci    else if (coap_event_dtls == COAP_EVENT_DTLS_CLOSED || coap_event_dtls == COAP_EVENT_DTLS_ERROR)
868c87c5fbaSopenharmony_ci      coap_session_disconnected(session, COAP_NACK_TLS_FAILED);
869c87c5fbaSopenharmony_ci  }
870c87c5fbaSopenharmony_ci
871c87c5fbaSopenharmony_ci  return err;
872c87c5fbaSopenharmony_ci}
873c87c5fbaSopenharmony_ci
874c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT
875c87c5fbaSopenharmony_ciint
876c87c5fbaSopenharmony_cicoap_dtls_hello(coap_session_t *session,
877c87c5fbaSopenharmony_ci                const uint8_t *data,
878c87c5fbaSopenharmony_ci                size_t data_len
879c87c5fbaSopenharmony_ci               ) {
880c87c5fbaSopenharmony_ci  session_t dtls_session;
881c87c5fbaSopenharmony_ci  coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
882c87c5fbaSopenharmony_ci  dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
883c87c5fbaSopenharmony_ci  uint8_t *data_rw;
884c87c5fbaSopenharmony_ci
885c87c5fbaSopenharmony_ci  assert(dtls_context);
886c87c5fbaSopenharmony_ci  dtls_session_init(&dtls_session);
887c87c5fbaSopenharmony_ci  put_session_addr(&session->addr_info.remote, &dtls_session);
888c87c5fbaSopenharmony_ci  dtls_session.ifindex = session->ifindex;
889c87c5fbaSopenharmony_ci  /* Need to do this to not get a compiler warning about const parameters */
890c87c5fbaSopenharmony_ci  memcpy(&data_rw, &data, sizeof(data_rw));
891c87c5fbaSopenharmony_ci  int res = dtls_handle_message(dtls_context, &dtls_session,
892c87c5fbaSopenharmony_ci                                data_rw, (int)data_len);
893c87c5fbaSopenharmony_ci  if (res >= 0) {
894c87c5fbaSopenharmony_ci    if (dtls_get_peer(dtls_context, &dtls_session))
895c87c5fbaSopenharmony_ci      res = 1;
896c87c5fbaSopenharmony_ci    else
897c87c5fbaSopenharmony_ci      res = 0;
898c87c5fbaSopenharmony_ci  }
899c87c5fbaSopenharmony_ci  return res;
900c87c5fbaSopenharmony_ci}
901c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */
902c87c5fbaSopenharmony_ci
903c87c5fbaSopenharmony_ciunsigned int
904c87c5fbaSopenharmony_cicoap_dtls_get_overhead(coap_session_t *session) {
905c87c5fbaSopenharmony_ci  (void)session;
906c87c5fbaSopenharmony_ci  return 13 + 8 + 8;
907c87c5fbaSopenharmony_ci}
908c87c5fbaSopenharmony_ci
909c87c5fbaSopenharmony_ciint
910c87c5fbaSopenharmony_cicoap_tls_is_supported(void) {
911c87c5fbaSopenharmony_ci  return 0;
912c87c5fbaSopenharmony_ci}
913c87c5fbaSopenharmony_ci
914c87c5fbaSopenharmony_cicoap_tls_version_t *
915c87c5fbaSopenharmony_cicoap_get_tls_library_version(void) {
916c87c5fbaSopenharmony_ci  static coap_tls_version_t version;
917c87c5fbaSopenharmony_ci  const char *vers = dtls_package_version();
918c87c5fbaSopenharmony_ci
919c87c5fbaSopenharmony_ci  version.version = 0;
920c87c5fbaSopenharmony_ci  if (vers) {
921c87c5fbaSopenharmony_ci    long int p1, p2 = 0, p3 = 0;
922c87c5fbaSopenharmony_ci    char *endptr;
923c87c5fbaSopenharmony_ci
924c87c5fbaSopenharmony_ci    p1 = strtol(vers, &endptr, 10);
925c87c5fbaSopenharmony_ci    if (*endptr == '.') {
926c87c5fbaSopenharmony_ci      p2 = strtol(endptr+1, &endptr, 10);
927c87c5fbaSopenharmony_ci      if (*endptr == '.') {
928c87c5fbaSopenharmony_ci        p3 = strtol(endptr+1, &endptr, 10);
929c87c5fbaSopenharmony_ci      }
930c87c5fbaSopenharmony_ci    }
931c87c5fbaSopenharmony_ci    version.version = (p1 << 16) | (p2 << 8) | p3;
932c87c5fbaSopenharmony_ci  }
933c87c5fbaSopenharmony_ci  version.built_version = version.version;
934c87c5fbaSopenharmony_ci  version.type = COAP_TLS_LIBRARY_TINYDTLS;
935c87c5fbaSopenharmony_ci  return &version;
936c87c5fbaSopenharmony_ci}
937c87c5fbaSopenharmony_ci
938c87c5fbaSopenharmony_ci#ifdef DTLS_ECC
939c87c5fbaSopenharmony_cistatic const uint8_t b64_6[256] = {
940c87c5fbaSopenharmony_ci  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
941c87c5fbaSopenharmony_ci  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
942c87c5fbaSopenharmony_ci  /*                                           +               / */
943c87c5fbaSopenharmony_ci  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
944c87c5fbaSopenharmony_ci  /* 0 1   2   3   4   5   6   7   8   9               =         */
945c87c5fbaSopenharmony_ci  52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
946c87c5fbaSopenharmony_ci  /*   A   B   C   D   E   F   G   H   I   J   K   L   M   N   O */
947c87c5fbaSopenharmony_ci  64,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
948c87c5fbaSopenharmony_ci  /* P Q   R   S   T   U   V   W   X   Y   Z                     */
949c87c5fbaSopenharmony_ci  15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
950c87c5fbaSopenharmony_ci  /*   a   b   c   d   e   f   g   h   i   j   k   l   m   n   o */
951c87c5fbaSopenharmony_ci  64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
952c87c5fbaSopenharmony_ci  /* p q   r   s   t   u   v   w   x   y   z                     */
953c87c5fbaSopenharmony_ci  41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
954c87c5fbaSopenharmony_ci  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
955c87c5fbaSopenharmony_ci  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
956c87c5fbaSopenharmony_ci  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
957c87c5fbaSopenharmony_ci  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
958c87c5fbaSopenharmony_ci  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
959c87c5fbaSopenharmony_ci  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
960c87c5fbaSopenharmony_ci  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
961c87c5fbaSopenharmony_ci  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
962c87c5fbaSopenharmony_ci};
963c87c5fbaSopenharmony_ci
964c87c5fbaSopenharmony_ci/* caller must free off returned coap_binary_t* */
965c87c5fbaSopenharmony_cistatic coap_binary_t *
966c87c5fbaSopenharmony_cipem_base64_decode(const uint8_t *data, size_t size) {
967c87c5fbaSopenharmony_ci  uint8_t *tbuf = coap_malloc_type(COAP_STRING, size);
968c87c5fbaSopenharmony_ci  size_t nbytesdecoded;
969c87c5fbaSopenharmony_ci  size_t i;
970c87c5fbaSopenharmony_ci  coap_binary_t *decoded;
971c87c5fbaSopenharmony_ci  uint8_t *ptr;
972c87c5fbaSopenharmony_ci  uint8_t *out;
973c87c5fbaSopenharmony_ci  size_t nb64bytes = 0;
974c87c5fbaSopenharmony_ci
975c87c5fbaSopenharmony_ci  for (i = 0; i < size; i++) {
976c87c5fbaSopenharmony_ci    switch (data[i]) {
977c87c5fbaSopenharmony_ci    case ' ':
978c87c5fbaSopenharmony_ci    case '\r':
979c87c5fbaSopenharmony_ci    case '\n':
980c87c5fbaSopenharmony_ci    case '\t':
981c87c5fbaSopenharmony_ci      break;
982c87c5fbaSopenharmony_ci    default:
983c87c5fbaSopenharmony_ci      if (b64_6[data[i]] == 64)
984c87c5fbaSopenharmony_ci        goto end;
985c87c5fbaSopenharmony_ci      tbuf[nb64bytes++] = data[i];
986c87c5fbaSopenharmony_ci      break;
987c87c5fbaSopenharmony_ci    }
988c87c5fbaSopenharmony_ci  }
989c87c5fbaSopenharmony_ci
990c87c5fbaSopenharmony_ciend:
991c87c5fbaSopenharmony_ci  nbytesdecoded = ((nb64bytes + 3) / 4) * 3;
992c87c5fbaSopenharmony_ci  decoded = coap_new_binary(nbytesdecoded + 1);
993c87c5fbaSopenharmony_ci  if (!decoded)
994c87c5fbaSopenharmony_ci    return NULL;
995c87c5fbaSopenharmony_ci
996c87c5fbaSopenharmony_ci  out = decoded->s;
997c87c5fbaSopenharmony_ci  ptr = tbuf;
998c87c5fbaSopenharmony_ci
999c87c5fbaSopenharmony_ci  while (nb64bytes > 4) {
1000c87c5fbaSopenharmony_ci    *(out++) = b64_6[ptr[0]] << 2 | b64_6[ptr[1]] >> 4;
1001c87c5fbaSopenharmony_ci    *(out++) = b64_6[ptr[1]] << 4 | b64_6[ptr[2]] >> 2;
1002c87c5fbaSopenharmony_ci    *(out++) = b64_6[ptr[2]] << 6 | b64_6[ptr[3]];
1003c87c5fbaSopenharmony_ci    ptr += 4;
1004c87c5fbaSopenharmony_ci    nb64bytes -= 4;
1005c87c5fbaSopenharmony_ci  }
1006c87c5fbaSopenharmony_ci
1007c87c5fbaSopenharmony_ci  /* Note: (nb64bytes == 1) is an error */
1008c87c5fbaSopenharmony_ci  if (nb64bytes > 1) {
1009c87c5fbaSopenharmony_ci    *(out++) = b64_6[ptr[0]] << 2 | b64_6[ptr[1]] >> 4;
1010c87c5fbaSopenharmony_ci  }
1011c87c5fbaSopenharmony_ci  if (nb64bytes > 2) {
1012c87c5fbaSopenharmony_ci    *(out++) = b64_6[ptr[1]] << 4 | b64_6[ptr[2]] >> 2;
1013c87c5fbaSopenharmony_ci  }
1014c87c5fbaSopenharmony_ci  if (nb64bytes > 3) {
1015c87c5fbaSopenharmony_ci    *(out++) = b64_6[ptr[2]] << 6 | b64_6[ptr[3]];
1016c87c5fbaSopenharmony_ci  }
1017c87c5fbaSopenharmony_ci
1018c87c5fbaSopenharmony_ci  decoded->length = nbytesdecoded - ((4 - nb64bytes) & 3);
1019c87c5fbaSopenharmony_ci  coap_free_type(COAP_STRING, tbuf);
1020c87c5fbaSopenharmony_ci  return decoded;
1021c87c5fbaSopenharmony_ci}
1022c87c5fbaSopenharmony_ci
1023c87c5fbaSopenharmony_citypedef coap_binary_t *(*asn1_callback)(const uint8_t *data, size_t size);
1024c87c5fbaSopenharmony_ci
1025c87c5fbaSopenharmony_cistatic int
1026c87c5fbaSopenharmony_ciasn1_verify_privkey(const uint8_t *data, size_t size) {
1027c87c5fbaSopenharmony_ci  /* Check if we have the private key (with optional leading 0x00) */
1028c87c5fbaSopenharmony_ci  /* skip leading 0x00 */
1029c87c5fbaSopenharmony_ci  if (size - 1 == DTLS_EC_KEY_SIZE && *data == '\000') {
1030c87c5fbaSopenharmony_ci    --size;
1031c87c5fbaSopenharmony_ci    ++data;
1032c87c5fbaSopenharmony_ci  }
1033c87c5fbaSopenharmony_ci
1034c87c5fbaSopenharmony_ci  /* Check if we have the private key */
1035c87c5fbaSopenharmony_ci  if (size != DTLS_EC_KEY_SIZE)
1036c87c5fbaSopenharmony_ci    return 0;
1037c87c5fbaSopenharmony_ci
1038c87c5fbaSopenharmony_ci  return 1;
1039c87c5fbaSopenharmony_ci}
1040c87c5fbaSopenharmony_ci
1041c87c5fbaSopenharmony_cistatic int
1042c87c5fbaSopenharmony_ciasn1_verify_pubkey(const uint8_t *data, size_t size) {
1043c87c5fbaSopenharmony_ci  (void)data;
1044c87c5fbaSopenharmony_ci
1045c87c5fbaSopenharmony_ci  /* We have the public key
1046c87c5fbaSopenharmony_ci     (with a leading 0x00 (no unused bits) 0x04 (not compressed() */
1047c87c5fbaSopenharmony_ci  if (size - 2 != 2 * DTLS_EC_KEY_SIZE)
1048c87c5fbaSopenharmony_ci    return 0;
1049c87c5fbaSopenharmony_ci
1050c87c5fbaSopenharmony_ci  return 1;
1051c87c5fbaSopenharmony_ci}
1052c87c5fbaSopenharmony_ci
1053c87c5fbaSopenharmony_cistatic int
1054c87c5fbaSopenharmony_ciasn1_verify_curve(const uint8_t *data, size_t size) {
1055c87c5fbaSopenharmony_ci  static uint8_t prime256v1_oid[] =
1056c87c5fbaSopenharmony_ci      /* OID 1.2.840.10045.3.1.7 */
1057c87c5fbaSopenharmony_ci  { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 };
1058c87c5fbaSopenharmony_ci
1059c87c5fbaSopenharmony_ci  /* Check that we have the correct EC (only one supported) */
1060c87c5fbaSopenharmony_ci  if (size != sizeof(prime256v1_oid) ||
1061c87c5fbaSopenharmony_ci      memcmp(data, prime256v1_oid, size) != 0)
1062c87c5fbaSopenharmony_ci    return 0;
1063c87c5fbaSopenharmony_ci
1064c87c5fbaSopenharmony_ci  return 1;
1065c87c5fbaSopenharmony_ci}
1066c87c5fbaSopenharmony_ci
1067c87c5fbaSopenharmony_cistatic int
1068c87c5fbaSopenharmony_ciasn1_verify_pkcs8_version(const uint8_t *data, size_t size) {
1069c87c5fbaSopenharmony_ci  /* Check that we have the version */
1070c87c5fbaSopenharmony_ci  if (size != 1 || *data != 0)
1071c87c5fbaSopenharmony_ci    return 0;
1072c87c5fbaSopenharmony_ci
1073c87c5fbaSopenharmony_ci  return 1;
1074c87c5fbaSopenharmony_ci}
1075c87c5fbaSopenharmony_ci
1076c87c5fbaSopenharmony_cistatic int
1077c87c5fbaSopenharmony_ciasn1_verify_ec_identifier(const uint8_t *data, size_t size) {
1078c87c5fbaSopenharmony_ci  static uint8_t ec_public_key_oid[] =
1079c87c5fbaSopenharmony_ci      /* OID 1.2.840.10045.2.1 */
1080c87c5fbaSopenharmony_ci  { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01 };
1081c87c5fbaSopenharmony_ci
1082c87c5fbaSopenharmony_ci  /* Check that we have the correct ecPublicKey */
1083c87c5fbaSopenharmony_ci  if (size != sizeof(ec_public_key_oid) ||
1084c87c5fbaSopenharmony_ci      memcmp(data, ec_public_key_oid, size) != 0)
1085c87c5fbaSopenharmony_ci    return 0;
1086c87c5fbaSopenharmony_ci
1087c87c5fbaSopenharmony_ci  return 1;
1088c87c5fbaSopenharmony_ci}
1089c87c5fbaSopenharmony_ci
1090c87c5fbaSopenharmony_cistatic int
1091c87c5fbaSopenharmony_ciasn1_verify_ec_key(const uint8_t *data, size_t size) {
1092c87c5fbaSopenharmony_ci  (void)data;
1093c87c5fbaSopenharmony_ci
1094c87c5fbaSopenharmony_ci  if (size == 0)
1095c87c5fbaSopenharmony_ci    return 0;
1096c87c5fbaSopenharmony_ci
1097c87c5fbaSopenharmony_ci  return 1;
1098c87c5fbaSopenharmony_ci}
1099c87c5fbaSopenharmony_ci
1100c87c5fbaSopenharmony_cistatic int
1101c87c5fbaSopenharmony_ciasn1_derive_keys(coap_tiny_context_t *t_context,
1102c87c5fbaSopenharmony_ci                 const uint8_t *priv_data, size_t priv_len,
1103c87c5fbaSopenharmony_ci                 const uint8_t *pub_data, size_t pub_len,
1104c87c5fbaSopenharmony_ci                 int is_pkcs8) {
1105c87c5fbaSopenharmony_ci  coap_binary_t *test;
1106c87c5fbaSopenharmony_ci
1107c87c5fbaSopenharmony_ci  t_context->priv_key = get_asn1_tag(COAP_ASN1_OCTETSTRING, priv_data,
1108c87c5fbaSopenharmony_ci                                     priv_len, asn1_verify_privkey);
1109c87c5fbaSopenharmony_ci  if (!t_context->priv_key) {
1110c87c5fbaSopenharmony_ci    coap_log_info("EC Private Key (RPK) invalid\n");
1111c87c5fbaSopenharmony_ci    return 0;
1112c87c5fbaSopenharmony_ci  }
1113c87c5fbaSopenharmony_ci  /* skip leading 0x00 */
1114c87c5fbaSopenharmony_ci  if (t_context->priv_key->length - 1 == DTLS_EC_KEY_SIZE &&
1115c87c5fbaSopenharmony_ci      t_context->priv_key->s[0] == '\000') {
1116c87c5fbaSopenharmony_ci    t_context->priv_key->length--;
1117c87c5fbaSopenharmony_ci    t_context->priv_key->s++;
1118c87c5fbaSopenharmony_ci  }
1119c87c5fbaSopenharmony_ci
1120c87c5fbaSopenharmony_ci  if (!is_pkcs8) {
1121c87c5fbaSopenharmony_ci    /* pkcs8 abstraction tested for valid eliptic curve */
1122c87c5fbaSopenharmony_ci    test = get_asn1_tag(COAP_ASN1_IDENTIFIER, priv_data, priv_len,
1123c87c5fbaSopenharmony_ci                        asn1_verify_curve);
1124c87c5fbaSopenharmony_ci    if (!test) {
1125c87c5fbaSopenharmony_ci      coap_log_info("EC Private Key (RPK) invalid elliptic curve\n");
1126c87c5fbaSopenharmony_ci      coap_delete_binary(t_context->priv_key);
1127c87c5fbaSopenharmony_ci      t_context->priv_key = NULL;
1128c87c5fbaSopenharmony_ci      return 0;
1129c87c5fbaSopenharmony_ci    }
1130c87c5fbaSopenharmony_ci    coap_delete_binary(test);
1131c87c5fbaSopenharmony_ci  }
1132c87c5fbaSopenharmony_ci
1133c87c5fbaSopenharmony_ci  t_context->pub_key = get_asn1_tag(COAP_ASN1_BITSTRING, pub_data, pub_len,
1134c87c5fbaSopenharmony_ci                                    asn1_verify_pubkey);
1135c87c5fbaSopenharmony_ci  if (!t_context->pub_key) {
1136c87c5fbaSopenharmony_ci    coap_log_info("EC Public Key (RPK) invalid\n");
1137c87c5fbaSopenharmony_ci    coap_delete_binary(t_context->priv_key);
1138c87c5fbaSopenharmony_ci    t_context->priv_key = NULL;
1139c87c5fbaSopenharmony_ci    return 0;
1140c87c5fbaSopenharmony_ci  }
1141c87c5fbaSopenharmony_ci  /* Drop leading 0x00 and 0x04 */
1142c87c5fbaSopenharmony_ci  t_context->pub_key->s += 2;
1143c87c5fbaSopenharmony_ci  t_context->pub_key->length -= 2;
1144c87c5fbaSopenharmony_ci  dtls_set_handler(t_context->dtls_context, &ec_cb);
1145c87c5fbaSopenharmony_ci  return 1;
1146c87c5fbaSopenharmony_ci}
1147c87c5fbaSopenharmony_ci
1148c87c5fbaSopenharmony_cistatic coap_binary_t *
1149c87c5fbaSopenharmony_ciec_abstract_pkcs8_asn1(const uint8_t *asn1_ptr, size_t asn1_length) {
1150c87c5fbaSopenharmony_ci  coap_binary_t *test;
1151c87c5fbaSopenharmony_ci
1152c87c5fbaSopenharmony_ci  test = get_asn1_tag(COAP_ASN1_INTEGER, asn1_ptr, asn1_length,
1153c87c5fbaSopenharmony_ci                      asn1_verify_pkcs8_version);
1154c87c5fbaSopenharmony_ci  if (!test)
1155c87c5fbaSopenharmony_ci    return 0;
1156c87c5fbaSopenharmony_ci
1157c87c5fbaSopenharmony_ci  coap_delete_binary(test);
1158c87c5fbaSopenharmony_ci
1159c87c5fbaSopenharmony_ci  test = get_asn1_tag(COAP_ASN1_IDENTIFIER, asn1_ptr, asn1_length,
1160c87c5fbaSopenharmony_ci                      asn1_verify_ec_identifier);
1161c87c5fbaSopenharmony_ci  if (!test)
1162c87c5fbaSopenharmony_ci    return 0;
1163c87c5fbaSopenharmony_ci  coap_delete_binary(test);
1164c87c5fbaSopenharmony_ci
1165c87c5fbaSopenharmony_ci  test = get_asn1_tag(COAP_ASN1_IDENTIFIER, asn1_ptr, asn1_length,
1166c87c5fbaSopenharmony_ci                      asn1_verify_curve);
1167c87c5fbaSopenharmony_ci  if (!test) {
1168c87c5fbaSopenharmony_ci    coap_log_info("EC Private Key (RPK) invalid elliptic curve\n");
1169c87c5fbaSopenharmony_ci    return 0;
1170c87c5fbaSopenharmony_ci  }
1171c87c5fbaSopenharmony_ci  coap_delete_binary(test);
1172c87c5fbaSopenharmony_ci
1173c87c5fbaSopenharmony_ci  test = get_asn1_tag(COAP_ASN1_OCTETSTRING, asn1_ptr, asn1_length,
1174c87c5fbaSopenharmony_ci                      asn1_verify_ec_key);
1175c87c5fbaSopenharmony_ci  return test;
1176c87c5fbaSopenharmony_ci}
1177c87c5fbaSopenharmony_ci
1178c87c5fbaSopenharmony_cistatic coap_binary_t *
1179c87c5fbaSopenharmony_cipem_decode_mem_asn1(const char *begstr, const uint8_t *str) {
1180c87c5fbaSopenharmony_ci  char *bcp = str ? strstr((const char *)str, begstr) : NULL;
1181c87c5fbaSopenharmony_ci  char *tcp = bcp ? strstr(bcp, "-----END ") : NULL;
1182c87c5fbaSopenharmony_ci
1183c87c5fbaSopenharmony_ci  if (bcp && tcp) {
1184c87c5fbaSopenharmony_ci    bcp += strlen(begstr);
1185c87c5fbaSopenharmony_ci    return pem_base64_decode((const uint8_t *)bcp, tcp - bcp);
1186c87c5fbaSopenharmony_ci  }
1187c87c5fbaSopenharmony_ci  return NULL;
1188c87c5fbaSopenharmony_ci}
1189c87c5fbaSopenharmony_ci
1190c87c5fbaSopenharmony_ci#endif /* DTLS_ECC */
1191c87c5fbaSopenharmony_ci
1192c87c5fbaSopenharmony_ciint
1193c87c5fbaSopenharmony_cicoap_dtls_context_set_pki(coap_context_t *ctx,
1194c87c5fbaSopenharmony_ci                          const coap_dtls_pki_t *setup_data,
1195c87c5fbaSopenharmony_ci                          const coap_dtls_role_t role COAP_UNUSED) {
1196c87c5fbaSopenharmony_ci#ifdef DTLS_ECC
1197c87c5fbaSopenharmony_ci  coap_tiny_context_t *t_context;
1198c87c5fbaSopenharmony_ci  coap_binary_t *asn1_priv;
1199c87c5fbaSopenharmony_ci  coap_binary_t *asn1_pub;
1200c87c5fbaSopenharmony_ci  coap_binary_t *asn1_temp;
1201c87c5fbaSopenharmony_ci  int is_pkcs8 = 0;
1202c87c5fbaSopenharmony_ci
1203c87c5fbaSopenharmony_ci  if (!setup_data)
1204c87c5fbaSopenharmony_ci    return 0;
1205c87c5fbaSopenharmony_ci  if (setup_data->version != COAP_DTLS_PKI_SETUP_VERSION)
1206c87c5fbaSopenharmony_ci    return 0;
1207c87c5fbaSopenharmony_ci  if (!setup_data->is_rpk_not_cert) {
1208c87c5fbaSopenharmony_ci    coap_log_warn("Only RPK, not full PKI is supported\n");
1209c87c5fbaSopenharmony_ci    return 0;
1210c87c5fbaSopenharmony_ci  }
1211c87c5fbaSopenharmony_ci  if (!ctx)
1212c87c5fbaSopenharmony_ci    return 0;
1213c87c5fbaSopenharmony_ci  t_context = (coap_tiny_context_t *)ctx->dtls_context;
1214c87c5fbaSopenharmony_ci  if (!t_context)
1215c87c5fbaSopenharmony_ci    return 0;
1216c87c5fbaSopenharmony_ci  if (t_context->priv_key) {
1217c87c5fbaSopenharmony_ci    coap_delete_binary(t_context->priv_key);
1218c87c5fbaSopenharmony_ci    t_context->priv_key = NULL;
1219c87c5fbaSopenharmony_ci  }
1220c87c5fbaSopenharmony_ci  if (t_context->pub_key) {
1221c87c5fbaSopenharmony_ci    coap_delete_binary(t_context->pub_key);
1222c87c5fbaSopenharmony_ci    t_context->pub_key = NULL;
1223c87c5fbaSopenharmony_ci  }
1224c87c5fbaSopenharmony_ci  t_context->setup_data = *setup_data;
1225c87c5fbaSopenharmony_ci
1226c87c5fbaSopenharmony_ci  /* All should be RPK only now */
1227c87c5fbaSopenharmony_ci  switch (setup_data->pki_key.key_type) {
1228c87c5fbaSopenharmony_ci  case COAP_PKI_KEY_PEM:
1229c87c5fbaSopenharmony_ci    coap_log_warn("RPK keys cannot be in COAP_PKI_KEY_PEM format\n");
1230c87c5fbaSopenharmony_ci    break;
1231c87c5fbaSopenharmony_ci  case COAP_PKI_KEY_PEM_BUF:
1232c87c5fbaSopenharmony_ci    if (setup_data->pki_key.key.pem_buf.public_cert &&
1233c87c5fbaSopenharmony_ci        setup_data->pki_key.key.pem_buf.public_cert[0] &&
1234c87c5fbaSopenharmony_ci        setup_data->pki_key.key.pem_buf.private_key &&
1235c87c5fbaSopenharmony_ci        setup_data->pki_key.key.pem_buf.private_key[0]) {
1236c87c5fbaSopenharmony_ci      /* Need to take PEM memory information and convert to binary */
1237c87c5fbaSopenharmony_ci      asn1_priv = pem_decode_mem_asn1("-----BEGIN EC PRIVATE KEY-----",
1238c87c5fbaSopenharmony_ci                                      setup_data->pki_key.key.pem_buf.private_key);
1239c87c5fbaSopenharmony_ci      if (!asn1_priv) {
1240c87c5fbaSopenharmony_ci        asn1_priv = pem_decode_mem_asn1("-----BEGIN PRIVATE KEY-----",
1241c87c5fbaSopenharmony_ci                                        setup_data->pki_key.key.pem_buf.private_key);
1242c87c5fbaSopenharmony_ci        if (!asn1_priv) {
1243c87c5fbaSopenharmony_ci          coap_log_info("Private Key (RPK) invalid\n");
1244c87c5fbaSopenharmony_ci          return 0;
1245c87c5fbaSopenharmony_ci        }
1246c87c5fbaSopenharmony_ci        asn1_temp = ec_abstract_pkcs8_asn1(asn1_priv->s, asn1_priv->length);
1247c87c5fbaSopenharmony_ci        if (!asn1_temp) {
1248c87c5fbaSopenharmony_ci          coap_log_info("PKCS#8 Private Key (RPK) invalid\n");
1249c87c5fbaSopenharmony_ci          coap_delete_binary(asn1_priv);
1250c87c5fbaSopenharmony_ci          return 0;
1251c87c5fbaSopenharmony_ci        }
1252c87c5fbaSopenharmony_ci        coap_delete_binary(asn1_priv);
1253c87c5fbaSopenharmony_ci        asn1_priv = asn1_temp;
1254c87c5fbaSopenharmony_ci        is_pkcs8 = 1;
1255c87c5fbaSopenharmony_ci      }
1256c87c5fbaSopenharmony_ci      asn1_pub = pem_decode_mem_asn1(
1257c87c5fbaSopenharmony_ci                     "-----BEGIN PUBLIC KEY-----",
1258c87c5fbaSopenharmony_ci                     setup_data->pki_key.key.pem_buf.public_cert);
1259c87c5fbaSopenharmony_ci      if (!asn1_pub) {
1260c87c5fbaSopenharmony_ci        asn1_pub = pem_decode_mem_asn1("-----BEGIN EC PRIVATE KEY-----",
1261c87c5fbaSopenharmony_ci                                       setup_data->pki_key.key.pem_buf.private_key);
1262c87c5fbaSopenharmony_ci        if (!asn1_pub) {
1263c87c5fbaSopenharmony_ci          asn1_pub = pem_decode_mem_asn1("-----BEGIN PRIVATE KEY-----",
1264c87c5fbaSopenharmony_ci                                         setup_data->pki_key.key.pem_buf.private_key);
1265c87c5fbaSopenharmony_ci          if (!asn1_pub) {
1266c87c5fbaSopenharmony_ci            coap_log_info("Public Key (RPK) invalid\n");
1267c87c5fbaSopenharmony_ci            coap_delete_binary(asn1_priv);
1268c87c5fbaSopenharmony_ci            return 0;
1269c87c5fbaSopenharmony_ci          }
1270c87c5fbaSopenharmony_ci          asn1_temp = ec_abstract_pkcs8_asn1(asn1_pub->s, asn1_pub->length);
1271c87c5fbaSopenharmony_ci          if (!asn1_temp) {
1272c87c5fbaSopenharmony_ci            coap_log_info("PKCS#8 Private Key (RPK) invalid\n");
1273c87c5fbaSopenharmony_ci            coap_delete_binary(asn1_priv);
1274c87c5fbaSopenharmony_ci            coap_delete_binary(asn1_pub);
1275c87c5fbaSopenharmony_ci            return 0;
1276c87c5fbaSopenharmony_ci          }
1277c87c5fbaSopenharmony_ci          coap_delete_binary(asn1_pub);
1278c87c5fbaSopenharmony_ci          asn1_pub = asn1_temp;
1279c87c5fbaSopenharmony_ci          is_pkcs8 = 1;
1280c87c5fbaSopenharmony_ci        }
1281c87c5fbaSopenharmony_ci      }
1282c87c5fbaSopenharmony_ci      if (!asn1_derive_keys(t_context, asn1_priv->s, asn1_priv->length,
1283c87c5fbaSopenharmony_ci                            asn1_pub->s, asn1_pub->length, is_pkcs8)) {
1284c87c5fbaSopenharmony_ci        coap_log_info("Unable to derive Public/Private Keys\n");
1285c87c5fbaSopenharmony_ci        coap_delete_binary(asn1_priv);
1286c87c5fbaSopenharmony_ci        coap_delete_binary(asn1_pub);
1287c87c5fbaSopenharmony_ci        return 0;
1288c87c5fbaSopenharmony_ci      }
1289c87c5fbaSopenharmony_ci      coap_delete_binary(asn1_priv);
1290c87c5fbaSopenharmony_ci      coap_delete_binary(asn1_pub);
1291c87c5fbaSopenharmony_ci      return 1;
1292c87c5fbaSopenharmony_ci    }
1293c87c5fbaSopenharmony_ci    break;
1294c87c5fbaSopenharmony_ci  case COAP_PKI_KEY_ASN1:
1295c87c5fbaSopenharmony_ci    if (setup_data->pki_key.key.asn1.private_key &&
1296c87c5fbaSopenharmony_ci        setup_data->pki_key.key.asn1.private_key_len &&
1297c87c5fbaSopenharmony_ci        setup_data->pki_key.key.asn1.private_key_type == COAP_ASN1_PKEY_EC) {
1298c87c5fbaSopenharmony_ci      const uint8_t *private_key = setup_data->pki_key.key.asn1.private_key;
1299c87c5fbaSopenharmony_ci      size_t private_key_len = setup_data->pki_key.key.asn1.private_key_len;
1300c87c5fbaSopenharmony_ci
1301c87c5fbaSopenharmony_ci      /* Check to see whether this is in pkcs8 format or not */
1302c87c5fbaSopenharmony_ci      asn1_temp = ec_abstract_pkcs8_asn1(
1303c87c5fbaSopenharmony_ci                      setup_data->pki_key.key.asn1.private_key,
1304c87c5fbaSopenharmony_ci                      setup_data->pki_key.key.asn1.private_key_len);
1305c87c5fbaSopenharmony_ci      if (asn1_temp) {
1306c87c5fbaSopenharmony_ci        private_key = asn1_temp->s;
1307c87c5fbaSopenharmony_ci        private_key_len = asn1_temp->length;
1308c87c5fbaSopenharmony_ci        is_pkcs8 = 1;
1309c87c5fbaSopenharmony_ci      }
1310c87c5fbaSopenharmony_ci      /* Need to take ASN1 memory information and convert to binary */
1311c87c5fbaSopenharmony_ci      if (setup_data->pki_key.key.asn1.public_cert &&
1312c87c5fbaSopenharmony_ci          setup_data->pki_key.key.asn1.public_cert_len) {
1313c87c5fbaSopenharmony_ci        if (!asn1_derive_keys(t_context,
1314c87c5fbaSopenharmony_ci                              private_key,
1315c87c5fbaSopenharmony_ci                              private_key_len,
1316c87c5fbaSopenharmony_ci                              setup_data->pki_key.key.asn1.public_cert,
1317c87c5fbaSopenharmony_ci                              setup_data->pki_key.key.asn1.public_cert_len,
1318c87c5fbaSopenharmony_ci                              is_pkcs8)) {
1319c87c5fbaSopenharmony_ci          coap_log_info("Unable to derive Public/Private Keys\n");
1320c87c5fbaSopenharmony_ci          if (asn1_temp)
1321c87c5fbaSopenharmony_ci            coap_delete_binary(asn1_temp);
1322c87c5fbaSopenharmony_ci          return 0;
1323c87c5fbaSopenharmony_ci        }
1324c87c5fbaSopenharmony_ci      } else {
1325c87c5fbaSopenharmony_ci        if (!asn1_derive_keys(t_context,
1326c87c5fbaSopenharmony_ci                              private_key,
1327c87c5fbaSopenharmony_ci                              private_key_len,
1328c87c5fbaSopenharmony_ci                              private_key,
1329c87c5fbaSopenharmony_ci                              private_key_len,
1330c87c5fbaSopenharmony_ci                              is_pkcs8)) {
1331c87c5fbaSopenharmony_ci          coap_log_info("Unable to derive Public/Private Keys\n");
1332c87c5fbaSopenharmony_ci          if (asn1_temp)
1333c87c5fbaSopenharmony_ci            coap_delete_binary(asn1_temp);
1334c87c5fbaSopenharmony_ci          return 0;
1335c87c5fbaSopenharmony_ci        }
1336c87c5fbaSopenharmony_ci      }
1337c87c5fbaSopenharmony_ci      return 1;
1338c87c5fbaSopenharmony_ci    }
1339c87c5fbaSopenharmony_ci    break;
1340c87c5fbaSopenharmony_ci  case COAP_PKI_KEY_PKCS11:
1341c87c5fbaSopenharmony_ci    coap_log_warn("RPK keys cannot be in COAP_PKI_KEY_PCKS11 format\n");
1342c87c5fbaSopenharmony_ci    break;
1343c87c5fbaSopenharmony_ci  default:
1344c87c5fbaSopenharmony_ci    break;
1345c87c5fbaSopenharmony_ci  }
1346c87c5fbaSopenharmony_ci#else /* ! DTLS_ECC */
1347c87c5fbaSopenharmony_ci  (void)ctx;
1348c87c5fbaSopenharmony_ci  (void)setup_data;
1349c87c5fbaSopenharmony_ci#endif /* ! DTLS_ECC */
1350c87c5fbaSopenharmony_ci  coap_log_warn("TinyDTLS not compiled with ECC support\n");
1351c87c5fbaSopenharmony_ci  return 0;
1352c87c5fbaSopenharmony_ci}
1353c87c5fbaSopenharmony_ci
1354c87c5fbaSopenharmony_ciint
1355c87c5fbaSopenharmony_cicoap_dtls_context_set_pki_root_cas(coap_context_t *ctx COAP_UNUSED,
1356c87c5fbaSopenharmony_ci                                   const char *ca_file COAP_UNUSED,
1357c87c5fbaSopenharmony_ci                                   const char *ca_path COAP_UNUSED
1358c87c5fbaSopenharmony_ci                                  ) {
1359c87c5fbaSopenharmony_ci  coap_log_warn("Root CAs PKI not supported\n");
1360c87c5fbaSopenharmony_ci  return 0;
1361c87c5fbaSopenharmony_ci}
1362c87c5fbaSopenharmony_ci
1363c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT
1364c87c5fbaSopenharmony_ciint
1365c87c5fbaSopenharmony_cicoap_dtls_context_set_cpsk(coap_context_t *coap_context COAP_UNUSED,
1366c87c5fbaSopenharmony_ci                           coap_dtls_cpsk_t *setup_data
1367c87c5fbaSopenharmony_ci                          ) {
1368c87c5fbaSopenharmony_ci  if (!setup_data)
1369c87c5fbaSopenharmony_ci    return 0;
1370c87c5fbaSopenharmony_ci
1371c87c5fbaSopenharmony_ci#ifdef DTLS_PSK
1372c87c5fbaSopenharmony_ci  return 1;
1373c87c5fbaSopenharmony_ci#else /* ! DTLS_PSK */
1374c87c5fbaSopenharmony_ci  coap_log_warn("TinyDTLS not compiled with PSK support\n");
1375c87c5fbaSopenharmony_ci  return 0;
1376c87c5fbaSopenharmony_ci#endif /* ! DTLS_PSK */
1377c87c5fbaSopenharmony_ci}
1378c87c5fbaSopenharmony_ci#endif /* COAP_CLIENT_SUPPORT */
1379c87c5fbaSopenharmony_ci
1380c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT
1381c87c5fbaSopenharmony_ciint
1382c87c5fbaSopenharmony_cicoap_dtls_context_set_spsk(coap_context_t *coap_context COAP_UNUSED,
1383c87c5fbaSopenharmony_ci                           coap_dtls_spsk_t *setup_data
1384c87c5fbaSopenharmony_ci                          ) {
1385c87c5fbaSopenharmony_ci  if (!setup_data)
1386c87c5fbaSopenharmony_ci    return 0;
1387c87c5fbaSopenharmony_ci
1388c87c5fbaSopenharmony_ci#ifdef DTLS_PSK
1389c87c5fbaSopenharmony_ci  if (setup_data->validate_sni_call_back) {
1390c87c5fbaSopenharmony_ci    coap_log_warn("CoAP Server with TinyDTLS does not support SNI selection\n");
1391c87c5fbaSopenharmony_ci  }
1392c87c5fbaSopenharmony_ci
1393c87c5fbaSopenharmony_ci  return 1;
1394c87c5fbaSopenharmony_ci#else /* ! DTLS_PSK */
1395c87c5fbaSopenharmony_ci  coap_log_warn("TinyDTLS not compiled with PSK support\n");
1396c87c5fbaSopenharmony_ci  return 0;
1397c87c5fbaSopenharmony_ci#endif /* ! DTLS_PSK */
1398c87c5fbaSopenharmony_ci}
1399c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */
1400c87c5fbaSopenharmony_ci
1401c87c5fbaSopenharmony_ciint
1402c87c5fbaSopenharmony_cicoap_dtls_context_check_keys_enabled(coap_context_t *ctx COAP_UNUSED) {
1403c87c5fbaSopenharmony_ci  return 1;
1404c87c5fbaSopenharmony_ci}
1405c87c5fbaSopenharmony_ci
1406c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP
1407c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT
1408c87c5fbaSopenharmony_civoid *
1409c87c5fbaSopenharmony_cicoap_tls_new_client_session(coap_session_t *session COAP_UNUSED) {
1410c87c5fbaSopenharmony_ci  return NULL;
1411c87c5fbaSopenharmony_ci}
1412c87c5fbaSopenharmony_ci#endif /* COAP_CLIENT_SUPPORT */
1413c87c5fbaSopenharmony_ci
1414c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT
1415c87c5fbaSopenharmony_civoid *
1416c87c5fbaSopenharmony_cicoap_tls_new_server_session(coap_session_t *session COAP_UNUSED) {
1417c87c5fbaSopenharmony_ci  return NULL;
1418c87c5fbaSopenharmony_ci}
1419c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */
1420c87c5fbaSopenharmony_ci
1421c87c5fbaSopenharmony_civoid
1422c87c5fbaSopenharmony_cicoap_tls_free_session(coap_session_t *coap_session COAP_UNUSED) {
1423c87c5fbaSopenharmony_ci}
1424c87c5fbaSopenharmony_ci
1425c87c5fbaSopenharmony_ci/*
1426c87c5fbaSopenharmony_ci * strm
1427c87c5fbaSopenharmony_ci * return +ve Number of bytes written.
1428c87c5fbaSopenharmony_ci *         -1 Error (error in errno).
1429c87c5fbaSopenharmony_ci */
1430c87c5fbaSopenharmony_cissize_t
1431c87c5fbaSopenharmony_cicoap_tls_write(coap_session_t *session COAP_UNUSED,
1432c87c5fbaSopenharmony_ci               const uint8_t *data COAP_UNUSED,
1433c87c5fbaSopenharmony_ci               size_t data_len COAP_UNUSED
1434c87c5fbaSopenharmony_ci              ) {
1435c87c5fbaSopenharmony_ci  return -1;
1436c87c5fbaSopenharmony_ci}
1437c87c5fbaSopenharmony_ci
1438c87c5fbaSopenharmony_ci/*
1439c87c5fbaSopenharmony_ci * strm
1440c87c5fbaSopenharmony_ci * return >=0 Number of bytes read.
1441c87c5fbaSopenharmony_ci *         -1 Error (error in errno).
1442c87c5fbaSopenharmony_ci */
1443c87c5fbaSopenharmony_cissize_t
1444c87c5fbaSopenharmony_cicoap_tls_read(coap_session_t *session COAP_UNUSED,
1445c87c5fbaSopenharmony_ci              uint8_t *data COAP_UNUSED,
1446c87c5fbaSopenharmony_ci              size_t data_len COAP_UNUSED) {
1447c87c5fbaSopenharmony_ci  errno = ENODEV;
1448c87c5fbaSopenharmony_ci  return -1;
1449c87c5fbaSopenharmony_ci}
1450c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */
1451c87c5fbaSopenharmony_ci
1452c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT
1453c87c5fbaSopenharmony_cicoap_digest_ctx_t *
1454c87c5fbaSopenharmony_cicoap_digest_setup(void) {
1455c87c5fbaSopenharmony_ci  dtls_sha256_ctx *digest_ctx = coap_malloc_type(COAP_STRING, sizeof(dtls_sha256_ctx));
1456c87c5fbaSopenharmony_ci
1457c87c5fbaSopenharmony_ci  if (digest_ctx) {
1458c87c5fbaSopenharmony_ci    dtls_sha256_init(digest_ctx);
1459c87c5fbaSopenharmony_ci  }
1460c87c5fbaSopenharmony_ci
1461c87c5fbaSopenharmony_ci  return digest_ctx;
1462c87c5fbaSopenharmony_ci}
1463c87c5fbaSopenharmony_ci
1464c87c5fbaSopenharmony_civoid
1465c87c5fbaSopenharmony_cicoap_digest_free(coap_digest_ctx_t *digest_ctx) {
1466c87c5fbaSopenharmony_ci  coap_free_type(COAP_STRING, digest_ctx);
1467c87c5fbaSopenharmony_ci}
1468c87c5fbaSopenharmony_ci
1469c87c5fbaSopenharmony_ciint
1470c87c5fbaSopenharmony_cicoap_digest_update(coap_digest_ctx_t *digest_ctx,
1471c87c5fbaSopenharmony_ci                   const uint8_t *data,
1472c87c5fbaSopenharmony_ci                   size_t data_len) {
1473c87c5fbaSopenharmony_ci  dtls_sha256_update(digest_ctx, data, data_len);
1474c87c5fbaSopenharmony_ci
1475c87c5fbaSopenharmony_ci  return 1;
1476c87c5fbaSopenharmony_ci}
1477c87c5fbaSopenharmony_ci
1478c87c5fbaSopenharmony_ciint
1479c87c5fbaSopenharmony_cicoap_digest_final(coap_digest_ctx_t *digest_ctx,
1480c87c5fbaSopenharmony_ci                  coap_digest_t *digest_buffer) {
1481c87c5fbaSopenharmony_ci  dtls_sha256_final((uint8_t *)digest_buffer, digest_ctx);
1482c87c5fbaSopenharmony_ci
1483c87c5fbaSopenharmony_ci  coap_digest_free(digest_ctx);
1484c87c5fbaSopenharmony_ci  return 1;
1485c87c5fbaSopenharmony_ci}
1486c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */
1487c87c5fbaSopenharmony_ci
1488c87c5fbaSopenharmony_ci#if COAP_WS_SUPPORT
1489c87c5fbaSopenharmony_ciint
1490c87c5fbaSopenharmony_cicoap_crypto_hash(cose_alg_t alg,
1491c87c5fbaSopenharmony_ci                 const coap_bin_const_t *data,
1492c87c5fbaSopenharmony_ci                 coap_bin_const_t **hash) {
1493c87c5fbaSopenharmony_ci  (void)alg;
1494c87c5fbaSopenharmony_ci  (void)data;
1495c87c5fbaSopenharmony_ci  (void)hash;
1496c87c5fbaSopenharmony_ci  return 0;
1497c87c5fbaSopenharmony_ci}
1498c87c5fbaSopenharmony_ci#endif /* COAP_WS_SUPPORT */
1499c87c5fbaSopenharmony_ci
1500c87c5fbaSopenharmony_ci#if COAP_OSCORE_SUPPORT
1501c87c5fbaSopenharmony_ci
1502c87c5fbaSopenharmony_ciint
1503c87c5fbaSopenharmony_cicoap_oscore_is_supported(void) {
1504c87c5fbaSopenharmony_ci  return 1;
1505c87c5fbaSopenharmony_ci}
1506c87c5fbaSopenharmony_ci
1507c87c5fbaSopenharmony_ci/*
1508c87c5fbaSopenharmony_ci * The struct cipher_algs and the function get_cipher_alg() are used to
1509c87c5fbaSopenharmony_ci * determine which cipher type to use for creating the required cipher
1510c87c5fbaSopenharmony_ci * suite object.
1511c87c5fbaSopenharmony_ci */
1512c87c5fbaSopenharmony_cistatic struct cipher_algs {
1513c87c5fbaSopenharmony_ci  cose_alg_t alg;
1514c87c5fbaSopenharmony_ci  u_int cipher_type;
1515c87c5fbaSopenharmony_ci} ciphers[] = {
1516c87c5fbaSopenharmony_ci  { COSE_ALGORITHM_AES_CCM_16_64_128, 1 },
1517c87c5fbaSopenharmony_ci};
1518c87c5fbaSopenharmony_ci
1519c87c5fbaSopenharmony_cistatic u_int
1520c87c5fbaSopenharmony_ciget_cipher_alg(cose_alg_t alg) {
1521c87c5fbaSopenharmony_ci  size_t idx;
1522c87c5fbaSopenharmony_ci
1523c87c5fbaSopenharmony_ci  for (idx = 0; idx < sizeof(ciphers)/sizeof(struct cipher_algs); idx++) {
1524c87c5fbaSopenharmony_ci    if (ciphers[idx].alg == alg)
1525c87c5fbaSopenharmony_ci      return ciphers[idx].cipher_type;
1526c87c5fbaSopenharmony_ci  }
1527c87c5fbaSopenharmony_ci  coap_log_debug("get_cipher_alg: COSE cipher %d not supported\n", alg);
1528c87c5fbaSopenharmony_ci  return 0;
1529c87c5fbaSopenharmony_ci}
1530c87c5fbaSopenharmony_ci
1531c87c5fbaSopenharmony_ci/*
1532c87c5fbaSopenharmony_ci * The struct hmac_algs and the function get_hmac_alg() are used to
1533c87c5fbaSopenharmony_ci * determine which hmac type to use for creating the required hmac
1534c87c5fbaSopenharmony_ci * suite object.
1535c87c5fbaSopenharmony_ci */
1536c87c5fbaSopenharmony_cistatic struct hmac_algs {
1537c87c5fbaSopenharmony_ci  cose_hmac_alg_t hmac_alg;
1538c87c5fbaSopenharmony_ci  u_int hmac_type;
1539c87c5fbaSopenharmony_ci} hmacs[] = {
1540c87c5fbaSopenharmony_ci  {COSE_HMAC_ALG_HMAC256_256, 1},
1541c87c5fbaSopenharmony_ci};
1542c87c5fbaSopenharmony_ci
1543c87c5fbaSopenharmony_cistatic u_int
1544c87c5fbaSopenharmony_ciget_hmac_alg(cose_hmac_alg_t hmac_alg) {
1545c87c5fbaSopenharmony_ci  size_t idx;
1546c87c5fbaSopenharmony_ci
1547c87c5fbaSopenharmony_ci  for (idx = 0; idx < sizeof(hmacs)/sizeof(struct hmac_algs); idx++) {
1548c87c5fbaSopenharmony_ci    if (hmacs[idx].hmac_alg == hmac_alg)
1549c87c5fbaSopenharmony_ci      return hmacs[idx].hmac_type;
1550c87c5fbaSopenharmony_ci  }
1551c87c5fbaSopenharmony_ci  coap_log_debug("get_hmac_alg: COSE HMAC %d not supported\n", hmac_alg);
1552c87c5fbaSopenharmony_ci  return 0;
1553c87c5fbaSopenharmony_ci}
1554c87c5fbaSopenharmony_ci
1555c87c5fbaSopenharmony_ciint
1556c87c5fbaSopenharmony_cicoap_crypto_check_cipher_alg(cose_alg_t alg) {
1557c87c5fbaSopenharmony_ci  return get_cipher_alg(alg);
1558c87c5fbaSopenharmony_ci}
1559c87c5fbaSopenharmony_ci
1560c87c5fbaSopenharmony_ciint
1561c87c5fbaSopenharmony_cicoap_crypto_check_hkdf_alg(cose_hkdf_alg_t hkdf_alg) {
1562c87c5fbaSopenharmony_ci  cose_hmac_alg_t hmac_alg;
1563c87c5fbaSopenharmony_ci
1564c87c5fbaSopenharmony_ci  if (!cose_get_hmac_alg_for_hkdf(hkdf_alg, &hmac_alg))
1565c87c5fbaSopenharmony_ci    return 0;
1566c87c5fbaSopenharmony_ci  return get_hmac_alg(hmac_alg);
1567c87c5fbaSopenharmony_ci}
1568c87c5fbaSopenharmony_ci
1569c87c5fbaSopenharmony_ciint
1570c87c5fbaSopenharmony_cicoap_crypto_aead_encrypt(const coap_crypto_param_t *params,
1571c87c5fbaSopenharmony_ci                         coap_bin_const_t *data,
1572c87c5fbaSopenharmony_ci                         coap_bin_const_t *aad,
1573c87c5fbaSopenharmony_ci                         uint8_t *result, size_t *max_result_len) {
1574c87c5fbaSopenharmony_ci  int num_bytes;
1575c87c5fbaSopenharmony_ci  const coap_crypto_aes_ccm_t *ccm;
1576c87c5fbaSopenharmony_ci  dtls_ccm_params_t dtls_params;
1577c87c5fbaSopenharmony_ci  coap_bin_const_t laad;
1578c87c5fbaSopenharmony_ci
1579c87c5fbaSopenharmony_ci  if (data == NULL)
1580c87c5fbaSopenharmony_ci    return 0;
1581c87c5fbaSopenharmony_ci
1582c87c5fbaSopenharmony_ci  assert(params);
1583c87c5fbaSopenharmony_ci
1584c87c5fbaSopenharmony_ci  if (get_cipher_alg(params->alg) == 0) {
1585c87c5fbaSopenharmony_ci    coap_log_debug("coap_crypto_encrypt: algorithm %d not supported\n",
1586c87c5fbaSopenharmony_ci                   params->alg);
1587c87c5fbaSopenharmony_ci    return 0;
1588c87c5fbaSopenharmony_ci  }
1589c87c5fbaSopenharmony_ci
1590c87c5fbaSopenharmony_ci  ccm = &params->params.aes;
1591c87c5fbaSopenharmony_ci  if (*max_result_len < (data->length + ccm->tag_len)) {
1592c87c5fbaSopenharmony_ci    coap_log_warn("coap_encrypt: result buffer too small\n");
1593c87c5fbaSopenharmony_ci    return 0;
1594c87c5fbaSopenharmony_ci  }
1595c87c5fbaSopenharmony_ci
1596c87c5fbaSopenharmony_ci  dtls_params.nonce = ccm->nonce;
1597c87c5fbaSopenharmony_ci  dtls_params.tag_length = ccm->tag_len;
1598c87c5fbaSopenharmony_ci  dtls_params.l = ccm->l;
1599c87c5fbaSopenharmony_ci
1600c87c5fbaSopenharmony_ci  if (aad) {
1601c87c5fbaSopenharmony_ci    laad = *aad;
1602c87c5fbaSopenharmony_ci  } else {
1603c87c5fbaSopenharmony_ci    laad.s = NULL;
1604c87c5fbaSopenharmony_ci    laad.length = 0;
1605c87c5fbaSopenharmony_ci  }
1606c87c5fbaSopenharmony_ci
1607c87c5fbaSopenharmony_ci  num_bytes = dtls_encrypt_params(&dtls_params,
1608c87c5fbaSopenharmony_ci                                  data->s, data->length,
1609c87c5fbaSopenharmony_ci                                  result,
1610c87c5fbaSopenharmony_ci                                  ccm->key.s, ccm->key.length,
1611c87c5fbaSopenharmony_ci                                  laad.s, laad.length);
1612c87c5fbaSopenharmony_ci  if (num_bytes < 0) {
1613c87c5fbaSopenharmony_ci    return 0;
1614c87c5fbaSopenharmony_ci  }
1615c87c5fbaSopenharmony_ci  *max_result_len = num_bytes;
1616c87c5fbaSopenharmony_ci  return 1;
1617c87c5fbaSopenharmony_ci}
1618c87c5fbaSopenharmony_ci
1619c87c5fbaSopenharmony_ciint
1620c87c5fbaSopenharmony_cicoap_crypto_aead_decrypt(const coap_crypto_param_t *params,
1621c87c5fbaSopenharmony_ci                         coap_bin_const_t *data,
1622c87c5fbaSopenharmony_ci                         coap_bin_const_t *aad,
1623c87c5fbaSopenharmony_ci                         uint8_t *result, size_t *max_result_len) {
1624c87c5fbaSopenharmony_ci  int num_bytes;
1625c87c5fbaSopenharmony_ci  const coap_crypto_aes_ccm_t *ccm;
1626c87c5fbaSopenharmony_ci  dtls_ccm_params_t dtls_params;
1627c87c5fbaSopenharmony_ci  coap_bin_const_t laad;
1628c87c5fbaSopenharmony_ci
1629c87c5fbaSopenharmony_ci  if (data == NULL)
1630c87c5fbaSopenharmony_ci    return 0;
1631c87c5fbaSopenharmony_ci
1632c87c5fbaSopenharmony_ci  assert(params);
1633c87c5fbaSopenharmony_ci
1634c87c5fbaSopenharmony_ci  if (get_cipher_alg(params->alg) == 0) {
1635c87c5fbaSopenharmony_ci    coap_log_debug("coap_crypto_decrypt: algorithm %d not supported\n",
1636c87c5fbaSopenharmony_ci                   params->alg);
1637c87c5fbaSopenharmony_ci    return 0;
1638c87c5fbaSopenharmony_ci  }
1639c87c5fbaSopenharmony_ci
1640c87c5fbaSopenharmony_ci  ccm = &params->params.aes;
1641c87c5fbaSopenharmony_ci
1642c87c5fbaSopenharmony_ci  if ((*max_result_len + ccm->tag_len) < data->length) {
1643c87c5fbaSopenharmony_ci    coap_log_warn("coap_decrypt: result buffer too small\n");
1644c87c5fbaSopenharmony_ci    return 0;
1645c87c5fbaSopenharmony_ci  }
1646c87c5fbaSopenharmony_ci
1647c87c5fbaSopenharmony_ci  dtls_params.nonce = ccm->nonce;
1648c87c5fbaSopenharmony_ci  dtls_params.tag_length = ccm->tag_len;
1649c87c5fbaSopenharmony_ci  dtls_params.l = ccm->l;
1650c87c5fbaSopenharmony_ci
1651c87c5fbaSopenharmony_ci  if (aad) {
1652c87c5fbaSopenharmony_ci    laad = *aad;
1653c87c5fbaSopenharmony_ci  } else {
1654c87c5fbaSopenharmony_ci    laad.s = NULL;
1655c87c5fbaSopenharmony_ci    laad.length = 0;
1656c87c5fbaSopenharmony_ci  }
1657c87c5fbaSopenharmony_ci
1658c87c5fbaSopenharmony_ci  num_bytes = dtls_decrypt_params(&dtls_params,
1659c87c5fbaSopenharmony_ci                                  data->s, data->length,
1660c87c5fbaSopenharmony_ci                                  result,
1661c87c5fbaSopenharmony_ci                                  ccm->key.s, ccm->key.length,
1662c87c5fbaSopenharmony_ci                                  laad.s, laad.length);
1663c87c5fbaSopenharmony_ci  if (num_bytes < 0) {
1664c87c5fbaSopenharmony_ci    return 0;
1665c87c5fbaSopenharmony_ci  }
1666c87c5fbaSopenharmony_ci  *max_result_len = num_bytes;
1667c87c5fbaSopenharmony_ci  return 1;
1668c87c5fbaSopenharmony_ci}
1669c87c5fbaSopenharmony_ci
1670c87c5fbaSopenharmony_ciint
1671c87c5fbaSopenharmony_cicoap_crypto_hmac(cose_hmac_alg_t hmac_alg, coap_bin_const_t *key,
1672c87c5fbaSopenharmony_ci                 coap_bin_const_t *data, coap_bin_const_t **hmac) {
1673c87c5fbaSopenharmony_ci  dtls_hmac_context_t hmac_context;
1674c87c5fbaSopenharmony_ci  int num_bytes;
1675c87c5fbaSopenharmony_ci  coap_binary_t *dummy;
1676c87c5fbaSopenharmony_ci
1677c87c5fbaSopenharmony_ci  if (data == NULL)
1678c87c5fbaSopenharmony_ci    return 0;
1679c87c5fbaSopenharmony_ci
1680c87c5fbaSopenharmony_ci  if (get_hmac_alg(hmac_alg) == 0) {
1681c87c5fbaSopenharmony_ci    coap_log_debug("coap_crypto_hmac: algorithm %d not supported\n", hmac_alg);
1682c87c5fbaSopenharmony_ci    return 0;
1683c87c5fbaSopenharmony_ci  }
1684c87c5fbaSopenharmony_ci
1685c87c5fbaSopenharmony_ci  dummy = coap_new_binary(DTLS_SHA256_DIGEST_LENGTH);
1686c87c5fbaSopenharmony_ci  if (dummy == NULL)
1687c87c5fbaSopenharmony_ci    return 0;
1688c87c5fbaSopenharmony_ci
1689c87c5fbaSopenharmony_ci  dtls_hmac_init(&hmac_context, key->s, key->length);
1690c87c5fbaSopenharmony_ci  dtls_hmac_update(&hmac_context, data->s, data->length);
1691c87c5fbaSopenharmony_ci  num_bytes = dtls_hmac_finalize(&hmac_context, dummy->s);
1692c87c5fbaSopenharmony_ci
1693c87c5fbaSopenharmony_ci  if (num_bytes != DTLS_SHA256_DIGEST_LENGTH) {
1694c87c5fbaSopenharmony_ci    coap_delete_binary(dummy);
1695c87c5fbaSopenharmony_ci    return 0;
1696c87c5fbaSopenharmony_ci  }
1697c87c5fbaSopenharmony_ci  *hmac = (coap_bin_const_t *)dummy;
1698c87c5fbaSopenharmony_ci  return 1;
1699c87c5fbaSopenharmony_ci}
1700c87c5fbaSopenharmony_ci
1701c87c5fbaSopenharmony_ci#endif /* COAP_OSCORE_SUPPORT */
1702c87c5fbaSopenharmony_ci
1703c87c5fbaSopenharmony_ci#else /* !COAP_WITH_LIBTINYDTLS */
1704c87c5fbaSopenharmony_ci
1705c87c5fbaSopenharmony_ci#ifdef __clang__
1706c87c5fbaSopenharmony_ci/* Make compilers happy that do not like empty modules. As this function is
1707c87c5fbaSopenharmony_ci * never used, we ignore -Wunused-function at the end of compiling this file
1708c87c5fbaSopenharmony_ci */
1709c87c5fbaSopenharmony_ci#pragma GCC diagnostic ignored "-Wunused-function"
1710c87c5fbaSopenharmony_ci#endif
1711c87c5fbaSopenharmony_cistatic inline void
1712c87c5fbaSopenharmony_cidummy(void) {
1713c87c5fbaSopenharmony_ci}
1714c87c5fbaSopenharmony_ci
1715c87c5fbaSopenharmony_ci#endif /* COAP_WITH_LIBTINYDTLS */
1716