Coverage Report

Created: 2026-08-08 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libcoap/src/coap_dtls.c
Line
Count
Source
1
/*
2
 * coap_dtls.c -- (D)TLS functions for libcoap
3
 *
4
 * Copyright (C) 2023-2026 Olaf Bergmann <bergmann@tzi.org>
5
 * Copyright (C) 2023-2026 Jon Shallow <supjps-libcoap@jpshallow.com>
6
 *
7
 * SPDX-License-Identifier: BSD-2-Clause
8
 *
9
 * This file is part of the CoAP library libcoap. Please see README for terms
10
 * of use.
11
 */
12
13
/**
14
 * @file coap_dtls.c
15
 * @brief CoAP (D)TLS handling functions
16
 */
17
18
#include "coap3/coap_libcoap_build.h"
19
20
#ifdef _WIN32
21
#define strcasecmp _stricmp
22
#define strncasecmp _strnicmp
23
#endif
24
25
void
26
0
coap_dtls_map_key_type_to_define(const coap_dtls_pki_t *setup_data, coap_dtls_key_t *key) {
27
0
  *key = setup_data->pki_key;
28
29
0
  switch (key->key_type) {
30
0
  case COAP_PKI_KEY_PEM:
31
0
    key->key_type = COAP_PKI_KEY_DEFINE;
32
0
    key->key.define.ca.s_byte = setup_data->pki_key.key.pem.ca_file;
33
0
    key->key.define.public_cert.s_byte = setup_data->pki_key.key.pem.public_cert;
34
0
    key->key.define.private_key.s_byte = setup_data->pki_key.key.pem.private_key;
35
36
0
    key->key.define.public_cert_def = COAP_PKI_KEY_DEF_PEM;
37
0
    key->key.define.private_key_def = COAP_PKI_KEY_DEF_PEM;
38
0
    key->key.define.ca_def = COAP_PKI_KEY_DEF_PEM;
39
0
    break;
40
0
  case COAP_PKI_KEY_ASN1:
41
0
    key->key_type = COAP_PKI_KEY_DEFINE;
42
0
    key->key.define.ca.u_byte = setup_data->pki_key.key.asn1.ca_cert;
43
0
    key->key.define.public_cert.u_byte = setup_data->pki_key.key.asn1.public_cert;
44
0
    key->key.define.private_key.u_byte = setup_data->pki_key.key.asn1.private_key;
45
46
0
    key->key.define.ca_len = setup_data->pki_key.key.asn1.ca_cert_len;
47
0
    key->key.define.public_cert_len = setup_data->pki_key.key.asn1.public_cert_len;
48
0
    key->key.define.private_key_len = setup_data->pki_key.key.asn1.private_key_len;
49
50
0
    key->key.define.private_key_type = setup_data->pki_key.key.asn1.private_key_type;
51
52
0
    key->key.define.public_cert_def = COAP_PKI_KEY_DEF_DER_BUF;
53
0
    key->key.define.private_key_def = COAP_PKI_KEY_DEF_DER_BUF;
54
0
    key->key.define.ca_def = COAP_PKI_KEY_DEF_DER_BUF;
55
0
    break;
56
0
  case COAP_PKI_KEY_PEM_BUF:
57
0
    key->key_type = COAP_PKI_KEY_DEFINE;
58
0
    key->key.define.ca.u_byte = setup_data->pki_key.key.pem_buf.ca_cert;
59
0
    key->key.define.public_cert.u_byte = setup_data->pki_key.key.pem_buf.public_cert;
60
0
    key->key.define.private_key.u_byte = setup_data->pki_key.key.pem_buf.private_key;
61
62
0
    key->key.define.ca_len = setup_data->pki_key.key.pem_buf.ca_cert_len;
63
0
    key->key.define.public_cert_len = setup_data->pki_key.key.pem_buf.public_cert_len;
64
0
    key->key.define.private_key_len = setup_data->pki_key.key.pem_buf.private_key_len;
65
66
0
    if (setup_data->is_rpk_not_cert) {
67
0
      key->key.define.public_cert_def = COAP_PKI_KEY_DEF_RPK_BUF;
68
0
      key->key.define.private_key_def = COAP_PKI_KEY_DEF_RPK_BUF;
69
0
      key->key.define.ca_def = COAP_PKI_KEY_DEF_RPK_BUF;
70
0
    } else {
71
0
      key->key.define.public_cert_def = COAP_PKI_KEY_DEF_PEM_BUF;
72
0
      key->key.define.private_key_def = COAP_PKI_KEY_DEF_PEM_BUF;
73
0
      key->key.define.ca_def = COAP_PKI_KEY_DEF_PEM_BUF;
74
0
    }
75
0
    break;
76
0
  case COAP_PKI_KEY_PKCS11:
77
0
    key->key_type = COAP_PKI_KEY_DEFINE;
78
0
    key->key.define.ca.s_byte = setup_data->pki_key.key.pkcs11.ca;
79
0
    key->key.define.public_cert.s_byte = setup_data->pki_key.key.pkcs11.public_cert;
80
0
    key->key.define.private_key.s_byte = setup_data->pki_key.key.pkcs11.private_key;
81
82
0
    key->key.define.user_pin = setup_data->pki_key.key.pkcs11.user_pin;
83
84
0
    if (strncasecmp(key->key.pkcs11.ca, "pkcs11:", 7) == 0) {
85
0
      if (setup_data->is_rpk_not_cert) {
86
0
        key->key.define.ca_def = COAP_PKI_KEY_DEF_PKCS11_RPK;
87
0
      } else {
88
0
        key->key.define.ca_def = COAP_PKI_KEY_DEF_PKCS11;
89
0
      }
90
0
    } else {
91
0
      if (setup_data->is_rpk_not_cert) {
92
0
        key->key.define.ca_def = COAP_PKI_KEY_DEF_RPK_BUF;
93
0
      } else {
94
0
        key->key.define.ca_def = COAP_PKI_KEY_DEF_DER;
95
0
      }
96
0
    }
97
0
    if (strncasecmp(key->key.pkcs11.public_cert, "pkcs11:", 7) == 0) {
98
0
      if (setup_data->is_rpk_not_cert) {
99
0
        key->key.define.public_cert_def = COAP_PKI_KEY_DEF_PKCS11_RPK;
100
0
      } else {
101
0
        key->key.define.public_cert_def = COAP_PKI_KEY_DEF_PKCS11;
102
0
      }
103
0
    } else {
104
0
      if (setup_data->is_rpk_not_cert) {
105
0
        key->key.define.public_cert_def = COAP_PKI_KEY_DEF_RPK_BUF;
106
0
      } else {
107
0
        key->key.define.public_cert_def = COAP_PKI_KEY_DEF_DER;
108
0
      }
109
0
    }
110
0
    if (strncasecmp(key->key.pkcs11.private_key, "pkcs11:", 7) == 0) {
111
0
      if (setup_data->is_rpk_not_cert) {
112
0
        key->key.define.private_key_def = COAP_PKI_KEY_DEF_PKCS11_RPK;
113
0
      } else {
114
0
        key->key.define.private_key_def = COAP_PKI_KEY_DEF_PKCS11;
115
0
      }
116
0
    } else {
117
0
      if (setup_data->is_rpk_not_cert) {
118
0
        key->key.define.private_key_def = COAP_PKI_KEY_DEF_RPK_BUF;
119
0
      } else {
120
0
        key->key.define.private_key_def = COAP_PKI_KEY_DEF_DER;
121
0
      }
122
0
    }
123
0
    break;
124
0
  case COAP_PKI_KEY_DEFINE:
125
    /* Already configured */
126
0
    break;
127
0
  default:
128
0
    break;
129
0
  }
130
0
}
131
132
#if (COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_ERR)
133
static const char *
134
0
coap_dtls_get_define_type(coap_pki_define_t def, coap_const_char_ptr_t name) {
135
0
  switch (def) {
136
0
  case COAP_PKI_KEY_DEF_PEM:
137
0
    return name.s_byte;
138
0
  case COAP_PKI_KEY_DEF_PEM_BUF:
139
0
    return "PEM_BUF";
140
0
  case COAP_PKI_KEY_DEF_RPK_BUF:
141
0
    return "RPK_BUF";
142
0
  case COAP_PKI_KEY_DEF_DER:
143
0
    return name.s_byte;
144
0
  case COAP_PKI_KEY_DEF_DER_BUF:
145
0
    return "DER_BUF";
146
0
  case COAP_PKI_KEY_DEF_PKCS11:
147
0
    return name.s_byte;
148
0
  case COAP_PKI_KEY_DEF_PKCS11_RPK:
149
0
    return name.s_byte;
150
0
  case COAP_PKI_KEY_DEF_ENGINE:
151
0
    return name.s_byte;
152
0
  default:
153
0
    return "???";
154
0
  }
155
0
}
156
#endif /* COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_ERR */
157
158
int
159
coap_dtls_define_issue(coap_define_issue_key_t type, coap_define_issue_fail_t fail,
160
0
                       coap_dtls_key_t *key, const coap_dtls_role_t role, int ret) {
161
0
#if (COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_ERR)
162
0
  coap_pki_key_define_t define = key->key.define;
163
0
  switch (type) {
164
0
  case COAP_DEFINE_KEY_CA:
165
0
    switch (fail) {
166
0
    case COAP_DEFINE_FAIL_BAD:
167
0
      coap_log_warn("*** setup_pki: (D)TLS: %s: %s CA configure failure\n",
168
0
                    coap_dtls_get_define_type(define.ca_def, define.ca),
169
0
                    role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
170
0
      break;
171
0
    case COAP_DEFINE_FAIL_NOT_SUPPORTED:
172
0
      coap_log_err("*** setup_pki: (D)TLS: %s: %s CA type not supported\n",
173
0
                   coap_dtls_get_define_type(define.ca_def, define.ca),
174
0
                   role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
175
0
      break;
176
0
    case COAP_DEFINE_FAIL_NONE:
177
0
      coap_log_err("*** setup_pki: (D)TLS: %s: %s CA not defined\n",
178
0
                   coap_dtls_get_define_type(define.ca_def, define.ca),
179
0
                   role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
180
0
      break;
181
0
    default:
182
0
      break;
183
0
    }
184
0
    break;
185
0
  case COAP_DEFINE_KEY_ROOT_CA:
186
0
    switch (fail) {
187
0
    case COAP_DEFINE_FAIL_BAD:
188
0
      coap_log_warn("*** setup_pki: (D)TLS: %s: %s Root CA configure failure\n",
189
0
                    coap_dtls_get_define_type(define.ca_def, define.ca),
190
0
                    role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
191
0
      break;
192
0
    case COAP_DEFINE_FAIL_NOT_SUPPORTED:
193
0
      coap_log_err("*** setup_pki: (D)TLS: %s: %s Root CA type not supported\n",
194
0
                   coap_dtls_get_define_type(define.ca_def, define.ca),
195
0
                   role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
196
0
      break;
197
0
    case COAP_DEFINE_FAIL_NONE:
198
0
      coap_log_err("*** setup_pki: (D)TLS: %s: %s Root CA not defined\n",
199
0
                   coap_dtls_get_define_type(define.ca_def, define.ca),
200
0
                   role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
201
0
      break;
202
0
    default:
203
0
      break;
204
0
    }
205
0
    break;
206
0
  case COAP_DEFINE_KEY_PUBLIC:
207
0
    switch (fail) {
208
0
    case COAP_DEFINE_FAIL_BAD:
209
0
      coap_log_warn("*** setup_pki: (D)TLS: %s: %s Certificate configure failure\n",
210
0
                    coap_dtls_get_define_type(define.public_cert_def, define.public_cert),
211
0
                    role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
212
0
      break;
213
0
    case COAP_DEFINE_FAIL_NOT_SUPPORTED:
214
0
      coap_log_err("*** setup_pki: (D)TLS: %s: %s Certificate type not supported\n",
215
0
                   coap_dtls_get_define_type(define.public_cert_def, define.public_cert),
216
0
                   role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
217
0
      break;
218
0
    case COAP_DEFINE_FAIL_NONE:
219
0
      coap_log_err("*** setup_pki: (D)TLS: %s: %s Certificate not defined\n",
220
0
                   coap_dtls_get_define_type(define.public_cert_def, define.public_cert),
221
0
                   role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
222
0
      break;
223
0
    default:
224
0
      break;
225
0
    }
226
0
    break;
227
0
  case COAP_DEFINE_KEY_PRIVATE:
228
0
    switch (fail) {
229
0
    case COAP_DEFINE_FAIL_BAD:
230
0
      coap_log_warn("*** setup_pki: (D)TLS: %s: %s Private Key configure failure\n",
231
0
                    coap_dtls_get_define_type(define.private_key_def, define.private_key),
232
0
                    role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
233
0
      break;
234
0
    case COAP_DEFINE_FAIL_NOT_SUPPORTED:
235
0
      coap_log_err("*** setup_pki: (D)TLS: %s: %s Private Key type not supported\n",
236
0
                   coap_dtls_get_define_type(define.private_key_def, define.private_key),
237
0
                   role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
238
0
      break;
239
0
    case COAP_DEFINE_FAIL_NONE:
240
0
      coap_log_err("*** setup_pki: (D)TLS: %s: %s Private Key not defined\n",
241
0
                   coap_dtls_get_define_type(define.private_key_def, define.private_key),
242
0
                   role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
243
0
      break;
244
0
    default:
245
0
      break;
246
0
    }
247
0
  default:
248
0
    break;
249
0
  }
250
#else /* COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_ERR */
251
  (void)type;
252
  (void)fail;
253
  (void)key;
254
  (void)role;
255
#endif /* COAP_MAX_LOGGING_LEVEL < _COAP_LOG_ERR */
256
0
  return ret;
257
0
}
258
259
void
260
0
coap_dtls_establish(coap_session_t *session) {
261
0
  session->state = COAP_SESSION_STATE_HANDSHAKE;
262
0
#if COAP_CLIENT_SUPPORT
263
0
  if (session->type == COAP_SESSION_TYPE_CLIENT || session->client_initiated)
264
0
    session->tls = coap_dtls_new_client_session(session);
265
0
  else
266
0
#endif /* COAP_CLIENT_SUPPORT */
267
0
#if COAP_SERVER_SUPPORT
268
0
    session->tls = coap_dtls_new_server_session(session);
269
0
#endif /* COAP_SERVER_SUPPORT */
270
271
0
  if (!session->tls) {
272
0
    coap_session_disconnected_lkd(session, COAP_NACK_TLS_LAYER_FAILED);
273
0
    return;
274
0
  }
275
0
  coap_ticks(&session->last_rx_tx);
276
0
}
277
278
void
279
0
coap_dtls_close(coap_session_t *session) {
280
0
  if (session->tls) {
281
0
    coap_dtls_free_session(session);
282
0
    session->tls = NULL;
283
0
  }
284
0
  session->sock.lfunc[COAP_LAYER_TLS].l_close(session);
285
0
}
286
287
int
288
0
coap_pki_name_match_sni(const char *name_entry, size_t name_length, const char *sni_match) {
289
0
  if (!sni_match)
290
0
    return 1;
291
292
0
  if (name_length >= 2 && name_entry[0] == '*' && name_entry[1] == '.') {
293
    /* Check for wildcard match */
294
0
    const char *cp = strchr(sni_match, '.');
295
296
0
    if (!cp || strlen(cp) != name_length -1 || memcmp(&name_entry[1], cp, name_length -1)) {
297
      /* Not an wildcard match */
298
0
      return 0;
299
0
    }
300
0
  } else {
301
0
    if (strlen(sni_match) != name_length || memcmp(name_entry, sni_match, name_length)) {
302
      /* Not an absolute match */
303
0
      return 0;
304
0
    }
305
0
  }
306
0
  return 1;
307
0
}
308
309
#if !COAP_DISABLE_TCP
310
void
311
0
coap_tls_establish(coap_session_t *session) {
312
0
  session->state = COAP_SESSION_STATE_HANDSHAKE;
313
0
#if COAP_CLIENT_SUPPORT
314
0
  if (session->type == COAP_SESSION_TYPE_CLIENT || session->client_initiated)
315
0
    session->tls = coap_tls_new_client_session(session);
316
0
  else
317
0
#endif /* COAP_CLIENT_SUPPORT */
318
0
#if COAP_SERVER_SUPPORT
319
0
    session->tls = coap_tls_new_server_session(session);
320
0
#endif /* COAP_SERVER_SUPPORT */
321
322
0
  if (!session->tls) {
323
0
    coap_session_disconnected_lkd(session, COAP_NACK_TLS_LAYER_FAILED);
324
0
    return;
325
0
  }
326
0
  coap_ticks(&session->last_rx_tx);
327
0
}
328
329
void
330
0
coap_tls_close(coap_session_t *session) {
331
0
  if (session->tls) {
332
0
    coap_tls_free_session(session);
333
    session->tls = NULL;
334
0
  }
335
0
  session->sock.lfunc[COAP_LAYER_TLS].l_close(session);
336
0
}
337
#endif /* !COAP_DISABLE_TCP */