Coverage Report

Created: 2026-11-12 06:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libcoap/src/coap_openssl.c
Line
Count
Source
1
/*
2
 * coap_openssl.c -- Datagram Transport Layer Support for libcoap with openssl
3
 *
4
 * Copyright (C) 2017      Jean-Claude Michelou <jcm@spinetix.com>
5
 * Copyright (C) 2018-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_openssl.c
15
 * @brief OpenSSL specific interface functions.
16
 */
17
18
#include "coap3/coap_libcoap_build.h"
19
20
#if COAP_WITH_LIBOPENSSL
21
22
/*
23
 * OpenSSL 1.1.0 has support for making decisions during receipt of
24
 * the Client Hello - the call back function is set up using
25
 * SSL_CTX_set_tlsext_servername_callback() which is called later in the
26
 * Client Hello processing - but called every Client Hello.
27
 * Certificates and Preshared Keys have to be set up in the SSL CTX before
28
 * SSL_accept() is called, making the code messy to decide whether this is a
29
 * PKI or PSK incoming request to handle things accordingly if both are
30
 * defined.  SNI has to create a new SSL CTX to handle different server names
31
 * with different crtificates.
32
 *
33
 * OpenSSL 1.1.1 introduces a new function SSL_CTX_set_client_hello_cb().
34
 * The call back is invoked early on in the Client Hello processing giving
35
 * the ability to easily use different Preshared Keys, Certificates etc.
36
 * Certificates do not have to be set up in the SSL CTX before SSL_accept is
37
 * called.
38
 * Later in the Client Hello code, the callback for
39
 * SSL_CTX_set_tlsext_servername_callback() is still called, but only if SNI
40
 * is being used by the client, so cannot be used for doing things the
41
 * OpenSSL 1.1.0 way.
42
 *
43
 * OpenSSL 1.1.1 supports TLS1.3.
44
 *
45
 * There is also support for OpenSSL 3.
46
 *
47
 * Consequently, this code has to have compile time options to include /
48
 * exclude code based on whether compiled against 1.1.0 or 1.1.1, as well as
49
 * have additional run time checks.
50
 *
51
 * It is possible to override the Ciphers, define the Algorithms or Groups,
52
 * and/or define the PKCS11 engine id to to use for the SSL negotiations at
53
 * compile time. This is done by the adding of the appropriate -D option to
54
 * the CPPFLAGS parameter that is used on the ./configure command line.
55
 * E.g.  ./configure CPPFLAGS="-DXX='\"YY\"' -DUU='\"VV\"'"
56
 * The parameter value is case-sensitive.
57
 *
58
 * The ciphers can be overridden with (example)
59
 *  -DCOAP_OPENSSL_CIPHERS='\"ECDHE-ECDSA-AES256-GCM-SHA384\"'
60
 *
61
 * The Algorithms can be defined by (example)
62
 *  -DCOAP_OPENSSL_SIGALGS='\"ed25519\"'
63
 *
64
 * The Groups (OpenSSL 1.1.1 or later) can be defined by (example)
65
 *  -DCOAP_OPENSSL_GROUPS='\"X25519\"'
66
 *
67
 * The PKCSLL engine ID can be defined by (example)
68
 + -DCOAP_OPENSSL_PKCS11_ENGINE_ID='\"pkcs11\"'
69
 *
70
 * The PSK security level can be defined by (example)
71
 * -DCOAP_OPENSSL_PSK_SECURITY_LEVEL=0
72
 *
73
 * ENINE_* functions are no longer supported by OpenSSL 4.0 and later.
74
 */
75
#include <openssl/ssl.h>
76
#if OPENSSL_VERSION_NUMBER < 0x40000000L
77
#include <openssl/engine.h>
78
#endif /* OPENSSL_VERSION_NUMBER < 0x40000000L */
79
#include <openssl/err.h>
80
#include <openssl/rand.h>
81
#include <openssl/hmac.h>
82
#include <openssl/x509v3.h>
83
84
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
85
#ifdef __GNUC__
86
/* Ignore OpenSSL 3.0 deprecated warnings for now */
87
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
88
#endif
89
#if defined(_WIN32)
90
#if !defined(__MINGW32__)
91
#pragma warning(disable : 4996)
92
#endif /* ! __MINGW32__ */
93
#endif /* _WIN32 */
94
#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
95
96
#ifdef COAP_EPOLL_SUPPORT
97
# include <sys/epoll.h>
98
#endif /* COAP_EPOLL_SUPPORT */
99
100
#if OPENSSL_VERSION_NUMBER < 0x10100000L
101
#error Must be compiled against OpenSSL 1.1.0 or later
102
#endif
103
104
#ifdef _WIN32
105
#define strcasecmp _stricmp
106
#define strncasecmp _strnicmp
107
#endif
108
109
/* RFC6091/RFC7250 */
110
#ifndef TLSEXT_TYPE_client_certificate_type
111
0
#define TLSEXT_TYPE_client_certificate_type 19
112
#endif
113
#ifndef TLSEXT_TYPE_server_certificate_type
114
#define TLSEXT_TYPE_server_certificate_type 20
115
#endif
116
117
#ifndef COAP_OPENSSL_CIPHERS
118
#if OPENSSL_VERSION_NUMBER >= 0x10101000L
119
0
#define COAP_OPENSSL_CIPHERS "TLSv1.3:TLSv1.2:!NULL"
120
#else /* OPENSSL_VERSION_NUMBER < 0x10101000L */
121
#define COAP_OPENSSL_CIPHERS "TLSv1.2:!NULL"
122
#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
123
#endif /*COAP_OPENSSL_CIPHERS */
124
125
#ifndef COAP_OPENSSL_PSK_CIPHERS
126
0
#define COAP_OPENSSL_PSK_CIPHERS "PSK:!NULL"
127
#endif /*COAP_OPENSSL_PSK_CIPHERS */
128
129
#ifndef COAP_OPENSSL_PKCS11_ENGINE_ID
130
0
#define COAP_OPENSSL_PKCS11_ENGINE_ID "pkcs11"
131
#endif /* COAP_OPENSSL_PKCS11_ENGINE_ID */
132
133
/* This structure encapsulates the OpenSSL context object. */
134
typedef struct coap_dtls_context_t {
135
  SSL_CTX *ctx;
136
  SSL *ssl;        /* OpenSSL object for listening to connection requests */
137
  HMAC_CTX *cookie_hmac;
138
  BIO_METHOD *meth;
139
  BIO_ADDR *bio_addr;
140
} coap_dtls_context_t;
141
142
typedef struct coap_tls_context_t {
143
  SSL_CTX *ctx;
144
  BIO_METHOD *meth;
145
} coap_tls_context_t;
146
147
0
#define IS_PSK 0x1
148
0
#define IS_PKI 0x2
149
150
typedef struct sni_entry {
151
  char *sni;
152
#if OPENSSL_VERSION_NUMBER < 0x10101000L
153
  SSL_CTX *ctx;
154
#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
155
  coap_dtls_key_t pki_key;
156
#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
157
} sni_entry;
158
159
typedef struct psk_sni_entry {
160
  char *sni;
161
#if OPENSSL_VERSION_NUMBER < 0x10101000L
162
  SSL_CTX *ctx;
163
#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
164
  coap_dtls_spsk_info_t psk_info;
165
} psk_sni_entry;
166
167
typedef struct coap_openssl_context_t {
168
  coap_dtls_context_t dtls;
169
#if !COAP_DISABLE_TCP
170
  coap_tls_context_t tls;
171
#endif /* !COAP_DISABLE_TCP */
172
  coap_dtls_pki_t setup_data;
173
  int psk_pki_enabled;
174
  size_t sni_count;
175
  sni_entry *sni_entry_list;
176
#if OPENSSL_VERSION_NUMBER < 0x10101000L
177
  size_t psk_sni_count;
178
  psk_sni_entry *psk_sni_entry_list;
179
#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
180
} coap_openssl_context_t;
181
182
#if COAP_SERVER_SUPPORT
183
#if OPENSSL_VERSION_NUMBER < 0x10101000L
184
static int psk_tls_server_name_call_back(SSL *ssl, int *sd, void *arg);
185
#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
186
static int tls_client_hello_call_back(SSL *ssl, int *al, void *arg);
187
#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
188
#endif /* COAP_SERVER_SUPPORT */
189
190
int
191
0
coap_dtls_is_supported(void) {
192
0
  if (SSLeay() < 0x10100000L) {
193
0
    coap_log_warn("OpenSSL version 1.1.0 or later is required\n");
194
0
    return 0;
195
0
  }
196
0
#if OPENSSL_VERSION_NUMBER >= 0x10101000L
197
  /*
198
   * For 1.1.1, we need to use SSL_CTX_set_client_hello_cb()
199
   * which is not in 1.1.0 instead of SSL_CTX_set_tlsext_servername_callback()
200
   *
201
   * However, there could be a runtime undefined external reference error
202
   * as SSL_CTX_set_client_hello_cb() is not there in 1.1.0.
203
   */
204
0
  if (SSLeay() < 0x10101000L) {
205
0
    coap_log_warn("OpenSSL version 1.1.1 or later is required\n");
206
0
    return 0;
207
0
  }
208
0
#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
209
0
  return 1;
210
0
}
211
212
int
213
0
coap_tls_is_supported(void) {
214
0
#if !COAP_DISABLE_TCP
215
0
  if (SSLeay() < 0x10100000L) {
216
0
    coap_log_warn("OpenSSL version 1.1.0 or later is required\n");
217
0
    return 0;
218
0
  }
219
0
#if OPENSSL_VERSION_NUMBER >= 0x10101000L
220
0
  if (SSLeay() < 0x10101000L) {
221
0
    coap_log_warn("OpenSSL version 1.1.1 or later is required\n");
222
0
    return 0;
223
0
  }
224
0
#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
225
0
  return 1;
226
#else /* COAP_DISABLE_TCP */
227
  return 0;
228
#endif /* COAP_DISABLE_TCP */
229
0
}
230
231
/*
232
 * return 0 failed
233
 *        1 passed
234
 */
235
int
236
0
coap_dtls_psk_is_supported(void) {
237
0
  return 1;
238
0
}
239
240
/*
241
 * return 0 failed
242
 *        1 passed
243
 */
244
int
245
0
coap_dtls_pki_is_supported(void) {
246
0
  return 1;
247
0
}
248
249
/*
250
 * return 0 failed
251
 *        1 passed
252
 */
253
int
254
0
coap_dtls_pkcs11_is_supported(void) {
255
0
#if OPENSSL_VERSION_NUMBER < 0x40000000L
256
0
  return 1;
257
#else /* OPENSSL_VERSION_NUMBER >= 0x40000000L */
258
  return 0;
259
#endif /* OPENSSL_VERSION_NUMBER >= 0x40000000L */
260
0
}
261
262
/*
263
 * return 0 failed
264
 *        1 passed
265
 */
266
int
267
0
coap_dtls_rpk_is_supported(void) {
268
0
  return 0;
269
0
}
270
271
/*
272
 * return 0 failed
273
 *        1 passed
274
 */
275
int
276
0
coap_dtls_cid_is_supported(void) {
277
0
  return 0;
278
0
}
279
280
#if COAP_CLIENT_SUPPORT
281
int
282
0
coap_dtls_set_cid_tuple_change(coap_context_t *c_context, uint8_t every) {
283
0
  (void)c_context;
284
0
  (void)every;
285
0
  return 0;
286
0
}
287
#endif /* COAP_CLIENT_SUPPORT */
288
289
coap_tls_version_t *
290
0
coap_get_tls_library_version(void) {
291
0
  static coap_tls_version_t version;
292
0
  version.version = SSLeay();
293
0
  version.built_version = OPENSSL_VERSION_NUMBER;
294
0
  version.type = COAP_TLS_LIBRARY_OPENSSL;
295
0
  return &version;
296
0
}
297
298
#if OPENSSL_VERSION_NUMBER < 0x40000000L
299
static ENGINE *pkcs11_engine = NULL;
300
static ENGINE *defined_engine = NULL;
301
#endif /* OPENSSL_VERSION_NUMBER < 0x40000000L */
302
303
void
304
0
coap_dtls_startup(void) {
305
0
  SSL_load_error_strings();
306
0
  SSL_library_init();
307
0
#if OPENSSL_VERSION_NUMBER < 0x40000000L
308
0
  ENGINE_load_dynamic();
309
0
#endif /* OPENSSL_VERSION_NUMBER < 0x40000000L */
310
0
}
311
312
void
313
0
coap_dtls_shutdown(void) {
314
0
#if OPENSSL_VERSION_NUMBER < 0x30000000L
315
0
  if (pkcs11_engine) {
316
    /* Release the functional reference from ENGINE_init() */
317
0
    ENGINE_finish(pkcs11_engine);
318
0
    pkcs11_engine = NULL;
319
0
  }
320
0
  if (defined_engine) {
321
    /* Release the functional reference from ENGINE_init() */
322
0
    ENGINE_finish(defined_engine);
323
0
    defined_engine = NULL;
324
0
  }
325
#elif OPENSSL_VERSION_NUMBER < 0x40000000L
326
  pkcs11_engine = NULL;
327
  defined_engine = NULL;
328
#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L && < 0x40000000L */
329
0
  ERR_free_strings();
330
0
  coap_dtls_set_log_level(COAP_LOG_EMERG);
331
0
}
332
333
void
334
0
coap_dtls_thread_shutdown(void) {
335
0
}
336
337
void *
338
coap_dtls_get_tls(const coap_session_t *c_session,
339
0
                  coap_tls_library_t *tls_lib) {
340
0
  if (tls_lib)
341
0
    *tls_lib = COAP_TLS_LIBRARY_OPENSSL;
342
0
  if (c_session) {
343
0
    return c_session->tls;
344
0
  }
345
0
  return NULL;
346
0
}
347
348
#if OPENSSL_VERSION_NUMBER < 0x40000000L
349
static int
350
get_split_conf_entry(const uint8_t **start, size_t size, const char *get_keyword,
351
0
                     coap_str_const_t **p1, coap_str_const_t **p2) {
352
0
  const uint8_t *begin = *start;
353
0
  const uint8_t *end;
354
0
  const uint8_t *kend;
355
0
  const uint8_t *split;
356
357
0
  *p1 = NULL;
358
0
  *p2 = NULL;
359
360
0
retry:
361
0
  kend = end = memchr(begin, '\n', size);
362
0
  if (end == NULL)
363
0
    return 0;
364
365
  /* Track beginning of next line */
366
0
  *start = end + 1;
367
0
  if (end > begin && end[-1] == '\r')
368
0
    end--;
369
370
0
  if (begin[0] == '#' || (end - begin) == 0) {
371
    /* Skip comment / blank line */
372
0
    size -= kend - begin + 1;
373
0
    begin = *start;
374
0
    goto retry;
375
0
  }
376
377
  /* Get in the keyword */
378
0
  split = memchr(begin, ':', end - begin);
379
0
  if (split == NULL)
380
0
    goto bad_entry;
381
382
0
  if ((size_t)(split - begin) != strlen(get_keyword)) {
383
0
    size -= kend - begin + 1;
384
0
    begin = *start;
385
0
    goto retry;
386
0
  }
387
0
  if (memcmp(begin, get_keyword, split - begin)) {
388
0
    size -= kend - begin + 1;
389
0
    begin = *start;
390
0
    goto retry;
391
0
  }
392
  /* Found entry we are looking for */
393
0
  begin = split + 1;
394
395
  /* parameter 1 is mandatory */
396
0
  if ((end - begin) == 0)
397
0
    goto bad_entry;
398
  /* Get in parameter #1 */
399
0
  split = memchr(begin, ':', end - begin);
400
0
  if (split == NULL) {
401
    /* Single entry - no parameter #2 */
402
0
    *p1 = coap_new_str_const(begin, end - begin);
403
0
    if (!(*p1)) {
404
0
      goto bad_entry;
405
0
    }
406
0
  } else {
407
0
    *p1 = coap_new_str_const(begin, split - begin);
408
0
    if (!(*p1)) {
409
0
      goto bad_entry;
410
0
    }
411
0
    if ((end - split) > 0) {
412
0
      *p2 = coap_new_str_const(split + 1, end - split - 1);
413
0
      if (!(*p2)) {
414
0
        goto bad_entry;
415
0
      }
416
0
    }
417
0
  }
418
419
0
  return 1;
420
421
0
bad_entry:
422
0
  coap_delete_str_const(*p1);
423
0
  coap_delete_str_const(*p2);
424
0
  return 0;
425
0
}
426
427
/*
428
 * Formatting of OpenSSL Engine configuration is:-
429
 * (Must be in this order)
430
 *
431
 * engine:XXX
432
 * pre-cmd:XXX:YYY
433
 *   ....
434
 * pre-cmd:XXX:YYY
435
 * post-cmd:XXX:YYY
436
 *   ....
437
 * post-cmd:XXX:YYY
438
 * enable-methods:unsigned-int
439
 *   OR'd set of ENGINE_METHOD_* or ENGINE_METHOD_ALL
440
 *
441
 * pre-cmd and post-cmd are optional
442
 * YYY does not have to be defined for some pre-cmd or post-cmd
443
 */
444
int
445
0
coap_tls_engine_configure(coap_str_const_t *conf_mem) {
446
0
  const uint8_t *start;
447
0
  const uint8_t *end;
448
0
  coap_str_const_t *p1 = NULL;
449
0
  coap_str_const_t *p2 = NULL;
450
0
  coap_str_const_t *engine_id = NULL;
451
0
  unsigned int defaults = 0;
452
0
  int done_engine_id = 0;
453
0
  int done_engine_init = 0;
454
455
0
  if (!conf_mem)
456
0
    return 0;
457
458
0
  start = conf_mem->s;
459
0
  end = start + conf_mem->length;
460
461
0
  if (defined_engine) {
462
0
    coap_log_warn("coap_tls_engine_configure: Freeing off previous engine definition\n");
463
0
    ENGINE_finish(defined_engine);
464
0
    defined_engine = NULL;
465
0
  }
466
467
  /* Set up engine */
468
0
  if (!get_split_conf_entry(&start, end - start, "engine", &engine_id, &p2)) {
469
0
    coap_log_warn("coap_tls_engine_configure: engine not defined\n");
470
0
    return 0;
471
0
  }
472
0
  defined_engine = ENGINE_by_id((const char *)engine_id->s);
473
0
  if (!defined_engine) {
474
0
    coap_log_warn("coap_tls_engine_configure: engine '%s' not known\n", engine_id->s);
475
0
    goto fail_cleanup;
476
0
  } else {
477
0
    done_engine_id = 1;
478
0
    coap_dtls_log(COAP_LOG_DEBUG, "coap_tls_engine_configure: engine '%s' started\n", engine_id->s);
479
0
  }
480
0
  coap_delete_str_const(p2);
481
482
0
  start = conf_mem->s;
483
  /* process all the pre-cmd defined */
484
0
  while (get_split_conf_entry(&start, end - start, "pre-cmd", &p1, &p2)) {
485
0
    if (!ENGINE_ctrl_cmd_string(defined_engine, (const char *)p1->s, p2 ? (const char *)p2->s : NULL,
486
0
                                0)) {
487
0
      coap_log_warn("coap_tls_engine_configure: engine %s pre-cmd '%s:%s' failed\n",
488
0
                    (const char *)engine_id->s,
489
0
                    (const char *)p1->s, p2 ? (const char *)p2->s : "(NULL)");
490
0
      goto fail_cleanup;
491
0
    } else {
492
0
      coap_dtls_log(COAP_LOG_DEBUG, "coap_tls_engine_configure: engine '%s' pre-cmd '%s:%s' success\n",
493
0
                    engine_id->s, p1->s, p2 ? (const char *)p2->s : "(NULL)");
494
0
    }
495
0
    coap_delete_str_const(p1);
496
0
    coap_delete_str_const(p2);
497
0
  }
498
499
0
  p1 = NULL;
500
0
  p2 = NULL;
501
  /* Start up the engine */
502
0
  if (!ENGINE_init(defined_engine)) {
503
0
    coap_log_warn("coap_tls_engine_configure: %s failed initialization\n", (const char *)engine_id->s);
504
0
    goto fail_cleanup;
505
0
  } else {
506
0
    done_engine_init = 1;
507
0
    coap_dtls_log(COAP_LOG_DEBUG, "coap_tls_engine_configure: %s initialized\n",
508
0
                  (const char *)engine_id->s);
509
0
  }
510
511
0
  start = conf_mem->s;
512
  /* process all the post-cmd defined */
513
0
  while (get_split_conf_entry(&start, end - start, "post-cmd", &p1, &p2)) {
514
0
    if (!ENGINE_ctrl_cmd_string(defined_engine, (const char *)p1->s, p2 ? (const char *)p2->s : NULL,
515
0
                                0)) {
516
0
      coap_log_warn("coap_tls_engine_configure: %s post-cmd '%s:%s' failed\n", (const char *)engine_id->s,
517
0
                    (const char *)p1->s, p2 ? (const char *)p2->s : "(NULL)");
518
0
      goto fail_cleanup;
519
0
    } else {
520
0
      coap_dtls_log(COAP_LOG_DEBUG, "coap_tls_engine_configure: %s post-cmd '%s:%s' success\n",
521
0
                    (const char *)engine_id->s,
522
0
                    (const char *)p1->s, p2 ? (const char *)p2->s : "(NULL)");
523
0
    }
524
0
    coap_delete_str_const(p1);
525
0
    coap_delete_str_const(p2);
526
0
  }
527
528
0
  start = conf_mem->s;
529
  /* See what we should be setting as the methods */
530
0
  if (!get_split_conf_entry(&start, end - start, "enable-methods", &p1, &p2)) {
531
0
    coap_log_warn("coap_tls_engine_configure: enable-methods not found\n");
532
0
    goto fail_cleanup;
533
0
  }
534
0
  defaults = strtoul((const char *)p1->s, NULL, 0);
535
0
  if (!ENGINE_set_default(defined_engine, defaults)) {
536
0
    coap_log_warn("coap_tls_engine_configure: enable-methods 0x%x invalid\n", defaults);
537
0
    goto fail_cleanup;
538
0
  } else {
539
0
    coap_dtls_log(COAP_LOG_DEBUG, "coap_tls_engine_configure: enable-methods 0x%x successful\n",
540
0
                  defaults);
541
0
  }
542
0
  coap_delete_str_const(engine_id);
543
0
  coap_delete_str_const(p1);
544
0
  coap_delete_str_const(p2);
545
  /* Success */
546
547
0
  return 1;
548
549
0
fail_cleanup:
550
0
  if (done_engine_id)
551
0
    ENGINE_free(defined_engine);
552
0
  if (done_engine_init)
553
0
    ENGINE_finish(defined_engine);
554
0
  defined_engine = NULL;
555
0
  coap_delete_str_const(engine_id);
556
0
  coap_delete_str_const(p1);
557
0
  coap_delete_str_const(p2);
558
0
  return 0;
559
0
}
560
561
int
562
0
coap_tls_engine_remove(void) {
563
0
  if (defined_engine) {
564
0
    ENGINE_finish(defined_engine);
565
0
    defined_engine = NULL;
566
0
    return 1;
567
0
  }
568
0
  return 0;
569
0
}
570
#else /*  OPENSSL_VERSION_NUMBER >= 0x40000000L */
571
572
int
573
coap_tls_engine_configure(coap_str_const_t *conf_mem) {
574
  (void)conf_mem;
575
  return 0;
576
}
577
578
int
579
coap_tls_engine_remove(void) {
580
  return 0;
581
}
582
#endif /* OPENSSL_VERSION_NUMBER >= 0x40000000L */
583
584
/*
585
 * Logging levels use the standard CoAP logging levels
586
 */
587
static coap_log_t dtls_log_level = COAP_LOG_EMERG;
588
589
void
590
0
coap_dtls_set_log_level(coap_log_t level) {
591
0
  dtls_log_level = level;
592
0
}
593
594
coap_log_t
595
0
coap_dtls_get_log_level(void) {
596
0
  return dtls_log_level;
597
0
}
598
599
typedef struct coap_ssl_data {
600
  coap_session_t *session;
601
  const void *pdu;
602
  unsigned pdu_len;
603
  unsigned peekmode;
604
  coap_tick_t timeout;
605
} coap_ssl_data;
606
607
static int
608
0
coap_dgram_create(BIO *a) {
609
0
  coap_ssl_data *data = NULL;
610
0
  data = malloc(sizeof(coap_ssl_data));
611
0
  if (data == NULL)
612
0
    return 0;
613
0
  BIO_set_init(a, 1);
614
0
  BIO_set_data(a, data);
615
0
  memset(data, 0x00, sizeof(coap_ssl_data));
616
0
  return 1;
617
0
}
618
619
static int
620
0
coap_dgram_destroy(BIO *a) {
621
0
  coap_ssl_data *data;
622
0
  if (a == NULL)
623
0
    return 0;
624
0
  data = (coap_ssl_data *)BIO_get_data(a);
625
0
  BIO_set_data(a, NULL);
626
0
  if (data != NULL)
627
0
    free(data);
628
0
  return 1;
629
0
}
630
631
static int
632
0
coap_dgram_read(BIO *a, char *out, int outl) {
633
0
  int ret = 0;
634
0
  coap_ssl_data *data = (coap_ssl_data *)BIO_get_data(a);
635
636
0
  if (out != NULL) {
637
0
    if (data != NULL && data->pdu_len > 0) {
638
0
      if (outl < (int)data->pdu_len) {
639
0
        memcpy(out, data->pdu, outl);
640
0
        ret = outl;
641
0
      } else {
642
0
        memcpy(out, data->pdu, data->pdu_len);
643
0
        ret = (int)data->pdu_len;
644
0
      }
645
0
      if (!data->peekmode) {
646
0
        data->pdu_len = 0;
647
0
        data->pdu = NULL;
648
0
      }
649
0
    } else {
650
0
      ret = -1;
651
0
    }
652
0
    BIO_clear_retry_flags(a);
653
0
    if (ret < 0)
654
0
      BIO_set_retry_read(a);
655
0
  }
656
0
  return ret;
657
0
}
658
659
static int
660
0
coap_dgram_write(BIO *a, const char *in, int inl) {
661
0
  int ret = 0;
662
0
  coap_ssl_data *data = (coap_ssl_data *)BIO_get_data(a);
663
664
0
  if (data && data->session) {
665
0
    if (!coap_netif_available(data->session)
666
0
#if COAP_SERVER_SUPPORT
667
0
        && data->session->endpoint == NULL
668
0
#endif /* COAP_SERVER_SUPPORT */
669
0
       ) {
670
      /* socket was closed on client due to error */
671
0
      BIO_clear_retry_flags(a);
672
0
      errno = ECONNRESET;
673
0
      return -1;
674
0
    }
675
0
    ret = (int)data->session->sock.lfunc[COAP_LAYER_TLS].l_write(data->session,
676
0
          (const uint8_t *)in,
677
0
          inl);
678
0
    BIO_clear_retry_flags(a);
679
0
    if (ret <= 0) {
680
0
      if (ret < 0 && (errno == ENOTCONN || errno == ECONNREFUSED))
681
0
        data->session->dtls_event = COAP_EVENT_DTLS_ERROR;
682
0
      BIO_set_retry_write(a);
683
0
    }
684
0
  } else {
685
0
    BIO_clear_retry_flags(a);
686
0
    ret = -1;
687
0
  }
688
0
  return ret;
689
0
}
690
691
static int
692
0
coap_dgram_puts(BIO *a, const char *pstr) {
693
0
  return coap_dgram_write(a, pstr, (int)strlen(pstr));
694
0
}
695
696
static long
697
0
coap_dgram_ctrl(BIO *a, int cmd, long num, void *ptr) {
698
0
  long ret = 1;
699
0
  coap_ssl_data *data = BIO_get_data(a);
700
701
0
  (void)ptr;
702
703
0
  switch (cmd) {
704
0
  case BIO_CTRL_GET_CLOSE:
705
0
    ret = BIO_get_shutdown(a);
706
0
    break;
707
0
  case BIO_CTRL_SET_CLOSE:
708
0
    BIO_set_shutdown(a, (int)num);
709
0
    break;
710
0
  case BIO_CTRL_DGRAM_SET_PEEK_MODE:
711
0
    if (data)
712
0
      data->peekmode = (unsigned)num;
713
0
    else
714
0
      ret = 0;
715
0
    break;
716
0
  case BIO_CTRL_DGRAM_CONNECT:
717
0
  case BIO_C_SET_FD:
718
0
  case BIO_C_GET_FD:
719
0
  case BIO_CTRL_DGRAM_SET_DONT_FRAG:
720
0
  case BIO_CTRL_DGRAM_GET_MTU:
721
0
  case BIO_CTRL_DGRAM_SET_MTU:
722
0
  case BIO_CTRL_DGRAM_QUERY_MTU:
723
0
  case BIO_CTRL_DGRAM_GET_FALLBACK_MTU:
724
0
    ret = -1;
725
0
    break;
726
0
  case BIO_CTRL_DUP:
727
0
  case BIO_CTRL_FLUSH:
728
0
  case BIO_CTRL_DGRAM_MTU_DISCOVER:
729
0
  case BIO_CTRL_DGRAM_SET_CONNECTED:
730
0
    break;
731
0
  case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
732
0
    if (data)
733
0
      data->timeout = coap_ticks_from_rt_us((uint64_t)((struct timeval *)ptr)->tv_sec * 1000000 +
734
0
                                            ((struct timeval *)ptr)->tv_usec);
735
0
    else
736
0
      ret = 0;
737
0
    break;
738
0
  case BIO_CTRL_RESET:
739
0
  case BIO_C_FILE_SEEK:
740
0
  case BIO_C_FILE_TELL:
741
0
  case BIO_CTRL_INFO:
742
0
  case BIO_CTRL_PENDING:
743
0
  case BIO_CTRL_WPENDING:
744
0
  case BIO_CTRL_DGRAM_GET_PEER:
745
0
  case BIO_CTRL_DGRAM_SET_PEER:
746
0
  case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:
747
0
  case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT:
748
0
  case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT:
749
0
  case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT:
750
0
  case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP:
751
0
  case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP:
752
0
  case BIO_CTRL_DGRAM_MTU_EXCEEDED:
753
0
  case BIO_CTRL_DGRAM_GET_MTU_OVERHEAD:
754
0
  default:
755
0
    ret = 0;
756
0
    break;
757
0
  }
758
0
  return ret;
759
0
}
760
761
static int
762
coap_dtls_generate_cookie(SSL *ssl,
763
                          unsigned char *cookie,
764
0
                          unsigned int *cookie_len) {
765
0
  SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
766
0
  coap_dtls_context_t *dtls = ctx ? (coap_dtls_context_t *)SSL_CTX_get_app_data(ctx) : NULL;
767
0
  coap_ssl_data *data = (coap_ssl_data *)BIO_get_data(SSL_get_rbio(ssl));
768
769
0
  if (dtls && data) {
770
0
    int r = HMAC_Init_ex(dtls->cookie_hmac, NULL, 0, NULL, NULL);
771
0
    r &= HMAC_Update(dtls->cookie_hmac,
772
0
                     (const uint8_t *)&data->session->addr_info.local.addr,
773
0
                     (size_t)data->session->addr_info.local.size);
774
0
    r &= HMAC_Update(dtls->cookie_hmac,
775
0
                     (const uint8_t *)&data->session->addr_info.remote.addr,
776
0
                     (size_t)data->session->addr_info.remote.size);
777
0
    r &= HMAC_Final(dtls->cookie_hmac, cookie, cookie_len);
778
0
    return r;
779
0
  }
780
0
  return 0;
781
0
}
782
783
static int
784
coap_dtls_verify_cookie(SSL *ssl,
785
                        const uint8_t *cookie,
786
0
                        unsigned int cookie_len) {
787
0
  uint8_t hmac[32];
788
0
  unsigned len = 32;
789
0
  if (coap_dtls_generate_cookie(ssl, hmac, &len) &&
790
0
      cookie_len == len && memcmp(cookie, hmac, len) == 0)
791
0
    return 1;
792
0
  else
793
0
    return 0;
794
0
}
795
796
#if COAP_CLIENT_SUPPORT
797
static unsigned int
798
coap_dtls_psk_client_callback(SSL *ssl,
799
                              const char *hint,
800
                              char *identity,
801
                              unsigned int max_identity_len,
802
                              unsigned char *psk,
803
0
                              unsigned int max_psk_len) {
804
0
  coap_session_t *c_session;
805
0
  coap_openssl_context_t *o_context;
806
0
  coap_dtls_cpsk_t *setup_data;
807
0
  coap_bin_const_t temp;
808
0
  const coap_dtls_cpsk_info_t *cpsk_info;
809
0
  const coap_bin_const_t *psk_key;
810
0
  const coap_bin_const_t *psk_identity;
811
812
0
  c_session = (coap_session_t *)SSL_get_app_data(ssl);
813
0
  if (c_session == NULL || c_session->context == NULL)
814
0
    return 0;
815
0
  o_context = (coap_openssl_context_t *)c_session->context->dtls_context;
816
0
  if (o_context == NULL)
817
0
    return 0;
818
0
  setup_data = &c_session->cpsk_setup_data;
819
820
0
  temp.s = hint ? (const uint8_t *)hint : (const uint8_t *)"";
821
0
  temp.length = strlen((const char *)temp.s);
822
0
  coap_session_refresh_psk_hint(c_session, &temp);
823
824
0
  coap_log_debug("got psk_identity_hint: '%.*s'\n", (int)temp.length,
825
0
                 (const char *)temp.s);
826
827
0
  if (setup_data->validate_ih_call_back) {
828
0
    coap_str_const_t lhint;
829
830
0
    lhint.s = temp.s;
831
0
    lhint.length = temp.length;
832
0
    coap_lock_callback_ret(cpsk_info,
833
0
                           setup_data->validate_ih_call_back(&lhint,
834
0
                                                             c_session,
835
0
                                                             setup_data->ih_call_back_arg));
836
837
0
    if (cpsk_info == NULL)
838
0
      return 0;
839
840
0
    coap_session_refresh_psk_identity(c_session, &cpsk_info->identity);
841
0
    coap_session_refresh_psk_key(c_session, &cpsk_info->key);
842
0
    psk_identity = &cpsk_info->identity;
843
0
    psk_key = &cpsk_info->key;
844
0
  } else {
845
0
    psk_identity = coap_get_session_client_psk_identity(c_session);
846
0
    psk_key = coap_get_session_client_psk_key(c_session);
847
0
  }
848
849
0
  if (psk_identity == NULL || psk_key == NULL) {
850
0
    coap_log_warn("no PSK available\n");
851
0
    return 0;
852
0
  }
853
854
  /* identity has to be NULL terminated */
855
0
  if (!max_identity_len)
856
0
    return 0;
857
0
  max_identity_len--;
858
0
  if (psk_identity->length > max_identity_len) {
859
0
    coap_log_warn("psk_identity too large, truncated to %d bytes\n",
860
0
                  max_identity_len);
861
0
  } else {
862
    /* Reduce to match */
863
0
    max_identity_len = (unsigned int)psk_identity->length;
864
0
  }
865
0
  memcpy(identity, psk_identity->s, max_identity_len);
866
0
  identity[max_identity_len] = '\000';
867
868
0
  if (psk_key->length > max_psk_len) {
869
0
    coap_log_warn("psk_key too large, truncated to %d bytes\n",
870
0
                  max_psk_len);
871
0
  } else {
872
    /* Reduce to match */
873
0
    max_psk_len = (unsigned int)psk_key->length;
874
0
  }
875
0
  memcpy(psk, psk_key->s, max_psk_len);
876
0
  return max_psk_len;
877
0
}
878
#endif /* COAP_CLIENT_SUPPORT */
879
880
#if COAP_SERVER_SUPPORT
881
static unsigned int
882
coap_dtls_psk_server_callback(
883
    SSL *ssl,
884
    const char *identity,
885
    unsigned char *psk,
886
    unsigned int max_psk_len
887
0
) {
888
0
  coap_session_t *c_session;
889
0
  coap_dtls_spsk_t *setup_data;
890
0
  coap_bin_const_t lidentity;
891
0
  const coap_bin_const_t *psk_key;
892
893
0
  c_session = (coap_session_t *)SSL_get_app_data(ssl);
894
0
  if (c_session == NULL || c_session->context == NULL)
895
0
    return 0;
896
897
0
  setup_data = &c_session->context->spsk_setup_data;
898
899
  /* Track the Identity being used */
900
0
  lidentity.s = identity ? (const uint8_t *)identity : (const uint8_t *)"";
901
0
  lidentity.length = strlen((const char *)lidentity.s);
902
0
  coap_session_refresh_psk_identity(c_session, &lidentity);
903
904
0
  coap_log_debug("got psk_identity: '%.*s'\n",
905
0
                 (int)lidentity.length, (const char *)lidentity.s);
906
907
0
  if (setup_data->validate_id_call_back) {
908
0
    psk_key = setup_data->validate_id_call_back(&lidentity,
909
0
                                                c_session,
910
0
                                                setup_data->id_call_back_arg);
911
912
0
    coap_session_refresh_psk_key(c_session, psk_key);
913
0
  } else {
914
0
    psk_key = coap_get_session_server_psk_key(c_session);
915
0
  }
916
917
0
  if (psk_key == NULL)
918
0
    return 0;
919
920
0
  if (psk_key->length > max_psk_len) {
921
0
    coap_log_warn("psk_key too large, truncated to %d bytes\n",
922
0
                  max_psk_len);
923
0
  } else {
924
    /* Reduce to match */
925
0
    max_psk_len = (unsigned int)psk_key->length;
926
0
  }
927
0
  memcpy(psk, psk_key->s, max_psk_len);
928
0
  return max_psk_len;
929
0
}
930
#endif /* COAP_SERVER_SUPPORT */
931
932
static const char *
933
0
ssl_function_definition(unsigned long e) {
934
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
935
  (void)e;
936
  return "";
937
#else /* OPENSSL_VERSION_NUMBER < 0x30000000L */
938
0
  static char buff[80];
939
940
0
  snprintf(buff, sizeof(buff), " at %s:%s",
941
0
           ERR_lib_error_string(e), ERR_func_error_string(e));
942
0
  return buff;
943
0
#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */
944
0
}
945
946
static void
947
0
coap_dtls_info_callback(const SSL *ssl, int where, int ret) {
948
0
  coap_session_t *session = (coap_session_t *)SSL_get_app_data(ssl);
949
0
  const char *pstr;
950
0
  int w = where &~SSL_ST_MASK;
951
952
0
  if (!session) {
953
0
    coap_dtls_log(COAP_LOG_WARN,
954
0
                  "coap_dtls_info_callback: session not determined, where 0x%0x and ret 0x%0x\n", where, ret);
955
0
    return;
956
0
  }
957
0
  if (w & SSL_ST_CONNECT)
958
0
    pstr = "SSL_connect";
959
0
  else if (w & SSL_ST_ACCEPT)
960
0
    pstr = "SSL_accept";
961
0
  else
962
0
    pstr = "undefined";
963
964
0
  if (where & SSL_CB_LOOP) {
965
0
    coap_dtls_log(COAP_LOG_DEBUG, "*  %s: %s:%s\n",
966
0
                  coap_session_str(session), pstr, SSL_state_string_long(ssl));
967
0
  } else if (where & SSL_CB_ALERT) {
968
0
    coap_log_t log_level = COAP_LOG_INFO;
969
0
    pstr = (where & SSL_CB_READ) ? "read" : "write";
970
0
    if ((where & (SSL_CB_WRITE|SSL_CB_READ)) && (ret >> 8) == SSL3_AL_FATAL) {
971
0
      session->dtls_event = COAP_EVENT_DTLS_ERROR;
972
0
      if ((ret & 0xff) != SSL3_AD_CLOSE_NOTIFY)
973
0
        log_level = COAP_LOG_WARN;
974
0
    }
975
    /* Need to let CoAP logging know why this session is dying */
976
0
    coap_log(log_level, "*  %s: SSL3 alert %s:%s:%s\n",
977
0
             coap_session_str(session),
978
0
             pstr,
979
0
             SSL_alert_type_string_long(ret),
980
0
             SSL_alert_desc_string_long(ret));
981
0
  } else if (where & SSL_CB_EXIT) {
982
0
    if (ret == 0) {
983
0
      if (dtls_log_level >= COAP_LOG_WARN) {
984
0
        unsigned long e;
985
0
        coap_dtls_log(COAP_LOG_WARN, "*  %s: %s:failed in %s\n",
986
0
                      coap_session_str(session), pstr, SSL_state_string_long(ssl));
987
0
        while ((e = ERR_get_error()))
988
0
          coap_dtls_log(COAP_LOG_WARN, "*  %s: %s%s\n",
989
0
                        coap_session_str(session), ERR_reason_error_string(e),
990
0
                        ssl_function_definition(e));
991
0
      }
992
0
    } else if (ret < 0) {
993
0
      if (dtls_log_level >= COAP_LOG_WARN) {
994
0
        int err = SSL_get_error(ssl, ret);
995
0
        if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE &&
996
0
            err != SSL_ERROR_WANT_CONNECT && err != SSL_ERROR_WANT_ACCEPT &&
997
0
            err != SSL_ERROR_WANT_X509_LOOKUP) {
998
0
          long e;
999
0
          coap_dtls_log(COAP_LOG_WARN, "*  %s: %s:error in %s\n",
1000
0
                        coap_session_str(session), pstr, SSL_state_string_long(ssl));
1001
0
          while ((e = ERR_get_error()))
1002
0
            coap_dtls_log(COAP_LOG_WARN, "*  %s: %s%s\n",
1003
0
                          coap_session_str(session), ERR_reason_error_string(e),
1004
0
                          ssl_function_definition(e));
1005
0
        }
1006
0
      } else {
1007
0
        while (ERR_get_error()) {
1008
0
        }
1009
0
      }
1010
0
    }
1011
0
  }
1012
1013
0
  if (where == SSL_CB_HANDSHAKE_START && SSL_get_state(ssl) == TLS_ST_OK)
1014
0
    session->dtls_event = COAP_EVENT_DTLS_RENEGOTIATE;
1015
0
}
1016
1017
#if !COAP_DISABLE_TCP
1018
static int
1019
0
coap_sock_create(BIO *a) {
1020
0
  BIO_set_init(a, 1);
1021
0
  return 1;
1022
0
}
1023
1024
static int
1025
0
coap_sock_destroy(BIO *a) {
1026
0
  (void)a;
1027
0
  return 1;
1028
0
}
1029
1030
/*
1031
 * strm
1032
 * return +ve data amount
1033
 *        0   no more
1034
 *        -1  error
1035
 */
1036
static int
1037
0
coap_sock_read(BIO *a, char *out, int outl) {
1038
0
  int ret = 0;
1039
0
  coap_session_t *session = (coap_session_t *)BIO_get_data(a);
1040
1041
0
  if (session && out != NULL) {
1042
0
    ret =(int)session->sock.lfunc[COAP_LAYER_TLS].l_read(session, (uint8_t *)out,
1043
0
                                                         outl);
1044
    /* Translate layer returns into what OpenSSL expects */
1045
0
    if (ret == 0) {
1046
0
      BIO_set_retry_read(a);
1047
0
      ret = -1;
1048
0
      errno = EAGAIN;
1049
0
    } else {
1050
0
      BIO_clear_retry_flags(a);
1051
0
    }
1052
0
  }
1053
0
  return ret;
1054
0
}
1055
1056
/*
1057
 * strm
1058
 * return +ve data amount
1059
 *        0   no more
1060
 *        -1  error (error in errno)
1061
 */
1062
static int
1063
0
coap_sock_write(BIO *a, const char *in, int inl) {
1064
0
  int ret = 0;
1065
0
  coap_session_t *session = (coap_session_t *)BIO_get_data(a);
1066
1067
0
  if (!session) {
1068
0
    errno = ENOMEM;
1069
0
    return -1;
1070
0
  } else {
1071
0
    ret = (int)session->sock.lfunc[COAP_LAYER_TLS].l_write(session,
1072
0
                                                           (const uint8_t *)in,
1073
0
                                                           inl);
1074
0
  }
1075
  /* Translate layer what returns into what OpenSSL expects */
1076
0
  BIO_clear_retry_flags(a);
1077
0
  if (ret == 0) {
1078
0
    BIO_set_retry_read(a);
1079
0
    ret = -1;
1080
0
    errno = EAGAIN;
1081
0
  } else {
1082
0
    BIO_clear_retry_flags(a);
1083
0
    if (ret == -1) {
1084
0
      if ((session->state == COAP_SESSION_STATE_CSM ||
1085
0
           session->state == COAP_SESSION_STATE_HANDSHAKE) &&
1086
0
          (errno == EPIPE || errno == ECONNRESET)) {
1087
        /*
1088
         * Need to handle a TCP timing window where an agent continues with
1089
         * the sending of the next handshake or a CSM.
1090
         * However, the peer does not like a certificate and so sends a
1091
         * fatal alert and closes the TCP session.
1092
         * The sending of the next handshake or CSM may get terminated because
1093
         * of the closed TCP session, but there is still an outstanding alert
1094
         * to be read in and reported on.
1095
         * In this case, pretend that sending the info was fine so that the
1096
         * alert can be read (which effectively is what happens with DTLS).
1097
         */
1098
0
        ret = inl;
1099
0
      }
1100
0
    }
1101
0
  }
1102
0
  return ret;
1103
0
}
1104
1105
static int
1106
0
coap_sock_puts(BIO *a, const char *pstr) {
1107
0
  return coap_sock_write(a, pstr, (int)strlen(pstr));
1108
0
}
1109
1110
static long
1111
0
coap_sock_ctrl(BIO *a, int cmd, long num, void *ptr) {
1112
0
  int r = 1;
1113
0
  (void)a;
1114
0
  (void)ptr;
1115
0
  (void)num;
1116
1117
0
  switch (cmd) {
1118
0
  case BIO_C_SET_FD:
1119
0
  case BIO_C_GET_FD:
1120
0
    r = -1;
1121
0
    break;
1122
0
  case BIO_CTRL_SET_CLOSE:
1123
0
  case BIO_CTRL_DUP:
1124
0
  case BIO_CTRL_FLUSH:
1125
0
    r = 1;
1126
0
    break;
1127
0
  default:
1128
0
  case BIO_CTRL_GET_CLOSE:
1129
0
    r = 0;
1130
0
    break;
1131
0
  }
1132
0
  return r;
1133
0
}
1134
#endif /* !COAP_DISABLE_TCP */
1135
1136
static void
1137
0
coap_set_user_prefs(SSL_CTX *ctx) {
1138
0
  SSL_CTX_set_cipher_list(ctx, COAP_OPENSSL_CIPHERS);
1139
1140
#ifdef COAP_OPENSSL_SIGALGS
1141
  SSL_CTX_set1_sigalgs_list(ctx, COAP_OPENSSL_SIGALGS);
1142
  SSL_CTX_set1_client_sigalgs_list(ctx, COAP_OPENSSL_SIGALGS);
1143
#endif
1144
1145
#if OPENSSL_VERSION_NUMBER >= 0x10101000L && defined(COAP_OPENSSL_GROUPS)
1146
  SSL_CTX_set1_groups_list(ctx, COAP_OPENSSL_GROUPS);
1147
#endif
1148
0
}
1149
1150
#if COAP_DTLS_RETRANSMIT_MS != 1000
1151
#if OPENSSL_VERSION_NUMBER >= 0x10101000L
1152
static unsigned int
1153
timer_cb(SSL *s, unsigned int timer_us) {
1154
  (void)s;
1155
  if (timer_us == 0)
1156
    return COAP_DTLS_RETRANSMIT_MS * 1000;
1157
  else
1158
    return 2 * timer_us;
1159
}
1160
#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1161
#endif /* COAP_DTLS_RETRANSMIT_MS != 1000 */
1162
1163
void *
1164
0
coap_dtls_new_context(coap_context_t *coap_context) {
1165
0
  coap_openssl_context_t *context;
1166
0
  (void)coap_context;
1167
1168
0
  context = (coap_openssl_context_t *)coap_malloc_type(COAP_STRING, sizeof(coap_openssl_context_t));
1169
0
  if (context) {
1170
0
    uint8_t cookie_secret[32];
1171
1172
0
    memset(context, 0, sizeof(coap_openssl_context_t));
1173
1174
    /* Set up DTLS context */
1175
0
    context->dtls.ctx = SSL_CTX_new(DTLS_method());
1176
0
    if (!context->dtls.ctx)
1177
0
      goto error;
1178
0
    SSL_CTX_set_min_proto_version(context->dtls.ctx, DTLS1_2_VERSION);
1179
0
    SSL_CTX_set_app_data(context->dtls.ctx, &context->dtls);
1180
0
    SSL_CTX_set_read_ahead(context->dtls.ctx, 1);
1181
0
    coap_set_user_prefs(context->dtls.ctx);
1182
0
    memset(cookie_secret, 0, sizeof(cookie_secret));
1183
0
    if (!RAND_bytes(cookie_secret, (int)sizeof(cookie_secret))) {
1184
0
      coap_dtls_log(COAP_LOG_WARN,
1185
0
                    "Insufficient entropy for random cookie generation");
1186
0
      coap_prng_lkd(cookie_secret, sizeof(cookie_secret));
1187
0
    }
1188
0
    context->dtls.cookie_hmac = HMAC_CTX_new();
1189
0
    if (!context->dtls.cookie_hmac)
1190
0
      goto error;
1191
0
    if (!HMAC_Init_ex(context->dtls.cookie_hmac, cookie_secret, (int)sizeof(cookie_secret),
1192
0
                      EVP_sha256(), NULL))
1193
0
      goto error;
1194
0
    SSL_CTX_set_cookie_generate_cb(context->dtls.ctx, coap_dtls_generate_cookie);
1195
0
    SSL_CTX_set_cookie_verify_cb(context->dtls.ctx, coap_dtls_verify_cookie);
1196
0
    SSL_CTX_set_info_callback(context->dtls.ctx, coap_dtls_info_callback);
1197
0
    SSL_CTX_set_options(context->dtls.ctx, SSL_OP_NO_QUERY_MTU);
1198
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1199
    SSL_CTX_set_options(context->dtls.ctx, SSL_OP_LEGACY_SERVER_CONNECT);
1200
#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
1201
0
    context->dtls.meth = BIO_meth_new(BIO_TYPE_DGRAM, "coapdgram");
1202
0
    if (!context->dtls.meth)
1203
0
      goto error;
1204
0
    context->dtls.bio_addr = BIO_ADDR_new();
1205
0
    if (!context->dtls.bio_addr)
1206
0
      goto error;
1207
0
    BIO_meth_set_write(context->dtls.meth, coap_dgram_write);
1208
0
    BIO_meth_set_read(context->dtls.meth, coap_dgram_read);
1209
0
    BIO_meth_set_puts(context->dtls.meth, coap_dgram_puts);
1210
0
    BIO_meth_set_ctrl(context->dtls.meth, coap_dgram_ctrl);
1211
0
    BIO_meth_set_create(context->dtls.meth, coap_dgram_create);
1212
0
    BIO_meth_set_destroy(context->dtls.meth, coap_dgram_destroy);
1213
1214
0
#if !COAP_DISABLE_TCP
1215
    /* Set up TLS context */
1216
0
    context->tls.ctx = SSL_CTX_new(TLS_method());
1217
0
    if (!context->tls.ctx)
1218
0
      goto error;
1219
0
    SSL_CTX_set_app_data(context->tls.ctx, &context->tls);
1220
0
    SSL_CTX_set_min_proto_version(context->tls.ctx, TLS1_VERSION);
1221
0
    coap_set_user_prefs(context->tls.ctx);
1222
0
    SSL_CTX_set_info_callback(context->tls.ctx, coap_dtls_info_callback);
1223
0
    context->tls.meth = BIO_meth_new(BIO_TYPE_SOCKET, "coapsock");
1224
0
    if (!context->tls.meth)
1225
0
      goto error;
1226
0
    BIO_meth_set_write(context->tls.meth, coap_sock_write);
1227
0
    BIO_meth_set_read(context->tls.meth, coap_sock_read);
1228
0
    BIO_meth_set_puts(context->tls.meth, coap_sock_puts);
1229
0
    BIO_meth_set_ctrl(context->tls.meth, coap_sock_ctrl);
1230
0
    BIO_meth_set_create(context->tls.meth, coap_sock_create);
1231
0
    BIO_meth_set_destroy(context->tls.meth, coap_sock_destroy);
1232
0
#endif /* !COAP_DISABLE_TCP */
1233
0
  }
1234
1235
0
  return context;
1236
1237
0
error:
1238
0
  coap_dtls_free_context(context);
1239
0
  return NULL;
1240
0
}
1241
1242
#if COAP_SERVER_SUPPORT
1243
int
1244
coap_dtls_context_set_spsk(coap_context_t *c_context,
1245
                           coap_dtls_spsk_t *setup_data
1246
0
                          ) {
1247
0
  coap_openssl_context_t *o_context =
1248
0
      ((coap_openssl_context_t *)c_context->dtls_context);
1249
0
  BIO *bio;
1250
1251
0
  if (!setup_data || !o_context)
1252
0
    return 0;
1253
1254
0
  SSL_CTX_set_psk_server_callback(o_context->dtls.ctx,
1255
0
                                  coap_dtls_psk_server_callback);
1256
0
#if !COAP_DISABLE_TCP
1257
0
  SSL_CTX_set_psk_server_callback(o_context->tls.ctx,
1258
0
                                  coap_dtls_psk_server_callback);
1259
0
#endif /* !COAP_DISABLE_TCP */
1260
0
  if (setup_data->psk_info.hint.s) {
1261
0
    char hint[COAP_DTLS_HINT_LENGTH];
1262
0
    snprintf(hint, sizeof(hint), "%.*s", (int)setup_data->psk_info.hint.length,
1263
0
             setup_data->psk_info.hint.s);
1264
0
    SSL_CTX_use_psk_identity_hint(o_context->dtls.ctx, hint);
1265
0
#if !COAP_DISABLE_TCP
1266
0
    SSL_CTX_use_psk_identity_hint(o_context->tls.ctx, hint);
1267
0
#endif /* !COAP_DISABLE_TCP */
1268
0
  }
1269
0
  if (setup_data->validate_sni_call_back) {
1270
#if OPENSSL_VERSION_NUMBER < 0x10101000L
1271
    SSL_CTX_set_tlsext_servername_arg(o_context->dtls.ctx,
1272
                                      &c_context->spsk_setup_data);
1273
    SSL_CTX_set_tlsext_servername_callback(o_context->dtls.ctx,
1274
                                           psk_tls_server_name_call_back);
1275
#if !COAP_DISABLE_TCP
1276
    SSL_CTX_set_tlsext_servername_arg(o_context->tls.ctx,
1277
                                      &c_context->spsk_setup_data);
1278
    SSL_CTX_set_tlsext_servername_callback(o_context->tls.ctx,
1279
                                           psk_tls_server_name_call_back);
1280
#endif /* !COAP_DISABLE_TCP */
1281
#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1282
0
    SSL_CTX_set_client_hello_cb(o_context->dtls.ctx,
1283
0
                                tls_client_hello_call_back,
1284
0
                                NULL);
1285
0
#if !COAP_DISABLE_TCP
1286
0
    SSL_CTX_set_client_hello_cb(o_context->tls.ctx,
1287
0
                                tls_client_hello_call_back,
1288
0
                                NULL);
1289
0
#endif /* !COAP_DISABLE_TCP */
1290
0
#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1291
0
  }
1292
1293
0
  if (!o_context->dtls.ssl) {
1294
    /* This is set up to handle new incoming sessions to a server */
1295
0
    o_context->dtls.ssl = SSL_new(o_context->dtls.ctx);
1296
0
    if (!o_context->dtls.ssl)
1297
0
      return 0;
1298
0
    bio = BIO_new(o_context->dtls.meth);
1299
0
    if (!bio) {
1300
0
      SSL_free(o_context->dtls.ssl);
1301
0
      o_context->dtls.ssl = NULL;
1302
0
      return 0;
1303
0
    }
1304
0
    SSL_set_bio(o_context->dtls.ssl, bio, bio);
1305
0
    SSL_set_app_data(o_context->dtls.ssl, NULL);
1306
0
    SSL_set_options(o_context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
1307
0
    SSL_set_mtu(o_context->dtls.ssl, COAP_DEFAULT_MTU);
1308
0
  }
1309
0
  if (setup_data->ec_jpake) {
1310
0
    coap_log_warn("OpenSSL has no EC-JPAKE support\n");
1311
0
  }
1312
0
  o_context->psk_pki_enabled |= IS_PSK;
1313
0
  return 1;
1314
0
}
1315
#endif /* COAP_SERVER_SUPPORT */
1316
1317
#if COAP_CLIENT_SUPPORT
1318
int
1319
coap_dtls_context_set_cpsk(coap_context_t *c_context,
1320
                           coap_dtls_cpsk_t *setup_data
1321
0
                          ) {
1322
0
  coap_openssl_context_t *o_context =
1323
0
      ((coap_openssl_context_t *)c_context->dtls_context);
1324
0
  BIO *bio;
1325
1326
0
  if (!setup_data || !o_context)
1327
0
    return 0;
1328
1329
0
  if (!o_context->dtls.ssl) {
1330
    /* This is set up to handle new incoming sessions to a server */
1331
0
    o_context->dtls.ssl = SSL_new(o_context->dtls.ctx);
1332
0
    if (!o_context->dtls.ssl)
1333
0
      return 0;
1334
0
    bio = BIO_new(o_context->dtls.meth);
1335
0
    if (!bio) {
1336
0
      SSL_free(o_context->dtls.ssl);
1337
0
      o_context->dtls.ssl = NULL;
1338
0
      return 0;
1339
0
    }
1340
0
    SSL_set_bio(o_context->dtls.ssl, bio, bio);
1341
0
    SSL_set_app_data(o_context->dtls.ssl, NULL);
1342
0
    SSL_set_options(o_context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
1343
0
    SSL_set_mtu(o_context->dtls.ssl, COAP_DEFAULT_MTU);
1344
0
  }
1345
0
  if (setup_data->ec_jpake) {
1346
0
    coap_log_warn("OpenSSL has no EC-JPAKE support\n");
1347
0
  }
1348
0
  if (setup_data->use_cid) {
1349
0
    coap_log_warn("OpenSSL has no Connection-ID support\n");
1350
0
  }
1351
0
  o_context->psk_pki_enabled |= IS_PSK;
1352
0
  return 1;
1353
0
}
1354
#endif /* COAP_CLIENT_SUPPORT */
1355
1356
static int
1357
map_key_type(int asn1_private_key_type
1358
0
            ) {
1359
0
  switch (asn1_private_key_type) {
1360
0
  case COAP_ASN1_PKEY_NONE:
1361
0
    return EVP_PKEY_NONE;
1362
0
  case COAP_ASN1_PKEY_RSA:
1363
0
    return EVP_PKEY_RSA;
1364
0
  case COAP_ASN1_PKEY_RSA2:
1365
0
    return EVP_PKEY_RSA2;
1366
0
  case COAP_ASN1_PKEY_DSA:
1367
0
    return EVP_PKEY_DSA;
1368
0
  case COAP_ASN1_PKEY_DSA1:
1369
0
    return EVP_PKEY_DSA1;
1370
0
  case COAP_ASN1_PKEY_DSA2:
1371
0
    return EVP_PKEY_DSA2;
1372
0
  case COAP_ASN1_PKEY_DSA3:
1373
0
    return EVP_PKEY_DSA3;
1374
0
  case COAP_ASN1_PKEY_DSA4:
1375
0
    return EVP_PKEY_DSA4;
1376
0
  case COAP_ASN1_PKEY_DH:
1377
0
    return EVP_PKEY_DH;
1378
0
  case COAP_ASN1_PKEY_DHX:
1379
0
    return EVP_PKEY_DHX;
1380
0
  case COAP_ASN1_PKEY_EC:
1381
0
    return EVP_PKEY_EC;
1382
0
  case COAP_ASN1_PKEY_HMAC:
1383
0
    return EVP_PKEY_HMAC;
1384
0
  case COAP_ASN1_PKEY_CMAC:
1385
0
    return EVP_PKEY_CMAC;
1386
0
  case COAP_ASN1_PKEY_TLS1_PRF:
1387
0
    return EVP_PKEY_TLS1_PRF;
1388
0
  case COAP_ASN1_PKEY_HKDF:
1389
0
    return EVP_PKEY_HKDF;
1390
0
  default:
1391
0
    coap_log_warn("*** setup_pki: DTLS: Unknown Private Key type %d for ASN1\n",
1392
0
                  asn1_private_key_type);
1393
0
    break;
1394
0
  }
1395
0
  return 0;
1396
0
}
1397
#if !COAP_DISABLE_TCP
1398
static uint8_t coap_alpn[] = { 4, 'c', 'o', 'a', 'p' };
1399
1400
#if COAP_SERVER_SUPPORT
1401
static int
1402
server_alpn_callback(SSL *ssl COAP_UNUSED,
1403
                     const unsigned char **out,
1404
                     unsigned char *outlen,
1405
                     const unsigned char *in,
1406
                     unsigned int inlen,
1407
                     void *arg COAP_UNUSED
1408
0
                    ) {
1409
0
  unsigned char *tout = NULL;
1410
0
  int ret;
1411
0
  if (inlen == 0)
1412
0
    return SSL_TLSEXT_ERR_NOACK;
1413
0
  ret = SSL_select_next_proto(&tout,
1414
0
                              outlen,
1415
0
                              coap_alpn,
1416
0
                              sizeof(coap_alpn),
1417
0
                              in,
1418
0
                              inlen);
1419
0
  *out = tout;
1420
0
  return (ret != OPENSSL_NPN_NEGOTIATED) ? SSL_TLSEXT_ERR_NOACK : SSL_TLSEXT_ERR_OK;
1421
0
}
1422
#endif /* COAP_SERVER_SUPPORT */
1423
#endif /* !COAP_DISABLE_TCP */
1424
1425
static void
1426
0
add_ca_to_cert_store(X509_STORE *st, X509 *x509) {
1427
0
  long e;
1428
1429
  /* Flush out existing errors */
1430
0
  while (ERR_get_error() != 0) {
1431
0
  }
1432
1433
0
  if (!X509_STORE_add_cert(st, x509)) {
1434
0
    while ((e = ERR_get_error()) != 0) {
1435
0
      int r = ERR_GET_REASON(e);
1436
0
      if (r != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
1437
        /* Not already added */
1438
0
        coap_log_warn("***setup_pki: (D)TLS: %s%s\n",
1439
0
                      ERR_reason_error_string(e),
1440
0
                      ssl_function_definition(e));
1441
0
      }
1442
0
    }
1443
0
  }
1444
0
}
1445
1446
#if OPENSSL_VERSION_NUMBER < 0x40000000L
1447
static X509 *
1448
0
missing_ENGINE_load_cert(ENGINE *engine, const char *cert_id) {
1449
0
  struct {
1450
0
    const char *cert_id;
1451
0
    X509 *cert;
1452
0
  } params;
1453
1454
0
  params.cert_id = cert_id;
1455
0
  params.cert = NULL;
1456
1457
  /* There is no ENGINE_load_cert() */
1458
0
  if (!ENGINE_ctrl_cmd(engine, "LOAD_CERT_CTRL", 0, &params, NULL, 1)) {
1459
0
    params.cert = NULL;
1460
0
  }
1461
0
  return params.cert;
1462
0
}
1463
1464
static int
1465
0
check_pkcs11_engine(void) {
1466
0
  static int already_tried = 0;
1467
1468
0
  if (already_tried)
1469
0
    return 0;
1470
1471
0
  if (!pkcs11_engine) {
1472
0
    pkcs11_engine = ENGINE_by_id(COAP_OPENSSL_PKCS11_ENGINE_ID);
1473
0
    if (!pkcs11_engine) {
1474
0
      coap_log_err("*** setup_pki: (D)TLS: No PKCS11 support - need OpenSSL %s engine\n",
1475
0
                   COAP_OPENSSL_PKCS11_ENGINE_ID);
1476
0
      already_tried = 1;
1477
0
      return 0;
1478
0
    }
1479
0
    if (!ENGINE_init(pkcs11_engine)) {
1480
      /* the engine couldn't initialise, release 'pkcs11_engine' */
1481
0
      ENGINE_free(pkcs11_engine);
1482
0
      pkcs11_engine = NULL;
1483
0
      coap_log_err("*** setup_pki: (D)TLS: PKCS11 engine initialize failed\n");
1484
0
      already_tried = 1;
1485
0
      return 0;
1486
0
    }
1487
    /*
1488
     * ENGINE_init() returned a functional reference, so free the structural
1489
     * reference from ENGINE_by_id().
1490
     */
1491
0
    ENGINE_free(pkcs11_engine);
1492
0
  }
1493
0
  return 1;
1494
0
}
1495
#endif /* OPENSSL_VERSION_NUMBER < 0x40000000L */
1496
1497
#if OPENSSL_VERSION_NUMBER < 0x10101000L && COAP_SERVER_SUPPORT
1498
1499
static int
1500
install_engine_public_cert_ctx(ENGINE *engine, SSL_CTX *ctx,
1501
                               const char *public_cert) {
1502
  X509 *x509;
1503
1504
  x509 = missing_ENGINE_load_cert(engine, public_cert);
1505
  if (!x509) {
1506
    coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1507
                  "%s Certificate\n",
1508
                  public_cert,
1509
                  "Server");
1510
    return 0;
1511
  }
1512
  if (!SSL_CTX_use_certificate(ctx, x509)) {
1513
    coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1514
                  "%s Certificate\n",
1515
                  public_cert,
1516
                  "Server");
1517
    X509_free(x509);
1518
    return 0;
1519
  }
1520
  X509_free(x509);
1521
  return 1;
1522
}
1523
1524
static int
1525
install_engine_private_key_ctx(ENGINE *engine, SSL_CTX *ctx,
1526
                               const char *private_key) {
1527
  EVP_PKEY *pkey = ENGINE_load_private_key(engine,
1528
                                           private_key,
1529
                                           NULL, NULL);
1530
1531
  if (!pkey) {
1532
    coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1533
                  "%s Private Key\n",
1534
                  private_key,
1535
                  "Server");
1536
    return 0;
1537
  }
1538
  if (!SSL_CTX_use_PrivateKey(ctx, pkey)) {
1539
    coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1540
                  "%s Private Key\n",
1541
                  private_key,
1542
                  "Server");
1543
    EVP_PKEY_free(pkey);
1544
    return 0;
1545
  }
1546
  EVP_PKEY_free(pkey);
1547
  return 1;
1548
}
1549
1550
static int
1551
install_engine_ca_ctx(ENGINE *engine, SSL_CTX *ctx, const char *ca) {
1552
  X509 *x509;
1553
  X509_STORE *st;
1554
1555
  x509 = missing_ENGINE_load_cert(engine,
1556
                                  ca);
1557
  if (!x509) {
1558
    coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1559
                  "%s CA Certificate\n",
1560
                  ca,
1561
                  "Server");
1562
    return 0;
1563
  }
1564
  if (!SSL_CTX_add_client_CA(ctx, x509)) {
1565
    coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1566
                  "%s CA Certificate\n",
1567
                  ca,
1568
                  "Server");
1569
    X509_free(x509);
1570
    return 0;
1571
  }
1572
  st = SSL_CTX_get_cert_store(ctx);
1573
  add_ca_to_cert_store(st, x509);
1574
  X509_free(x509);
1575
  return 1;
1576
}
1577
1578
static int
1579
load_in_cas_ctx(SSL_CTX *ctx,
1580
                const char *ca_file) {
1581
  STACK_OF(X509_NAME) *cert_names;
1582
  X509_STORE *st;
1583
  BIO *in;
1584
  X509 *x = NULL;
1585
  char *rw_var = NULL;
1586
  cert_names = SSL_load_client_CA_file(ca_file);
1587
  if (cert_names != NULL)
1588
    SSL_CTX_set_client_CA_list(ctx, cert_names);
1589
  else {
1590
    coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1591
                  "client CA File\n",
1592
                  ca_file);
1593
    return 0;
1594
  }
1595
1596
  /* Add CA to the trusted root CA store */
1597
  st = SSL_CTX_get_cert_store(ctx);
1598
  in = BIO_new(BIO_s_file());
1599
  if (!in)
1600
    return 0;
1601
  /* Need to do this to not get a compiler warning about const parameters */
1602
  memcpy(&rw_var, &ca_file, sizeof(rw_var));
1603
  if (!BIO_read_filename(in, rw_var)) {
1604
    BIO_free(in);
1605
    return 0;
1606
  }
1607
1608
  for (;;) {
1609
    if ((x = PEM_read_bio_X509(in, NULL, NULL, NULL)) == NULL)
1610
      break;
1611
    add_ca_to_cert_store(st, x);
1612
    X509_free(x);
1613
  }
1614
  BIO_free(in);
1615
  return 1;
1616
}
1617
1618
static int
1619
setup_pki_server(SSL_CTX *ctx,
1620
                 const coap_dtls_pki_t *setup_data) {
1621
  coap_dtls_key_t key;
1622
1623
  /* Map over to the new define format to save code duplication */
1624
  coap_dtls_map_key_type_to_define(setup_data, &key);
1625
1626
  assert(key.key_type == COAP_PKI_KEY_DEFINE);
1627
1628
  /*
1629
   * Configure the Private Key
1630
   */
1631
  if (key.key.define.private_key.u_byte &&
1632
      key.key.define.private_key.u_byte[0]) {
1633
    switch (key.key.define.private_key_def) {
1634
    case COAP_PKI_KEY_DEF_PEM: /* define private key */
1635
      if (!(SSL_CTX_use_PrivateKey_file(ctx,
1636
                                        key.key.define.private_key.s_byte,
1637
                                        SSL_FILETYPE_PEM))) {
1638
        return coap_dtls_define_issue(COAP_DEFINE_KEY_PRIVATE,
1639
                                      COAP_DEFINE_FAIL_BAD,
1640
                                      &key, COAP_DTLS_ROLE_SERVER, 0);
1641
      }
1642
      break;
1643
    case COAP_PKI_KEY_DEF_PEM_BUF: /* define private key */
1644
      if (key.key.define.private_key_len) {
1645
        BIO *bp = BIO_new_mem_buf(key.key.define.private_key.u_byte,
1646
                                  (int)key.key.define.private_key_len);
1647
        EVP_PKEY *pkey = bp ? PEM_read_bio_PrivateKey(bp, NULL, 0, NULL) : NULL;
1648
1649
        if (!pkey || !SSL_CTX_use_PrivateKey(ctx, pkey)) {
1650
          if (bp)
1651
            BIO_free(bp);
1652
          if (pkey)
1653
            EVP_PKEY_free(pkey);
1654
          return coap_dtls_define_issue(COAP_DEFINE_KEY_PRIVATE,
1655
                                        COAP_DEFINE_FAIL_BAD,
1656
                                        &key, COAP_DTLS_ROLE_SERVER, 0);
1657
        }
1658
        if (bp)
1659
          BIO_free(bp);
1660
        if (pkey)
1661
          EVP_PKEY_free(pkey);
1662
      } else {
1663
        return coap_dtls_define_issue(COAP_DEFINE_KEY_PRIVATE,
1664
                                      COAP_DEFINE_FAIL_NONE,
1665
                                      &key, COAP_DTLS_ROLE_SERVER, 0);
1666
      }
1667
      break;
1668
    case COAP_PKI_KEY_DEF_RPK_BUF: /* define private key */
1669
      return coap_dtls_define_issue(COAP_DEFINE_KEY_PRIVATE,
1670
                                    COAP_DEFINE_FAIL_NOT_SUPPORTED,
1671
                                    &key, COAP_DTLS_ROLE_SERVER, 0);
1672
    case COAP_PKI_KEY_DEF_DER: /* define private key */
1673
      if (!(SSL_CTX_use_PrivateKey_file(ctx,
1674
                                        key.key.define.private_key.s_byte,
1675
                                        SSL_FILETYPE_ASN1))) {
1676
        return coap_dtls_define_issue(COAP_DEFINE_KEY_PRIVATE,
1677
                                      COAP_DEFINE_FAIL_BAD,
1678
                                      &key, COAP_DTLS_ROLE_SERVER, 0);
1679
      }
1680
      break;
1681
    case COAP_PKI_KEY_DEF_DER_BUF: /* define private key */
1682
      if (key.key.define.private_key_len == 0 ||
1683
          !(SSL_CTX_use_PrivateKey_ASN1(map_key_type(key.key.define.private_key_type),
1684
                                        ctx,
1685
                                        key.key.define.private_key.u_byte,
1686
                                        (long)key.key.define.private_key_len))) {
1687
        return coap_dtls_define_issue(COAP_DEFINE_KEY_PRIVATE,
1688
                                      COAP_DEFINE_FAIL_BAD,
1689
                                      &key, COAP_DTLS_ROLE_SERVER, 0);
1690
      }
1691
      break;
1692
    case COAP_PKI_KEY_DEF_PKCS11: /* define private key */
1693
      if (!check_pkcs11_engine()) {
1694
        return 0;
1695
      }
1696
      if (key.key.define.user_pin) {
1697
        /* If not set, pin-value may be held in pkcs11: URI */
1698
        if (ENGINE_ctrl_cmd_string(pkcs11_engine,
1699
                                   "PIN",
1700
                                   key.key.define.user_pin, 0) == 0) {
1701
          coap_log_warn("*** setup_pki: (D)TLS: PKCS11: %s: Unable to set pin\n",
1702
                        key.key.define.user_pin);
1703
          return 0;
1704
        }
1705
      }
1706
      if (!install_engine_private_key_ctx(pkcs11_engine, ctx,
1707
                                          key.key.define.private_key.s_byte)) {
1708
        return coap_dtls_define_issue(COAP_DEFINE_KEY_PRIVATE,
1709
                                      COAP_DEFINE_FAIL_BAD,
1710
                                      &key, COAP_DTLS_ROLE_SERVER, 0);
1711
      }
1712
      break;
1713
    case COAP_PKI_KEY_DEF_ENGINE: /* define private key */
1714
      if (!defined_engine ||
1715
          !install_engine_private_key_ctx(defined_engine, ctx,
1716
                                          key.key.define.private_key.s_byte)) {
1717
        return coap_dtls_define_issue(COAP_DEFINE_KEY_PRIVATE,
1718
                                      COAP_DEFINE_FAIL_BAD,
1719
                                      &key, COAP_DTLS_ROLE_SERVER, 0);
1720
      }
1721
      break;
1722
    case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define private key */
1723
    default:
1724
      return coap_dtls_define_issue(COAP_DEFINE_KEY_PRIVATE,
1725
                                    COAP_DEFINE_FAIL_NOT_SUPPORTED,
1726
                                    &key, COAP_DTLS_ROLE_SERVER, 0);
1727
    }
1728
  } else if (key.key.define.public_cert.u_byte && key.key.define.public_cert.u_byte[0]) {
1729
    return coap_dtls_define_issue(COAP_DEFINE_KEY_PRIVATE,
1730
                                  COAP_DEFINE_FAIL_NONE,
1731
                                  &key, COAP_DTLS_ROLE_SERVER, 0);
1732
  }
1733
1734
  /*
1735
   * Configure the Public Certificate / Key
1736
   * OpenSSL < 1.1.1 and Server
1737
   */
1738
  if (key.key.define.public_cert.u_byte &&
1739
      key.key.define.public_cert.u_byte[0]) {
1740
    switch (key.key.define.public_cert_def) {
1741
    case COAP_PKI_KEY_DEF_PEM: /* define public cert */
1742
      if (key.key.define.ca.u_byte &&
1743
          key.key.define.ca.u_byte[0]) {
1744
        if (!(SSL_CTX_use_certificate_file(ctx,
1745
                                           key.key.define.public_cert.s_byte,
1746
                                           SSL_FILETYPE_PEM))) {
1747
          return coap_dtls_define_issue(COAP_DEFINE_KEY_PUBLIC,
1748
                                        COAP_DEFINE_FAIL_BAD,
1749
                                        &key, COAP_DTLS_ROLE_SERVER, 0);
1750
        }
1751
      } else {
1752
        if (!SSL_CTX_use_certificate_chain_file(ctx,
1753
                                                key.key.define.public_cert.s_byte)) {
1754
          return coap_dtls_define_issue(COAP_DEFINE_KEY_PUBLIC,
1755
                                        COAP_DEFINE_FAIL_BAD,
1756
                                        &key, COAP_DTLS_ROLE_SERVER, 0);
1757
        }
1758
      }
1759
      break;
1760
    case COAP_PKI_KEY_DEF_PEM_BUF: /* define public cert */
1761
      if (key.key.define.public_cert_len) {
1762
        BIO *bp = BIO_new_mem_buf(key.key.define.public_cert.u_byte,
1763
                                  (int)key.key.define.public_cert_len);
1764
        X509 *cert = bp ? PEM_read_bio_X509(bp, NULL, 0, NULL) : NULL;
1765
1766
        if (!cert || !SSL_CTX_use_certificate(ctx, cert)) {
1767
          if (bp)
1768
            BIO_free(bp);
1769
          if (cert)
1770
            X509_free(cert);
1771
          return coap_dtls_define_issue(COAP_DEFINE_KEY_PUBLIC,
1772
                                        COAP_DEFINE_FAIL_BAD,
1773
                                        &key, COAP_DTLS_ROLE_SERVER, 0);
1774
        }
1775
        if (bp)
1776
          BIO_free(bp);
1777
        if (cert)
1778
          X509_free(cert);
1779
      } else {
1780
        return coap_dtls_define_issue(COAP_DEFINE_KEY_PUBLIC,
1781
                                      COAP_DEFINE_FAIL_BAD,
1782
                                      &key, COAP_DTLS_ROLE_SERVER, 0);
1783
      }
1784
      break;
1785
    case COAP_PKI_KEY_DEF_RPK_BUF: /* define public cert */
1786
      return coap_dtls_define_issue(COAP_DEFINE_KEY_PUBLIC,
1787
                                    COAP_DEFINE_FAIL_NOT_SUPPORTED,
1788
                                    &key, COAP_DTLS_ROLE_SERVER, 0);
1789
    case COAP_PKI_KEY_DEF_DER: /* define public cert */
1790
      if (!(SSL_CTX_use_certificate_file(ctx,
1791
                                         key.key.define.public_cert.s_byte,
1792
                                         SSL_FILETYPE_ASN1))) {
1793
        return coap_dtls_define_issue(COAP_DEFINE_KEY_PUBLIC,
1794
                                      COAP_DEFINE_FAIL_BAD,
1795
                                      &key, COAP_DTLS_ROLE_SERVER, 0);
1796
      }
1797
      break;
1798
    case COAP_PKI_KEY_DEF_DER_BUF: /* define public cert */
1799
      if (key.key.define.public_cert_len == 0 ||
1800
          !(SSL_CTX_use_certificate_ASN1(ctx,
1801
                                         (int)key.key.define.public_cert_len,
1802
                                         key.key.define.public_cert.u_byte))) {
1803
        return coap_dtls_define_issue(COAP_DEFINE_KEY_PUBLIC,
1804
                                      COAP_DEFINE_FAIL_BAD,
1805
                                      &key, COAP_DTLS_ROLE_SERVER, 0);
1806
      }
1807
      break;
1808
    case COAP_PKI_KEY_DEF_PKCS11: /* define public cert */
1809
      if (!check_pkcs11_engine()) {
1810
        return 0;
1811
      }
1812
      if (!install_engine_public_cert_ctx(pkcs11_engine, ctx,
1813
                                          key.key.define.public_cert.s_byte)) {
1814
        return coap_dtls_define_issue(COAP_DEFINE_KEY_PUBLIC,
1815
                                      COAP_DEFINE_FAIL_BAD,
1816
                                      &key, COAP_DTLS_ROLE_SERVER, 0);
1817
      }
1818
      break;
1819
    case COAP_PKI_KEY_DEF_ENGINE: /* define public cert */
1820
      if (!defined_engine ||
1821
          !install_engine_public_cert_ctx(defined_engine, ctx,
1822
                                          key.key.define.public_cert.s_byte)) {
1823
        return coap_dtls_define_issue(COAP_DEFINE_KEY_PUBLIC,
1824
                                      COAP_DEFINE_FAIL_BAD,
1825
                                      &key, COAP_DTLS_ROLE_SERVER, 0);
1826
      }
1827
      break;
1828
    case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define public cert */
1829
    default:
1830
      return coap_dtls_define_issue(COAP_DEFINE_KEY_PUBLIC,
1831
                                    COAP_DEFINE_FAIL_NOT_SUPPORTED,
1832
                                    &key, COAP_DTLS_ROLE_SERVER, 0);
1833
    }
1834
  } else if (key.key.define.private_key.u_byte &&
1835
             key.key.define.private_key.u_byte[0]) {
1836
    return coap_dtls_define_issue(COAP_DEFINE_KEY_PUBLIC,
1837
                                  COAP_DEFINE_FAIL_NONE,
1838
                                  &key, COAP_DTLS_ROLE_SERVER, 0);
1839
  }
1840
1841
  /*
1842
   * Configure the CA
1843
   */
1844
  if (key.key.define.ca.u_byte &&
1845
      key.key.define.ca.u_byte[0]) {
1846
    switch (key.key.define.ca_def) {
1847
    case COAP_PKI_KEY_DEF_PEM:
1848
      if (!load_in_cas_ctx(ctx, key.key.define.ca.s_byte)) {
1849
        return coap_dtls_define_issue(COAP_DEFINE_KEY_CA,
1850
                                      COAP_DEFINE_FAIL_BAD,
1851
                                      &key, COAP_DTLS_ROLE_SERVER, 0);
1852
      }
1853
      break;
1854
    case COAP_PKI_KEY_DEF_PEM_BUF: /* define ca */
1855
      if (key.key.define.ca_len) {
1856
        BIO *bp = BIO_new_mem_buf(key.key.define.ca.s_byte,
1857
                                  (int)key.key.define.ca_len);
1858
        X509 *x;
1859
        X509_STORE *st = SSL_CTX_get_cert_store(ctx);
1860
1861
        if (bp) {
1862
          for (;;) {
1863
            if ((x = PEM_read_bio_X509(bp, NULL, NULL, NULL)) == NULL)
1864
              break;
1865
            add_ca_to_cert_store(st, x);
1866
            SSL_CTX_add_client_CA(ctx, x);
1867
            X509_free(x);
1868
          }
1869
          BIO_free(bp);
1870
        }
1871
      } else {
1872
        return coap_dtls_define_issue(COAP_DEFINE_KEY_CA,
1873
                                      COAP_DEFINE_FAIL_BAD,
1874
                                      &key, COAP_DTLS_ROLE_SERVER, 0);
1875
      }
1876
      break;
1877
    case COAP_PKI_KEY_DEF_RPK_BUF: /* define ca */
1878
      return coap_dtls_define_issue(COAP_DEFINE_KEY_CA,
1879
                                    COAP_DEFINE_FAIL_NOT_SUPPORTED,
1880
                                    &key, COAP_DTLS_ROLE_SERVER, 0);
1881
    case COAP_PKI_KEY_DEF_DER: /* define ca */
1882
      if (!(SSL_CTX_use_certificate_file(ctx,
1883
                                         key.key.define.ca.s_byte,
1884
                                         SSL_FILETYPE_ASN1))) {
1885
        return coap_dtls_define_issue(COAP_DEFINE_KEY_CA,
1886
                                      COAP_DEFINE_FAIL_BAD,
1887
                                      &key, COAP_DTLS_ROLE_SERVER, 0);
1888
      }
1889
      break;
1890
    case COAP_PKI_KEY_DEF_DER_BUF: /* define ca */
1891
      if (key.key.define.ca_len > 0) {
1892
        /* Need to use a temp variable as it gets incremented*/
1893
        const uint8_t *p = key.key.define.ca.u_byte;
1894
        X509 *x509 = d2i_X509(NULL, &p, (long)key.key.define.ca_len);
1895
        X509_STORE *st;
1896
1897
        if (!x509 || !SSL_CTX_add_client_CA(ctx, x509)) {
1898
          X509_free(x509);
1899
          return coap_dtls_define_issue(COAP_DEFINE_KEY_CA,
1900
                                        COAP_DEFINE_FAIL_BAD,
1901
                                        &key, COAP_DTLS_ROLE_SERVER, 0);
1902
        }
1903
1904
        /* Add CA to the trusted root CA store */
1905
        st = SSL_CTX_get_cert_store(ctx);
1906
        add_ca_to_cert_store(st, x509);
1907
        X509_free(x509);
1908
      }
1909
      break;
1910
    case COAP_PKI_KEY_DEF_PKCS11: /* define ca */
1911
      if (!check_pkcs11_engine()) {
1912
        return 0;
1913
      }
1914
      if (!install_engine_ca_ctx(pkcs11_engine, ctx,
1915
                                 key.key.define.ca.s_byte)) {
1916
        return coap_dtls_define_issue(COAP_DEFINE_KEY_CA,
1917
                                      COAP_DEFINE_FAIL_BAD,
1918
                                      &key, COAP_DTLS_ROLE_SERVER, 0);
1919
      }
1920
      break;
1921
    case COAP_PKI_KEY_DEF_ENGINE: /* define ca */
1922
      if (!defined_engine ||
1923
          !install_engine_ca_ctx(defined_engine, ctx,
1924
                                 key.key.define.ca.s_byte)) {
1925
        return coap_dtls_define_issue(COAP_DEFINE_KEY_CA,
1926
                                      COAP_DEFINE_FAIL_BAD,
1927
                                      &key, COAP_DTLS_ROLE_SERVER, 0);
1928
      }
1929
      break;
1930
    case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define ca */
1931
    default:
1932
      return coap_dtls_define_issue(COAP_DEFINE_KEY_CA,
1933
                                    COAP_DEFINE_FAIL_NOT_SUPPORTED,
1934
                                    &key, COAP_DTLS_ROLE_SERVER, 0);
1935
    }
1936
  }
1937
1938
  return 1;
1939
}
1940
#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L && COAP_SERVER_SUPPORT */
1941
1942
#if OPENSSL_VERSION_NUMBER >= 0x10101000L || COAP_CLIENT_SUPPORT
1943
1944
#if OPENSSL_VERSION_NUMBER < 0x40000000L
1945
static int
1946
install_engine_public_cert(ENGINE *engine, SSL *ssl, const char *public_cert,
1947
0
                           coap_dtls_role_t role) {
1948
0
  X509 *x509;
1949
1950
0
  x509 = missing_ENGINE_load_cert(engine, public_cert);
1951
0
  if (!x509) {
1952
0
    coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1953
0
                  "%s Certificate\n",
1954
0
                  public_cert,
1955
0
                  role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1956
0
    return 0;
1957
0
  }
1958
0
  if (!SSL_use_certificate(ssl, x509)) {
1959
0
    coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1960
0
                  "%s Certificate\n",
1961
0
                  public_cert,
1962
0
                  role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1963
0
    X509_free(x509);
1964
0
    return 0;
1965
0
  }
1966
0
  X509_free(x509);
1967
0
  return 1;
1968
0
}
1969
1970
static int
1971
install_engine_private_key(ENGINE *engine, SSL *ssl, const char *private_key,
1972
0
                           coap_dtls_role_t role) {
1973
0
  EVP_PKEY *pkey = ENGINE_load_private_key(engine,
1974
0
                                           private_key,
1975
0
                                           NULL, NULL);
1976
1977
0
  if (!pkey) {
1978
0
    coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1979
0
                  "%s Private Key\n",
1980
0
                  private_key,
1981
0
                  role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1982
0
    return 0;
1983
0
  }
1984
0
  if (!SSL_use_PrivateKey(ssl, pkey)) {
1985
0
    coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1986
0
                  "%s Private Key\n",
1987
0
                  private_key,
1988
0
                  role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1989
0
    EVP_PKEY_free(pkey);
1990
0
    return 0;
1991
0
  }
1992
0
  EVP_PKEY_free(pkey);
1993
0
  return 1;
1994
0
}
1995
1996
static int
1997
install_engine_ca(ENGINE *engine, SSL *ssl, const char *ca,
1998
0
                  coap_dtls_role_t role) {
1999
0
  X509 *x509;
2000
0
  SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
2001
0
  X509_STORE *st;
2002
2003
0
  if (!ctx) {
2004
0
    coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
2005
0
                  "%s CA Certificate (no ctx)\n",
2006
0
                  ca,
2007
0
                  role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
2008
0
    return 0;
2009
0
  }
2010
0
  x509 = missing_ENGINE_load_cert(engine,
2011
0
                                  ca);
2012
0
  if (!x509) {
2013
0
    coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
2014
0
                  "%s CA Certificate\n",
2015
0
                  ca,
2016
0
                  role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
2017
0
    return 0;
2018
0
  }
2019
0
  if (!SSL_add_client_CA(ssl, x509)) {
2020
0
    coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
2021
0
                  "%s CA Certificate\n",
2022
0
                  ca,
2023
0
                  role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
2024
0
    X509_free(x509);
2025
0
    return 0;
2026
0
  }
2027
0
  st = SSL_CTX_get_cert_store(ctx);
2028
0
  add_ca_to_cert_store(st, x509);
2029
0
  X509_free(x509);
2030
0
  return 1;
2031
0
}
2032
#endif /* OPENSSL_VERSION_NUMBER < 0x40000000L */
2033
2034
static int
2035
load_in_cas(SSL *ssl,
2036
0
            const char *ca_file, coap_dtls_role_t role) {
2037
0
  X509_STORE *st;
2038
0
  BIO *in;
2039
0
  X509 *x = NULL;
2040
0
  char *rw_var = NULL;
2041
0
  SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
2042
2043
0
  if (role == COAP_DTLS_ROLE_SERVER) {
2044
0
    STACK_OF(X509_NAME) *cert_names = SSL_load_client_CA_file(ca_file);
2045
2046
0
    if (cert_names != NULL)
2047
0
      SSL_set_client_CA_list(ssl, cert_names);
2048
0
    else {
2049
0
      return 0;
2050
0
    }
2051
0
  }
2052
2053
0
  if (!ctx)
2054
0
    return 0;
2055
2056
  /* Add CA to the trusted root CA store */
2057
0
  in = BIO_new(BIO_s_file());
2058
0
  if (!in)
2059
0
    return 0;
2060
  /* Need to do this to not get a compiler warning about const parameters */
2061
0
  memcpy(&rw_var, &ca_file, sizeof(rw_var));
2062
0
  if (!BIO_read_filename(in, rw_var)) {
2063
0
    BIO_free(in);
2064
0
    return 0;
2065
0
  }
2066
0
  st = SSL_CTX_get_cert_store(ctx);
2067
0
  for (;;) {
2068
0
    if ((x = PEM_read_bio_X509(in, NULL, NULL, NULL)) == NULL)
2069
0
      break;
2070
0
    add_ca_to_cert_store(st, x);
2071
0
    X509_free(x);
2072
0
  }
2073
0
  BIO_free(in);
2074
0
  return 1;
2075
0
}
2076
2077
static int
2078
setup_pki_ssl(SSL *ssl,
2079
0
              coap_dtls_pki_t *setup_data, coap_dtls_role_t role) {
2080
0
  coap_dtls_key_t key;
2081
2082
  /* Map over to the new define format to save code duplication */
2083
0
  coap_dtls_map_key_type_to_define(setup_data, &key);
2084
2085
0
  assert(key.key_type == COAP_PKI_KEY_DEFINE);
2086
2087
  /*
2088
   * Configure the Private Key
2089
   */
2090
0
  if (key.key.define.private_key.u_byte &&
2091
0
      key.key.define.private_key.u_byte[0]) {
2092
0
    switch (key.key.define.private_key_def) {
2093
0
    case COAP_PKI_KEY_DEF_PEM: /* define private key */
2094
0
      if (!(SSL_use_PrivateKey_file(ssl,
2095
0
                                    key.key.define.private_key.s_byte,
2096
0
                                    SSL_FILETYPE_PEM))) {
2097
0
        goto fail_bad_private;
2098
0
      }
2099
0
      break;
2100
0
    case COAP_PKI_KEY_DEF_PEM_BUF: /* define private key */
2101
0
      if (key.key.define.private_key_len) {
2102
0
        BIO *bp = BIO_new_mem_buf(key.key.define.private_key.u_byte,
2103
0
                                  (int)key.key.define.private_key_len);
2104
0
        EVP_PKEY *pkey = bp ? PEM_read_bio_PrivateKey(bp, NULL, 0, NULL) : NULL;
2105
2106
0
        if (!pkey || !SSL_use_PrivateKey(ssl, pkey)) {
2107
0
          if (bp)
2108
0
            BIO_free(bp);
2109
0
          if (pkey)
2110
0
            EVP_PKEY_free(pkey);
2111
0
          goto fail_bad_private;
2112
0
        }
2113
0
        if (bp)
2114
0
          BIO_free(bp);
2115
0
        if (pkey)
2116
0
          EVP_PKEY_free(pkey);
2117
0
      } else {
2118
0
        goto fail_none_private;
2119
0
      }
2120
0
      break;
2121
0
    case COAP_PKI_KEY_DEF_RPK_BUF: /* define private key */
2122
0
      goto fail_ns_private;
2123
0
    case COAP_PKI_KEY_DEF_DER: /* define private key */
2124
0
      if (!(SSL_use_PrivateKey_file(ssl,
2125
0
                                    key.key.define.private_key.s_byte,
2126
0
                                    SSL_FILETYPE_ASN1))) {
2127
0
        goto fail_bad_private;
2128
0
      }
2129
0
      break;
2130
0
    case COAP_PKI_KEY_DEF_DER_BUF: /* define private key */
2131
0
      if (key.key.define.private_key_len == 0 ||
2132
0
          !(SSL_use_PrivateKey_ASN1(map_key_type(key.key.define.private_key_type),
2133
0
                                    ssl,
2134
0
                                    key.key.define.private_key.u_byte,
2135
0
                                    (long)key.key.define.private_key_len))) {
2136
0
        goto fail_bad_private;
2137
0
      }
2138
0
      break;
2139
0
    case COAP_PKI_KEY_DEF_PKCS11: /* define private key */
2140
0
#if OPENSSL_VERSION_NUMBER < 0x40000000L
2141
0
      if (!check_pkcs11_engine()) {
2142
0
        goto fail_bad_private;
2143
0
      }
2144
0
      if (key.key.define.user_pin) {
2145
        /* If not set, pin-value may be held in pkcs11: URI */
2146
0
        if (ENGINE_ctrl_cmd_string(pkcs11_engine,
2147
0
                                   "PIN",
2148
0
                                   key.key.define.user_pin, 0) == 0) {
2149
0
          coap_log_warn("*** setup_pki: (D)TLS: PKCS11: %s: Unable to set pin\n",
2150
0
                        key.key.define.user_pin);
2151
0
          goto fail_bad_private;
2152
0
        }
2153
0
      }
2154
0
      if (!install_engine_private_key(pkcs11_engine, ssl,
2155
0
                                      key.key.define.private_key.s_byte,
2156
0
                                      role)) {
2157
0
        goto fail_bad_private;
2158
0
      }
2159
#else /* OPENSSL_VERSION_NUMBER >= 0x40000000L */
2160
      goto fail_bad_private;
2161
#endif /* OPENSSL_VERSION_NUMBER >= 0x40000000L */
2162
0
      break;
2163
0
    case COAP_PKI_KEY_DEF_ENGINE: /* define private key */
2164
0
#if OPENSSL_VERSION_NUMBER < 0x40000000L
2165
0
      if (!defined_engine ||
2166
0
          !install_engine_private_key(defined_engine, ssl,
2167
0
                                      key.key.define.private_key.s_byte,
2168
0
                                      role)) {
2169
0
        goto fail_bad_private;
2170
0
      }
2171
0
      break;
2172
0
#endif /* OPENSSL_VERSION_NUMBER < 0x40000000L */
2173
0
    case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define private key */
2174
0
    default:
2175
0
      goto fail_ns_private;
2176
0
    }
2177
0
  } else if (role == COAP_DTLS_ROLE_SERVER ||
2178
0
             (key.key.define.public_cert.u_byte &&
2179
0
              key.key.define.public_cert.u_byte[0])) {
2180
0
    goto fail_none_private;
2181
0
  }
2182
2183
  /*
2184
   * Configure the Public Certificate / Key
2185
   */
2186
0
  if (key.key.define.public_cert.u_byte &&
2187
0
      key.key.define.public_cert.u_byte[0]) {
2188
0
    switch (key.key.define.public_cert_def) {
2189
0
    case COAP_PKI_KEY_DEF_PEM: /* define public cert */
2190
0
      if (key.key.define.ca.u_byte &&
2191
0
          key.key.define.ca.u_byte[0]) {
2192
        /* If CA is separately defined */
2193
0
        if (!(SSL_use_certificate_file(ssl,
2194
0
                                       key.key.define.public_cert.s_byte,
2195
0
                                       SSL_FILETYPE_PEM))) {
2196
0
          goto fail_bad_public;
2197
0
        }
2198
0
      } else {
2199
0
        if (!SSL_use_certificate_chain_file(ssl,
2200
0
                                            key.key.define.public_cert.s_byte)) {
2201
0
          goto fail_bad_public;
2202
0
        }
2203
0
      }
2204
0
      break;
2205
0
    case COAP_PKI_KEY_DEF_PEM_BUF: /* define public cert */
2206
0
      if (key.key.define.public_cert_len) {
2207
0
        BIO *bp = BIO_new_mem_buf(key.key.define.public_cert.s_byte,
2208
0
                                  (int)key.key.define.public_cert_len);
2209
0
        X509 *cert = bp ? PEM_read_bio_X509(bp, NULL, 0, NULL) : NULL;
2210
2211
0
        if (!cert || !SSL_use_certificate(ssl, cert)) {
2212
0
          if (bp)
2213
0
            BIO_free(bp);
2214
0
          if (cert)
2215
0
            X509_free(cert);
2216
0
          goto fail_bad_public;
2217
0
        }
2218
0
        if (bp)
2219
0
          BIO_free(bp);
2220
0
        if (cert)
2221
0
          X509_free(cert);
2222
0
      } else {
2223
0
        goto fail_bad_public;
2224
0
      }
2225
0
      break;
2226
0
    case COAP_PKI_KEY_DEF_RPK_BUF: /* define public cert */
2227
0
      goto fail_ns_public;
2228
0
    case COAP_PKI_KEY_DEF_DER: /* define public cert */
2229
0
      if (!(SSL_use_certificate_file(ssl,
2230
0
                                     key.key.define.public_cert.s_byte,
2231
0
                                     SSL_FILETYPE_ASN1))) {
2232
0
        goto fail_bad_public;
2233
0
      }
2234
0
      break;
2235
0
    case COAP_PKI_KEY_DEF_DER_BUF: /* define public cert */
2236
0
      if (key.key.define.public_cert_len == 0 ||
2237
0
          !(SSL_use_certificate_ASN1(ssl,
2238
0
                                     key.key.define.public_cert.u_byte,
2239
0
                                     (int)key.key.define.public_cert_len))) {
2240
0
        goto fail_bad_public;
2241
0
      }
2242
0
      break;
2243
0
    case COAP_PKI_KEY_DEF_PKCS11: /* define public cert */
2244
0
#if OPENSSL_VERSION_NUMBER < 0x40000000L
2245
0
      if (!check_pkcs11_engine()) {
2246
0
        goto fail_bad_public;
2247
0
      }
2248
0
      if (!install_engine_public_cert(pkcs11_engine, ssl,
2249
0
                                      key.key.define.public_cert.s_byte,
2250
0
                                      role)) {
2251
0
        goto fail_bad_public;
2252
0
      }
2253
#else /* OPENSSL_VERSION_NUMBER >= 0x40000000L */
2254
      goto fail_bad_public;
2255
#endif /* OPENSSL_VERSION_NUMBER >= 0x40000000L */
2256
0
      break;
2257
0
    case COAP_PKI_KEY_DEF_ENGINE: /* define public cert */
2258
0
#if OPENSSL_VERSION_NUMBER < 0x40000000L
2259
0
      if (!defined_engine ||
2260
0
          !install_engine_public_cert(defined_engine, ssl,
2261
0
                                      key.key.define.public_cert.s_byte,
2262
0
                                      role)) {
2263
0
        goto fail_bad_public;
2264
0
      }
2265
0
      break;
2266
0
#endif /* OPENSSL_VERSION_NUMBER < 0x40000000L */
2267
0
    case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define public cert */
2268
0
    default:
2269
0
      goto fail_ns_public;
2270
0
    }
2271
0
  } else if (role == COAP_DTLS_ROLE_SERVER ||
2272
0
             (key.key.define.private_key.u_byte &&
2273
0
              key.key.define.private_key.u_byte[0])) {
2274
2275
0
    return coap_dtls_define_issue(COAP_DEFINE_KEY_PUBLIC,
2276
0
                                  COAP_DEFINE_FAIL_NONE,
2277
0
                                  &key, role, 0);
2278
0
  }
2279
2280
  /*
2281
   * Configure the CA
2282
   */
2283
0
  if (key.key.define.ca.u_byte &&
2284
0
      key.key.define.ca.u_byte[0]) {
2285
0
    switch (key.key.define.ca_def) {
2286
0
    case COAP_PKI_KEY_DEF_PEM:
2287
0
      if (!load_in_cas(ssl, key.key.define.ca.s_byte, role)) {
2288
0
        goto fail_bad_ca;
2289
0
      }
2290
0
      break;
2291
0
    case COAP_PKI_KEY_DEF_PEM_BUF: /* define ca */
2292
0
      if (key.key.define.ca_len) {
2293
0
        BIO *bp = BIO_new_mem_buf(key.key.define.ca.u_byte,
2294
0
                                  (int)key.key.define.ca_len);
2295
0
        SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
2296
0
        X509 *x;
2297
0
        X509_STORE *st = ctx? SSL_CTX_get_cert_store(ctx) : NULL;
2298
2299
0
        if (bp) {
2300
0
          for (;;) {
2301
0
            if ((x = PEM_read_bio_X509(bp, NULL, 0, NULL)) == NULL)
2302
0
              break;
2303
0
            if (st)
2304
0
              add_ca_to_cert_store(st, x);
2305
0
            SSL_add_client_CA(ssl, x);
2306
0
            X509_free(x);
2307
0
          }
2308
0
          BIO_free(bp);
2309
0
        }
2310
0
      } else {
2311
0
        goto fail_bad_ca;
2312
0
      }
2313
0
      break;
2314
0
    case COAP_PKI_KEY_DEF_RPK_BUF: /* define ca */
2315
0
      goto fail_ns_ca;
2316
0
    case COAP_PKI_KEY_DEF_DER: /* define ca */
2317
0
      if (!(SSL_use_certificate_file(ssl,
2318
0
                                     key.key.define.ca.s_byte,
2319
0
                                     SSL_FILETYPE_ASN1))) {
2320
0
        goto fail_bad_ca;
2321
0
      }
2322
0
      break;
2323
0
    case COAP_PKI_KEY_DEF_DER_BUF: /* define ca */
2324
0
      if (key.key.define.ca_len > 0) {
2325
        /* Need to use a temp variable as it gets incremented*/
2326
0
        const uint8_t *p = key.key.define.ca.u_byte;
2327
0
        X509 *x509 = d2i_X509(NULL, &p, (long)key.key.define.ca_len);
2328
0
        X509_STORE *st;
2329
0
        SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
2330
2331
0
        if (role == COAP_DTLS_ROLE_SERVER) {
2332
0
          if (!x509 || !SSL_add_client_CA(ssl, x509)) {
2333
0
            X509_free(x509);
2334
0
            goto fail_bad_ca;
2335
0
          }
2336
0
        }
2337
2338
        /* Add CA to the trusted root CA store */
2339
0
        st = ctx ? SSL_CTX_get_cert_store(ctx) : NULL;
2340
0
        if (st)
2341
0
          add_ca_to_cert_store(st, x509);
2342
0
        X509_free(x509);
2343
0
      }
2344
0
      break;
2345
0
    case COAP_PKI_KEY_DEF_PKCS11: /* define ca */
2346
0
#if OPENSSL_VERSION_NUMBER < 0x40000000L
2347
0
      if (!check_pkcs11_engine()) {
2348
0
        goto fail_bad_ca;
2349
0
      }
2350
0
      if (!install_engine_ca(pkcs11_engine, ssl,
2351
0
                             key.key.define.ca.s_byte,
2352
0
                             role)) {
2353
0
        goto fail_bad_ca;
2354
0
      }
2355
#else /* OPENSSL_VERSION_NUMBER >= 0x40000000L */
2356
      goto fail_bad_ca;
2357
#endif /* OPENSSL_VERSION_NUMBER >= 0x40000000L */
2358
0
      break;
2359
0
    case COAP_PKI_KEY_DEF_ENGINE: /* define ca */
2360
0
#if OPENSSL_VERSION_NUMBER < 0x40000000L
2361
0
      if (!defined_engine ||
2362
0
          !install_engine_ca(defined_engine, ssl,
2363
0
                             key.key.define.ca.s_byte,
2364
0
                             role)) {
2365
0
        goto fail_bad_ca;
2366
0
      }
2367
0
      break;
2368
0
#endif /* OPENSSL_VERSION_NUMBER < 0x40000000L */
2369
0
    case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define ca */
2370
0
    default:
2371
0
      goto fail_ns_ca;
2372
0
    }
2373
0
  }
2374
2375
0
  return 1;
2376
2377
0
fail_bad_private:
2378
0
  return coap_dtls_define_issue(COAP_DEFINE_KEY_PRIVATE,
2379
0
                                COAP_DEFINE_FAIL_BAD,
2380
0
                                &key, role, 0);
2381
0
fail_ns_private:
2382
0
  return coap_dtls_define_issue(COAP_DEFINE_KEY_PRIVATE,
2383
0
                                COAP_DEFINE_FAIL_NOT_SUPPORTED,
2384
0
                                &key, role, 0);
2385
0
fail_none_private:
2386
0
  return coap_dtls_define_issue(COAP_DEFINE_KEY_PRIVATE,
2387
0
                                COAP_DEFINE_FAIL_NONE,
2388
0
                                &key, role, 0);
2389
0
fail_bad_public:
2390
0
  return coap_dtls_define_issue(COAP_DEFINE_KEY_PUBLIC,
2391
0
                                COAP_DEFINE_FAIL_BAD,
2392
0
                                &key, role, 0);
2393
0
fail_ns_public:
2394
0
  return coap_dtls_define_issue(COAP_DEFINE_KEY_PUBLIC,
2395
0
                                COAP_DEFINE_FAIL_NOT_SUPPORTED,
2396
0
                                &key, role, 0);
2397
0
fail_bad_ca:
2398
0
  return coap_dtls_define_issue(COAP_DEFINE_KEY_CA,
2399
0
                                COAP_DEFINE_FAIL_BAD,
2400
0
                                &key, role, 0);
2401
0
fail_ns_ca:
2402
0
  return coap_dtls_define_issue(COAP_DEFINE_KEY_CA,
2403
0
                                COAP_DEFINE_FAIL_NOT_SUPPORTED,
2404
0
                                &key, role, 0);
2405
2406
0
}
2407
#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L || COAP_CLIENT_SUPPORT */
2408
2409
static char *
2410
0
get_san_or_cn_from_cert(coap_session_t *session, X509 *x509, const char *sni_match) {
2411
0
  if (x509) {
2412
0
    char *cn;
2413
0
    int n;
2414
0
    STACK_OF(GENERAL_NAME) *san_list;
2415
0
    char buffer[256];
2416
2417
0
    (void)session;
2418
0
    san_list = X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL);
2419
0
    if (san_list) {
2420
0
      int san_count = sk_GENERAL_NAME_num(san_list);
2421
2422
0
      for (n = 0; n < san_count; n++) {
2423
0
        const GENERAL_NAME *name = sk_GENERAL_NAME_value(san_list, n);
2424
2425
0
        if (name && name->type == GEN_DNS) {
2426
0
          const char *dns_name = (const char *)ASN1_STRING_get0_data(name->d.dNSName);
2427
2428
          /* Make sure that there is not an embedded NUL in the dns_name */
2429
0
          if (ASN1_STRING_length(name->d.dNSName) != (int)strlen(dns_name))
2430
0
            continue;
2431
0
          if (sni_match) {
2432
0
            if (strcmp(dns_name, sni_match)) {
2433
0
              continue;
2434
0
            }
2435
0
          }
2436
0
          cn = OPENSSL_strdup(dns_name);
2437
0
          sk_GENERAL_NAME_pop_free(san_list, GENERAL_NAME_free);
2438
0
          return cn;
2439
0
        }
2440
0
      }
2441
0
      sk_GENERAL_NAME_pop_free(san_list, GENERAL_NAME_free);
2442
0
    }
2443
    /* Otherwise look for the CN= field */
2444
0
    X509_NAME_oneline(X509_get_subject_name(x509), buffer, sizeof(buffer));
2445
2446
    /* Need to emulate strcasestr() here.  Looking for CN= */
2447
0
    n = (int)strlen(buffer) - 3;
2448
0
    cn = buffer;
2449
0
    while (n > 0) {
2450
0
      if (((cn[0] == 'C') || (cn[0] == 'c')) &&
2451
0
          ((cn[1] == 'N') || (cn[1] == 'n')) &&
2452
0
          (cn[2] == '=')) {
2453
0
        cn += 3;
2454
0
        break;
2455
0
      }
2456
0
      cn++;
2457
0
      n--;
2458
0
    }
2459
0
    if (n > 0) {
2460
0
      char *ecn = strchr(cn, '/');
2461
0
      if (ecn) {
2462
0
        cn[ecn-cn] = '\000';
2463
0
      }
2464
0
      if (sni_match) {
2465
0
        if (!coap_pki_name_match_sni(cn, strlen(cn), sni_match)) {
2466
0
          coap_log_debug("   %s: got CN '%s'\n",
2467
0
                         coap_session_str(session), cn);
2468
0
          goto no_match;
2469
0
        }
2470
0
      }
2471
0
      return OPENSSL_strdup(cn);
2472
0
    }
2473
0
no_match:
2474
0
    if (!sni_match) {
2475
0
      return NULL;
2476
0
    }
2477
0
    san_list = X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL);
2478
0
    if (san_list) {
2479
0
      int san_count = sk_GENERAL_NAME_num(san_list);
2480
2481
0
      for (n = 0; n < san_count; n++) {
2482
0
        const GENERAL_NAME *name = sk_GENERAL_NAME_value(san_list, n);
2483
2484
0
        if (name && name->type == GEN_DNS) {
2485
0
          const char *dns_name = (const char *)ASN1_STRING_get0_data(name->d.dNSName);
2486
2487
          /* Make sure that there is not an embedded NUL in the dns_name */
2488
0
          if (ASN1_STRING_length(name->d.dNSName) != (int)strlen(dns_name))
2489
0
            continue;
2490
0
          coap_log_debug("   %s: got DNS.%d '%s'\n",
2491
0
                         coap_session_str(session), n + 1, dns_name);
2492
0
        }
2493
0
      }
2494
0
      sk_GENERAL_NAME_pop_free(san_list, GENERAL_NAME_free);
2495
0
    }
2496
0
  }
2497
0
  return NULL;
2498
0
}
2499
2500
static int
2501
0
tls_verify_call_back(int preverify_ok, X509_STORE_CTX *ctx) {
2502
0
  int index = SSL_get_ex_data_X509_STORE_CTX_idx();
2503
0
  SSL *ssl = index >= 0 ? X509_STORE_CTX_get_ex_data(ctx, index) : NULL;
2504
0
  coap_session_t *session = ssl ? SSL_get_app_data(ssl) : NULL;
2505
0
  coap_openssl_context_t *context = (session && session->context) ?
2506
0
                                    ((coap_openssl_context_t *)session->context->dtls_context) : NULL;
2507
0
  coap_dtls_pki_t *setup_data = context ? &context->setup_data : NULL;
2508
0
  int depth = X509_STORE_CTX_get_error_depth(ctx);
2509
0
  int err = X509_STORE_CTX_get_error(ctx);
2510
0
  X509 *x509 = X509_STORE_CTX_get_current_cert(ctx);
2511
0
  char *cn = NULL;
2512
2513
0
  if (!setup_data || !x509) {
2514
0
    X509_STORE_CTX_set_error(ctx, X509_V_ERR_UNSPECIFIED);
2515
0
    return 0;
2516
0
  }
2517
0
  if (depth == 0 && session->type == COAP_SESSION_TYPE_CLIENT && setup_data->client_sni &&
2518
0
      !setup_data->allow_sni_cn_mismatch) {
2519
0
    cn = get_san_or_cn_from_cert(session, x509, setup_data->client_sni);
2520
0
    if (!cn) {
2521
0
      coap_log_info("   %s: SNI '%s' not returned in certificate\n",
2522
0
                    coap_session_str(session), setup_data->client_sni);
2523
0
      preverify_ok = 0;
2524
0
      X509_STORE_CTX_set_error(ctx, X509_V_ERR_SUBJECT_ISSUER_MISMATCH);
2525
0
      err = X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
2526
0
    }
2527
0
  }
2528
0
  if (!cn)
2529
0
    cn = get_san_or_cn_from_cert(session, x509, NULL);
2530
2531
0
  coap_dtls_log(COAP_LOG_DEBUG, "depth %d error %x preverify %d cert '%s'\n",
2532
0
                depth, err, preverify_ok, cn);
2533
2534
  /* Certificate - depth == 0 is the Client Cert */
2535
0
  if (setup_data->validate_cn_call_back) {
2536
0
    int length = i2d_X509(x509, NULL);
2537
0
    uint8_t *base_buf;
2538
0
    uint8_t *base_buf2 = base_buf = length > 0 ? OPENSSL_malloc(length) : NULL;
2539
0
    int ret;
2540
2541
0
    if (base_buf) {
2542
      /* base_buf2 gets moved to the end */
2543
0
      assert(i2d_X509(x509, &base_buf2) > 0);
2544
0
      (void)base_buf2;
2545
0
      coap_lock_callback_ret(ret,
2546
0
                             setup_data->validate_cn_call_back(cn, base_buf, length, session,
2547
0
                                                               depth, preverify_ok,
2548
0
                                                               setup_data->cn_call_back_arg));
2549
0
      if (!ret) {
2550
0
        if (depth == 0) {
2551
0
          X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
2552
0
        } else {
2553
0
          X509_STORE_CTX_set_error(ctx, X509_V_ERR_INVALID_CA);
2554
0
        }
2555
0
        preverify_ok = 0;
2556
0
      }
2557
0
      OPENSSL_free(base_buf);
2558
0
    } else {
2559
0
      X509_STORE_CTX_set_error(ctx, X509_V_ERR_UNSPECIFIED);
2560
0
      preverify_ok = 0;
2561
0
    }
2562
0
  }
2563
0
  if (!preverify_ok) {
2564
0
    switch (err) {
2565
0
    case X509_V_ERR_CERT_NOT_YET_VALID:
2566
0
    case X509_V_ERR_CERT_HAS_EXPIRED:
2567
0
      if (setup_data->allow_expired_certs)
2568
0
        preverify_ok = 1;
2569
0
      break;
2570
0
    case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
2571
0
      if (setup_data->allow_self_signed && !setup_data->check_common_ca)
2572
0
        preverify_ok = 1;
2573
0
      break;
2574
0
    case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: /* Set if the CA is not known */
2575
0
      if (!setup_data->verify_peer_cert)
2576
0
        preverify_ok = 1;
2577
0
      break;
2578
0
    case X509_V_ERR_UNABLE_TO_GET_CRL:
2579
0
      if (setup_data->allow_no_crl)
2580
0
        preverify_ok = 1;
2581
0
      break;
2582
0
    case X509_V_ERR_CRL_NOT_YET_VALID:
2583
0
    case X509_V_ERR_CRL_HAS_EXPIRED:
2584
0
      if (setup_data->allow_expired_crl)
2585
0
        preverify_ok = 1;
2586
0
      break;
2587
0
    case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
2588
0
    case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
2589
0
    case X509_V_ERR_AKID_SKID_MISMATCH:
2590
0
      if (!setup_data->verify_peer_cert)
2591
0
        preverify_ok = 1;
2592
0
      break;
2593
0
    case X509_V_ERR_SUBJECT_ISSUER_MISMATCH:
2594
0
      if (setup_data->allow_sni_cn_mismatch)
2595
0
        preverify_ok = 1;
2596
0
      break;
2597
0
    default:
2598
0
      break;
2599
0
    }
2600
0
    if (setup_data->cert_chain_validation &&
2601
0
        depth > (setup_data->cert_chain_verify_depth + 1)) {
2602
0
      preverify_ok = 0;
2603
0
      err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
2604
0
      X509_STORE_CTX_set_error(ctx, err);
2605
0
    }
2606
0
    if (!preverify_ok) {
2607
0
      if (err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) {
2608
0
        coap_log_warn("   %s: %s: '%s' depth=%d\n",
2609
0
                      coap_session_str(session),
2610
0
                      "Unknown CA", cn ? cn : "?", depth);
2611
0
      } else {
2612
0
        coap_log_warn("   %s: %s: '%s' depth=%d\n",
2613
0
                      coap_session_str(session),
2614
0
                      X509_verify_cert_error_string(err), cn ? cn : "?", depth);
2615
0
      }
2616
0
    } else {
2617
0
      coap_log_info("   %s: %s: overridden: '%s' depth=%d\n",
2618
0
                    coap_session_str(session),
2619
0
                    X509_verify_cert_error_string(err), cn ? cn : "?", depth);
2620
0
    }
2621
0
  }
2622
0
  OPENSSL_free(cn);
2623
0
  return preverify_ok;
2624
0
}
2625
2626
#if COAP_SERVER_SUPPORT
2627
#if OPENSSL_VERSION_NUMBER < 0x10101000L
2628
/* OpenSSL < 1.1.1 */
2629
/*
2630
 * During the SSL/TLS initial negotiations, tls_secret_call_back() is called so
2631
 * it is possible to determine whether this is a PKI or PSK incoming
2632
 * request and adjust the ciphers if necessary
2633
 *
2634
 * Set up by SSL_set_session_secret_cb() in tls_server_name_call_back()
2635
 */
2636
static int
2637
tls_secret_call_back(SSL *ssl,
2638
                     void *secret,
2639
                     int *secretlen,
2640
                     STACK_OF(SSL_CIPHER) *peer_ciphers,
2641
                     const SSL_CIPHER **cipher COAP_UNUSED,
2642
                     void *arg) {
2643
  int     ii;
2644
  int     psk_requested = 0;
2645
  coap_session_t *session;
2646
  coap_dtls_pki_t *setup_data = (coap_dtls_pki_t *)arg;
2647
2648
  session = (coap_session_t *)SSL_get_app_data(ssl);
2649
  assert(session != NULL);
2650
  assert(session->context != NULL);
2651
  if (session == NULL ||
2652
      session->context == NULL)
2653
    return 0;
2654
2655
  if ((session->psk_key) ||
2656
      (session->context->spsk_setup_data.psk_info.key.s &&
2657
       session->context->spsk_setup_data.psk_info.key.length)) {
2658
    /* Is PSK being requested - if so, we need to change algorithms */
2659
    for (ii = 0; ii < sk_SSL_CIPHER_num(peer_ciphers); ii++) {
2660
      const SSL_CIPHER *peer_cipher = sk_SSL_CIPHER_value(peer_ciphers, ii);
2661
2662
      coap_dtls_log(COAP_LOG_INFO, "Client cipher: %s\n",
2663
                    SSL_CIPHER_get_name(peer_cipher));
2664
      if (strstr(SSL_CIPHER_get_name(peer_cipher), "PSK")) {
2665
        psk_requested = 1;
2666
        break;
2667
      }
2668
    }
2669
  }
2670
  if (!psk_requested) {
2671
    coap_log_debug("   %s: Using PKI ciphers\n",
2672
                   coap_session_str(session));
2673
2674
    if (setup_data->verify_peer_cert) {
2675
      SSL_set_verify(ssl,
2676
                     SSL_VERIFY_PEER |
2677
                     SSL_VERIFY_CLIENT_ONCE |
2678
                     SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
2679
                     tls_verify_call_back);
2680
    } else {
2681
      SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_call_back);
2682
    }
2683
2684
    /* Check CA Chain */
2685
    if (setup_data->cert_chain_validation)
2686
      SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth + 2);
2687
2688
    /* Certificate Revocation */
2689
    if (setup_data->check_cert_revocation) {
2690
      X509_VERIFY_PARAM *param;
2691
2692
      param = X509_VERIFY_PARAM_new();
2693
      if (param) {
2694
        X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
2695
        SSL_set1_param(ssl, param);
2696
        X509_VERIFY_PARAM_free(param);
2697
      }
2698
    }
2699
    if (setup_data->additional_tls_setup_call_back) {
2700
      /* Additional application setup wanted */
2701
      if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
2702
        return 0;
2703
    }
2704
  } else {
2705
    if (session->psk_key) {
2706
      memcpy(secret, session->psk_key->s, session->psk_key->length);
2707
      *secretlen = session->psk_key->length;
2708
    } else if (session->context->spsk_setup_data.psk_info.key.s &&
2709
               session->context->spsk_setup_data.psk_info.key.length) {
2710
      memcpy(secret, session->context->spsk_setup_data.psk_info.key.s,
2711
             session->context->spsk_setup_data.psk_info.key.length);
2712
      *secretlen = session->context->spsk_setup_data.psk_info.key.length;
2713
    }
2714
    coap_log_debug("   %s: Setting PSK ciphers\n",
2715
                   coap_session_str(session));
2716
    /*
2717
     * Force a PSK algorithm to be used, so we do PSK
2718
     */
2719
    SSL_set_cipher_list(ssl, COAP_OPENSSL_PSK_CIPHERS);
2720
#ifdef COAP_OPENSSL_PSK_SECURITY_LEVEL
2721
    /*
2722
     * Set to 0 if, for example, PSK-AES128-CCM8 is to be supported (64 bits).
2723
     * Potentially opens up security vulnerabilities.
2724
     * Default value is 1.
2725
    */
2726
    SSL_set_security_level(ssl, COAP_OPENSSL_PSK_SECURITY_LEVEL);
2727
#endif /* COAP_OPENSSL_PSK_SECURITY_LEVEL */
2728
    SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
2729
  }
2730
  return 0;
2731
}
2732
2733
/* OpenSSL < 1.1.1 */
2734
/*
2735
 * During the SSL/TLS initial negotiations, tls_server_name_call_back() is
2736
 * called so it is possible to set up an extra callback to determine whether
2737
 * this is a PKI or PSK incoming request and adjust the ciphers if necessary
2738
 *
2739
 * Set up by SSL_CTX_set_tlsext_servername_callback() in
2740
 * coap_dtls_context_set_pki()
2741
 */
2742
static int
2743
tls_server_name_call_back(SSL *ssl,
2744
                          int *sd COAP_UNUSED,
2745
                          void *arg) {
2746
  coap_dtls_pki_t *setup_data = (coap_dtls_pki_t *)arg;
2747
2748
  if (!ssl) {
2749
    return SSL_TLSEXT_ERR_NOACK;
2750
  }
2751
2752
  if (setup_data->validate_sni_call_back) {
2753
    /* SNI checking requested */
2754
    coap_session_t *session = (coap_session_t *)SSL_get_app_data(ssl);
2755
    coap_openssl_context_t *context = (session && session->context) ?
2756
                                      ((coap_openssl_context_t *)session->context->dtls_context) : NULL;
2757
    const char *sni = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
2758
    size_t i;
2759
2760
    if (!context)
2761
      return SSL_TLSEXT_ERR_NOACK;
2762
2763
    if (!sni || !sni[0]) {
2764
      sni = "";
2765
    }
2766
    for (i = 0; i < context->sni_count; i++) {
2767
      if (!strcasecmp(sni, context->sni_entry_list[i].sni)) {
2768
        break;
2769
      }
2770
    }
2771
    if (i == context->sni_count) {
2772
      SSL_CTX *ctx;
2773
      coap_dtls_pki_t sni_setup_data;
2774
      coap_dtls_key_t *new_entry;
2775
2776
      coap_lock_callback_ret(new_entry,
2777
                             setup_data->validate_sni_call_back(sni,
2778
                                                                setup_data->sni_call_back_arg));
2779
      if (!new_entry) {
2780
        return SSL_TLSEXT_ERR_ALERT_FATAL;
2781
      }
2782
      /* Need to set up a new SSL_CTX to switch to */
2783
      if (session->proto == COAP_PROTO_DTLS) {
2784
        /* Set up DTLS context */
2785
        ctx = SSL_CTX_new(DTLS_method());
2786
        if (!ctx)
2787
          goto error;
2788
        SSL_CTX_set_min_proto_version(ctx, DTLS1_2_VERSION);
2789
        SSL_CTX_set_app_data(ctx, &context->dtls);
2790
        SSL_CTX_set_read_ahead(ctx, 1);
2791
        coap_set_user_prefs(ctx);
2792
        SSL_CTX_set_cookie_generate_cb(ctx, coap_dtls_generate_cookie);
2793
        SSL_CTX_set_cookie_verify_cb(ctx, coap_dtls_verify_cookie);
2794
        SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2795
        SSL_CTX_set_options(ctx, SSL_OP_NO_QUERY_MTU);
2796
      }
2797
#if !COAP_DISABLE_TCP
2798
      else {
2799
        /* Set up TLS context */
2800
        ctx = SSL_CTX_new(TLS_method());
2801
        if (!ctx)
2802
          goto error;
2803
        SSL_CTX_set_app_data(ctx, &context->tls);
2804
        SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2805
        coap_set_user_prefs(ctx);
2806
        SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2807
        SSL_CTX_set_alpn_select_cb(ctx, server_alpn_callback, NULL);
2808
      }
2809
#endif /* !COAP_DISABLE_TCP */
2810
      sni_setup_data = *setup_data;
2811
      sni_setup_data.pki_key = *new_entry;
2812
      setup_pki_server(ctx, &sni_setup_data);
2813
2814
      context->sni_entry_list = OPENSSL_realloc(context->sni_entry_list,
2815
                                                (context->sni_count+1)*sizeof(sni_entry));
2816
      context->sni_entry_list[context->sni_count].sni = OPENSSL_strdup(sni);
2817
      context->sni_entry_list[context->sni_count].ctx = ctx;
2818
      context->sni_count++;
2819
    }
2820
    SSL_set_SSL_CTX(ssl, context->sni_entry_list[i].ctx);
2821
    SSL_clear_options(ssl, 0xFFFFFFFFL);
2822
    SSL_set_options(ssl, SSL_CTX_get_options(context->sni_entry_list[i].ctx));
2823
  }
2824
2825
  /*
2826
   * Have to do extra call back next to get client algorithms
2827
   * SSL_get_client_ciphers() does not work this early on
2828
   */
2829
  SSL_set_session_secret_cb(ssl, tls_secret_call_back, arg);
2830
  return SSL_TLSEXT_ERR_OK;
2831
2832
error:
2833
  return SSL_TLSEXT_ERR_ALERT_WARNING;
2834
}
2835
2836
/* OpenSSL < 1.1.1 */
2837
/*
2838
 * During the SSL/TLS initial negotiations, psk_tls_server_name_call_back() is
2839
 * called to see if SNI is being used.
2840
 *
2841
 * Set up by SSL_CTX_set_tlsext_servername_callback()
2842
 * in coap_dtls_context_set_spsk()
2843
 */
2844
static int
2845
psk_tls_server_name_call_back(SSL *ssl,
2846
                              int *sd COAP_UNUSED,
2847
                              void *arg
2848
                             ) {
2849
  coap_dtls_spsk_t *setup_data = (coap_dtls_spsk_t *)arg;
2850
2851
  if (!ssl) {
2852
    return SSL_TLSEXT_ERR_NOACK;
2853
  }
2854
2855
  if (setup_data->validate_sni_call_back) {
2856
    /* SNI checking requested */
2857
    coap_session_t *c_session = (coap_session_t *)SSL_get_app_data(ssl);
2858
    coap_openssl_context_t *o_context = (c_session && c_session->context) ?
2859
                                        ((coap_openssl_context_t *)c_session->context->dtls_context) : NULL;
2860
    const char *sni = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
2861
    size_t i;
2862
    char lhint[COAP_DTLS_HINT_LENGTH];
2863
2864
    if (!o_context)
2865
      return SSL_TLSEXT_ERR_ALERT_FATAL;
2866
2867
    if (!sni || !sni[0]) {
2868
      sni = "";
2869
    }
2870
    for (i = 0; i < o_context->psk_sni_count; i++) {
2871
      if (!strcasecmp(sni, (char *)o_context->psk_sni_entry_list[i].sni)) {
2872
        break;
2873
      }
2874
    }
2875
    if (i == o_context->psk_sni_count) {
2876
      SSL_CTX *ctx;
2877
      const coap_dtls_spsk_info_t *new_entry;
2878
2879
      coap_lock_callback_ret(new_entry,
2880
                             setup_data->validate_sni_call_back(sni,
2881
                                                                c_session,
2882
                                                                setup_data->sni_call_back_arg));
2883
      if (!new_entry) {
2884
        return SSL_TLSEXT_ERR_ALERT_FATAL;
2885
      }
2886
      /* Need to set up a new SSL_CTX to switch to */
2887
      if (c_session->proto == COAP_PROTO_DTLS) {
2888
        /* Set up DTLS context */
2889
        ctx = SSL_CTX_new(DTLS_method());
2890
        if (!ctx)
2891
          goto error;
2892
        SSL_CTX_set_min_proto_version(ctx, DTLS1_2_VERSION);
2893
        SSL_CTX_set_app_data(ctx, &o_context->dtls);
2894
        SSL_CTX_set_read_ahead(ctx, 1);
2895
        SSL_CTX_set_cipher_list(ctx, COAP_OPENSSL_CIPHERS);
2896
        SSL_CTX_set_cookie_generate_cb(ctx, coap_dtls_generate_cookie);
2897
        SSL_CTX_set_cookie_verify_cb(ctx, coap_dtls_verify_cookie);
2898
        SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2899
        SSL_CTX_set_options(ctx, SSL_OP_NO_QUERY_MTU);
2900
      }
2901
#if !COAP_DISABLE_TCP
2902
      else {
2903
        /* Set up TLS context */
2904
        ctx = SSL_CTX_new(TLS_method());
2905
        if (!ctx)
2906
          goto error;
2907
        SSL_CTX_set_app_data(ctx, &o_context->tls);
2908
        SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2909
        SSL_CTX_set_cipher_list(ctx, COAP_OPENSSL_CIPHERS);
2910
        SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2911
        SSL_CTX_set_alpn_select_cb(ctx, server_alpn_callback, NULL);
2912
      }
2913
#endif /* !COAP_DISABLE_TCP */
2914
2915
      o_context->psk_sni_entry_list =
2916
          OPENSSL_realloc(o_context->psk_sni_entry_list,
2917
                          (o_context->psk_sni_count+1)*sizeof(psk_sni_entry));
2918
      o_context->psk_sni_entry_list[o_context->psk_sni_count].sni =
2919
          OPENSSL_strdup(sni);
2920
      o_context->psk_sni_entry_list[o_context->psk_sni_count].psk_info =
2921
          *new_entry;
2922
      o_context->psk_sni_entry_list[o_context->psk_sni_count].ctx =
2923
          ctx;
2924
      o_context->psk_sni_count++;
2925
    }
2926
    SSL_set_SSL_CTX(ssl, o_context->psk_sni_entry_list[i].ctx);
2927
    SSL_clear_options(ssl, 0xFFFFFFFFL);
2928
    SSL_set_options(ssl,
2929
                    SSL_CTX_get_options(o_context->psk_sni_entry_list[i].ctx));
2930
    coap_session_refresh_psk_key(c_session,
2931
                                 &o_context->psk_sni_entry_list[i].psk_info.key);
2932
    snprintf(lhint, sizeof(lhint), "%.*s",
2933
             (int)o_context->psk_sni_entry_list[i].psk_info.hint.length,
2934
             o_context->psk_sni_entry_list[i].psk_info.hint.s);
2935
    SSL_use_psk_identity_hint(ssl, lhint);
2936
  }
2937
2938
  /*
2939
   * Have to do extra call back next to get client algorithms
2940
   * SSL_get_client_ciphers() does not work this early on
2941
   */
2942
  SSL_set_session_secret_cb(ssl, tls_secret_call_back, arg);
2943
  return SSL_TLSEXT_ERR_OK;
2944
2945
error:
2946
  return SSL_TLSEXT_ERR_ALERT_WARNING;
2947
}
2948
#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
2949
/* OpenSSL >= 1.1.1 */
2950
/*
2951
 * During the SSL/TLS initial negotiations, tls_client_hello_call_back() is
2952
 * called early in the Client Hello processing so it is possible to determine
2953
 * whether this is a PKI or PSK incoming request and adjust the ciphers if
2954
 * necessary.
2955
 *
2956
 * Set up by SSL_CTX_set_client_hello_cb().
2957
 */
2958
static int
2959
tls_client_hello_call_back(SSL *ssl,
2960
                           int *al,
2961
                           void *arg COAP_UNUSED
2962
0
                          ) {
2963
0
  coap_session_t *session;
2964
0
  coap_openssl_context_t *dtls_context;
2965
0
  coap_dtls_pki_t *setup_data;
2966
0
  int psk_requested = 0;
2967
0
  const unsigned char *out;
2968
0
  size_t outlen;
2969
2970
0
  if (!ssl) {
2971
0
    *al = SSL_AD_INTERNAL_ERROR;
2972
0
    return SSL_CLIENT_HELLO_ERROR;
2973
0
  }
2974
0
  session = (coap_session_t *)SSL_get_app_data(ssl);
2975
0
  assert(session != NULL);
2976
0
  assert(session->context != NULL);
2977
0
  assert(session->context->dtls_context != NULL);
2978
0
  if (session == NULL ||
2979
0
      session->context == NULL ||
2980
0
      session->context->dtls_context == NULL) {
2981
0
    *al = SSL_AD_INTERNAL_ERROR;
2982
0
    return SSL_CLIENT_HELLO_ERROR;
2983
0
  }
2984
0
  dtls_context = (coap_openssl_context_t *)session->context->dtls_context;
2985
0
  setup_data = &dtls_context->setup_data;
2986
2987
  /*
2988
   * See if PSK being requested
2989
   */
2990
0
  if ((session->psk_key) ||
2991
0
      (session->context->spsk_setup_data.psk_info.key.s &&
2992
0
       session->context->spsk_setup_data.psk_info.key.length)) {
2993
0
    size_t len = SSL_client_hello_get0_ciphers(ssl, &out);
2994
0
    STACK_OF(SSL_CIPHER) *peer_ciphers = NULL;
2995
0
    STACK_OF(SSL_CIPHER) *scsvc = NULL;
2996
2997
0
    if (len && SSL_bytes_to_cipher_list(ssl, out, len,
2998
0
                                        SSL_client_hello_isv2(ssl),
2999
0
                                        &peer_ciphers, &scsvc)) {
3000
0
      int ii;
3001
0
      for (ii = 0; ii < sk_SSL_CIPHER_num(peer_ciphers); ii++) {
3002
0
        const SSL_CIPHER *peer_cipher = sk_SSL_CIPHER_value(peer_ciphers, ii);
3003
3004
0
        coap_dtls_log(COAP_LOG_INFO,
3005
0
                      "Client cipher: %s (%04x)\n",
3006
0
                      SSL_CIPHER_get_name(peer_cipher),
3007
0
                      SSL_CIPHER_get_protocol_id(peer_cipher));
3008
0
        if (strstr(SSL_CIPHER_get_name(peer_cipher), "PSK")) {
3009
0
          psk_requested = 1;
3010
0
          break;
3011
0
        }
3012
0
      }
3013
0
    }
3014
0
    sk_SSL_CIPHER_free(peer_ciphers);
3015
0
    sk_SSL_CIPHER_free(scsvc);
3016
0
  }
3017
3018
0
  if (psk_requested) {
3019
    /*
3020
     * Client has requested PSK and it is supported
3021
     */
3022
0
    coap_dtls_spsk_t *psk_setup_data = &session->context->spsk_setup_data;
3023
3024
0
    if (psk_setup_data->validate_sni_call_back) {
3025
0
      const char *sni = "";
3026
0
      char *sni_tmp = NULL;
3027
0
      char lhint[COAP_DTLS_HINT_LENGTH];
3028
0
      const coap_dtls_spsk_info_t *new_entry;
3029
3030
0
      if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name,
3031
0
                                    &out, &outlen) &&
3032
0
          outlen > 5 &&
3033
0
          (((out[0] << 8) + out[1] + 2) == (int)outlen) &&
3034
0
          out[2] == TLSEXT_NAMETYPE_host_name &&
3035
0
          (((out[3] << 8) + out[4] + 2 + 3) == (int)outlen)) {
3036
        /* Skip over length, type and length */
3037
0
        out += 5;
3038
0
        outlen -= 5;
3039
0
        sni_tmp = OPENSSL_malloc(outlen + 1);
3040
0
        if (sni_tmp) {
3041
0
          sni_tmp[outlen] = '\000';
3042
0
          memcpy(sni_tmp, out, outlen);
3043
0
          sni = sni_tmp;
3044
0
        }
3045
0
      }
3046
3047
0
      coap_lock_callback_ret(new_entry,
3048
0
                             psk_setup_data->validate_sni_call_back(
3049
0
                                 sni,
3050
0
                                 session,
3051
0
                                 psk_setup_data->sni_call_back_arg));
3052
0
      if (!new_entry) {
3053
0
        if (sni_tmp) {
3054
0
          OPENSSL_free(sni_tmp);
3055
0
        }
3056
0
        *al = SSL_AD_UNRECOGNIZED_NAME;
3057
0
        return SSL_CLIENT_HELLO_ERROR;
3058
0
      }
3059
3060
0
      if (sni_tmp) {
3061
0
        OPENSSL_free(sni_tmp);
3062
0
      }
3063
0
      if (coap_session_refresh_psk_hint(session, &new_entry->hint) == 0) {
3064
0
        *al = SSL_AD_INTERNAL_ERROR;
3065
0
        return SSL_CLIENT_HELLO_ERROR;
3066
0
      }
3067
0
      if (coap_session_refresh_psk_key(session, &new_entry->key) == 0) {
3068
0
        *al = SSL_AD_INTERNAL_ERROR;
3069
0
        return SSL_CLIENT_HELLO_ERROR;
3070
0
      }
3071
0
      if (new_entry->hint.s) {
3072
0
        snprintf(lhint, sizeof(lhint), "%.*s",
3073
0
                 (int)new_entry->hint.length,
3074
0
                 new_entry->hint.s);
3075
0
        SSL_use_psk_identity_hint(ssl, lhint);
3076
0
      }
3077
0
    }
3078
0
    coap_log_debug("   %s: PSK request\n",
3079
0
                   coap_session_str(session));
3080
0
    SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
3081
0
    if (setup_data->additional_tls_setup_call_back) {
3082
      /* Additional application setup wanted */
3083
0
      if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
3084
0
        return 0;
3085
0
    }
3086
0
    return SSL_CLIENT_HELLO_SUCCESS;
3087
0
  }
3088
3089
  /*
3090
   * Handle Certificate requests
3091
   */
3092
3093
  /*
3094
   * Determine what type of certificate is being requested
3095
   */
3096
0
  if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_client_certificate_type,
3097
0
                                &out, &outlen)) {
3098
0
    size_t ii;
3099
0
    for (ii = 0; ii < outlen; ii++) {
3100
0
      switch (out[ii]) {
3101
0
      case 0:
3102
        /* RFC6091 X.509 */
3103
0
        if (outlen >= 2) {
3104
          /* X.509 cannot be the singular entry. RFC6091 3.1. Client Hello */
3105
0
          goto is_x509;
3106
0
        }
3107
0
        break;
3108
0
      case 2:
3109
        /* RFC7250 RPK - not yet supported */
3110
0
        break;
3111
0
      default:
3112
0
        break;
3113
0
      }
3114
0
    }
3115
0
    *al = SSL_AD_UNSUPPORTED_EXTENSION;
3116
0
    return SSL_CLIENT_HELLO_ERROR;
3117
0
  }
3118
3119
0
is_x509:
3120
0
  if (setup_data->validate_sni_call_back) {
3121
    /*
3122
     * SNI checking requested
3123
     */
3124
0
    coap_dtls_pki_t sni_setup_data;
3125
0
    coap_openssl_context_t *context =
3126
0
        ((coap_openssl_context_t *)session->context->dtls_context);
3127
0
    const char *sni = "";
3128
0
    char *sni_tmp = NULL;
3129
0
    size_t i;
3130
3131
0
    if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &out, &outlen) &&
3132
0
        outlen > 5 &&
3133
0
        (((out[0]<<8) + out[1] +2) == (int)outlen) &&
3134
0
        out[2] == TLSEXT_NAMETYPE_host_name &&
3135
0
        (((out[3]<<8) + out[4] +2 +3) == (int)outlen)) {
3136
      /* Skip over length, type and length */
3137
0
      out += 5;
3138
0
      outlen -= 5;
3139
0
      sni_tmp = OPENSSL_malloc(outlen+1);
3140
0
      sni_tmp[outlen] = '\000';
3141
0
      memcpy(sni_tmp, out, outlen);
3142
0
      sni = sni_tmp;
3143
0
    }
3144
    /* Is this a cached entry? */
3145
0
    for (i = 0; i < context->sni_count; i++) {
3146
0
      if (!strcasecmp(sni, context->sni_entry_list[i].sni)) {
3147
0
        break;
3148
0
      }
3149
0
    }
3150
0
    if (i == context->sni_count) {
3151
      /*
3152
       * New SNI request
3153
       */
3154
0
      coap_dtls_key_t *new_entry;
3155
3156
0
      coap_lock_callback_ret(new_entry,
3157
0
                             setup_data->validate_sni_call_back(sni,
3158
0
                                                                setup_data->sni_call_back_arg));
3159
0
      if (!new_entry) {
3160
0
        *al = SSL_AD_UNRECOGNIZED_NAME;
3161
0
        return SSL_CLIENT_HELLO_ERROR;
3162
0
      }
3163
3164
3165
0
      context->sni_entry_list = OPENSSL_realloc(context->sni_entry_list,
3166
0
                                                (context->sni_count+1)*sizeof(sni_entry));
3167
0
      context->sni_entry_list[context->sni_count].sni = OPENSSL_strdup(sni);
3168
0
      context->sni_entry_list[context->sni_count].pki_key = *new_entry;
3169
0
      context->sni_count++;
3170
0
    }
3171
0
    if (sni_tmp) {
3172
0
      OPENSSL_free(sni_tmp);
3173
0
    }
3174
0
    sni_setup_data = *setup_data;
3175
0
    sni_setup_data.pki_key = context->sni_entry_list[i].pki_key;
3176
0
    setup_pki_ssl(ssl, &sni_setup_data, COAP_DTLS_ROLE_SERVER);
3177
0
  } else {
3178
0
    setup_pki_ssl(ssl, setup_data, COAP_DTLS_ROLE_SERVER);
3179
0
  }
3180
3181
0
  coap_log_debug("   %s: Using PKI ciphers\n",
3182
0
                 coap_session_str(session));
3183
3184
0
  if (setup_data->verify_peer_cert) {
3185
0
    SSL_set_verify(ssl,
3186
0
                   SSL_VERIFY_PEER |
3187
0
                   SSL_VERIFY_CLIENT_ONCE |
3188
0
                   SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
3189
0
                   tls_verify_call_back);
3190
0
  } else {
3191
0
    SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_call_back);
3192
0
  }
3193
3194
  /* Check CA Chain */
3195
0
  if (setup_data->cert_chain_validation)
3196
0
    SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth + 2);
3197
3198
  /* Certificate Revocation */
3199
0
  if (setup_data->check_cert_revocation) {
3200
0
    X509_VERIFY_PARAM *param;
3201
3202
0
    param = X509_VERIFY_PARAM_new();
3203
0
    if (param) {
3204
0
      X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
3205
0
      SSL_set1_param(ssl, param);
3206
0
      X509_VERIFY_PARAM_free(param);
3207
0
    }
3208
0
  }
3209
0
  if (setup_data->additional_tls_setup_call_back) {
3210
    /* Additional application setup wanted */
3211
0
    if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
3212
0
      return 0;
3213
0
  }
3214
0
  return SSL_CLIENT_HELLO_SUCCESS;
3215
0
}
3216
3217
#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3218
#endif /* COAP_SERVER_SUPPORT */
3219
3220
int
3221
coap_dtls_context_set_pki(coap_context_t *ctx,
3222
                          const coap_dtls_pki_t *setup_data,
3223
0
                          const coap_dtls_role_t role) {
3224
0
  coap_openssl_context_t *context =
3225
0
      ((coap_openssl_context_t *)ctx->dtls_context);
3226
0
  BIO *bio;
3227
0
  if (!setup_data)
3228
0
    return 0;
3229
0
  context->setup_data = *setup_data;
3230
3231
0
#if OPENSSL_VERSION_NUMBER < 0x40000000L
3232
0
  if (context->setup_data.pki_key.key_type == COAP_PKI_KEY_DEFINE) {
3233
0
    if (context->setup_data.pki_key.key.define.ca_def == COAP_PKI_KEY_DEF_ENGINE ||
3234
0
        context->setup_data.pki_key.key.define.public_cert_def == COAP_PKI_KEY_DEF_ENGINE ||
3235
0
        context->setup_data.pki_key.key.define.private_key_def == COAP_PKI_KEY_DEF_ENGINE) {
3236
0
      if (!defined_engine) {
3237
0
        coap_log_warn("setup_pki: OpenSSL Engine not configured, PKI not set up\n");
3238
0
        return 0;
3239
0
      }
3240
0
    }
3241
0
  }
3242
0
#endif /* OPENSSL_VERSION_NUMBER < 0x40000000L */
3243
3244
0
  if (!context->setup_data.verify_peer_cert) {
3245
    /* Needs to be clear so that no CA DNs are transmitted */
3246
0
    context->setup_data.check_common_ca = 0;
3247
    /* Allow all of these but warn if issue */
3248
0
    context->setup_data.allow_self_signed = 1;
3249
0
    context->setup_data.allow_expired_certs = 1;
3250
0
    context->setup_data.cert_chain_validation = 1;
3251
0
    context->setup_data.cert_chain_verify_depth = 10;
3252
0
    context->setup_data.check_cert_revocation = 1;
3253
0
    context->setup_data.allow_no_crl = 1;
3254
0
    context->setup_data.allow_expired_crl = 1;
3255
0
    context->setup_data.allow_bad_md_hash = 1;
3256
0
    context->setup_data.allow_short_rsa_length = 1;
3257
0
  }
3258
0
#if COAP_SERVER_SUPPORT
3259
0
  if (role == COAP_DTLS_ROLE_SERVER) {
3260
0
    if (context->dtls.ctx) {
3261
      /* SERVER DTLS */
3262
#if OPENSSL_VERSION_NUMBER < 0x10101000L
3263
      if (!setup_pki_server(context->dtls.ctx, setup_data))
3264
        return 0;
3265
#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3266
      /* libcoap is managing TLS connection based on setup_data options */
3267
      /* Need to set up logic to differentiate between a PSK or PKI session */
3268
      /*
3269
       * For OpenSSL 1.1.1, we need to use SSL_CTX_set_client_hello_cb()
3270
       * which is not in 1.1.0
3271
       */
3272
#if OPENSSL_VERSION_NUMBER < 0x10101000L
3273
      if (SSLeay() >= 0x10101000L) {
3274
        coap_log_warn("OpenSSL compiled with %lux, linked with %lux, so "
3275
                      "no certificate checking\n",
3276
                      OPENSSL_VERSION_NUMBER, SSLeay());
3277
      }
3278
      SSL_CTX_set_tlsext_servername_arg(context->dtls.ctx, &context->setup_data);
3279
      SSL_CTX_set_tlsext_servername_callback(context->dtls.ctx,
3280
                                             tls_server_name_call_back);
3281
#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3282
0
      SSL_CTX_set_client_hello_cb(context->dtls.ctx,
3283
0
                                  tls_client_hello_call_back,
3284
0
                                  NULL);
3285
0
#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3286
0
    }
3287
0
#if !COAP_DISABLE_TCP
3288
0
    if (context->tls.ctx) {
3289
      /* SERVER TLS */
3290
#if OPENSSL_VERSION_NUMBER < 0x10101000L
3291
      if (!setup_pki_server(context->tls.ctx, setup_data))
3292
        return 0;
3293
#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3294
      /* libcoap is managing TLS connection based on setup_data options */
3295
      /* Need to set up logic to differentiate between a PSK or PKI session */
3296
      /*
3297
       * For OpenSSL 1.1.1, we need to use SSL_CTX_set_client_hello_cb()
3298
       * which is not in 1.1.0
3299
       */
3300
#if OPENSSL_VERSION_NUMBER < 0x10101000L
3301
      if (SSLeay() >= 0x10101000L) {
3302
        coap_log_warn("OpenSSL compiled with %lux, linked with %lux, so "
3303
                      "no certificate checking\n",
3304
                      OPENSSL_VERSION_NUMBER, SSLeay());
3305
      }
3306
      SSL_CTX_set_tlsext_servername_arg(context->tls.ctx, &context->setup_data);
3307
      SSL_CTX_set_tlsext_servername_callback(context->tls.ctx,
3308
                                             tls_server_name_call_back);
3309
#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3310
0
      SSL_CTX_set_client_hello_cb(context->tls.ctx,
3311
0
                                  tls_client_hello_call_back,
3312
0
                                  NULL);
3313
0
#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3314
      /* TLS Only */
3315
0
      SSL_CTX_set_alpn_select_cb(context->tls.ctx, server_alpn_callback, NULL);
3316
0
    }
3317
0
#endif /* !COAP_DISABLE_TCP */
3318
0
  }
3319
#else /* ! COAP_SERVER_SUPPORT */
3320
  (void)role;
3321
#endif /* ! COAP_SERVER_SUPPORT */
3322
0
#if COAP_CLIENT_SUPPORT
3323
0
  if (role == COAP_DTLS_ROLE_CLIENT) {
3324
0
    context->psk_pki_enabled &= ~IS_PSK;
3325
0
  }
3326
0
#endif /* COAP_CLIENT_SUPPORT */
3327
3328
0
  if (!context->dtls.ssl) {
3329
    /* This is set up to handle new incoming sessions to a server */
3330
0
    context->dtls.ssl = SSL_new(context->dtls.ctx);
3331
0
    if (!context->dtls.ssl)
3332
0
      return 0;
3333
0
    bio = BIO_new(context->dtls.meth);
3334
0
    if (!bio) {
3335
0
      SSL_free(context->dtls.ssl);
3336
0
      context->dtls.ssl = NULL;
3337
0
      return 0;
3338
0
    }
3339
0
    SSL_set_bio(context->dtls.ssl, bio, bio);
3340
0
    SSL_set_app_data(context->dtls.ssl, NULL);
3341
0
    SSL_set_options(context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
3342
0
    SSL_set_mtu(context->dtls.ssl, COAP_DEFAULT_MTU);
3343
0
  }
3344
0
  context->psk_pki_enabled |= IS_PKI;
3345
0
  if (setup_data->use_cid) {
3346
0
    coap_log_warn("OpenSSL has no Connection-ID support\n");
3347
0
  }
3348
0
  return 1;
3349
0
}
3350
3351
int
3352
coap_dtls_context_set_pki_root_cas(coap_context_t *ctx,
3353
                                   const char *ca_file,
3354
                                   const char *ca_dir
3355
0
                                  ) {
3356
0
  coap_openssl_context_t *context =
3357
0
      ((coap_openssl_context_t *)ctx->dtls_context);
3358
0
  if (context->dtls.ctx) {
3359
0
    if (!SSL_CTX_load_verify_locations(context->dtls.ctx, ca_file, ca_dir)) {
3360
0
      coap_log_warn("Unable to install root CAs (%s : %s)\n",
3361
0
                    ca_file ? ca_file : "NULL", ca_dir ? ca_dir : "NULL");
3362
0
      return 0;
3363
0
    }
3364
0
  }
3365
0
#if !COAP_DISABLE_TCP
3366
0
  if (context->tls.ctx) {
3367
0
    if (!SSL_CTX_load_verify_locations(context->tls.ctx, ca_file, ca_dir)) {
3368
0
      coap_log_warn("Unable to install root CAs (%s : %s)\n",
3369
0
                    ca_file ? ca_file : "NULL", ca_dir ? ca_dir : "NULL");
3370
0
      return 0;
3371
0
    }
3372
0
  }
3373
0
#endif /* !COAP_DISABLE_TCP */
3374
0
  return 1;
3375
0
}
3376
3377
int
3378
0
coap_dtls_context_load_pki_trust_store(coap_context_t *ctx) {
3379
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3380
  coap_openssl_context_t *context =
3381
      ((coap_openssl_context_t *)ctx->dtls_context);
3382
  if (context->dtls.ctx) {
3383
    if (!SSL_CTX_set_default_verify_paths(context->dtls.ctx)) {
3384
      coap_log_warn("Unable to load trusted root CAs\n");
3385
      return 0;
3386
    }
3387
  }
3388
#if !COAP_DISABLE_TCP
3389
  if (context->tls.ctx) {
3390
    if (!SSL_CTX_set_default_verify_paths(context->tls.ctx)) {
3391
      coap_log_warn("Unable to load trusted root CAs\n");
3392
      return 0;
3393
    }
3394
  }
3395
#endif /* !COAP_DISABLE_TCP */
3396
  return 1;
3397
#else /* OPENSSL_VERSION_NUMBER < 0x30000000L */
3398
0
  (void)ctx;
3399
0
  coap_log_warn("coap_context_set_pki_trust_store: (D)TLS environment "
3400
0
                "not supported for OpenSSL < v3.0.0\n");
3401
0
  return 0;
3402
0
#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */
3403
0
}
3404
3405
int
3406
0
coap_dtls_context_check_keys_enabled(coap_context_t *ctx) {
3407
0
  coap_openssl_context_t *context =
3408
0
      ((coap_openssl_context_t *)ctx->dtls_context);
3409
0
  return context->psk_pki_enabled ? 1 : 0;
3410
0
}
3411
3412
3413
void
3414
0
coap_dtls_free_context(void *handle) {
3415
0
  size_t i;
3416
0
  coap_openssl_context_t *context = (coap_openssl_context_t *)handle;
3417
3418
0
  if (context->dtls.ssl)
3419
0
    SSL_free(context->dtls.ssl);
3420
0
  if (context->dtls.ctx)
3421
0
    SSL_CTX_free(context->dtls.ctx);
3422
0
  if (context->dtls.cookie_hmac)
3423
0
    HMAC_CTX_free(context->dtls.cookie_hmac);
3424
0
  if (context->dtls.meth)
3425
0
    BIO_meth_free(context->dtls.meth);
3426
0
  if (context->dtls.bio_addr)
3427
0
    BIO_ADDR_free(context->dtls.bio_addr);
3428
0
#if !COAP_DISABLE_TCP
3429
0
  if (context->tls.ctx)
3430
0
    SSL_CTX_free(context->tls.ctx);
3431
0
  if (context->tls.meth)
3432
0
    BIO_meth_free(context->tls.meth);
3433
0
#endif /* !COAP_DISABLE_TCP */
3434
0
  for (i = 0; i < context->sni_count; i++) {
3435
0
    OPENSSL_free(context->sni_entry_list[i].sni);
3436
#if OPENSSL_VERSION_NUMBER < 0x10101000L
3437
    SSL_CTX_free(context->sni_entry_list[i].ctx);
3438
#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3439
0
  }
3440
0
  if (context->sni_count)
3441
0
    OPENSSL_free(context->sni_entry_list);
3442
#if OPENSSL_VERSION_NUMBER < 0x10101000L
3443
  for (i = 0; i < context->psk_sni_count; i++) {
3444
    OPENSSL_free((char *)context->psk_sni_entry_list[i].sni);
3445
    SSL_CTX_free(context->psk_sni_entry_list[i].ctx);
3446
  }
3447
  if (context->psk_sni_count)
3448
    OPENSSL_free(context->psk_sni_entry_list);
3449
#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3450
0
  coap_free_type(COAP_STRING, context);
3451
0
}
3452
3453
#if COAP_SERVER_SUPPORT
3454
void *
3455
0
coap_dtls_new_server_session(coap_session_t *session) {
3456
0
  BIO *nbio = NULL;
3457
0
  SSL *nssl = NULL, *ssl = NULL;
3458
0
  coap_ssl_data *data;
3459
0
  coap_dtls_context_t *dtls = &((coap_openssl_context_t *)session->context->dtls_context)->dtls;
3460
0
  int r;
3461
0
  const coap_bin_const_t *psk_hint;
3462
0
  BIO *rbio;
3463
3464
0
  nssl = SSL_new(dtls->ctx);
3465
0
  if (!nssl)
3466
0
    goto error;
3467
0
  nbio = BIO_new(dtls->meth);
3468
0
  if (!nbio)
3469
0
    goto error;
3470
0
  SSL_set_bio(nssl, nbio, nbio);
3471
0
  SSL_set_app_data(nssl, NULL);
3472
0
  SSL_set_options(nssl, SSL_OP_COOKIE_EXCHANGE);
3473
0
  SSL_set_mtu(nssl, (long)session->mtu);
3474
0
  ssl = dtls->ssl;
3475
0
  dtls->ssl = nssl;
3476
0
  nssl = NULL;
3477
0
  SSL_set_app_data(ssl, session);
3478
3479
0
  rbio = SSL_get_rbio(ssl);
3480
0
  data = rbio ? (coap_ssl_data *)BIO_get_data(rbio) : NULL;
3481
0
  if (!data)
3482
0
    goto error;
3483
0
  data->session = session;
3484
3485
  /* hint may get updated if/when handling SNI callback */
3486
0
  psk_hint = coap_get_session_server_psk_hint(session);
3487
0
  if (psk_hint != NULL && psk_hint->length) {
3488
0
    char *hint = OPENSSL_malloc(psk_hint->length + 1);
3489
3490
0
    if (hint) {
3491
0
      memcpy(hint, psk_hint->s, psk_hint->length);
3492
0
      hint[psk_hint->length] = '\000';
3493
0
      SSL_use_psk_identity_hint(ssl, hint);
3494
0
      OPENSSL_free(hint);
3495
0
    } else {
3496
0
      coap_log_warn("hint malloc failure\n");
3497
0
    }
3498
0
  }
3499
3500
0
  r = SSL_accept(ssl);
3501
0
  if (r == -1) {
3502
0
    int err = SSL_get_error(ssl, r);
3503
0
    if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
3504
0
      r = 0;
3505
0
  }
3506
3507
0
  if (r == 0) {
3508
0
    SSL_free(ssl);
3509
0
    return NULL;
3510
0
  }
3511
3512
0
  return ssl;
3513
3514
0
error:
3515
0
  if (nssl)
3516
0
    SSL_free(nssl);
3517
0
  return NULL;
3518
0
}
3519
#endif /* COAP_SERVER_SUPPORT */
3520
3521
#if COAP_CLIENT_SUPPORT
3522
static int
3523
setup_client_ssl_session(coap_session_t *session, SSL *ssl
3524
0
                        ) {
3525
0
  coap_openssl_context_t *context =
3526
0
      ((coap_openssl_context_t *)session->context->dtls_context);
3527
3528
0
  if (context->psk_pki_enabled & IS_PSK) {
3529
0
    coap_dtls_cpsk_t *setup_data = &session->cpsk_setup_data;
3530
3531
    /* Issue SNI if requested */
3532
0
    if (setup_data->client_sni &&
3533
0
        SSL_set_tlsext_host_name(ssl, setup_data->client_sni) != 1) {
3534
0
      coap_log_warn("SSL_set_tlsext_host_name: set '%s' failed",
3535
0
                    setup_data->client_sni);
3536
0
    }
3537
0
    SSL_set_psk_client_callback(ssl, coap_dtls_psk_client_callback);
3538
0
#if COAP_SERVER_SUPPORT
3539
0
    SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
3540
0
#endif /* COAP_SERVER_SUPPORT */
3541
0
    SSL_set_cipher_list(ssl, COAP_OPENSSL_PSK_CIPHERS);
3542
#ifdef COAP_OPENSSL_PSK_SECURITY_LEVEL
3543
    /*
3544
     * Set to 0 if, for example, PSK-AES128-CCM8 is to be supported (64 bits).
3545
     * Potentially opens up security vulnerabilities.
3546
     * Default value is 1.
3547
    */
3548
    SSL_set_security_level(ssl, COAP_OPENSSL_PSK_SECURITY_LEVEL);
3549
#endif /* COAP_OPENSSL_PSK_SECURITY_LEVEL */
3550
0
    if (setup_data->validate_ih_call_back) {
3551
0
      if (session->proto == COAP_PROTO_DTLS) {
3552
0
        SSL_set_max_proto_version(ssl, DTLS1_2_VERSION);
3553
0
      }
3554
0
#if !COAP_DISABLE_TCP
3555
0
      else {
3556
0
        SSL_set_max_proto_version(ssl, TLS1_2_VERSION);
3557
0
      }
3558
0
#endif /* !COAP_DISABLE_TCP */
3559
0
      coap_log_debug("CoAP Client restricted to (D)TLS1.2 with Identity Hint callback\n");
3560
0
    }
3561
0
  }
3562
0
  if ((context->psk_pki_enabled & IS_PKI) ||
3563
0
      (context->psk_pki_enabled & (IS_PSK | IS_PKI)) == 0) {
3564
    /*
3565
     * If neither PSK or PKI have been set up, use PKI basics.
3566
     * This works providing COAP_PKI_KEY_PEM has a value of 0.
3567
     */
3568
0
    coap_dtls_pki_t *setup_data = &context->setup_data;
3569
3570
0
    if (!(context->psk_pki_enabled & IS_PKI)) {
3571
      /* PKI not defined - set up some defaults */
3572
0
      setup_data->verify_peer_cert        = 1;
3573
0
      setup_data->check_common_ca         = 0;
3574
0
      setup_data->allow_self_signed       = 1;
3575
0
      setup_data->allow_expired_certs     = 1;
3576
0
      setup_data->cert_chain_validation   = 1;
3577
0
      setup_data->cert_chain_verify_depth = 2;
3578
0
      setup_data->check_cert_revocation   = 1;
3579
0
      setup_data->allow_no_crl            = 1;
3580
0
      setup_data->allow_expired_crl       = 1;
3581
0
      setup_data->is_rpk_not_cert         = 0;
3582
0
      setup_data->use_cid                 = 0;
3583
0
    }
3584
0
    if (!setup_pki_ssl(ssl, setup_data, COAP_DTLS_ROLE_CLIENT))
3585
0
      return 0;
3586
    /* libcoap is managing (D)TLS connection based on setup_data options */
3587
0
#if !COAP_DISABLE_TCP
3588
0
    if (session->proto == COAP_PROTO_TLS)
3589
0
      SSL_set_alpn_protos(ssl, coap_alpn, sizeof(coap_alpn));
3590
0
#endif /* !COAP_DISABLE_TCP */
3591
3592
    /* Issue SNI if requested */
3593
0
    if (setup_data->client_sni &&
3594
0
        SSL_set_tlsext_host_name(ssl, setup_data->client_sni) != 1) {
3595
0
      coap_log_warn("SSL_set_tlsext_host_name: set '%s' failed",
3596
0
                    setup_data->client_sni);
3597
0
    }
3598
    /* Certificate Revocation */
3599
0
    if (setup_data->check_cert_revocation) {
3600
0
      X509_VERIFY_PARAM *param;
3601
3602
0
      param = X509_VERIFY_PARAM_new();
3603
0
      if (param) {
3604
0
        X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
3605
0
        SSL_set1_param(ssl, param);
3606
0
        X509_VERIFY_PARAM_free(param);
3607
0
      }
3608
0
    }
3609
3610
    /* Verify Peer */
3611
0
    if (setup_data->verify_peer_cert)
3612
0
      SSL_set_verify(ssl,
3613
0
                     SSL_VERIFY_PEER |
3614
0
                     SSL_VERIFY_CLIENT_ONCE |
3615
0
                     SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
3616
0
                     tls_verify_call_back);
3617
0
    else
3618
0
      SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_call_back);
3619
3620
    /* Check CA Chain */
3621
0
    if (setup_data->cert_chain_validation)
3622
0
      SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth + 1);
3623
3624
0
  }
3625
#if COAP_DTLS_RETRANSMIT_MS != 1000
3626
#if OPENSSL_VERSION_NUMBER >= 0x10101000L
3627
  if (session->proto == COAP_PROTO_DTLS) {
3628
    DTLS_set_timer_cb(ssl, timer_cb);
3629
  }
3630
#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3631
#endif /* COAP_DTLS_RETRANSMIT_MS != 1000 */
3632
0
  return 1;
3633
0
}
3634
3635
void *
3636
0
coap_dtls_new_client_session(coap_session_t *session) {
3637
0
  BIO *bio = NULL;
3638
0
  SSL *ssl = NULL;
3639
0
  coap_ssl_data *data;
3640
0
  int r;
3641
0
  coap_openssl_context_t *context = ((coap_openssl_context_t *)session->context->dtls_context);
3642
0
  coap_dtls_context_t *dtls = &context->dtls;
3643
3644
0
  ssl = SSL_new(dtls->ctx);
3645
0
  if (!ssl)
3646
0
    goto error;
3647
0
  bio = BIO_new(dtls->meth);
3648
0
  if (!bio)
3649
0
    goto error;
3650
0
  data = (coap_ssl_data *)BIO_get_data(bio);
3651
0
  if (!data)
3652
0
    goto error;
3653
0
  data->session = session;
3654
0
  SSL_set_bio(ssl, bio, bio);
3655
0
  SSL_set_app_data(ssl, session);
3656
0
  SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE);
3657
0
  SSL_set_mtu(ssl, (long)session->mtu);
3658
3659
0
  if (!setup_client_ssl_session(session, ssl))
3660
0
    goto error;
3661
3662
0
  session->dtls_timeout_count = 0;
3663
3664
0
  r = SSL_connect(ssl);
3665
0
  if (r == -1) {
3666
0
    int ret = SSL_get_error(ssl, r);
3667
0
    if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE)
3668
0
      r = 0;
3669
0
  }
3670
3671
0
  if (r == 0)
3672
0
    goto error;
3673
3674
0
  session->tls = ssl;
3675
0
  return ssl;
3676
3677
0
error:
3678
0
  if (ssl)
3679
0
    SSL_free(ssl);
3680
0
  return NULL;
3681
0
}
3682
3683
void
3684
0
coap_dtls_session_update_mtu(coap_session_t *session) {
3685
0
  SSL *ssl = (SSL *)session->tls;
3686
0
  if (ssl)
3687
0
    SSL_set_mtu(ssl, (long)session->mtu);
3688
0
}
3689
#endif /* COAP_CLIENT_SUPPORT */
3690
3691
void
3692
0
coap_dtls_free_session(coap_session_t *session) {
3693
0
  SSL *ssl = (SSL *)session->tls;
3694
0
  if (ssl) {
3695
0
    if (!SSL_in_init(ssl) && !(SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN)) {
3696
0
      int r = SSL_shutdown(ssl);
3697
0
      if (r == 0)
3698
0
        SSL_shutdown(ssl);
3699
0
    }
3700
0
    SSL_free(ssl);
3701
0
    session->tls = NULL;
3702
0
    if (session->context)
3703
0
      coap_handle_event_lkd(session->context, COAP_EVENT_DTLS_CLOSED, session);
3704
0
  }
3705
0
}
3706
3707
ssize_t
3708
coap_dtls_send(coap_session_t *session,
3709
0
               const uint8_t *data, size_t data_len) {
3710
0
  int r;
3711
0
  SSL *ssl = (SSL *)session->tls;
3712
3713
0
  if (ssl == NULL) {
3714
0
    session->dtls_event = COAP_EVENT_DTLS_CLOSED;
3715
0
    return -1;
3716
0
  }
3717
3718
0
  session->dtls_event = -1;
3719
0
  coap_log_debug("*  %s: dtls:  sent %4d bytes\n",
3720
0
                 coap_session_str(session), (int)data_len);
3721
0
  ERR_clear_error();
3722
0
  r = SSL_write(ssl, data, (int)data_len);
3723
3724
0
  if (r <= 0) {
3725
0
    int err = SSL_get_error(ssl, r);
3726
0
    if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
3727
0
      r = 0;
3728
0
    } else {
3729
0
      if (err == SSL_ERROR_ZERO_RETURN)
3730
0
        session->dtls_event = COAP_EVENT_DTLS_CLOSED;
3731
0
      else if (err == SSL_ERROR_SSL) {
3732
0
        unsigned long e = ERR_get_error();
3733
3734
0
        coap_log_info("***%s: coap_dtls_send: cannot send PDU: %d: %s\n",
3735
0
                      coap_session_str(session),
3736
0
                      ERR_GET_REASON(e), ERR_reason_error_string(e));
3737
0
        session->dtls_event = COAP_EVENT_DTLS_ERROR;
3738
0
      } else {
3739
0
        coap_log_info("***%s: coap_dtls_send: cannot send PDU: %d\n",
3740
0
                      coap_session_str(session), err);
3741
0
      }
3742
0
      r = -1;
3743
0
    }
3744
0
  }
3745
3746
0
  if (session->dtls_event >= 0) {
3747
0
    coap_handle_event_lkd(session->context, session->dtls_event, session);
3748
0
    if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
3749
0
        session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
3750
0
      r = -1;
3751
0
    }
3752
0
  }
3753
3754
0
  return r;
3755
0
}
3756
3757
int
3758
0
coap_dtls_is_context_timeout(void) {
3759
0
  return 0;
3760
0
}
3761
3762
coap_tick_t
3763
0
coap_dtls_get_context_timeout(void *dtls_context) {
3764
0
  (void)dtls_context;
3765
0
  return 0;
3766
0
}
3767
3768
coap_tick_t
3769
0
coap_dtls_get_timeout(coap_session_t *session, coap_tick_t now COAP_UNUSED) {
3770
0
  SSL *ssl = (SSL *)session->tls;
3771
0
  coap_ssl_data *ssl_data;
3772
0
  BIO *rbio;
3773
3774
0
  assert(ssl != NULL && session->state == COAP_SESSION_STATE_HANDSHAKE);
3775
0
  rbio = ssl ? SSL_get_rbio(ssl) : NULL;
3776
0
  ssl_data = rbio ? (coap_ssl_data *)BIO_get_data(rbio) : NULL;
3777
0
  return ssl_data ? ssl_data->timeout : 1000;
3778
0
}
3779
3780
/*
3781
 * return 1 timed out
3782
 *        0 still timing out
3783
 */
3784
int
3785
0
coap_dtls_handle_timeout(coap_session_t *session) {
3786
0
  SSL *ssl = (SSL *)session->tls;
3787
3788
0
  if (ssl != NULL && session->state == COAP_SESSION_STATE_HANDSHAKE) {
3789
0
    if ((++session->dtls_timeout_count > session->max_retransmit) ||
3790
0
        (DTLSv1_handle_timeout(ssl) < 0)) {
3791
      /* Too many retries */
3792
0
      coap_session_disconnected_lkd(session, COAP_NACK_TLS_FAILED);
3793
0
      return 1;
3794
0
    }
3795
0
    return 0;
3796
0
  }
3797
0
  return 1;
3798
0
}
3799
3800
#if COAP_SERVER_SUPPORT
3801
int
3802
coap_dtls_hello(coap_session_t *session,
3803
0
                const uint8_t *data, size_t data_len) {
3804
0
  coap_dtls_context_t *dtls = &((coap_openssl_context_t *)session->context->dtls_context)->dtls;
3805
0
  coap_ssl_data *ssl_data;
3806
0
  int r;
3807
0
  BIO *rbio;
3808
3809
0
  SSL_set_mtu(dtls->ssl, (long)session->mtu);
3810
0
  rbio = dtls->ssl ? SSL_get_rbio(dtls->ssl) : NULL;
3811
0
  ssl_data = rbio ? (coap_ssl_data *)BIO_get_data(rbio) : NULL;
3812
0
  assert(ssl_data != NULL);
3813
0
  if (!ssl_data) {
3814
0
    errno = ENOMEM;
3815
0
    return -1;
3816
0
  }
3817
0
  if (ssl_data->pdu_len) {
3818
0
    coap_log_err("** %s: Previous data not read %u bytes\n",
3819
0
                 coap_session_str(session), ssl_data->pdu_len);
3820
0
  }
3821
0
  ssl_data->session = session;
3822
0
  ssl_data->pdu = data;
3823
0
  ssl_data->pdu_len = (unsigned)data_len;
3824
0
  r = DTLSv1_listen(dtls->ssl, dtls->bio_addr);
3825
0
  if (r <= 0) {
3826
0
    int err = SSL_get_error(dtls->ssl, r);
3827
0
    if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
3828
      /* Got a ClientHello, sent-out a VerifyRequest */
3829
0
      r = 0;
3830
0
    }
3831
0
  } else {
3832
    /* Got a valid answer to a VerifyRequest */
3833
0
    r = 1;
3834
0
  }
3835
3836
  /*
3837
   * Cannot check if data is left on the stack in error as DTLSv1_listen()
3838
   * only does a 'peek' read of the incoming data.
3839
   *
3840
   */
3841
0
  return r;
3842
0
}
3843
#endif /* COAP_SERVER_SUPPORT */
3844
3845
static void
3846
0
coap_dtls_receive_done(coap_ssl_data *ssl_data, int r) {
3847
0
  if (ssl_data->pdu_len) {
3848
    /* pdu data is held on stack which will not stay there */
3849
0
    coap_log_debug("coap_dtls_receive: ret %d: remaining data %u\n", r, ssl_data->pdu_len);
3850
0
    ssl_data->pdu_len = 0;
3851
0
    ssl_data->pdu = NULL;
3852
0
  }
3853
0
}
3854
3855
int
3856
0
coap_dtls_receive(coap_session_t *session, const uint8_t *data, size_t data_len) {
3857
0
  coap_ssl_data *ssl_data;
3858
0
  SSL *ssl = (SSL *)session->tls;
3859
0
  int r;
3860
0
  BIO *rbio;
3861
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3862
  int retry = 0;
3863
#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
3864
3865
0
  assert(ssl != NULL);
3866
3867
0
  int in_init = SSL_in_init(ssl);
3868
0
  uint8_t pdu[COAP_RXBUFFER_SIZE];
3869
0
  rbio = ssl ? SSL_get_rbio(ssl) : NULL;
3870
0
  ssl_data = rbio ? (coap_ssl_data *)BIO_get_data(rbio) : NULL;
3871
0
  if (!ssl_data) {
3872
0
    errno = ENOTCONN;
3873
0
    return -1;
3874
0
  }
3875
3876
0
  if (ssl_data->pdu_len) {
3877
0
    coap_log_err("** %s: Previous data not read %u bytes\n",
3878
0
                 coap_session_str(session), ssl_data->pdu_len);
3879
0
  }
3880
0
  ssl_data->pdu = data;
3881
0
  ssl_data->pdu_len = (unsigned)data_len;
3882
3883
0
  session->dtls_event = -1;
3884
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3885
retry:
3886
#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
3887
0
  ERR_clear_error();
3888
0
  r = SSL_read(ssl, pdu, (int)sizeof(pdu));
3889
0
  if (r > 0) {
3890
0
    coap_log_debug("*  %s: dtls:  recv %4d bytes\n",
3891
0
                   coap_session_str(session), r);
3892
0
    coap_dtls_receive_done(ssl_data, r);
3893
    /* May close session->tls, so ssl_data is no longer used */
3894
0
    return coap_handle_dgram(session->context, session, pdu, (size_t)r);
3895
0
  } else {
3896
0
    int err = SSL_get_error(ssl, r);
3897
0
    if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
3898
0
      if (in_init && SSL_is_init_finished(ssl)) {
3899
        /* Event and establish may close session->tls */
3900
0
        coap_dtls_receive_done(ssl_data, 0);
3901
0
        ssl_data = NULL;
3902
0
        coap_dtls_log(COAP_LOG_INFO, "*  %s: Using cipher: %s\n",
3903
0
                      coap_session_str(session), SSL_get_cipher_name(ssl));
3904
0
        coap_handle_event_lkd(session->context, COAP_EVENT_DTLS_CONNECTED, session);
3905
0
        session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
3906
0
      }
3907
0
      r = 0;
3908
0
    } else {
3909
0
      if (err == SSL_ERROR_ZERO_RETURN)        /* Got a close notify alert from the remote side */
3910
0
        session->dtls_event = COAP_EVENT_DTLS_CLOSED;
3911
0
      else if (err == SSL_ERROR_SSL) {
3912
0
        unsigned long e = ERR_get_error();
3913
3914
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3915
#include <openssl/proverr.h>
3916
        if (ERR_GET_REASON(e) == PROV_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES && !retry) {
3917
          /* Loading trust store - first access causes a directory read error */
3918
          retry = 1;
3919
          goto retry;
3920
        }
3921
#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
3922
0
        coap_log_info("***%s: coap_dtls_receive: cannot recv PDU: %d: %s\n",
3923
0
                      coap_session_str(session),
3924
0
                      ERR_GET_REASON(e), ERR_reason_error_string(e));
3925
0
        session->dtls_event = COAP_EVENT_DTLS_ERROR;
3926
0
      } else {
3927
0
        coap_log_info("***%s: coap_dtls_receive: cannot send PDU %d\n",
3928
0
                      coap_session_str(session), err);
3929
0
      }
3930
0
      r = -1;
3931
0
    }
3932
0
    if (session->dtls_event >= 0) {
3933
0
      coap_handle_event_lkd(session->context, session->dtls_event, session);
3934
0
      if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
3935
0
          session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
3936
        /* Cause disconnect on a read */
3937
0
        coap_session_disconnected_lkd(session, COAP_NACK_TLS_FAILED);
3938
0
        ssl_data = NULL;
3939
0
        r = -1;
3940
0
      }
3941
0
    }
3942
0
  }
3943
3944
0
  if (ssl_data)
3945
0
    coap_dtls_receive_done(ssl_data, r);
3946
0
  return r;
3947
0
}
3948
3949
unsigned int
3950
0
coap_dtls_get_overhead(coap_session_t *session) {
3951
0
  unsigned int overhead = 37;
3952
0
  const SSL_CIPHER *s_ciph = NULL;
3953
0
  if (session->tls != NULL)
3954
0
    s_ciph = SSL_get_current_cipher(session->tls);
3955
0
  if (s_ciph) {
3956
0
    unsigned int ivlen, maclen, blocksize = 1, pad = 0;
3957
3958
0
    const EVP_CIPHER *e_ciph;
3959
0
    const EVP_MD *e_md;
3960
0
    char cipher[128];
3961
3962
0
    e_ciph = EVP_get_cipherbynid(SSL_CIPHER_get_cipher_nid(s_ciph));
3963
3964
0
    switch (EVP_CIPHER_mode(e_ciph)) {
3965
0
    case EVP_CIPH_GCM_MODE:
3966
0
      ivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN;
3967
0
      maclen = EVP_GCM_TLS_TAG_LEN;
3968
0
      break;
3969
3970
0
    case EVP_CIPH_CCM_MODE:
3971
0
      ivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN;
3972
0
      SSL_CIPHER_description(s_ciph, cipher, sizeof(cipher));
3973
0
      if (strstr(cipher, "CCM8"))
3974
0
        maclen = 8;
3975
0
      else
3976
0
        maclen = 16;
3977
0
      break;
3978
3979
0
    case EVP_CIPH_CBC_MODE:
3980
0
      e_md = EVP_get_digestbynid(SSL_CIPHER_get_digest_nid(s_ciph));
3981
0
      blocksize = EVP_CIPHER_block_size(e_ciph);
3982
0
      ivlen = EVP_CIPHER_iv_length(e_ciph);
3983
0
      pad = 1;
3984
0
      maclen = EVP_MD_size(e_md);
3985
0
      break;
3986
3987
0
    case EVP_CIPH_STREAM_CIPHER:
3988
      /* Seen with PSK-CHACHA20-POLY1305 */
3989
0
      ivlen = 8;
3990
0
      maclen = 8;
3991
0
      break;
3992
3993
0
    default:
3994
0
      SSL_CIPHER_description(s_ciph, cipher, sizeof(cipher));
3995
0
      coap_log_warn("Unknown overhead for DTLS with cipher %s\n",
3996
0
                    cipher);
3997
0
      ivlen = 8;
3998
0
      maclen = 16;
3999
0
      break;
4000
0
    }
4001
0
    overhead = DTLS1_RT_HEADER_LENGTH + ivlen + maclen + blocksize - 1 + pad;
4002
0
  }
4003
0
  return overhead;
4004
0
}
4005
4006
#if !COAP_DISABLE_TCP
4007
#if COAP_CLIENT_SUPPORT
4008
void *
4009
0
coap_tls_new_client_session(coap_session_t *session) {
4010
0
  BIO *bio = NULL;
4011
0
  SSL *ssl = NULL;
4012
0
  int r;
4013
0
  coap_openssl_context_t *context = ((coap_openssl_context_t *)session->context->dtls_context);
4014
0
  coap_tls_context_t *tls = &context->tls;
4015
4016
0
  ssl = SSL_new(tls->ctx);
4017
0
  if (!ssl)
4018
0
    goto error;
4019
0
  bio = BIO_new(tls->meth);
4020
0
  if (!bio)
4021
0
    goto error;
4022
0
  BIO_set_data(bio, session);
4023
0
  SSL_set_bio(ssl, bio, bio);
4024
0
  SSL_set_app_data(ssl, session);
4025
4026
0
  if (!setup_client_ssl_session(session, ssl))
4027
0
    return 0;
4028
4029
0
  r = SSL_connect(ssl);
4030
0
  if (r == -1) {
4031
0
    int ret = SSL_get_error(ssl, r);
4032
0
    if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE)
4033
0
      r = 0;
4034
0
    if (ret == SSL_ERROR_WANT_READ)
4035
0
      session->sock.flags |= COAP_SOCKET_WANT_READ;
4036
0
    if (ret == SSL_ERROR_WANT_WRITE) {
4037
0
      session->sock.flags |= COAP_SOCKET_WANT_WRITE;
4038
0
#ifdef COAP_EPOLL_SUPPORT
4039
0
      coap_epoll_ctl_mod(&session->sock,
4040
0
                         EPOLLOUT |
4041
0
                         ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
4042
0
                          EPOLLIN : 0),
4043
0
                         __func__);
4044
0
#endif /* COAP_EPOLL_SUPPORT */
4045
0
    }
4046
0
  }
4047
4048
0
  if (r == 0)
4049
0
    goto error;
4050
4051
0
  session->tls = ssl;
4052
0
  if (SSL_is_init_finished(ssl)) {
4053
0
    coap_handle_event_lkd(session->context, COAP_EVENT_DTLS_CONNECTED, session);
4054
0
    session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4055
0
  }
4056
4057
0
  return ssl;
4058
4059
0
error:
4060
0
  if (ssl)
4061
0
    SSL_free(ssl);
4062
0
  return NULL;
4063
0
}
4064
#endif /* COAP_CLIENT_SUPPORT */
4065
4066
#if COAP_SERVER_SUPPORT
4067
void *
4068
0
coap_tls_new_server_session(coap_session_t *session) {
4069
0
  BIO *bio = NULL;
4070
0
  SSL *ssl = NULL;
4071
0
  coap_tls_context_t *tls = &((coap_openssl_context_t *)session->context->dtls_context)->tls;
4072
0
  int r;
4073
0
  const coap_bin_const_t *psk_hint;
4074
4075
0
  ssl = SSL_new(tls->ctx);
4076
0
  if (!ssl)
4077
0
    goto error;
4078
0
  bio = BIO_new(tls->meth);
4079
0
  if (!bio)
4080
0
    goto error;
4081
0
  BIO_set_data(bio, session);
4082
0
  SSL_set_bio(ssl, bio, bio);
4083
0
  SSL_set_app_data(ssl, session);
4084
4085
0
  psk_hint = coap_get_session_server_psk_hint(session);
4086
0
  if (psk_hint != NULL && psk_hint->length) {
4087
0
    char *hint = OPENSSL_malloc(psk_hint->length + 1);
4088
4089
0
    if (hint) {
4090
0
      memcpy(hint, psk_hint->s, psk_hint->length);
4091
0
      hint[psk_hint->length] = '\000';
4092
0
      SSL_use_psk_identity_hint(ssl, hint);
4093
0
      OPENSSL_free(hint);
4094
0
    } else {
4095
0
      coap_log_warn("hint malloc failure\n");
4096
0
    }
4097
0
  }
4098
4099
0
  r = SSL_accept(ssl);
4100
0
  if (r == -1) {
4101
0
    int err = SSL_get_error(ssl, r);
4102
0
    if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
4103
0
      r = 0;
4104
0
    if (err == SSL_ERROR_WANT_READ)
4105
0
      session->sock.flags |= COAP_SOCKET_WANT_READ;
4106
0
    if (err == SSL_ERROR_WANT_WRITE) {
4107
0
      session->sock.flags |= COAP_SOCKET_WANT_WRITE;
4108
0
#ifdef COAP_EPOLL_SUPPORT
4109
0
      coap_epoll_ctl_mod(&session->sock,
4110
0
                         EPOLLOUT |
4111
0
                         ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
4112
0
                          EPOLLIN : 0),
4113
0
                         __func__);
4114
0
#endif /* COAP_EPOLL_SUPPORT */
4115
0
    }
4116
0
  }
4117
4118
0
  if (r == 0)
4119
0
    goto error;
4120
4121
0
  session->tls = ssl;
4122
0
  if (SSL_is_init_finished(ssl)) {
4123
0
    coap_handle_event_lkd(session->context, COAP_EVENT_DTLS_CONNECTED, session);
4124
0
    session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4125
0
  }
4126
4127
#if COAP_DTLS_RETRANSMIT_MS != 1000
4128
#if OPENSSL_VERSION_NUMBER >= 0x10101000L
4129
  if (session->proto == COAP_PROTO_DTLS) {
4130
    DTLS_set_timer_cb(ssl, timer_cb);
4131
  }
4132
#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
4133
#endif /* COAP_DTLS_RETRANSMIT_MS != 1000 */
4134
4135
0
  return ssl;
4136
4137
0
error:
4138
0
  if (ssl)
4139
0
    SSL_free(ssl);
4140
0
  return NULL;
4141
0
}
4142
#endif /* COAP_SERVER_SUPPORT */
4143
4144
void
4145
0
coap_tls_free_session(coap_session_t *session) {
4146
0
  SSL *ssl = (SSL *)session->tls;
4147
0
  if (ssl) {
4148
0
    if (!SSL_in_init(ssl) && !(SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN)) {
4149
0
      int r = SSL_shutdown(ssl);
4150
0
      if (r == 0)
4151
0
        SSL_shutdown(ssl);
4152
0
    }
4153
0
    SSL_free(ssl);
4154
0
    session->tls = NULL;
4155
0
    if (session->context)
4156
0
      coap_handle_event_lkd(session->context, COAP_EVENT_DTLS_CLOSED, session);
4157
0
  }
4158
0
}
4159
4160
/*
4161
 * strm
4162
 * return +ve Number of bytes written.
4163
 *         -1 Error (error in errno).
4164
 */
4165
ssize_t
4166
0
coap_tls_write(coap_session_t *session, const uint8_t *data, size_t data_len) {
4167
0
  SSL *ssl = (SSL *)session->tls;
4168
0
  int r, in_init;
4169
4170
0
  if (ssl == NULL)
4171
0
    return -1;
4172
4173
0
  in_init = !SSL_is_init_finished(ssl);
4174
0
  session->dtls_event = -1;
4175
0
  ERR_clear_error();
4176
0
  r = SSL_write(ssl, data, (int)data_len);
4177
4178
0
  if (r <= 0) {
4179
0
    int err = SSL_get_error(ssl, r);
4180
0
    if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
4181
0
      if (in_init && SSL_is_init_finished(ssl)) {
4182
0
        coap_dtls_log(COAP_LOG_INFO, "*  %s: Using cipher: %s\n",
4183
0
                      coap_session_str(session), SSL_get_cipher_name(ssl));
4184
0
        coap_handle_event_lkd(session->context, COAP_EVENT_DTLS_CONNECTED, session);
4185
0
        session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4186
0
      }
4187
0
      if (err == SSL_ERROR_WANT_READ)
4188
0
        session->sock.flags |= COAP_SOCKET_WANT_READ;
4189
0
      else if (err == SSL_ERROR_WANT_WRITE) {
4190
0
        session->sock.flags |= COAP_SOCKET_WANT_WRITE;
4191
0
#ifdef COAP_EPOLL_SUPPORT
4192
0
        coap_epoll_ctl_mod(&session->sock,
4193
0
                           EPOLLOUT |
4194
0
                           ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
4195
0
                            EPOLLIN : 0),
4196
0
                           __func__);
4197
0
#endif /* COAP_EPOLL_SUPPORT */
4198
0
      }
4199
0
      r = 0;
4200
0
    } else {
4201
0
      if (err == SSL_ERROR_ZERO_RETURN)
4202
0
        session->dtls_event = COAP_EVENT_DTLS_CLOSED;
4203
0
      else if (err == SSL_ERROR_SSL) {
4204
0
        unsigned long e = ERR_get_error();
4205
4206
0
        coap_log_info("***%s: coap_tls_write: cannot send PDU: %d: %s\n",
4207
0
                      coap_session_str(session),
4208
0
                      ERR_GET_REASON(e), ERR_reason_error_string(e));
4209
0
        session->dtls_event = COAP_EVENT_DTLS_ERROR;
4210
0
      } else {
4211
0
        coap_log_info("***%s: coap_tls_send: cannot send PDU: %d\n",
4212
0
                      coap_session_str(session), err);
4213
0
      }
4214
0
      r = -1;
4215
0
    }
4216
0
  } else if (in_init && SSL_is_init_finished(ssl)) {
4217
0
    coap_dtls_log(COAP_LOG_INFO, "*  %s: Using cipher: %s\n",
4218
0
                  coap_session_str(session), SSL_get_cipher_name(ssl));
4219
0
    coap_handle_event_lkd(session->context, COAP_EVENT_DTLS_CONNECTED, session);
4220
0
    session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4221
0
  }
4222
4223
0
  if (session->dtls_event >= 0) {
4224
0
    coap_handle_event_lkd(session->context, session->dtls_event, session);
4225
0
    if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
4226
0
        session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
4227
0
      r = -1;
4228
0
    }
4229
0
  }
4230
4231
0
  if (r >= 0) {
4232
0
    if (r == (ssize_t)data_len)
4233
0
      coap_log_debug("*  %s: tls:   sent %4d bytes\n",
4234
0
                     coap_session_str(session), r);
4235
0
    else
4236
0
      coap_log_debug("*  %s: tls:   sent %4d of %4" PRIdS " bytes\n",
4237
0
                     coap_session_str(session), r, data_len);
4238
0
  }
4239
0
  return r;
4240
0
}
4241
4242
/*
4243
 * strm
4244
 * return >=0 Number of bytes read.
4245
 *         -1 Error (error in errno).
4246
 */
4247
ssize_t
4248
0
coap_tls_read(coap_session_t *session, uint8_t *data, size_t data_len) {
4249
0
  SSL *ssl = (SSL *)session->tls;
4250
0
  int r, in_init;
4251
4252
0
  if (ssl == NULL) {
4253
0
    errno = ENOTCONN;
4254
0
    return -1;
4255
0
  }
4256
4257
0
  in_init = !SSL_is_init_finished(ssl);
4258
0
  session->dtls_event = -1;
4259
0
  ERR_clear_error();
4260
0
  r = SSL_read(ssl, data, (int)data_len);
4261
0
  if (r <= 0) {
4262
0
    int err = SSL_get_error(ssl, r);
4263
0
    if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
4264
0
      if (in_init && SSL_is_init_finished(ssl)) {
4265
0
        coap_dtls_log(COAP_LOG_INFO, "*  %s: Using cipher: %s\n",
4266
0
                      coap_session_str(session), SSL_get_cipher_name(ssl));
4267
0
        coap_handle_event_lkd(session->context, COAP_EVENT_DTLS_CONNECTED, session);
4268
0
        session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4269
0
      }
4270
0
      if (err == SSL_ERROR_WANT_READ)
4271
0
        session->sock.flags |= COAP_SOCKET_WANT_READ;
4272
0
      if (err == SSL_ERROR_WANT_WRITE) {
4273
0
        session->sock.flags |= COAP_SOCKET_WANT_WRITE;
4274
0
#ifdef COAP_EPOLL_SUPPORT
4275
0
        coap_epoll_ctl_mod(&session->sock,
4276
0
                           EPOLLOUT |
4277
0
                           ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
4278
0
                            EPOLLIN : 0),
4279
0
                           __func__);
4280
0
#endif /* COAP_EPOLL_SUPPORT */
4281
0
      }
4282
0
      r = 0;
4283
0
    } else {
4284
0
      if (err == SSL_ERROR_ZERO_RETURN)        /* Got a close notify alert from the remote side */
4285
0
        session->dtls_event = COAP_EVENT_DTLS_CLOSED;
4286
0
      else if (err == SSL_ERROR_SSL) {
4287
0
        unsigned long e = ERR_get_error();
4288
4289
0
        coap_log_info("***%s: coap_tls_read: cannot recv PDU: %d: %s\n",
4290
0
                      coap_session_str(session),
4291
0
                      ERR_GET_REASON(e), ERR_reason_error_string(e));
4292
0
        session->dtls_event = COAP_EVENT_DTLS_ERROR;
4293
0
      } else {
4294
0
        coap_log_info("***%s: coap_tls_read: cannot read PDU %d\n",
4295
0
                      coap_session_str(session), err);
4296
0
      }
4297
0
      r = -1;
4298
0
    }
4299
0
  } else if (in_init && SSL_is_init_finished(ssl)) {
4300
0
    coap_dtls_log(COAP_LOG_INFO, "*  %s: Using cipher: %s\n",
4301
0
                  coap_session_str(session), SSL_get_cipher_name(ssl));
4302
0
    coap_handle_event_lkd(session->context, COAP_EVENT_DTLS_CONNECTED, session);
4303
0
    session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4304
0
  }
4305
4306
0
  if (session->dtls_event >= 0) {
4307
0
    coap_handle_event_lkd(session->context, session->dtls_event, session);
4308
0
    if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
4309
0
        session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
4310
      /* Cause disconnect on a read */
4311
0
      coap_session_disconnected_lkd(session, COAP_NACK_TLS_FAILED);
4312
0
      r = -1;
4313
0
    }
4314
0
  }
4315
4316
0
  if (r > 0) {
4317
0
    coap_log_debug("*  %s: tls:   recv %4d bytes\n",
4318
0
                   coap_session_str(session), r);
4319
0
  }
4320
0
  return r;
4321
0
}
4322
#endif /* !COAP_DISABLE_TCP */
4323
4324
#if COAP_SERVER_SUPPORT
4325
coap_digest_ctx_t *
4326
0
coap_digest_setup(void) {
4327
0
  EVP_MD_CTX *digest_ctx = EVP_MD_CTX_new();
4328
4329
0
  if (digest_ctx) {
4330
0
    EVP_DigestInit_ex(digest_ctx, EVP_sha256(), NULL);
4331
0
  }
4332
0
  return digest_ctx;
4333
0
}
4334
4335
void
4336
0
coap_digest_free(coap_digest_ctx_t *digest_ctx) {
4337
0
  if (digest_ctx)
4338
0
    EVP_MD_CTX_free(digest_ctx);
4339
0
}
4340
4341
int
4342
coap_digest_update(coap_digest_ctx_t *digest_ctx,
4343
                   const uint8_t *data,
4344
0
                   size_t data_len) {
4345
0
  return EVP_DigestUpdate(digest_ctx, data, data_len);
4346
0
}
4347
4348
int
4349
coap_digest_final(coap_digest_ctx_t *digest_ctx,
4350
0
                  coap_digest_t *digest_buffer) {
4351
0
  unsigned int size = sizeof(coap_digest_t);
4352
0
  int ret = EVP_DigestFinal_ex(digest_ctx, (uint8_t *)digest_buffer, &size);
4353
4354
0
  coap_digest_free(digest_ctx);
4355
0
  return ret;
4356
0
}
4357
#endif /* COAP_SERVER_SUPPORT */
4358
4359
#if COAP_WS_SUPPORT || COAP_OSCORE_SUPPORT
4360
static void
4361
0
coap_crypto_output_errors(const char *prefix) {
4362
#if COAP_MAX_LOGGING_LEVEL < _COAP_LOG_WARN
4363
  (void)prefix;
4364
#else /* COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_WARN */
4365
0
  unsigned long e;
4366
4367
0
  while ((e = ERR_get_error()))
4368
0
    coap_log_warn("%s: %s%s\n",
4369
0
                  prefix,
4370
0
                  ERR_reason_error_string(e),
4371
0
                  ssl_function_definition(e));
4372
0
#endif /* COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_WARN */
4373
0
}
4374
#endif /* COAP_WS_SUPPORT || COAP_OSCORE_SUPPORT */
4375
4376
#if COAP_WS_SUPPORT
4377
/*
4378
 * The struct hash_algs and the function get_hash_alg() are used to
4379
 * determine which hash type to use for creating the required hash object.
4380
 */
4381
static struct hash_algs {
4382
  cose_alg_t alg;
4383
  const EVP_MD *(*get_hash)(void);
4384
  size_t length; /* in bytes */
4385
} hashes[] = {
4386
  {COSE_ALGORITHM_SHA_1, EVP_sha1, 20},
4387
  {COSE_ALGORITHM_SHA_256_64, EVP_sha256, 8},
4388
  {COSE_ALGORITHM_SHA_256_256, EVP_sha256, 32},
4389
  {COSE_ALGORITHM_SHA_512, EVP_sha512, 64},
4390
};
4391
4392
static const EVP_MD *
4393
0
get_hash_alg(cose_alg_t alg, size_t *length) {
4394
0
  size_t idx;
4395
4396
0
  for (idx = 0; idx < sizeof(hashes) / sizeof(struct hash_algs); idx++) {
4397
0
    if (hashes[idx].alg == alg) {
4398
0
      *length = hashes[idx].length;
4399
0
      return hashes[idx].get_hash();
4400
0
    }
4401
0
  }
4402
0
  coap_log_debug("get_hash_alg: COSE hash %d not supported\n", alg);
4403
0
  return NULL;
4404
0
}
4405
4406
int
4407
coap_crypto_hash(cose_alg_t alg,
4408
                 const coap_bin_const_t *data,
4409
0
                 coap_bin_const_t **hash) {
4410
0
  unsigned int length;
4411
0
  const EVP_MD *evp_md;
4412
0
  EVP_MD_CTX *evp_ctx = NULL;
4413
0
  coap_binary_t *dummy = NULL;
4414
0
  size_t hash_length;
4415
4416
0
  if ((evp_md = get_hash_alg(alg, &hash_length)) == NULL) {
4417
0
    coap_log_debug("coap_crypto_hash: algorithm %d not supported\n", alg);
4418
0
    return 0;
4419
0
  }
4420
0
  evp_ctx = EVP_MD_CTX_new();
4421
0
  if (evp_ctx == NULL)
4422
0
    goto error;
4423
0
  if (EVP_DigestInit_ex(evp_ctx, evp_md, NULL) == 0)
4424
0
    goto error;
4425
0
  ;
4426
0
  if (EVP_DigestUpdate(evp_ctx, data->s, data->length) == 0)
4427
0
    goto error;
4428
0
  ;
4429
0
  dummy = coap_new_binary(EVP_MAX_MD_SIZE);
4430
0
  if (dummy == NULL)
4431
0
    goto error;
4432
0
  if (EVP_DigestFinal_ex(evp_ctx, dummy->s, &length) == 0)
4433
0
    goto error;
4434
0
  dummy->length = length;
4435
0
  if (hash_length < dummy->length)
4436
0
    dummy->length = hash_length;
4437
0
  *hash = (coap_bin_const_t *)(dummy);
4438
0
  EVP_MD_CTX_free(evp_ctx);
4439
0
  return 1;
4440
4441
0
error:
4442
0
  coap_crypto_output_errors("coap_crypto_hash");
4443
0
  coap_delete_binary(dummy);
4444
0
  if (evp_ctx)
4445
0
    EVP_MD_CTX_free(evp_ctx);
4446
0
  return 0;
4447
0
}
4448
#endif /* COAP_WS_SUPPORT */
4449
4450
#if COAP_OSCORE_SUPPORT
4451
int
4452
0
coap_oscore_is_supported(void) {
4453
0
  return 1;
4454
0
}
4455
4456
#include <openssl/evp.h>
4457
#include <openssl/hmac.h>
4458
4459
/*
4460
 * The struct cipher_algs and the function get_cipher_alg() are used to
4461
 * determine which cipher type to use for creating the required cipher
4462
 * suite object.
4463
 */
4464
static struct cipher_algs {
4465
  cose_alg_t alg;
4466
  const EVP_CIPHER *(*get_cipher)(void);
4467
} ciphers[] = {{COSE_ALGORITHM_AES_CCM_16_64_128, EVP_aes_128_ccm},
4468
  {COSE_ALGORITHM_AES_CCM_16_64_256, EVP_aes_256_ccm}
4469
};
4470
4471
static const EVP_CIPHER *
4472
0
get_cipher_alg(cose_alg_t alg) {
4473
0
  size_t idx;
4474
4475
0
  for (idx = 0; idx < sizeof(ciphers) / sizeof(struct cipher_algs); idx++) {
4476
0
    if (ciphers[idx].alg == alg)
4477
0
      return ciphers[idx].get_cipher();
4478
0
  }
4479
0
  coap_log_debug("get_cipher_alg: COSE cipher %d not supported\n", alg);
4480
0
  return NULL;
4481
0
}
4482
4483
/*
4484
 * The struct hmac_algs and the function get_hmac_alg() are used to
4485
 * determine which hmac type to use for creating the required hmac
4486
 * suite object.
4487
 */
4488
static struct hmac_algs {
4489
  cose_hmac_alg_t hmac_alg;
4490
  const EVP_MD *(*get_hmac)(void);
4491
} hmacs[] = {
4492
  {COSE_HMAC_ALG_HMAC256_256, EVP_sha256},
4493
  {COSE_HMAC_ALG_HMAC384_384, EVP_sha384},
4494
  {COSE_HMAC_ALG_HMAC512_512, EVP_sha512},
4495
};
4496
4497
static const EVP_MD *
4498
0
get_hmac_alg(cose_hmac_alg_t hmac_alg) {
4499
0
  size_t idx;
4500
4501
0
  for (idx = 0; idx < sizeof(hmacs) / sizeof(struct hmac_algs); idx++) {
4502
0
    if (hmacs[idx].hmac_alg == hmac_alg)
4503
0
      return hmacs[idx].get_hmac();
4504
0
  }
4505
0
  coap_log_debug("get_hmac_alg: COSE HMAC %d not supported\n", hmac_alg);
4506
0
  return NULL;
4507
0
}
4508
4509
int
4510
0
coap_crypto_check_cipher_alg(cose_alg_t alg) {
4511
0
  return get_cipher_alg(alg) != NULL;
4512
0
}
4513
4514
int
4515
0
coap_crypto_check_hkdf_alg(cose_hkdf_alg_t hkdf_alg) {
4516
0
  cose_hmac_alg_t hmac_alg;
4517
4518
0
  if (!cose_get_hmac_alg_for_hkdf(hkdf_alg, &hmac_alg))
4519
0
    return 0;
4520
0
  return get_hmac_alg(hmac_alg) != NULL;
4521
0
}
4522
4523
#define C(Func)                                                                \
4524
0
  if (1 != (Func)) {                                                           \
4525
0
    goto error;                                                                \
4526
0
  }
4527
4528
int
4529
coap_crypto_aead_encrypt(const coap_crypto_param_t *params,
4530
                         coap_bin_const_t *data,
4531
                         coap_bin_const_t *aad,
4532
                         uint8_t *result,
4533
0
                         size_t *max_result_len) {
4534
0
  const EVP_CIPHER *cipher;
4535
0
  const coap_crypto_aes_ccm_t *ccm;
4536
0
  int tmp;
4537
0
  int result_len = (int)(*max_result_len & INT_MAX);
4538
0
  EVP_CIPHER_CTX *ctx;
4539
4540
0
  if (data == NULL)
4541
0
    return 0;
4542
4543
0
  assert(params != NULL);
4544
0
  if (!params || ((cipher = get_cipher_alg(params->alg)) == NULL)) {
4545
0
    return 0;
4546
0
  }
4547
4548
  /* TODO: set evp_md depending on params->alg */
4549
0
  ccm = &params->params.aes;
4550
4551
0
  ctx = EVP_CIPHER_CTX_new();
4552
0
  if (!ctx)
4553
0
    return 0;
4554
4555
  /* EVP_CIPHER_CTX_init(ctx); */
4556
0
  C(EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL));
4557
0
  C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_L, (int)ccm->l, NULL));
4558
0
  C(EVP_CIPHER_CTX_ctrl(ctx,
4559
0
                        EVP_CTRL_AEAD_SET_IVLEN,
4560
0
                        (int)(15 - ccm->l),
4561
0
                        NULL));
4562
0
  C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, (int)ccm->tag_len, NULL));
4563
0
  C(EVP_EncryptInit_ex(ctx, NULL, NULL, ccm->key.s, ccm->nonce));
4564
  /* C(EVP_CIPHER_CTX_set_padding(ctx, 0)); */
4565
4566
0
  C(EVP_EncryptUpdate(ctx, NULL, &result_len, NULL, (int)data->length));
4567
0
  if (aad && aad->s && (aad->length > 0)) {
4568
0
    C(EVP_EncryptUpdate(ctx, NULL, &result_len, aad->s, (int)aad->length));
4569
0
  }
4570
0
  C(EVP_EncryptUpdate(ctx, result, &result_len, data->s, (int)data->length));
4571
  /* C(EVP_EncryptFinal_ex(ctx, result + result_len, &tmp)); */
4572
0
  tmp = result_len;
4573
0
  C(EVP_EncryptFinal_ex(ctx, result + result_len, &tmp));
4574
0
  result_len += tmp;
4575
4576
  /* retrieve the tag */
4577
0
  C(EVP_CIPHER_CTX_ctrl(ctx,
4578
0
                        EVP_CTRL_CCM_GET_TAG,
4579
0
                        (int)ccm->tag_len,
4580
0
                        result + result_len));
4581
4582
0
  *max_result_len = result_len + ccm->tag_len;
4583
0
  EVP_CIPHER_CTX_free(ctx);
4584
0
  return 1;
4585
4586
0
error:
4587
0
  coap_crypto_output_errors("coap_crypto_aead_encrypt");
4588
0
  return 0;
4589
0
}
4590
4591
int
4592
coap_crypto_aead_decrypt(const coap_crypto_param_t *params,
4593
                         coap_bin_const_t *data,
4594
                         coap_bin_const_t *aad,
4595
                         uint8_t *result,
4596
0
                         size_t *max_result_len) {
4597
0
  const EVP_CIPHER *cipher;
4598
0
  const coap_crypto_aes_ccm_t *ccm;
4599
0
  int tmp;
4600
0
  int len;
4601
0
  const uint8_t *tag;
4602
0
  uint8_t *rwtag;
4603
0
  EVP_CIPHER_CTX *ctx;
4604
4605
0
  if (data == NULL)
4606
0
    return 0;
4607
4608
0
  assert(params != NULL);
4609
0
  if (!params || ((cipher = get_cipher_alg(params->alg)) == NULL)) {
4610
0
    return 0;
4611
0
  }
4612
4613
0
  ccm = &params->params.aes;
4614
4615
0
  if (data->length < ccm->tag_len) {
4616
0
    return 0;
4617
0
  } else {
4618
0
    tag = data->s + data->length - ccm->tag_len;
4619
0
    data->length -= ccm->tag_len;
4620
    /* Kludge to stop compiler warning */
4621
0
    memcpy(&rwtag, &tag, sizeof(rwtag));
4622
0
  }
4623
4624
0
  ctx = EVP_CIPHER_CTX_new();
4625
0
  if (!ctx)
4626
0
    return 0;
4627
4628
0
  C(EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL));
4629
0
  C(EVP_CIPHER_CTX_ctrl(ctx,
4630
0
                        EVP_CTRL_AEAD_SET_IVLEN,
4631
0
                        (int)(15 - ccm->l),
4632
0
                        NULL));
4633
0
  C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, (int)ccm->tag_len, rwtag));
4634
0
  C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_L, (int)ccm->l, NULL));
4635
  /* C(EVP_CIPHER_CTX_set_padding(ctx, 0)); */
4636
0
  C(EVP_DecryptInit_ex(ctx, NULL, NULL, ccm->key.s, ccm->nonce));
4637
4638
0
  C(EVP_DecryptUpdate(ctx, NULL, &len, NULL, (int)data->length));
4639
0
  if (aad && aad->s && (aad->length > 0)) {
4640
0
    C(EVP_DecryptUpdate(ctx, NULL, &len, aad->s, (int)aad->length));
4641
0
  }
4642
0
  tmp = EVP_DecryptUpdate(ctx, result, &len, data->s, (int)data->length);
4643
0
  EVP_CIPHER_CTX_free(ctx);
4644
0
  if (tmp <= 0) {
4645
0
    *max_result_len = 0;
4646
0
    return 0;
4647
0
  }
4648
0
  *max_result_len = len;
4649
0
  return 1;
4650
4651
0
error:
4652
0
  coap_crypto_output_errors("coap_crypto_aead_decrypt");
4653
0
  return 0;
4654
0
}
4655
4656
int
4657
coap_crypto_hmac(cose_hmac_alg_t hmac_alg,
4658
                 coap_bin_const_t *key,
4659
                 coap_bin_const_t *data,
4660
0
                 coap_bin_const_t **hmac) {
4661
0
  unsigned int result_len;
4662
0
  const EVP_MD *evp_md;
4663
0
  coap_binary_t *dummy = NULL;
4664
4665
0
  assert(key);
4666
0
  assert(data);
4667
0
  assert(hmac);
4668
4669
0
  if ((evp_md = get_hmac_alg(hmac_alg)) == 0) {
4670
0
    coap_log_debug("coap_crypto_hmac: algorithm %d not supported\n", hmac_alg);
4671
0
    return 0;
4672
0
  }
4673
0
  dummy = coap_new_binary(EVP_MAX_MD_SIZE);
4674
0
  if (dummy == NULL)
4675
0
    return 0;
4676
0
  result_len = (unsigned int)dummy->length;
4677
0
  if (HMAC(evp_md,
4678
0
           key->s,
4679
0
           (int)key->length,
4680
0
           data->s,
4681
0
           (int)data->length,
4682
0
           dummy->s,
4683
0
           &result_len)) {
4684
0
    dummy->length = result_len;
4685
0
    *hmac = (coap_bin_const_t *)dummy;
4686
0
    return 1;
4687
0
  }
4688
4689
0
  coap_delete_binary(dummy);
4690
0
  coap_crypto_output_errors("coap_crypto_hmac");
4691
0
  return 0;
4692
0
}
4693
4694
#endif /* COAP_OSCORE_SUPPORT */
4695
4696
#else /* ! COAP_WITH_LIBOPENSSL */
4697
4698
#ifdef __clang__
4699
/* Make compilers happy that do not like empty modules. As this function is
4700
 * never used, we ignore -Wunused-function at the end of compiling this file
4701
 */
4702
#pragma GCC diagnostic ignored "-Wunused-function"
4703
#endif
4704
static inline void
4705
dummy(void) {
4706
}
4707
4708
#endif /* ! COAP_WITH_LIBOPENSSL */