20#if COAP_WITH_LIBOPENSSL
75#include <openssl/ssl.h>
76#if OPENSSL_VERSION_NUMBER < 0x40000000L
77#include <openssl/engine.h>
79#include <openssl/err.h>
80#include <openssl/rand.h>
81#include <openssl/hmac.h>
82#include <openssl/x509v3.h>
84#if OPENSSL_VERSION_NUMBER >= 0x30000000L
87#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
90#if !defined(__MINGW32__)
91#pragma warning(disable : 4996)
96#ifdef COAP_EPOLL_SUPPORT
97# include <sys/epoll.h>
100#if OPENSSL_VERSION_NUMBER < 0x10100000L
101#error Must be compiled against OpenSSL 1.1.0 or later
105#define strcasecmp _stricmp
106#define strncasecmp _strnicmp
110#ifndef TLSEXT_TYPE_client_certificate_type
111#define TLSEXT_TYPE_client_certificate_type 19
113#ifndef TLSEXT_TYPE_server_certificate_type
114#define TLSEXT_TYPE_server_certificate_type 20
117#ifndef COAP_OPENSSL_CIPHERS
118#if OPENSSL_VERSION_NUMBER >= 0x10101000L
119#define COAP_OPENSSL_CIPHERS "TLSv1.3:TLSv1.2:!NULL"
121#define COAP_OPENSSL_CIPHERS "TLSv1.2:!NULL"
125#ifndef COAP_OPENSSL_PSK_CIPHERS
126#define COAP_OPENSSL_PSK_CIPHERS "PSK:!NULL"
129#ifndef COAP_OPENSSL_PKCS11_ENGINE_ID
130#define COAP_OPENSSL_PKCS11_ENGINE_ID "pkcs11"
134typedef struct coap_dtls_context_t {
137 HMAC_CTX *cookie_hmac;
140} coap_dtls_context_t;
142typedef struct coap_tls_context_t {
150typedef struct sni_entry {
152#if OPENSSL_VERSION_NUMBER < 0x10101000L
159typedef struct psk_sni_entry {
161#if OPENSSL_VERSION_NUMBER < 0x10101000L
167typedef struct coap_openssl_context_t {
168 coap_dtls_context_t dtls;
170 coap_tls_context_t tls;
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;
180} coap_openssl_context_t;
182#if COAP_SERVER_SUPPORT
183#if OPENSSL_VERSION_NUMBER < 0x10101000L
184static int psk_tls_server_name_call_back(SSL *ssl,
int *sd,
void *arg);
186static int tls_client_hello_call_back(SSL *ssl,
int *al,
void *arg);
192 if (SSLeay() < 0x10100000L) {
193 coap_log_warn(
"OpenSSL version 1.1.0 or later is required\n");
196#if OPENSSL_VERSION_NUMBER >= 0x10101000L
204 if (SSLeay() < 0x10101000L) {
205 coap_log_warn(
"OpenSSL version 1.1.1 or later is required\n");
215 if (SSLeay() < 0x10100000L) {
216 coap_log_warn(
"OpenSSL version 1.1.0 or later is required\n");
219#if OPENSSL_VERSION_NUMBER >= 0x10101000L
220 if (SSLeay() < 0x10101000L) {
221 coap_log_warn(
"OpenSSL version 1.1.1 or later is required\n");
255#if OPENSSL_VERSION_NUMBER < 0x40000000L
280#if COAP_CLIENT_SUPPORT
298#if OPENSSL_VERSION_NUMBER < 0x40000000L
299static ENGINE *pkcs11_engine =
NULL;
300static ENGINE *defined_engine =
NULL;
305 SSL_load_error_strings();
307#if OPENSSL_VERSION_NUMBER < 0x40000000L
308 ENGINE_load_dynamic();
314#if OPENSSL_VERSION_NUMBER < 0x30000000L
317 ENGINE_finish(pkcs11_engine);
318 pkcs11_engine =
NULL;
320 if (defined_engine) {
322 ENGINE_finish(defined_engine);
323 defined_engine =
NULL;
325#elif OPENSSL_VERSION_NUMBER < 0x40000000L
326 pkcs11_engine =
NULL;
327 defined_engine =
NULL;
343 return c_session->
tls;
348#if OPENSSL_VERSION_NUMBER < 0x40000000L
350get_split_conf_entry(
const uint8_t **start,
size_t size,
const char *get_keyword,
352 const uint8_t *begin = *start;
355 const uint8_t *split;
361 kend = end = memchr(begin,
'\n', size);
367 if (end > begin && end[-1] ==
'\r')
370 if (begin[0] ==
'#' || (end - begin) == 0) {
372 size -= kend - begin + 1;
378 split = memchr(begin,
':', end - begin);
382 if ((
size_t)(split - begin) != strlen(get_keyword)) {
383 size -= kend - begin + 1;
387 if (memcmp(begin, get_keyword, split - begin)) {
388 size -= kend - begin + 1;
396 if ((end - begin) == 0)
399 split = memchr(begin,
':', end - begin);
411 if ((end - split) > 0) {
446 const uint8_t *start;
451 unsigned int defaults = 0;
452 int done_engine_id = 0;
453 int done_engine_init = 0;
459 end = start + conf_mem->
length;
461 if (defined_engine) {
462 coap_log_warn(
"coap_tls_engine_configure: Freeing off previous engine definition\n");
463 ENGINE_finish(defined_engine);
464 defined_engine =
NULL;
468 if (!get_split_conf_entry(&start, end - start,
"engine", &engine_id, &p2)) {
469 coap_log_warn(
"coap_tls_engine_configure: engine not defined\n");
472 defined_engine = ENGINE_by_id((
const char *)engine_id->
s);
473 if (!defined_engine) {
474 coap_log_warn(
"coap_tls_engine_configure: engine '%s' not known\n", engine_id->
s);
484 while (get_split_conf_entry(&start, end - start,
"pre-cmd", &p1, &p2)) {
485 if (!ENGINE_ctrl_cmd_string(defined_engine, (
const char *)p1->
s, p2 ? (
const char *)p2->
s :
NULL,
487 coap_log_warn(
"coap_tls_engine_configure: engine %s pre-cmd '%s:%s' failed\n",
488 (
const char *)engine_id->
s,
489 (
const char *)p1->
s, p2 ? (
const char *)p2->
s :
"(NULL)");
493 engine_id->
s, p1->
s, p2 ? (
const char *)p2->
s :
"(NULL)");
502 if (!ENGINE_init(defined_engine)) {
503 coap_log_warn(
"coap_tls_engine_configure: %s failed initialization\n", (
const char *)engine_id->
s);
506 done_engine_init = 1;
508 (
const char *)engine_id->
s);
513 while (get_split_conf_entry(&start, end - start,
"post-cmd", &p1, &p2)) {
514 if (!ENGINE_ctrl_cmd_string(defined_engine, (
const char *)p1->
s, p2 ? (
const char *)p2->
s :
NULL,
516 coap_log_warn(
"coap_tls_engine_configure: %s post-cmd '%s:%s' failed\n", (
const char *)engine_id->
s,
517 (
const char *)p1->
s, p2 ? (
const char *)p2->
s :
"(NULL)");
521 (
const char *)engine_id->
s,
522 (
const char *)p1->
s, p2 ? (
const char *)p2->
s :
"(NULL)");
530 if (!get_split_conf_entry(&start, end - start,
"enable-methods", &p1, &p2)) {
531 coap_log_warn(
"coap_tls_engine_configure: enable-methods not found\n");
534 defaults = strtoul((
const char *)p1->
s,
NULL, 0);
535 if (!ENGINE_set_default(defined_engine, defaults)) {
536 coap_log_warn(
"coap_tls_engine_configure: enable-methods 0x%x invalid\n", defaults);
551 ENGINE_free(defined_engine);
552 if (done_engine_init)
553 ENGINE_finish(defined_engine);
554 defined_engine =
NULL;
563 if (defined_engine) {
564 ENGINE_finish(defined_engine);
565 defined_engine =
NULL;
599typedef struct coap_ssl_data {
608coap_dgram_create(BIO *a) {
609 coap_ssl_data *data =
NULL;
610 data = malloc(
sizeof(coap_ssl_data));
614 BIO_set_data(a, data);
615 memset(data, 0x00,
sizeof(coap_ssl_data));
620coap_dgram_destroy(BIO *a) {
624 data = (coap_ssl_data *)BIO_get_data(a);
625 BIO_set_data(a,
NULL);
632coap_dgram_read(BIO *a,
char *out,
int outl) {
634 coap_ssl_data *data = (coap_ssl_data *)BIO_get_data(a);
637 if (data !=
NULL && data->pdu_len > 0) {
638 if (outl < (
int)data->pdu_len) {
639 memcpy(out, data->pdu, outl);
642 memcpy(out, data->pdu, data->pdu_len);
643 ret = (int)data->pdu_len;
645 if (!data->peekmode) {
652 BIO_clear_retry_flags(a);
654 BIO_set_retry_read(a);
660coap_dgram_write(BIO *a,
const char *in,
int inl) {
662 coap_ssl_data *data = (coap_ssl_data *)BIO_get_data(a);
664 if (data && data->session) {
667 && data->session->endpoint ==
NULL
671 BIO_clear_retry_flags(a);
675 ret = (int)data->session->sock.lfunc[
COAP_LAYER_TLS].l_write(data->session,
678 BIO_clear_retry_flags(a);
680 if (ret < 0 && (errno == ENOTCONN || errno == ECONNREFUSED))
682 BIO_set_retry_write(a);
685 BIO_clear_retry_flags(a);
692coap_dgram_puts(BIO *a,
const char *pstr) {
693 return coap_dgram_write(a, pstr, (
int)strlen(pstr));
697coap_dgram_ctrl(BIO *a,
int cmd,
long num,
void *ptr) {
699 coap_ssl_data *data = BIO_get_data(a);
704 case BIO_CTRL_GET_CLOSE:
705 ret = BIO_get_shutdown(a);
707 case BIO_CTRL_SET_CLOSE:
708 BIO_set_shutdown(a, (
int)num);
710 case BIO_CTRL_DGRAM_SET_PEEK_MODE:
712 data->peekmode = (unsigned)num;
716 case BIO_CTRL_DGRAM_CONNECT:
719 case BIO_CTRL_DGRAM_SET_DONT_FRAG:
720 case BIO_CTRL_DGRAM_GET_MTU:
721 case BIO_CTRL_DGRAM_SET_MTU:
722 case BIO_CTRL_DGRAM_QUERY_MTU:
723 case BIO_CTRL_DGRAM_GET_FALLBACK_MTU:
728 case BIO_CTRL_DGRAM_MTU_DISCOVER:
729 case BIO_CTRL_DGRAM_SET_CONNECTED:
731 case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
734 ((
struct timeval *)ptr)->tv_usec);
739 case BIO_C_FILE_SEEK:
740 case BIO_C_FILE_TELL:
742 case BIO_CTRL_PENDING:
743 case BIO_CTRL_WPENDING:
744 case BIO_CTRL_DGRAM_GET_PEER:
745 case BIO_CTRL_DGRAM_SET_PEER:
746 case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:
747 case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT:
748 case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT:
749 case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT:
750 case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP:
751 case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP:
752 case BIO_CTRL_DGRAM_MTU_EXCEEDED:
753 case BIO_CTRL_DGRAM_GET_MTU_OVERHEAD:
762coap_dtls_generate_cookie(SSL *ssl,
763 unsigned char *cookie,
764 unsigned int *cookie_len) {
765 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
766 coap_dtls_context_t *dtls = ctx ? (coap_dtls_context_t *)SSL_CTX_get_app_data(ctx) :
NULL;
767 coap_ssl_data *data = (coap_ssl_data *)BIO_get_data(SSL_get_rbio(ssl));
770 int r = HMAC_Init_ex(dtls->cookie_hmac,
NULL, 0,
NULL,
NULL);
771 r &= HMAC_Update(dtls->cookie_hmac,
772 (
const uint8_t *)&data->session->addr_info.local.addr,
773 (
size_t)data->session->addr_info.local.size);
774 r &= HMAC_Update(dtls->cookie_hmac,
775 (
const uint8_t *)&data->session->addr_info.remote.addr,
776 (
size_t)data->session->addr_info.remote.size);
777 r &= HMAC_Final(dtls->cookie_hmac, cookie, cookie_len);
784coap_dtls_verify_cookie(SSL *ssl,
785 const uint8_t *cookie,
786 unsigned int cookie_len) {
789 if (coap_dtls_generate_cookie(ssl, hmac, &len) &&
790 cookie_len == len && memcmp(cookie, hmac, len) == 0)
796#if COAP_CLIENT_SUPPORT
798coap_dtls_psk_client_callback(SSL *ssl,
801 unsigned int max_identity_len,
803 unsigned int max_psk_len) {
805 coap_openssl_context_t *o_context;
816 if (o_context ==
NULL)
820 temp.
s = hint ? (
const uint8_t *)hint : (const uint8_t *)
"";
821 temp.
length = strlen((
const char *)temp.
s);
825 (
const char *)temp.
s);
837 if (cpsk_info ==
NULL)
842 psk_identity = &cpsk_info->
identity;
843 psk_key = &cpsk_info->
key;
849 if (psk_identity ==
NULL || psk_key ==
NULL) {
855 if (!max_identity_len)
858 if (psk_identity->
length > max_identity_len) {
859 coap_log_warn(
"psk_identity too large, truncated to %d bytes\n",
863 max_identity_len = (
unsigned int)psk_identity->
length;
865 memcpy(identity, psk_identity->
s, max_identity_len);
866 identity[max_identity_len] =
'\000';
868 if (psk_key->
length > max_psk_len) {
873 max_psk_len = (
unsigned int)psk_key->
length;
875 memcpy(psk, psk_key->
s, max_psk_len);
880#if COAP_SERVER_SUPPORT
882coap_dtls_psk_server_callback(
884 const char *identity,
886 unsigned int max_psk_len
897 setup_data = &c_session->
context->spsk_setup_data;
900 lidentity.
s = identity ? (
const uint8_t *)identity : (const uint8_t *)
"";
901 lidentity.
length = strlen((
const char *)lidentity.
s);
905 (
int)lidentity.
length, (
const char *)lidentity.
s);
920 if (psk_key->
length > max_psk_len) {
925 max_psk_len = (
unsigned int)psk_key->
length;
927 memcpy(psk, psk_key->
s, max_psk_len);
933ssl_function_definition(
unsigned long e) {
934#if OPENSSL_VERSION_NUMBER >= 0x30000000L
938 static char buff[80];
940 snprintf(buff,
sizeof(buff),
" at %s:%s",
941 ERR_lib_error_string(e), ERR_func_error_string(e));
947coap_dtls_info_callback(
const SSL *ssl,
int where,
int ret) {
950 int w = where &~SSL_ST_MASK;
954 "coap_dtls_info_callback: session not determined, where 0x%0x and ret 0x%0x\n", where, ret);
957 if (w & SSL_ST_CONNECT)
958 pstr =
"SSL_connect";
959 else if (w & SSL_ST_ACCEPT)
964 if (where & SSL_CB_LOOP) {
967 }
else if (where & SSL_CB_ALERT) {
969 pstr = (where & SSL_CB_READ) ?
"read" :
"write";
970 if ((where & (SSL_CB_WRITE|SSL_CB_READ)) && (ret >> 8) == SSL3_AL_FATAL) {
972 if ((ret & 0xff) != SSL3_AD_CLOSE_NOTIFY)
976 coap_log(log_level,
"* %s: SSL3 alert %s:%s:%s\n",
979 SSL_alert_type_string_long(ret),
980 SSL_alert_desc_string_long(ret));
981 }
else if (where & SSL_CB_EXIT) {
987 while ((e = ERR_get_error()))
990 ssl_function_definition(e));
992 }
else if (ret < 0) {
994 int err = SSL_get_error(ssl, ret);
995 if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE &&
996 err != SSL_ERROR_WANT_CONNECT && err != SSL_ERROR_WANT_ACCEPT &&
997 err != SSL_ERROR_WANT_X509_LOOKUP) {
1001 while ((e = ERR_get_error()))
1004 ssl_function_definition(e));
1007 while (ERR_get_error()) {
1013 if (where == SSL_CB_HANDSHAKE_START && SSL_get_state(ssl) == TLS_ST_OK)
1017#if !COAP_DISABLE_TCP
1019coap_sock_create(BIO *a) {
1025coap_sock_destroy(BIO *a) {
1037coap_sock_read(BIO *a,
char *out,
int outl) {
1041 if (session && out !=
NULL) {
1046 BIO_set_retry_read(a);
1050 BIO_clear_retry_flags(a);
1063coap_sock_write(BIO *a,
const char *in,
int inl) {
1072 (
const uint8_t *)in,
1076 BIO_clear_retry_flags(a);
1078 BIO_set_retry_read(a);
1082 BIO_clear_retry_flags(a);
1086 (errno == EPIPE || errno == ECONNRESET)) {
1106coap_sock_puts(BIO *a,
const char *pstr) {
1107 return coap_sock_write(a, pstr, (
int)strlen(pstr));
1111coap_sock_ctrl(BIO *a,
int cmd,
long num,
void *ptr) {
1122 case BIO_CTRL_SET_CLOSE:
1124 case BIO_CTRL_FLUSH:
1128 case BIO_CTRL_GET_CLOSE:
1137coap_set_user_prefs(SSL_CTX *ctx) {
1138 SSL_CTX_set_cipher_list(ctx, COAP_OPENSSL_CIPHERS);
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);
1145#if OPENSSL_VERSION_NUMBER >= 0x10101000L && defined(COAP_OPENSSL_GROUPS)
1146 SSL_CTX_set1_groups_list(ctx, COAP_OPENSSL_GROUPS);
1150#if COAP_DTLS_RETRANSMIT_MS != 1000
1151#if OPENSSL_VERSION_NUMBER >= 0x10101000L
1153timer_cb(SSL *s,
unsigned int timer_us) {
1158 return 2 * timer_us;
1165 coap_openssl_context_t *context;
1170 uint8_t cookie_secret[32];
1172 memset(context, 0,
sizeof(coap_openssl_context_t));
1175 context->dtls.ctx = SSL_CTX_new(DTLS_method());
1176 if (!context->dtls.ctx)
1178 SSL_CTX_set_min_proto_version(context->dtls.ctx, DTLS1_2_VERSION);
1179 SSL_CTX_set_app_data(context->dtls.ctx, &context->dtls);
1180 SSL_CTX_set_read_ahead(context->dtls.ctx, 1);
1181 coap_set_user_prefs(context->dtls.ctx);
1182 memset(cookie_secret, 0,
sizeof(cookie_secret));
1183 if (!RAND_bytes(cookie_secret, (
int)
sizeof(cookie_secret))) {
1185 "Insufficient entropy for random cookie generation");
1188 context->dtls.cookie_hmac = HMAC_CTX_new();
1189 if (!context->dtls.cookie_hmac)
1191 if (!HMAC_Init_ex(context->dtls.cookie_hmac, cookie_secret, (
int)
sizeof(cookie_secret),
1192 EVP_sha256(),
NULL))
1194 SSL_CTX_set_cookie_generate_cb(context->dtls.ctx, coap_dtls_generate_cookie);
1195 SSL_CTX_set_cookie_verify_cb(context->dtls.ctx, coap_dtls_verify_cookie);
1196 SSL_CTX_set_info_callback(context->dtls.ctx, coap_dtls_info_callback);
1197 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);
1201 context->dtls.meth = BIO_meth_new(BIO_TYPE_DGRAM,
"coapdgram");
1202 if (!context->dtls.meth)
1204 context->dtls.bio_addr = BIO_ADDR_new();
1205 if (!context->dtls.bio_addr)
1207 BIO_meth_set_write(context->dtls.meth, coap_dgram_write);
1208 BIO_meth_set_read(context->dtls.meth, coap_dgram_read);
1209 BIO_meth_set_puts(context->dtls.meth, coap_dgram_puts);
1210 BIO_meth_set_ctrl(context->dtls.meth, coap_dgram_ctrl);
1211 BIO_meth_set_create(context->dtls.meth, coap_dgram_create);
1212 BIO_meth_set_destroy(context->dtls.meth, coap_dgram_destroy);
1214#if !COAP_DISABLE_TCP
1216 context->tls.ctx = SSL_CTX_new(TLS_method());
1217 if (!context->tls.ctx)
1219 SSL_CTX_set_app_data(context->tls.ctx, &context->tls);
1220 SSL_CTX_set_min_proto_version(context->tls.ctx, TLS1_VERSION);
1221 coap_set_user_prefs(context->tls.ctx);
1222 SSL_CTX_set_info_callback(context->tls.ctx, coap_dtls_info_callback);
1223 context->tls.meth = BIO_meth_new(BIO_TYPE_SOCKET,
"coapsock");
1224 if (!context->tls.meth)
1226 BIO_meth_set_write(context->tls.meth, coap_sock_write);
1227 BIO_meth_set_read(context->tls.meth, coap_sock_read);
1228 BIO_meth_set_puts(context->tls.meth, coap_sock_puts);
1229 BIO_meth_set_ctrl(context->tls.meth, coap_sock_ctrl);
1230 BIO_meth_set_create(context->tls.meth, coap_sock_create);
1231 BIO_meth_set_destroy(context->tls.meth, coap_sock_destroy);
1242#if COAP_SERVER_SUPPORT
1247 coap_openssl_context_t *o_context =
1251 if (!setup_data || !o_context)
1254 SSL_CTX_set_psk_server_callback(o_context->dtls.ctx,
1255 coap_dtls_psk_server_callback);
1256#if !COAP_DISABLE_TCP
1257 SSL_CTX_set_psk_server_callback(o_context->tls.ctx,
1258 coap_dtls_psk_server_callback);
1264 SSL_CTX_use_psk_identity_hint(o_context->dtls.ctx, hint);
1265#if !COAP_DISABLE_TCP
1266 SSL_CTX_use_psk_identity_hint(o_context->tls.ctx, hint);
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);
1282 SSL_CTX_set_client_hello_cb(o_context->dtls.ctx,
1283 tls_client_hello_call_back,
1285#if !COAP_DISABLE_TCP
1286 SSL_CTX_set_client_hello_cb(o_context->tls.ctx,
1287 tls_client_hello_call_back,
1293 if (!o_context->dtls.ssl) {
1295 o_context->dtls.ssl = SSL_new(o_context->dtls.ctx);
1296 if (!o_context->dtls.ssl)
1298 bio = BIO_new(o_context->dtls.meth);
1300 SSL_free(o_context->dtls.ssl);
1301 o_context->dtls.ssl =
NULL;
1304 SSL_set_bio(o_context->dtls.ssl, bio, bio);
1305 SSL_set_app_data(o_context->dtls.ssl,
NULL);
1306 SSL_set_options(o_context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
1312 o_context->psk_pki_enabled |= IS_PSK;
1317#if COAP_CLIENT_SUPPORT
1322 coap_openssl_context_t *o_context =
1326 if (!setup_data || !o_context)
1329 if (!o_context->dtls.ssl) {
1331 o_context->dtls.ssl = SSL_new(o_context->dtls.ctx);
1332 if (!o_context->dtls.ssl)
1334 bio = BIO_new(o_context->dtls.meth);
1336 SSL_free(o_context->dtls.ssl);
1337 o_context->dtls.ssl =
NULL;
1340 SSL_set_bio(o_context->dtls.ssl, bio, bio);
1341 SSL_set_app_data(o_context->dtls.ssl,
NULL);
1342 SSL_set_options(o_context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
1351 o_context->psk_pki_enabled |= IS_PSK;
1357map_key_type(
int asn1_private_key_type
1359 switch (asn1_private_key_type) {
1361 return EVP_PKEY_NONE;
1363 return EVP_PKEY_RSA;
1365 return EVP_PKEY_RSA2;
1367 return EVP_PKEY_DSA;
1369 return EVP_PKEY_DSA1;
1371 return EVP_PKEY_DSA2;
1373 return EVP_PKEY_DSA3;
1375 return EVP_PKEY_DSA4;
1379 return EVP_PKEY_DHX;
1383 return EVP_PKEY_HMAC;
1385 return EVP_PKEY_CMAC;
1387 return EVP_PKEY_TLS1_PRF;
1389 return EVP_PKEY_HKDF;
1391 coap_log_warn(
"*** setup_pki: DTLS: Unknown Private Key type %d for ASN1\n",
1392 asn1_private_key_type);
1397#if !COAP_DISABLE_TCP
1398static uint8_t coap_alpn[] = { 4,
'c',
'o',
'a',
'p' };
1400#if COAP_SERVER_SUPPORT
1403 const unsigned char **out,
1404 unsigned char *outlen,
1405 const unsigned char *in,
1409 unsigned char *tout =
NULL;
1412 return SSL_TLSEXT_ERR_NOACK;
1413 ret = SSL_select_next_proto(&tout,
1420 return (ret != OPENSSL_NPN_NEGOTIATED) ? SSL_TLSEXT_ERR_NOACK : SSL_TLSEXT_ERR_OK;
1426add_ca_to_cert_store(X509_STORE *st, X509 *x509) {
1430 while (ERR_get_error() != 0) {
1433 if (!X509_STORE_add_cert(st, x509)) {
1434 while ((e = ERR_get_error()) != 0) {
1435 int r = ERR_GET_REASON(e);
1436 if (r != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
1439 ERR_reason_error_string(e),
1440 ssl_function_definition(e));
1446#if OPENSSL_VERSION_NUMBER < 0x40000000L
1448missing_ENGINE_load_cert(ENGINE *engine,
const char *cert_id) {
1450 const char *cert_id;
1454 params.cert_id = cert_id;
1458 if (!ENGINE_ctrl_cmd(engine,
"LOAD_CERT_CTRL", 0, ¶ms,
NULL, 1)) {
1465check_pkcs11_engine(
void) {
1466 static int already_tried = 0;
1471 if (!pkcs11_engine) {
1472 pkcs11_engine = ENGINE_by_id(COAP_OPENSSL_PKCS11_ENGINE_ID);
1473 if (!pkcs11_engine) {
1474 coap_log_err(
"*** setup_pki: (D)TLS: No PKCS11 support - need OpenSSL %s engine\n",
1475 COAP_OPENSSL_PKCS11_ENGINE_ID);
1479 if (!ENGINE_init(pkcs11_engine)) {
1481 ENGINE_free(pkcs11_engine);
1482 pkcs11_engine =
NULL;
1483 coap_log_err(
"*** setup_pki: (D)TLS: PKCS11 engine initialize failed\n");
1491 ENGINE_free(pkcs11_engine);
1497#if OPENSSL_VERSION_NUMBER < 0x10101000L && COAP_SERVER_SUPPORT
1500install_engine_public_cert_ctx(ENGINE *engine, SSL_CTX *ctx,
1501 const char *public_cert) {
1504 x509 = missing_ENGINE_load_cert(engine, public_cert);
1512 if (!SSL_CTX_use_certificate(ctx, x509)) {
1513 coap_log_warn(
"*** setup_pki: (D)TLS: %s: Unable to configure "
1525install_engine_private_key_ctx(ENGINE *engine, SSL_CTX *ctx,
1526 const char *private_key) {
1527 EVP_PKEY *pkey = ENGINE_load_private_key(engine,
1538 if (!SSL_CTX_use_PrivateKey(ctx, pkey)) {
1539 coap_log_warn(
"*** setup_pki: (D)TLS: %s: Unable to configure "
1543 EVP_PKEY_free(pkey);
1546 EVP_PKEY_free(pkey);
1551install_engine_ca_ctx(ENGINE *engine, SSL_CTX *ctx,
const char *ca) {
1555 x509 = missing_ENGINE_load_cert(engine,
1559 "%s CA Certificate\n",
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",
1572 st = SSL_CTX_get_cert_store(ctx);
1573 add_ca_to_cert_store(st, x509);
1579load_in_cas_ctx(SSL_CTX *ctx,
1580 const char *ca_file) {
1581 STACK_OF(X509_NAME) *cert_names;
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);
1590 coap_log_warn(
"*** setup_pki: (D)TLS: %s: Unable to configure "
1597 st = SSL_CTX_get_cert_store(ctx);
1598 in = BIO_new(BIO_s_file());
1602 memcpy(&rw_var, &ca_file,
sizeof(rw_var));
1603 if (!BIO_read_filename(in, rw_var)) {
1611 add_ca_to_cert_store(st, x);
1619setup_pki_server(SSL_CTX *ctx,
1635 if (!(SSL_CTX_use_PrivateKey_file(ctx,
1637 SSL_FILETYPE_PEM))) {
1647 EVP_PKEY *pkey = bp ? PEM_read_bio_PrivateKey(bp,
NULL, 0,
NULL) :
NULL;
1649 if (!pkey || !SSL_CTX_use_PrivateKey(ctx, pkey)) {
1653 EVP_PKEY_free(pkey);
1661 EVP_PKEY_free(pkey);
1673 if (!(SSL_CTX_use_PrivateKey_file(ctx,
1675 SSL_FILETYPE_ASN1))) {
1693 if (!check_pkcs11_engine()) {
1698 if (ENGINE_ctrl_cmd_string(pkcs11_engine,
1701 coap_log_warn(
"*** setup_pki: (D)TLS: PKCS11: %s: Unable to set pin\n",
1706 if (!install_engine_private_key_ctx(pkcs11_engine, ctx,
1714 if (!defined_engine ||
1715 !install_engine_private_key_ctx(defined_engine, ctx,
1744 if (!(SSL_CTX_use_certificate_file(ctx,
1746 SSL_FILETYPE_PEM))) {
1752 if (!SSL_CTX_use_certificate_chain_file(ctx,
1764 X509 *cert = bp ? PEM_read_bio_X509(bp,
NULL, 0,
NULL) :
NULL;
1766 if (!cert || !SSL_CTX_use_certificate(ctx, cert)) {
1790 if (!(SSL_CTX_use_certificate_file(ctx,
1792 SSL_FILETYPE_ASN1))) {
1800 !(SSL_CTX_use_certificate_ASN1(ctx,
1809 if (!check_pkcs11_engine()) {
1812 if (!install_engine_public_cert_ctx(pkcs11_engine, ctx,
1820 if (!defined_engine ||
1821 !install_engine_public_cert_ctx(defined_engine, ctx,
1859 X509_STORE *st = SSL_CTX_get_cert_store(ctx);
1865 add_ca_to_cert_store(st, x);
1866 SSL_CTX_add_client_CA(ctx, x);
1882 if (!(SSL_CTX_use_certificate_file(ctx,
1884 SSL_FILETYPE_ASN1))) {
1897 if (!x509 || !SSL_CTX_add_client_CA(ctx, x509)) {
1905 st = SSL_CTX_get_cert_store(ctx);
1906 add_ca_to_cert_store(st, x509);
1911 if (!check_pkcs11_engine()) {
1914 if (!install_engine_ca_ctx(pkcs11_engine, ctx,
1922 if (!defined_engine ||
1923 !install_engine_ca_ctx(defined_engine, ctx,
1942#if OPENSSL_VERSION_NUMBER >= 0x10101000L || COAP_CLIENT_SUPPORT
1944#if OPENSSL_VERSION_NUMBER < 0x40000000L
1946install_engine_public_cert(ENGINE *engine, SSL *ssl,
const char *public_cert,
1950 x509 = missing_ENGINE_load_cert(engine, public_cert);
1958 if (!SSL_use_certificate(ssl, x509)) {
1959 coap_log_warn(
"*** setup_pki: (D)TLS: %s: Unable to configure "
1971install_engine_private_key(ENGINE *engine, SSL *ssl,
const char *private_key,
1973 EVP_PKEY *pkey = ENGINE_load_private_key(engine,
1984 if (!SSL_use_PrivateKey(ssl, pkey)) {
1985 coap_log_warn(
"*** setup_pki: (D)TLS: %s: Unable to configure "
1989 EVP_PKEY_free(pkey);
1992 EVP_PKEY_free(pkey);
1997install_engine_ca(ENGINE *engine, SSL *ssl,
const char *ca,
2000 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
2005 "%s CA Certificate (no ctx)\n",
2010 x509 = missing_ENGINE_load_cert(engine,
2014 "%s CA Certificate\n",
2019 if (!SSL_add_client_CA(ssl, x509)) {
2020 coap_log_warn(
"*** setup_pki: (D)TLS: %s: Unable to configure "
2021 "%s CA Certificate\n",
2027 st = SSL_CTX_get_cert_store(ctx);
2028 add_ca_to_cert_store(st, x509);
2035load_in_cas(SSL *ssl,
2040 char *rw_var =
NULL;
2041 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
2044 STACK_OF(X509_NAME) *cert_names = SSL_load_client_CA_file(ca_file);
2046 if (cert_names !=
NULL)
2047 SSL_set_client_CA_list(ssl, cert_names);
2057 in = BIO_new(BIO_s_file());
2061 memcpy(&rw_var, &ca_file,
sizeof(rw_var));
2062 if (!BIO_read_filename(in, rw_var)) {
2066 st = SSL_CTX_get_cert_store(ctx);
2070 add_ca_to_cert_store(st, x);
2078setup_pki_ssl(SSL *ssl,
2094 if (!(SSL_use_PrivateKey_file(ssl,
2096 SSL_FILETYPE_PEM))) {
2097 goto fail_bad_private;
2104 EVP_PKEY *pkey = bp ? PEM_read_bio_PrivateKey(bp,
NULL, 0,
NULL) :
NULL;
2106 if (!pkey || !SSL_use_PrivateKey(ssl, pkey)) {
2110 EVP_PKEY_free(pkey);
2111 goto fail_bad_private;
2116 EVP_PKEY_free(pkey);
2118 goto fail_none_private;
2122 goto fail_ns_private;
2124 if (!(SSL_use_PrivateKey_file(ssl,
2126 SSL_FILETYPE_ASN1))) {
2127 goto fail_bad_private;
2136 goto fail_bad_private;
2140#if OPENSSL_VERSION_NUMBER < 0x40000000L
2141 if (!check_pkcs11_engine()) {
2142 goto fail_bad_private;
2146 if (ENGINE_ctrl_cmd_string(pkcs11_engine,
2149 coap_log_warn(
"*** setup_pki: (D)TLS: PKCS11: %s: Unable to set pin\n",
2151 goto fail_bad_private;
2154 if (!install_engine_private_key(pkcs11_engine, ssl,
2157 goto fail_bad_private;
2160 goto fail_bad_private;
2164#if OPENSSL_VERSION_NUMBER < 0x40000000L
2165 if (!defined_engine ||
2166 !install_engine_private_key(defined_engine, ssl,
2169 goto fail_bad_private;
2175 goto fail_ns_private;
2180 goto fail_none_private;
2193 if (!(SSL_use_certificate_file(ssl,
2195 SSL_FILETYPE_PEM))) {
2196 goto fail_bad_public;
2199 if (!SSL_use_certificate_chain_file(ssl,
2201 goto fail_bad_public;
2209 X509 *cert = bp ? PEM_read_bio_X509(bp,
NULL, 0,
NULL) :
NULL;
2211 if (!cert || !SSL_use_certificate(ssl, cert)) {
2216 goto fail_bad_public;
2223 goto fail_bad_public;
2227 goto fail_ns_public;
2229 if (!(SSL_use_certificate_file(ssl,
2231 SSL_FILETYPE_ASN1))) {
2232 goto fail_bad_public;
2237 !(SSL_use_certificate_ASN1(ssl,
2240 goto fail_bad_public;
2244#if OPENSSL_VERSION_NUMBER < 0x40000000L
2245 if (!check_pkcs11_engine()) {
2246 goto fail_bad_public;
2248 if (!install_engine_public_cert(pkcs11_engine, ssl,
2251 goto fail_bad_public;
2254 goto fail_bad_public;
2258#if OPENSSL_VERSION_NUMBER < 0x40000000L
2259 if (!defined_engine ||
2260 !install_engine_public_cert(defined_engine, ssl,
2263 goto fail_bad_public;
2269 goto fail_ns_public;
2295 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
2297 X509_STORE *st = ctx? SSL_CTX_get_cert_store(ctx) :
NULL;
2301 if ((x = PEM_read_bio_X509(bp,
NULL, 0,
NULL)) ==
NULL)
2304 add_ca_to_cert_store(st, x);
2305 SSL_add_client_CA(ssl, x);
2317 if (!(SSL_use_certificate_file(ssl,
2319 SSL_FILETYPE_ASN1))) {
2329 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
2332 if (!x509 || !SSL_add_client_CA(ssl, x509)) {
2339 st = ctx ? SSL_CTX_get_cert_store(ctx) :
NULL;
2341 add_ca_to_cert_store(st, x509);
2346#if OPENSSL_VERSION_NUMBER < 0x40000000L
2347 if (!check_pkcs11_engine()) {
2350 if (!install_engine_ca(pkcs11_engine, ssl,
2360#if OPENSSL_VERSION_NUMBER < 0x40000000L
2361 if (!defined_engine ||
2362 !install_engine_ca(defined_engine, ssl,
2410get_san_or_cn_from_cert(
coap_session_t *session, X509 *x509,
const char *sni_match) {
2414 STACK_OF(GENERAL_NAME) *san_list;
2418 san_list = X509_get_ext_d2i(x509, NID_subject_alt_name,
NULL,
NULL);
2420 int san_count = sk_GENERAL_NAME_num(san_list);
2422 for (n = 0; n < san_count; n++) {
2423 const GENERAL_NAME *name = sk_GENERAL_NAME_value(san_list, n);
2425 if (name && name->type == GEN_DNS) {
2426 const char *dns_name = (
const char *)ASN1_STRING_get0_data(name->d.dNSName);
2429 if (ASN1_STRING_length(name->d.dNSName) != (
int)strlen(dns_name))
2432 if (strcmp(dns_name, sni_match)) {
2436 cn = OPENSSL_strdup(dns_name);
2437 sk_GENERAL_NAME_pop_free(san_list, GENERAL_NAME_free);
2441 sk_GENERAL_NAME_pop_free(san_list, GENERAL_NAME_free);
2444 n = X509_NAME_get_text_by_NID(X509_get_subject_name(x509), NID_commonName,
2445 buffer,
sizeof(buffer));
2447 if (n > 0 && n == (
int)strlen(buffer)) {
2456 return OPENSSL_strdup(cn);
2462 san_list = X509_get_ext_d2i(x509, NID_subject_alt_name,
NULL,
NULL);
2464 int san_count = sk_GENERAL_NAME_num(san_list);
2466 for (n = 0; n < san_count; n++) {
2467 const GENERAL_NAME *name = sk_GENERAL_NAME_value(san_list, n);
2469 if (name && name->type == GEN_DNS) {
2470 const char *dns_name = (
const char *)ASN1_STRING_get0_data(name->d.dNSName);
2473 if (ASN1_STRING_length(name->d.dNSName) != (
int)strlen(dns_name))
2479 sk_GENERAL_NAME_pop_free(san_list, GENERAL_NAME_free);
2486tls_verify_call_back(
int preverify_ok, X509_STORE_CTX *ctx) {
2487 int index = SSL_get_ex_data_X509_STORE_CTX_idx();
2488 SSL *ssl = index >= 0 ? X509_STORE_CTX_get_ex_data(ctx, index) :
NULL;
2490 coap_openssl_context_t *context = (session && session->
context) ?
2493 int depth = X509_STORE_CTX_get_error_depth(ctx);
2494 int err = X509_STORE_CTX_get_error(ctx);
2495 X509 *x509 = X509_STORE_CTX_get_current_cert(ctx);
2498 if (!setup_data || !x509) {
2499 X509_STORE_CTX_set_error(ctx, X509_V_ERR_UNSPECIFIED);
2504 cn = get_san_or_cn_from_cert(session, x509, setup_data->
client_sni);
2506 coap_log_info(
" %s: SNI '%s' not returned in certificate\n",
2509 X509_STORE_CTX_set_error(ctx, X509_V_ERR_SUBJECT_ISSUER_MISMATCH);
2510 err = X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
2514 cn = get_san_or_cn_from_cert(session, x509,
NULL);
2517 depth, err, preverify_ok, cn);
2521 int length = i2d_X509(x509,
NULL);
2523 uint8_t *base_buf2 = base_buf = length > 0 ? OPENSSL_malloc(length) :
NULL;
2528 assert(i2d_X509(x509, &base_buf2) > 0);
2532 depth, preverify_ok,
2536 X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
2538 X509_STORE_CTX_set_error(ctx, X509_V_ERR_INVALID_CA);
2542 OPENSSL_free(base_buf);
2544 X509_STORE_CTX_set_error(ctx, X509_V_ERR_UNSPECIFIED);
2548 if (!preverify_ok) {
2550 case X509_V_ERR_CERT_NOT_YET_VALID:
2551 case X509_V_ERR_CERT_HAS_EXPIRED:
2555 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
2559 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
2563 case X509_V_ERR_UNABLE_TO_GET_CRL:
2567 case X509_V_ERR_CRL_NOT_YET_VALID:
2568 case X509_V_ERR_CRL_HAS_EXPIRED:
2572 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
2573 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
2574 case X509_V_ERR_AKID_SKID_MISMATCH:
2578 case X509_V_ERR_SUBJECT_ISSUER_MISMATCH:
2588 err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
2589 X509_STORE_CTX_set_error(ctx, err);
2591 if (!preverify_ok) {
2592 if (err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) {
2595 "Unknown CA", cn ? cn :
"?", depth);
2599 X509_verify_cert_error_string(err), cn ? cn :
"?", depth);
2604 X509_verify_cert_error_string(err), cn ? cn :
"?", depth);
2608 return preverify_ok;
2611#if COAP_SERVER_SUPPORT
2612#if OPENSSL_VERSION_NUMBER < 0x10101000L
2622tls_secret_call_back(SSL *ssl,
2625 STACK_OF(SSL_CIPHER) *peer_ciphers,
2629 int psk_requested = 0;
2634 assert(session !=
NULL);
2636 if (session ==
NULL ||
2641 (session->
context->spsk_setup_data.psk_info.key.s &&
2642 session->
context->spsk_setup_data.psk_info.key.length)) {
2644 for (ii = 0; ii < sk_SSL_CIPHER_num(peer_ciphers); ii++) {
2645 const SSL_CIPHER *peer_cipher = sk_SSL_CIPHER_value(peer_ciphers, ii);
2648 SSL_CIPHER_get_name(peer_cipher));
2649 if (strstr(SSL_CIPHER_get_name(peer_cipher),
"PSK")) {
2655 if (!psk_requested) {
2662 SSL_VERIFY_CLIENT_ONCE |
2663 SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
2664 tls_verify_call_back);
2666 SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_call_back);
2675 X509_VERIFY_PARAM *param;
2677 param = X509_VERIFY_PARAM_new();
2679 X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
2680 SSL_set1_param(ssl, param);
2681 X509_VERIFY_PARAM_free(param);
2693 }
else if (session->
context->spsk_setup_data.psk_info.key.s &&
2694 session->
context->spsk_setup_data.psk_info.key.length) {
2695 memcpy(secret, session->
context->spsk_setup_data.psk_info.key.s,
2696 session->
context->spsk_setup_data.psk_info.key.length);
2697 *secretlen = session->
context->spsk_setup_data.psk_info.key.length;
2704 SSL_set_cipher_list(ssl, COAP_OPENSSL_PSK_CIPHERS);
2705#ifdef COAP_OPENSSL_PSK_SECURITY_LEVEL
2711 SSL_set_security_level(ssl, COAP_OPENSSL_PSK_SECURITY_LEVEL);
2713 SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
2728tls_server_name_call_back(SSL *ssl,
2734 return SSL_TLSEXT_ERR_NOACK;
2740 coap_openssl_context_t *context = (session && session->
context) ?
2742 const char *sni = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
2746 return SSL_TLSEXT_ERR_NOACK;
2748 if (!sni || !sni[0]) {
2751 for (i = 0; i < context->sni_count; i++) {
2752 if (!strcasecmp(sni, context->sni_entry_list[i].sni)) {
2756 if (i == context->sni_count) {
2765 return SSL_TLSEXT_ERR_ALERT_FATAL;
2770 ctx = SSL_CTX_new(DTLS_method());
2773 SSL_CTX_set_min_proto_version(ctx, DTLS1_2_VERSION);
2774 SSL_CTX_set_app_data(ctx, &context->dtls);
2775 SSL_CTX_set_read_ahead(ctx, 1);
2776 coap_set_user_prefs(ctx);
2777 SSL_CTX_set_cookie_generate_cb(ctx, coap_dtls_generate_cookie);
2778 SSL_CTX_set_cookie_verify_cb(ctx, coap_dtls_verify_cookie);
2779 SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2780 SSL_CTX_set_options(ctx, SSL_OP_NO_QUERY_MTU);
2782#if !COAP_DISABLE_TCP
2785 ctx = SSL_CTX_new(TLS_method());
2788 SSL_CTX_set_app_data(ctx, &context->tls);
2789 SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2790 coap_set_user_prefs(ctx);
2791 SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2792 SSL_CTX_set_alpn_select_cb(ctx, server_alpn_callback,
NULL);
2795 sni_setup_data = *setup_data;
2796 sni_setup_data.
pki_key = *new_entry;
2797 setup_pki_server(ctx, &sni_setup_data);
2799 context->sni_entry_list = OPENSSL_realloc(context->sni_entry_list,
2800 (context->sni_count+1)*
sizeof(sni_entry));
2801 context->sni_entry_list[context->sni_count].sni = OPENSSL_strdup(sni);
2802 context->sni_entry_list[context->sni_count].ctx = ctx;
2803 context->sni_count++;
2805 SSL_set_SSL_CTX(ssl, context->sni_entry_list[i].ctx);
2806 SSL_clear_options(ssl, 0xFFFFFFFFL);
2807 SSL_set_options(ssl, SSL_CTX_get_options(context->sni_entry_list[i].ctx));
2814 SSL_set_session_secret_cb(ssl, tls_secret_call_back, arg);
2815 return SSL_TLSEXT_ERR_OK;
2818 return SSL_TLSEXT_ERR_ALERT_WARNING;
2830psk_tls_server_name_call_back(SSL *ssl,
2837 return SSL_TLSEXT_ERR_NOACK;
2843 coap_openssl_context_t *o_context = (c_session && c_session->
context) ?
2845 const char *sni = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
2850 return SSL_TLSEXT_ERR_ALERT_FATAL;
2852 if (!sni || !sni[0]) {
2855 for (i = 0; i < o_context->psk_sni_count; i++) {
2856 if (!strcasecmp(sni, (
char *)o_context->psk_sni_entry_list[i].sni)) {
2860 if (i == o_context->psk_sni_count) {
2869 return SSL_TLSEXT_ERR_ALERT_FATAL;
2874 ctx = SSL_CTX_new(DTLS_method());
2877 SSL_CTX_set_min_proto_version(ctx, DTLS1_2_VERSION);
2878 SSL_CTX_set_app_data(ctx, &o_context->dtls);
2879 SSL_CTX_set_read_ahead(ctx, 1);
2880 SSL_CTX_set_cipher_list(ctx, COAP_OPENSSL_CIPHERS);
2881 SSL_CTX_set_cookie_generate_cb(ctx, coap_dtls_generate_cookie);
2882 SSL_CTX_set_cookie_verify_cb(ctx, coap_dtls_verify_cookie);
2883 SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2884 SSL_CTX_set_options(ctx, SSL_OP_NO_QUERY_MTU);
2886#if !COAP_DISABLE_TCP
2889 ctx = SSL_CTX_new(TLS_method());
2892 SSL_CTX_set_app_data(ctx, &o_context->tls);
2893 SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2894 SSL_CTX_set_cipher_list(ctx, COAP_OPENSSL_CIPHERS);
2895 SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2896 SSL_CTX_set_alpn_select_cb(ctx, server_alpn_callback,
NULL);
2900 o_context->psk_sni_entry_list =
2901 OPENSSL_realloc(o_context->psk_sni_entry_list,
2902 (o_context->psk_sni_count+1)*
sizeof(psk_sni_entry));
2903 o_context->psk_sni_entry_list[o_context->psk_sni_count].sni =
2904 OPENSSL_strdup(sni);
2905 o_context->psk_sni_entry_list[o_context->psk_sni_count].psk_info =
2907 o_context->psk_sni_entry_list[o_context->psk_sni_count].ctx =
2909 o_context->psk_sni_count++;
2911 SSL_set_SSL_CTX(ssl, o_context->psk_sni_entry_list[i].ctx);
2912 SSL_clear_options(ssl, 0xFFFFFFFFL);
2913 SSL_set_options(ssl,
2914 SSL_CTX_get_options(o_context->psk_sni_entry_list[i].ctx));
2916 &o_context->psk_sni_entry_list[i].psk_info.key);
2917 snprintf(lhint,
sizeof(lhint),
"%.*s",
2918 (
int)o_context->psk_sni_entry_list[i].psk_info.hint.length,
2919 o_context->psk_sni_entry_list[i].psk_info.hint.s);
2920 SSL_use_psk_identity_hint(ssl, lhint);
2927 SSL_set_session_secret_cb(ssl, tls_secret_call_back, arg);
2928 return SSL_TLSEXT_ERR_OK;
2931 return SSL_TLSEXT_ERR_ALERT_WARNING;
2944tls_client_hello_call_back(SSL *ssl,
2949 coap_openssl_context_t *dtls_context;
2951 int psk_requested = 0;
2952 const unsigned char *out;
2956 *al = SSL_AD_INTERNAL_ERROR;
2957 return SSL_CLIENT_HELLO_ERROR;
2960 assert(session !=
NULL);
2963 if (session ==
NULL ||
2966 *al = SSL_AD_INTERNAL_ERROR;
2967 return SSL_CLIENT_HELLO_ERROR;
2970 setup_data = &dtls_context->setup_data;
2976 (session->
context->spsk_setup_data.psk_info.key.s &&
2977 session->
context->spsk_setup_data.psk_info.key.length)) {
2978 size_t len = SSL_client_hello_get0_ciphers(ssl, &out);
2979 STACK_OF(SSL_CIPHER) *peer_ciphers =
NULL;
2980 STACK_OF(SSL_CIPHER) *scsvc =
NULL;
2982 if (len && SSL_bytes_to_cipher_list(ssl, out, len,
2983 SSL_client_hello_isv2(ssl),
2984 &peer_ciphers, &scsvc)) {
2986 for (ii = 0; ii < sk_SSL_CIPHER_num(peer_ciphers); ii++) {
2987 const SSL_CIPHER *peer_cipher = sk_SSL_CIPHER_value(peer_ciphers, ii);
2990 "Client cipher: %s (%04x)\n",
2991 SSL_CIPHER_get_name(peer_cipher),
2992 SSL_CIPHER_get_protocol_id(peer_cipher));
2993 if (strstr(SSL_CIPHER_get_name(peer_cipher),
"PSK")) {
2999 sk_SSL_CIPHER_free(peer_ciphers);
3000 sk_SSL_CIPHER_free(scsvc);
3003 if (psk_requested) {
3010 const char *sni =
"";
3011 char *sni_tmp =
NULL;
3015 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name,
3018 (((out[0] << 8) + out[1] + 2) == (
int)outlen) &&
3019 out[2] == TLSEXT_NAMETYPE_host_name &&
3020 (((out[3] << 8) + out[4] + 2 + 3) == (
int)outlen)) {
3024 sni_tmp = OPENSSL_malloc(outlen + 1);
3026 sni_tmp[outlen] =
'\000';
3027 memcpy(sni_tmp, out, outlen);
3039 OPENSSL_free(sni_tmp);
3041 *al = SSL_AD_UNRECOGNIZED_NAME;
3042 return SSL_CLIENT_HELLO_ERROR;
3046 OPENSSL_free(sni_tmp);
3049 *al = SSL_AD_INTERNAL_ERROR;
3050 return SSL_CLIENT_HELLO_ERROR;
3053 *al = SSL_AD_INTERNAL_ERROR;
3054 return SSL_CLIENT_HELLO_ERROR;
3056 if (new_entry->
hint.
s) {
3057 snprintf(lhint,
sizeof(lhint),
"%.*s",
3060 SSL_use_psk_identity_hint(ssl, lhint);
3065 SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
3071 return SSL_CLIENT_HELLO_SUCCESS;
3081 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_client_certificate_type,
3084 for (ii = 0; ii < outlen; ii++) {
3100 *al = SSL_AD_UNSUPPORTED_EXTENSION;
3101 return SSL_CLIENT_HELLO_ERROR;
3110 coap_openssl_context_t *context =
3112 const char *sni =
"";
3113 char *sni_tmp =
NULL;
3116 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &out, &outlen) &&
3118 (((out[0]<<8) + out[1] +2) == (
int)outlen) &&
3119 out[2] == TLSEXT_NAMETYPE_host_name &&
3120 (((out[3]<<8) + out[4] +2 +3) == (
int)outlen)) {
3124 sni_tmp = OPENSSL_malloc(outlen+1);
3125 sni_tmp[outlen] =
'\000';
3126 memcpy(sni_tmp, out, outlen);
3130 for (i = 0; i < context->sni_count; i++) {
3131 if (!strcasecmp(sni, context->sni_entry_list[i].sni)) {
3135 if (i == context->sni_count) {
3145 *al = SSL_AD_UNRECOGNIZED_NAME;
3146 return SSL_CLIENT_HELLO_ERROR;
3150 context->sni_entry_list = OPENSSL_realloc(context->sni_entry_list,
3151 (context->sni_count+1)*
sizeof(sni_entry));
3152 context->sni_entry_list[context->sni_count].sni = OPENSSL_strdup(sni);
3153 context->sni_entry_list[context->sni_count].pki_key = *new_entry;
3154 context->sni_count++;
3157 OPENSSL_free(sni_tmp);
3159 sni_setup_data = *setup_data;
3160 sni_setup_data.
pki_key = context->sni_entry_list[i].pki_key;
3172 SSL_VERIFY_CLIENT_ONCE |
3173 SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
3174 tls_verify_call_back);
3176 SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_call_back);
3185 X509_VERIFY_PARAM *param;
3187 param = X509_VERIFY_PARAM_new();
3189 X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
3190 SSL_set1_param(ssl, param);
3191 X509_VERIFY_PARAM_free(param);
3199 return SSL_CLIENT_HELLO_SUCCESS;
3209 coap_openssl_context_t *context =
3214 context->setup_data = *setup_data;
3216#if OPENSSL_VERSION_NUMBER < 0x40000000L
3221 if (!defined_engine) {
3222 coap_log_warn(
"setup_pki: OpenSSL Engine not configured, PKI not set up\n");
3229 if (!context->setup_data.verify_peer_cert) {
3231 context->setup_data.check_common_ca = 0;
3233 context->setup_data.allow_self_signed = 1;
3234 context->setup_data.allow_expired_certs = 1;
3235 context->setup_data.cert_chain_validation = 1;
3236 context->setup_data.cert_chain_verify_depth = 10;
3237 context->setup_data.check_cert_revocation = 1;
3238 context->setup_data.allow_no_crl = 1;
3239 context->setup_data.allow_expired_crl = 1;
3240 context->setup_data.allow_bad_md_hash = 1;
3241 context->setup_data.allow_short_rsa_length = 1;
3243#if COAP_SERVER_SUPPORT
3245 if (context->dtls.ctx) {
3247#if OPENSSL_VERSION_NUMBER < 0x10101000L
3248 if (!setup_pki_server(context->dtls.ctx, setup_data))
3257#if OPENSSL_VERSION_NUMBER < 0x10101000L
3258 if (SSLeay() >= 0x10101000L) {
3259 coap_log_warn(
"OpenSSL compiled with %lux, linked with %lux, so "
3260 "no certificate checking\n",
3261 OPENSSL_VERSION_NUMBER, SSLeay());
3263 SSL_CTX_set_tlsext_servername_arg(context->dtls.ctx, &context->setup_data);
3264 SSL_CTX_set_tlsext_servername_callback(context->dtls.ctx,
3265 tls_server_name_call_back);
3267 SSL_CTX_set_client_hello_cb(context->dtls.ctx,
3268 tls_client_hello_call_back,
3272#if !COAP_DISABLE_TCP
3273 if (context->tls.ctx) {
3275#if OPENSSL_VERSION_NUMBER < 0x10101000L
3276 if (!setup_pki_server(context->tls.ctx, setup_data))
3285#if OPENSSL_VERSION_NUMBER < 0x10101000L
3286 if (SSLeay() >= 0x10101000L) {
3287 coap_log_warn(
"OpenSSL compiled with %lux, linked with %lux, so "
3288 "no certificate checking\n",
3289 OPENSSL_VERSION_NUMBER, SSLeay());
3291 SSL_CTX_set_tlsext_servername_arg(context->tls.ctx, &context->setup_data);
3292 SSL_CTX_set_tlsext_servername_callback(context->tls.ctx,
3293 tls_server_name_call_back);
3295 SSL_CTX_set_client_hello_cb(context->tls.ctx,
3296 tls_client_hello_call_back,
3300 SSL_CTX_set_alpn_select_cb(context->tls.ctx, server_alpn_callback,
NULL);
3307#if COAP_CLIENT_SUPPORT
3309 context->psk_pki_enabled &= ~IS_PSK;
3313 if (!context->dtls.ssl) {
3315 context->dtls.ssl = SSL_new(context->dtls.ctx);
3316 if (!context->dtls.ssl)
3318 bio = BIO_new(context->dtls.meth);
3320 SSL_free(context->dtls.ssl);
3321 context->dtls.ssl =
NULL;
3324 SSL_set_bio(context->dtls.ssl, bio, bio);
3325 SSL_set_app_data(context->dtls.ssl,
NULL);
3326 SSL_set_options(context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
3329 context->psk_pki_enabled |= IS_PKI;
3338 const char *ca_file,
3341 coap_openssl_context_t *context =
3343 if (context->dtls.ctx) {
3344 if (!SSL_CTX_load_verify_locations(context->dtls.ctx, ca_file, ca_dir)) {
3346 ca_file ? ca_file :
"NULL", ca_dir ? ca_dir :
"NULL");
3350#if !COAP_DISABLE_TCP
3351 if (context->tls.ctx) {
3352 if (!SSL_CTX_load_verify_locations(context->tls.ctx, ca_file, ca_dir)) {
3354 ca_file ? ca_file :
"NULL", ca_dir ? ca_dir :
"NULL");
3364#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3365 coap_openssl_context_t *context =
3367 if (context->dtls.ctx) {
3368 if (!SSL_CTX_set_default_verify_paths(context->dtls.ctx)) {
3373#if !COAP_DISABLE_TCP
3374 if (context->tls.ctx) {
3375 if (!SSL_CTX_set_default_verify_paths(context->tls.ctx)) {
3384 coap_log_warn(
"coap_context_set_pki_trust_store: (D)TLS environment "
3385 "not supported for OpenSSL < v3.0.0\n");
3392 coap_openssl_context_t *context =
3394 return context->psk_pki_enabled ? 1 : 0;
3401 coap_openssl_context_t *context = (coap_openssl_context_t *)handle;
3403 if (context->dtls.ssl)
3404 SSL_free(context->dtls.ssl);
3405 if (context->dtls.ctx)
3406 SSL_CTX_free(context->dtls.ctx);
3407 if (context->dtls.cookie_hmac)
3408 HMAC_CTX_free(context->dtls.cookie_hmac);
3409 if (context->dtls.meth)
3410 BIO_meth_free(context->dtls.meth);
3411 if (context->dtls.bio_addr)
3412 BIO_ADDR_free(context->dtls.bio_addr);
3413#if !COAP_DISABLE_TCP
3414 if (context->tls.ctx)
3415 SSL_CTX_free(context->tls.ctx);
3416 if (context->tls.meth)
3417 BIO_meth_free(context->tls.meth);
3419 for (i = 0; i < context->sni_count; i++) {
3420 OPENSSL_free(context->sni_entry_list[i].sni);
3421#if OPENSSL_VERSION_NUMBER < 0x10101000L
3422 SSL_CTX_free(context->sni_entry_list[i].ctx);
3425 if (context->sni_count)
3426 OPENSSL_free(context->sni_entry_list);
3427#if OPENSSL_VERSION_NUMBER < 0x10101000L
3428 for (i = 0; i < context->psk_sni_count; i++) {
3429 OPENSSL_free((
char *)context->psk_sni_entry_list[i].sni);
3430 SSL_CTX_free(context->psk_sni_entry_list[i].ctx);
3432 if (context->psk_sni_count)
3433 OPENSSL_free(context->psk_sni_entry_list);
3438#if COAP_SERVER_SUPPORT
3443 coap_ssl_data *data;
3444 coap_dtls_context_t *dtls = &((coap_openssl_context_t *)session->
context->
dtls_context)->dtls;
3449 nssl = SSL_new(dtls->ctx);
3452 nbio = BIO_new(dtls->meth);
3455 SSL_set_bio(nssl, nbio, nbio);
3456 SSL_set_app_data(nssl,
NULL);
3457 SSL_set_options(nssl, SSL_OP_COOKIE_EXCHANGE);
3458 SSL_set_mtu(nssl, (
long)session->
mtu);
3462 SSL_set_app_data(ssl, session);
3464 rbio = SSL_get_rbio(ssl);
3465 data = rbio ? (coap_ssl_data *)BIO_get_data(rbio) :
NULL;
3468 data->session = session;
3473 char *hint = OPENSSL_malloc(psk_hint->
length + 1);
3476 memcpy(hint, psk_hint->
s, psk_hint->
length);
3477 hint[psk_hint->
length] =
'\000';
3478 SSL_use_psk_identity_hint(ssl, hint);
3485 r = SSL_accept(ssl);
3487 int err = SSL_get_error(ssl, r);
3488 if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
3506#if COAP_CLIENT_SUPPORT
3510 coap_openssl_context_t *context =
3513 if (context->psk_pki_enabled & IS_PSK) {
3518 SSL_set_tlsext_host_name(ssl, setup_data->
client_sni) != 1) {
3522 SSL_set_psk_client_callback(ssl, coap_dtls_psk_client_callback);
3523#if COAP_SERVER_SUPPORT
3524 SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
3526 SSL_set_cipher_list(ssl, COAP_OPENSSL_PSK_CIPHERS);
3527#ifdef COAP_OPENSSL_PSK_SECURITY_LEVEL
3533 SSL_set_security_level(ssl, COAP_OPENSSL_PSK_SECURITY_LEVEL);
3537 SSL_set_max_proto_version(ssl, DTLS1_2_VERSION);
3539#if !COAP_DISABLE_TCP
3541 SSL_set_max_proto_version(ssl, TLS1_2_VERSION);
3544 coap_log_debug(
"CoAP Client restricted to (D)TLS1.2 with Identity Hint callback\n");
3547 if ((context->psk_pki_enabled & IS_PKI) ||
3548 (context->psk_pki_enabled & (IS_PSK | IS_PKI)) == 0) {
3555 if (!(context->psk_pki_enabled & IS_PKI)) {
3572#if !COAP_DISABLE_TCP
3574 SSL_set_alpn_protos(ssl, coap_alpn,
sizeof(coap_alpn));
3579 SSL_set_tlsext_host_name(ssl, setup_data->
client_sni) != 1) {
3585 X509_VERIFY_PARAM *param;
3587 param = X509_VERIFY_PARAM_new();
3589 X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
3590 SSL_set1_param(ssl, param);
3591 X509_VERIFY_PARAM_free(param);
3599 SSL_VERIFY_CLIENT_ONCE |
3600 SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
3601 tls_verify_call_back);
3603 SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_call_back);
3610#if COAP_DTLS_RETRANSMIT_MS != 1000
3611#if OPENSSL_VERSION_NUMBER >= 0x10101000L
3613 DTLS_set_timer_cb(ssl, timer_cb);
3624 coap_ssl_data *data;
3626 coap_openssl_context_t *context = ((coap_openssl_context_t *)session->
context->
dtls_context);
3627 coap_dtls_context_t *dtls = &context->dtls;
3629 ssl = SSL_new(dtls->ctx);
3632 bio = BIO_new(dtls->meth);
3635 data = (coap_ssl_data *)BIO_get_data(bio);
3638 data->session = session;
3639 SSL_set_bio(ssl, bio, bio);
3640 SSL_set_app_data(ssl, session);
3641 SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE);
3642 SSL_set_mtu(ssl, (
long)session->
mtu);
3644 if (!setup_client_ssl_session(session, ssl))
3649 r = SSL_connect(ssl);
3651 int ret = SSL_get_error(ssl, r);
3652 if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE)
3670 SSL *ssl = (SSL *)session->
tls;
3672 SSL_set_mtu(ssl, (
long)session->
mtu);
3678 SSL *ssl = (SSL *)session->
tls;
3680 if (!SSL_in_init(ssl) && !(SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN)) {
3681 int r = SSL_shutdown(ssl);
3694 const uint8_t *data,
size_t data_len) {
3696 SSL *ssl = (SSL *)session->
tls;
3707 r = SSL_write(ssl, data, (
int)data_len);
3710 int err = SSL_get_error(ssl, r);
3711 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
3714 if (err == SSL_ERROR_ZERO_RETURN)
3716 else if (err == SSL_ERROR_SSL) {
3717 unsigned long e = ERR_get_error();
3719 coap_log_info(
"***%s: coap_dtls_send: cannot send PDU: %d: %s\n",
3721 ERR_GET_REASON(e), ERR_reason_error_string(e));
3724 coap_log_info(
"***%s: coap_dtls_send: cannot send PDU: %d\n",
3755 SSL *ssl = (SSL *)session->
tls;
3756 coap_ssl_data *ssl_data;
3760 rbio = ssl ? SSL_get_rbio(ssl) :
NULL;
3761 ssl_data = rbio ? (coap_ssl_data *)BIO_get_data(rbio) :
NULL;
3762 return ssl_data ? ssl_data->timeout : 1000;
3771 SSL *ssl = (SSL *)session->
tls;
3775 (DTLSv1_handle_timeout(ssl) < 0)) {
3785#if COAP_SERVER_SUPPORT
3788 const uint8_t *data,
size_t data_len) {
3789 coap_dtls_context_t *dtls = &((coap_openssl_context_t *)session->
context->
dtls_context)->dtls;
3790 coap_ssl_data *ssl_data;
3794 SSL_set_mtu(dtls->ssl, (
long)session->
mtu);
3795 rbio = dtls->ssl ? SSL_get_rbio(dtls->ssl) :
NULL;
3796 ssl_data = rbio ? (coap_ssl_data *)BIO_get_data(rbio) :
NULL;
3797 assert(ssl_data !=
NULL);
3802 if (ssl_data->pdu_len) {
3803 coap_log_err(
"** %s: Previous data not read %u bytes\n",
3806 ssl_data->session = session;
3807 ssl_data->pdu = data;
3808 ssl_data->pdu_len = (unsigned)data_len;
3809 r = DTLSv1_listen(dtls->ssl, dtls->bio_addr);
3811 int err = SSL_get_error(dtls->ssl, r);
3812 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
3831coap_dtls_receive_done(coap_ssl_data *ssl_data,
int r) {
3832 if (ssl_data->pdu_len) {
3834 coap_log_debug(
"coap_dtls_receive: ret %d: remaining data %u\n", r, ssl_data->pdu_len);
3835 ssl_data->pdu_len = 0;
3836 ssl_data->pdu =
NULL;
3842 coap_ssl_data *ssl_data;
3843 SSL *ssl = (SSL *)session->
tls;
3846#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3850 assert(ssl !=
NULL);
3852 int in_init = SSL_in_init(ssl);
3854 rbio = ssl ? SSL_get_rbio(ssl) :
NULL;
3855 ssl_data = rbio ? (coap_ssl_data *)BIO_get_data(rbio) :
NULL;
3861 if (ssl_data->pdu_len) {
3862 coap_log_err(
"** %s: Previous data not read %u bytes\n",
3865 ssl_data->pdu = data;
3866 ssl_data->pdu_len = (unsigned)data_len;
3869#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3873 r = SSL_read(ssl, pdu, (
int)
sizeof(pdu));
3877 coap_dtls_receive_done(ssl_data, r);
3881 int err = SSL_get_error(ssl, r);
3882 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
3883 if (in_init && SSL_is_init_finished(ssl)) {
3885 coap_dtls_receive_done(ssl_data, 0);
3894 if (err == SSL_ERROR_ZERO_RETURN)
3896 else if (err == SSL_ERROR_SSL) {
3897 unsigned long e = ERR_get_error();
3899#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3900#include <openssl/proverr.h>
3901 if (ERR_GET_REASON(e) == PROV_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES && !retry) {
3907 coap_log_info(
"***%s: coap_dtls_receive: cannot recv PDU: %d: %s\n",
3909 ERR_GET_REASON(e), ERR_reason_error_string(e));
3912 coap_log_info(
"***%s: coap_dtls_receive: cannot send PDU %d\n",
3930 coap_dtls_receive_done(ssl_data, r);
3936 unsigned int overhead = 37;
3937 const SSL_CIPHER *s_ciph =
NULL;
3939 s_ciph = SSL_get_current_cipher(session->
tls);
3941 unsigned int ivlen, maclen, blocksize = 1, pad = 0;
3943 const EVP_CIPHER *e_ciph;
3947 e_ciph = EVP_get_cipherbynid(SSL_CIPHER_get_cipher_nid(s_ciph));
3949 switch (EVP_CIPHER_mode(e_ciph)) {
3950 case EVP_CIPH_GCM_MODE:
3951 ivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN;
3952 maclen = EVP_GCM_TLS_TAG_LEN;
3955 case EVP_CIPH_CCM_MODE:
3956 ivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN;
3957 SSL_CIPHER_description(s_ciph, cipher,
sizeof(cipher));
3958 if (strstr(cipher,
"CCM8"))
3964 case EVP_CIPH_CBC_MODE:
3965 e_md = EVP_get_digestbynid(SSL_CIPHER_get_digest_nid(s_ciph));
3966 blocksize = EVP_CIPHER_block_size(e_ciph);
3967 ivlen = EVP_CIPHER_iv_length(e_ciph);
3969 maclen = EVP_MD_size(e_md);
3972 case EVP_CIPH_STREAM_CIPHER:
3979 SSL_CIPHER_description(s_ciph, cipher,
sizeof(cipher));
3986 overhead = DTLS1_RT_HEADER_LENGTH + ivlen + maclen + blocksize - 1 + pad;
3991#if !COAP_DISABLE_TCP
3992#if COAP_CLIENT_SUPPORT
3998 coap_openssl_context_t *context = ((coap_openssl_context_t *)session->
context->
dtls_context);
3999 coap_tls_context_t *tls = &context->tls;
4001 ssl = SSL_new(tls->ctx);
4004 bio = BIO_new(tls->meth);
4007 BIO_set_data(bio, session);
4008 SSL_set_bio(ssl, bio, bio);
4009 SSL_set_app_data(ssl, session);
4011 if (!setup_client_ssl_session(session, ssl))
4014 r = SSL_connect(ssl);
4016 int ret = SSL_get_error(ssl, r);
4017 if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE)
4019 if (ret == SSL_ERROR_WANT_READ)
4021 if (ret == SSL_ERROR_WANT_WRITE) {
4023#ifdef COAP_EPOLL_SUPPORT
4037 if (SSL_is_init_finished(ssl)) {
4051#if COAP_SERVER_SUPPORT
4056 coap_tls_context_t *tls = &((coap_openssl_context_t *)session->
context->
dtls_context)->tls;
4060 ssl = SSL_new(tls->ctx);
4063 bio = BIO_new(tls->meth);
4066 BIO_set_data(bio, session);
4067 SSL_set_bio(ssl, bio, bio);
4068 SSL_set_app_data(ssl, session);
4072 char *hint = OPENSSL_malloc(psk_hint->
length + 1);
4075 memcpy(hint, psk_hint->
s, psk_hint->
length);
4076 hint[psk_hint->
length] =
'\000';
4077 SSL_use_psk_identity_hint(ssl, hint);
4084 r = SSL_accept(ssl);
4086 int err = SSL_get_error(ssl, r);
4087 if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
4089 if (err == SSL_ERROR_WANT_READ)
4091 if (err == SSL_ERROR_WANT_WRITE) {
4093#ifdef COAP_EPOLL_SUPPORT
4107 if (SSL_is_init_finished(ssl)) {
4112#if COAP_DTLS_RETRANSMIT_MS != 1000
4113#if OPENSSL_VERSION_NUMBER >= 0x10101000L
4115 DTLS_set_timer_cb(ssl, timer_cb);
4131 SSL *ssl = (SSL *)session->
tls;
4133 if (!SSL_in_init(ssl) && !(SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN)) {
4134 int r = SSL_shutdown(ssl);
4152 SSL *ssl = (SSL *)session->
tls;
4158 in_init = !SSL_is_init_finished(ssl);
4161 r = SSL_write(ssl, data, (
int)data_len);
4164 int err = SSL_get_error(ssl, r);
4165 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
4166 if (in_init && SSL_is_init_finished(ssl)) {
4172 if (err == SSL_ERROR_WANT_READ)
4174 else if (err == SSL_ERROR_WANT_WRITE) {
4176#ifdef COAP_EPOLL_SUPPORT
4186 if (err == SSL_ERROR_ZERO_RETURN)
4188 else if (err == SSL_ERROR_SSL) {
4189 unsigned long e = ERR_get_error();
4191 coap_log_info(
"***%s: coap_tls_write: cannot send PDU: %d: %s\n",
4193 ERR_GET_REASON(e), ERR_reason_error_string(e));
4196 coap_log_info(
"***%s: coap_tls_send: cannot send PDU: %d\n",
4201 }
else if (in_init && SSL_is_init_finished(ssl)) {
4217 if (r == (ssize_t)data_len)
4234 SSL *ssl = (SSL *)session->
tls;
4242 in_init = !SSL_is_init_finished(ssl);
4245 r = SSL_read(ssl, data, (
int)data_len);
4247 int err = SSL_get_error(ssl, r);
4248 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
4249 if (in_init && SSL_is_init_finished(ssl)) {
4255 if (err == SSL_ERROR_WANT_READ)
4257 if (err == SSL_ERROR_WANT_WRITE) {
4259#ifdef COAP_EPOLL_SUPPORT
4269 if (err == SSL_ERROR_ZERO_RETURN)
4271 else if (err == SSL_ERROR_SSL) {
4272 unsigned long e = ERR_get_error();
4274 coap_log_info(
"***%s: coap_tls_read: cannot recv PDU: %d: %s\n",
4276 ERR_GET_REASON(e), ERR_reason_error_string(e));
4284 }
else if (in_init && SSL_is_init_finished(ssl)) {
4309#if COAP_SERVER_SUPPORT
4311coap_digest_setup(
void) {
4312 EVP_MD_CTX *digest_ctx = EVP_MD_CTX_new();
4315 EVP_DigestInit_ex(digest_ctx, EVP_sha256(),
NULL);
4321coap_digest_free(coap_digest_ctx_t *digest_ctx) {
4323 EVP_MD_CTX_free(digest_ctx);
4327coap_digest_update(coap_digest_ctx_t *digest_ctx,
4328 const uint8_t *data,
4330 return EVP_DigestUpdate(digest_ctx, data, data_len);
4334coap_digest_final(coap_digest_ctx_t *digest_ctx,
4335 coap_digest_t *digest_buffer) {
4336 unsigned int size =
sizeof(coap_digest_t);
4337 int ret = EVP_DigestFinal_ex(digest_ctx, (uint8_t *)digest_buffer, &size);
4339 coap_digest_free(digest_ctx);
4344#if COAP_WS_SUPPORT || COAP_OSCORE_SUPPORT
4346coap_crypto_output_errors(
const char *prefix) {
4347#if COAP_MAX_LOGGING_LEVEL < _COAP_LOG_WARN
4352 while ((e = ERR_get_error()))
4355 ERR_reason_error_string(e),
4356 ssl_function_definition(e));
4366static struct hash_algs {
4368 const EVP_MD *(*get_hash)(void);
4377static const EVP_MD *
4378get_hash_alg(
cose_alg_t alg,
size_t *length) {
4381 for (idx = 0; idx <
sizeof(hashes) /
sizeof(
struct hash_algs); idx++) {
4382 if (hashes[idx].alg == alg) {
4383 *length = hashes[idx].length;
4384 return hashes[idx].get_hash();
4387 coap_log_debug(
"get_hash_alg: COSE hash %d not supported\n", alg);
4395 unsigned int length;
4396 const EVP_MD *evp_md;
4397 EVP_MD_CTX *evp_ctx =
NULL;
4401 if ((evp_md = get_hash_alg(alg, &hash_length)) ==
NULL) {
4402 coap_log_debug(
"coap_crypto_hash: algorithm %d not supported\n", alg);
4405 evp_ctx = EVP_MD_CTX_new();
4406 if (evp_ctx ==
NULL)
4408 if (EVP_DigestInit_ex(evp_ctx, evp_md,
NULL) == 0)
4411 if (EVP_DigestUpdate(evp_ctx, data->
s, data->
length) == 0)
4417 if (EVP_DigestFinal_ex(evp_ctx,
dummy->s, &length) == 0)
4419 dummy->length = length;
4420 if (hash_length < dummy->length)
4421 dummy->length = hash_length;
4423 EVP_MD_CTX_free(evp_ctx);
4427 coap_crypto_output_errors(
"coap_crypto_hash");
4430 EVP_MD_CTX_free(evp_ctx);
4435#if COAP_OSCORE_SUPPORT
4441#include <openssl/evp.h>
4442#include <openssl/hmac.h>
4449static struct cipher_algs {
4451 const EVP_CIPHER *(*get_cipher)(void);
4456static const EVP_CIPHER *
4460 for (idx = 0; idx <
sizeof(ciphers) /
sizeof(
struct cipher_algs); idx++) {
4461 if (ciphers[idx].alg == alg)
4462 return ciphers[idx].get_cipher();
4464 coap_log_debug(
"get_cipher_alg: COSE cipher %d not supported\n", alg);
4473static struct hmac_algs {
4475 const EVP_MD *(*get_hmac)(void);
4482static const EVP_MD *
4486 for (idx = 0; idx <
sizeof(hmacs) /
sizeof(
struct hmac_algs); idx++) {
4487 if (hmacs[idx].hmac_alg == hmac_alg)
4488 return hmacs[idx].get_hmac();
4490 coap_log_debug(
"get_hmac_alg: COSE HMAC %d not supported\n", hmac_alg);
4496 return get_cipher_alg(alg) !=
NULL;
4505 return get_hmac_alg(hmac_alg) !=
NULL;
4509 if (1 != (Func)) { \
4518 size_t *max_result_len) {
4519 const EVP_CIPHER *cipher;
4522 int result_len = (int)(*max_result_len & INT_MAX);
4523 EVP_CIPHER_CTX *ctx;
4528 assert(params !=
NULL);
4529 if (!params || ((cipher = get_cipher_alg(params->
alg)) ==
NULL)) {
4536 ctx = EVP_CIPHER_CTX_new();
4542 C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_L, (
int)ccm->
l,
NULL));
4543 C(EVP_CIPHER_CTX_ctrl(ctx,
4544 EVP_CTRL_AEAD_SET_IVLEN,
4547 C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, (
int)ccm->
tag_len,
NULL));
4551 C(EVP_EncryptUpdate(ctx,
NULL, &result_len,
NULL, (
int)data->
length));
4552 if (aad && aad->
s && (aad->
length > 0)) {
4553 C(EVP_EncryptUpdate(ctx,
NULL, &result_len, aad->
s, (
int)aad->
length));
4555 C(EVP_EncryptUpdate(ctx, result, &result_len, data->
s, (
int)data->
length));
4558 C(EVP_EncryptFinal_ex(ctx, result + result_len, &tmp));
4562 C(EVP_CIPHER_CTX_ctrl(ctx,
4563 EVP_CTRL_CCM_GET_TAG,
4565 result + result_len));
4567 *max_result_len = result_len + ccm->
tag_len;
4568 EVP_CIPHER_CTX_free(ctx);
4572 coap_crypto_output_errors(
"coap_crypto_aead_encrypt");
4581 size_t *max_result_len) {
4582 const EVP_CIPHER *cipher;
4588 EVP_CIPHER_CTX *ctx;
4593 assert(params !=
NULL);
4594 if (!params || ((cipher = get_cipher_alg(params->
alg)) ==
NULL)) {
4606 memcpy(&rwtag, &tag,
sizeof(rwtag));
4609 ctx = EVP_CIPHER_CTX_new();
4614 C(EVP_CIPHER_CTX_ctrl(ctx,
4615 EVP_CTRL_AEAD_SET_IVLEN,
4618 C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, (
int)ccm->
tag_len, rwtag));
4619 C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_L, (
int)ccm->
l,
NULL));
4624 if (aad && aad->
s && (aad->
length > 0)) {
4625 C(EVP_DecryptUpdate(ctx,
NULL, &len, aad->
s, (
int)aad->
length));
4627 tmp = EVP_DecryptUpdate(ctx, result, &len, data->
s, (
int)data->
length);
4628 EVP_CIPHER_CTX_free(ctx);
4630 *max_result_len = 0;
4633 *max_result_len = len;
4637 coap_crypto_output_errors(
"coap_crypto_aead_decrypt");
4646 unsigned int result_len;
4647 const EVP_MD *evp_md;
4654 if ((evp_md = get_hmac_alg(hmac_alg)) == 0) {
4655 coap_log_debug(
"coap_crypto_hmac: algorithm %d not supported\n", hmac_alg);
4661 result_len = (
unsigned int)
dummy->length;
4669 dummy->length = result_len;
4675 coap_crypto_output_errors(
"coap_crypto_hmac");
4687#pragma GCC diagnostic ignored "-Wunused-function"
struct coap_session_t coap_session_t
#define COAP_SERVER_SUPPORT
#define COAP_RXBUFFER_SIZE
#define COAP_SOCKET_WANT_READ
non blocking socket is waiting for reading
#define COAP_SOCKET_WANT_WRITE
non blocking socket is waiting for writing
void coap_epoll_ctl_mod(coap_socket_t *sock, uint32_t events, const char *func)
Epoll specific function to modify the state of events that epoll is tracking on the appropriate file ...
Library specific build wrapper for coap_internal.h.
void * coap_malloc_type(coap_memory_tag_t type, size_t size)
Allocates a chunk of size bytes and returns a pointer to the newly allocated memory.
void coap_free_type(coap_memory_tag_t type, void *p)
Releases the memory that was allocated by coap_malloc_type().
int coap_dtls_context_set_pki(coap_context_t *ctx COAP_UNUSED, const coap_dtls_pki_t *setup_data COAP_UNUSED, const coap_dtls_role_t role COAP_UNUSED)
coap_tick_t coap_dtls_get_timeout(coap_session_t *session COAP_UNUSED, coap_tick_t now COAP_UNUSED)
ssize_t coap_tls_read(coap_session_t *session COAP_UNUSED, uint8_t *data COAP_UNUSED, size_t data_len COAP_UNUSED)
coap_tick_t coap_dtls_get_context_timeout(void *dtls_context COAP_UNUSED)
int coap_dtls_receive(coap_session_t *session COAP_UNUSED, const uint8_t *data COAP_UNUSED, size_t data_len COAP_UNUSED)
void * coap_dtls_get_tls(const coap_session_t *c_session COAP_UNUSED, coap_tls_library_t *tls_lib)
unsigned int coap_dtls_get_overhead(coap_session_t *session COAP_UNUSED)
int coap_dtls_context_load_pki_trust_store(coap_context_t *ctx COAP_UNUSED)
static coap_log_t dtls_log_level
int coap_dtls_context_check_keys_enabled(coap_context_t *ctx COAP_UNUSED)
ssize_t coap_dtls_send(coap_session_t *session COAP_UNUSED, const uint8_t *data COAP_UNUSED, size_t data_len COAP_UNUSED)
ssize_t coap_tls_write(coap_session_t *session COAP_UNUSED, const uint8_t *data COAP_UNUSED, size_t data_len COAP_UNUSED)
void coap_dtls_session_update_mtu(coap_session_t *session COAP_UNUSED)
int coap_dtls_context_set_pki_root_cas(coap_context_t *ctx COAP_UNUSED, const char *ca_file COAP_UNUSED, const char *ca_path COAP_UNUSED)
int coap_dtls_handle_timeout(coap_session_t *session COAP_UNUSED)
void coap_dtls_free_context(void *handle COAP_UNUSED)
void coap_dtls_free_session(coap_session_t *coap_session COAP_UNUSED)
void * coap_dtls_new_context(coap_context_t *coap_context COAP_UNUSED)
void coap_tls_free_session(coap_session_t *coap_session COAP_UNUSED)
coap_tick_t coap_ticks_from_rt_us(uint64_t t)
Helper function that converts POSIX wallclock time in us to coap ticks.
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
int coap_prng_lkd(void *buf, size_t len)
Fills buf with len random bytes using the default pseudo random number generator.
int coap_handle_event_lkd(coap_context_t *context, coap_event_t event, coap_session_t *session)
Invokes the event handler of context for the given event and data.
int coap_handle_dgram(coap_context_t *ctx, coap_session_t *session, uint8_t *msg, size_t msg_len)
Parses and interprets a CoAP datagram with context ctx.
int coap_crypto_hmac(cose_hmac_alg_t hmac_alg, coap_bin_const_t *key, coap_bin_const_t *data, coap_bin_const_t **hmac)
Create a HMAC hash of the provided data.
int coap_crypto_aead_decrypt(const coap_crypto_param_t *params, coap_bin_const_t *data, coap_bin_const_t *aad, uint8_t *result, size_t *max_result_len)
Decrypt the provided encrypted data into plaintext.
int coap_crypto_aead_encrypt(const coap_crypto_param_t *params, coap_bin_const_t *data, coap_bin_const_t *aad, uint8_t *result, size_t *max_result_len)
Encrypt the provided plaintext data.
int coap_crypto_hash(cose_alg_t alg, const coap_bin_const_t *data, coap_bin_const_t **hash)
Create a hash of the provided data.
int coap_crypto_check_hkdf_alg(cose_hkdf_alg_t hkdf_alg)
Check whether the defined hkdf algorithm is supported by the underlying crypto library.
int coap_crypto_check_cipher_alg(cose_alg_t alg)
Check whether the defined cipher algorithm is supported by the underlying crypto library.
const coap_bin_const_t * coap_get_session_client_psk_identity(const coap_session_t *coap_session)
Get the current client's PSK identity.
void coap_dtls_startup(void)
Initialize the underlying (D)TLS Library layer.
#define COAP_DTLS_RETRANSMIT_MS
int coap_dtls_define_issue(coap_define_issue_key_t type, coap_define_issue_fail_t fail, coap_dtls_key_t *key, const coap_dtls_role_t role, int ret)
Report PKI DEFINE type issue.
int coap_pki_name_match_sni(const char *name_entry, size_t name_length, const char *sni_match)
Check if the PKI name entry is a (wildcard) match for the requested SNI.
void coap_dtls_thread_shutdown(void)
Close down the underlying (D)TLS Library layer.
int coap_dtls_set_cid_tuple_change(coap_context_t *context, uint8_t every)
Set the Connection ID client tuple frequency change for testing CIDs.
int coap_dtls_is_context_timeout(void)
Check if timeout is handled per CoAP session or per CoAP context.
void coap_dtls_shutdown(void)
Close down the underlying (D)TLS Library layer.
const coap_bin_const_t * coap_get_session_client_psk_key(const coap_session_t *coap_session)
Get the current client's PSK key.
void coap_dtls_map_key_type_to_define(const coap_dtls_pki_t *setup_data, coap_dtls_key_t *key)
Map the PKI key definitions to the new DEFINE format.
const coap_bin_const_t * coap_get_session_server_psk_key(const coap_session_t *coap_session)
Get the current server's PSK key.
const coap_bin_const_t * coap_get_session_server_psk_hint(const coap_session_t *coap_session)
Get the current server's PSK identity hint.
@ COAP_DEFINE_KEY_PRIVATE
@ COAP_DEFINE_FAIL_NOT_SUPPORTED
#define COAP_DTLS_HINT_LENGTH
int coap_tls_engine_configure(coap_str_const_t *conf_mem)
Configure an ENGINE for a TLS library.
coap_tls_version_t * coap_get_tls_library_version(void)
Determine the type and version of the underlying (D)TLS library.
struct coap_dtls_key_t coap_dtls_key_t
The structure that holds the PKI key information.
int coap_tls_engine_remove(void)
Remove a previously configured ENGINE from a TLS library.
struct coap_dtls_spsk_info_t coap_dtls_spsk_info_t
The structure that holds the Server Pre-Shared Key and Identity Hint information.
struct coap_dtls_pki_t coap_dtls_pki_t
@ COAP_PKI_KEY_DEF_PKCS11
The PKI key type is PKCS11 (pkcs11:...).
@ COAP_PKI_KEY_DEF_DER_BUF
The PKI key type is DER buffer (ASN.1).
@ COAP_PKI_KEY_DEF_PEM_BUF
The PKI key type is PEM buffer.
@ COAP_PKI_KEY_DEF_PEM
The PKI key type is PEM file.
@ COAP_PKI_KEY_DEF_ENGINE
The PKI key type is to be passed to ENGINE.
@ COAP_PKI_KEY_DEF_RPK_BUF
The PKI key type is RPK in buffer.
@ COAP_PKI_KEY_DEF_DER
The PKI key type is DER file.
@ COAP_PKI_KEY_DEF_PKCS11_RPK
The PKI key type is PKCS11 w/ RPK (pkcs11:...).
@ COAP_DTLS_ROLE_SERVER
Internal function invoked for server.
@ COAP_DTLS_ROLE_CLIENT
Internal function invoked for client.
@ COAP_PKI_KEY_DEFINE
The individual PKI key types are Definable.
@ COAP_ASN1_PKEY_DH
DH type.
@ COAP_ASN1_PKEY_NONE
NONE.
@ COAP_ASN1_PKEY_TLS1_PRF
TLS1_PRF type.
@ COAP_ASN1_PKEY_RSA2
RSA2 type.
@ COAP_ASN1_PKEY_DSA
DSA type.
@ COAP_ASN1_PKEY_DHX
DHX type.
@ COAP_ASN1_PKEY_DSA4
DSA4 type.
@ COAP_ASN1_PKEY_DSA2
DSA2 type.
@ COAP_ASN1_PKEY_RSA
RSA type.
@ COAP_ASN1_PKEY_DSA1
DSA1 type.
@ COAP_ASN1_PKEY_HKDF
HKDF type.
@ COAP_ASN1_PKEY_EC
EC type.
@ COAP_ASN1_PKEY_DSA3
DSA3 type.
@ COAP_ASN1_PKEY_HMAC
HMAC type.
@ COAP_ASN1_PKEY_CMAC
CMAC type.
@ COAP_TLS_LIBRARY_OPENSSL
Using OpenSSL library.
@ COAP_EVENT_DTLS_CLOSED
Triggerrd when (D)TLS session closed.
@ COAP_EVENT_DTLS_CONNECTED
Triggered when (D)TLS session connected.
@ COAP_EVENT_DTLS_RENEGOTIATE
Triggered when (D)TLS session renegotiated.
@ COAP_EVENT_DTLS_ERROR
Triggered when (D)TLS error occurs.
#define coap_lock_callback_ret(r, func)
Dummy for no thread-safe code.
#define coap_log_debug(...)
coap_log_t coap_dtls_get_log_level(void)
Get the current (D)TLS logging.
#define coap_dtls_log(level,...)
Logging function.
void coap_dtls_set_log_level(coap_log_t level)
Sets the (D)TLS logging level to the specified level.
const char * coap_session_str(const coap_session_t *session)
Get session description.
#define coap_log_info(...)
#define coap_log_warn(...)
#define coap_log_err(...)
#define coap_log(level,...)
Logging function.
int coap_netif_available(coap_session_t *session)
Function interface to check whether netif for session is still available.
int cose_get_hmac_alg_for_hkdf(cose_hkdf_alg_t hkdf_alg, cose_hmac_alg_t *hmac_alg)
@ COSE_HMAC_ALG_HMAC384_384
@ COSE_HMAC_ALG_HMAC256_256
@ COSE_HMAC_ALG_HMAC512_512
@ COSE_ALGORITHM_SHA_256_64
@ COSE_ALGORITHM_SHA_256_256
@ COSE_ALGORITHM_AES_CCM_16_64_128
@ COSE_ALGORITHM_AES_CCM_16_64_256
int coap_session_refresh_psk_hint(coap_session_t *session, const coap_bin_const_t *psk_hint)
Refresh the session's current Identity Hint (PSK).
int coap_session_refresh_psk_key(coap_session_t *session, const coap_bin_const_t *psk_key)
Refresh the session's current pre-shared key (PSK).
int coap_session_refresh_psk_identity(coap_session_t *session, const coap_bin_const_t *psk_identity)
Refresh the session's current pre-shared identity (PSK).
void coap_session_disconnected_lkd(coap_session_t *session, coap_nack_reason_t reason)
Notify session that it has failed.
@ COAP_SESSION_TYPE_CLIENT
client-side
@ COAP_SESSION_STATE_HANDSHAKE
void coap_delete_str_const(coap_str_const_t *s)
Deletes the given const string and releases any memory allocated.
coap_binary_t * coap_new_binary(size_t size)
Returns a new binary object with at least size bytes storage allocated.
void coap_delete_binary(coap_binary_t *s)
Deletes the given coap_binary_t object and releases any memory allocated.
coap_str_const_t * coap_new_str_const(const uint8_t *data, size_t size)
Returns a new const string object with at least size+1 bytes storage allocated, and the provided data...
int coap_dtls_cid_is_supported(void)
Check whether (D)TLS CID is available.
int coap_dtls_psk_is_supported(void)
Check whether (D)TLS PSK is available.
int coap_tls_is_supported(void)
Check whether TLS is available.
int coap_oscore_is_supported(void)
Check whether OSCORE is available.
int coap_dtls_is_supported(void)
Check whether DTLS is available.
int coap_dtls_pki_is_supported(void)
Check whether (D)TLS PKI is available.
int coap_dtls_rpk_is_supported(void)
Check whether (D)TLS RPK is available.
int coap_dtls_pkcs11_is_supported(void)
Check whether (D)TLS PKCS11 is available.
CoAP binary data definition with const data.
size_t length
length of binary data
const uint8_t * s
read-only binary data
CoAP binary data definition.
The CoAP stack's global state is stored in a coap_context_t object.
The structure that holds the AES Crypto information.
size_t l
The number of bytes in the length field.
const uint8_t * nonce
must be exactly 15 - l bytes
coap_crypto_key_t key
The Key to use.
size_t tag_len
The size of the Tag.
The common structure that holds the Crypto information.
union coap_crypto_param_t::@360202231002166314161306143105206133250310351041 params
coap_crypto_aes_ccm_t aes
Used if AES type encryption.
cose_alg_t alg
The COSE algorithm to use.
The structure that holds the Client PSK information.
coap_bin_const_t identity
The structure used for defining the Client PSK setup data to be used.
uint8_t use_cid
Set to 1 if DTLS Connection ID is to be used.
void * ih_call_back_arg
Passed in to the Identity Hint callback function.
char * client_sni
If not NULL, SNI to use in client TLS setup.
coap_dtls_ih_callback_t validate_ih_call_back
Identity Hint check callback function.
uint8_t ec_jpake
Set to COAP_DTLS_CPSK_SETUP_VERSION to support this version of the struct.
The structure that holds the PKI key information.
coap_pki_key_define_t define
for definable type keys
coap_pki_key_t key_type
key format type
union coap_dtls_key_t::@304163316016047256036005037024112317316237364050 key
The structure used for defining the PKI setup data to be used.
uint8_t allow_no_crl
1 ignore if CRL not there
void * cn_call_back_arg
Passed in to the CN callback function.
uint8_t allow_sni_cn_mismatch
1 if SNI and returned CN allowed to mismatch (Client only).
uint8_t cert_chain_validation
1 if to check cert_chain_verify_depth
uint8_t use_cid
1 if DTLS Connection ID is to be used (Client only, server always enabled) if supported
uint8_t check_cert_revocation
1 if revocation checks wanted
coap_dtls_pki_sni_callback_t validate_sni_call_back
SNI check callback function.
uint8_t cert_chain_verify_depth
recommended depth is 3
coap_dtls_security_setup_t additional_tls_setup_call_back
Additional Security callback handler that is invoked when libcoap has done the standard,...
uint8_t allow_expired_certs
1 if expired certs are allowed
uint8_t verify_peer_cert
Set to COAP_DTLS_PKI_SETUP_VERSION to support this version of the struct.
char * client_sni
If not NULL, SNI to use in client TLS setup.
uint8_t allow_self_signed
1 if self-signed certs are allowed.
void * sni_call_back_arg
Passed in to the sni callback function.
coap_dtls_cn_callback_t validate_cn_call_back
CN check callback function.
uint8_t allow_expired_crl
1 if expired crl is allowed
uint8_t is_rpk_not_cert
1 is RPK instead of Public Certificate.
uint8_t check_common_ca
1 if peer cert is to be signed by the same CA as the local cert
coap_dtls_key_t pki_key
PKI key definition.
The structure that holds the Server Pre-Shared Key and Identity Hint information.
The structure used for defining the Server PSK setup data to be used.
coap_dtls_psk_sni_callback_t validate_sni_call_back
SNI check callback function.
coap_dtls_id_callback_t validate_id_call_back
Identity check callback function.
void * id_call_back_arg
Passed in to the Identity callback function.
uint8_t ec_jpake
Set to COAP_DTLS_SPSK_SETUP_VERSION to support this version of the struct.
void * sni_call_back_arg
Passed in to the SNI callback function.
coap_dtls_spsk_info_t psk_info
Server PSK definition.
coap_layer_write_t l_write
coap_layer_establish_t l_establish
coap_const_char_ptr_t public_cert
define: Public Cert
coap_asn1_privatekey_type_t private_key_type
define: ASN1 Private Key Type (if needed)
const char * user_pin
define: User pin to access type PKCS11.
coap_const_char_ptr_t private_key
define: Private Key
coap_const_char_ptr_t ca
define: Common CA Certificate
size_t public_cert_len
define Public Cert length (if needed)
size_t ca_len
define CA Cert length (if needed)
coap_pki_define_t private_key_def
define: Private Key type definition
size_t private_key_len
define Private Key length (if needed)
coap_pki_define_t ca_def
define: Common CA type definition
coap_pki_define_t public_cert_def
define: Public Cert type definition
Abstraction of virtual session that can be attached to coap_context_t (client) or coap_endpoint_t (se...
unsigned int dtls_timeout_count
dtls setup retry counter
coap_bin_const_t * psk_key
If client, this field contains the current pre-shared key for server; When this field is NULL,...
coap_socket_t sock
socket object for the session, if any
coap_session_state_t state
current state of relationship with peer
coap_proto_t proto
protocol used
coap_dtls_cpsk_t cpsk_setup_data
client provided PSK initial setup data
size_t mtu
path or CSM mtu (xmt)
int dtls_event
Tracking any (D)TLS events on this session.
void * tls
security parameters
uint16_t max_retransmit
maximum re-transmit count (default 4)
coap_session_type_t type
client or server side socket
coap_context_t * context
session's context
coap_layer_func_t lfunc[COAP_LAYER_LAST]
Layer functions to use.
coap_socket_flags_t flags
1 or more of COAP_SOCKET* flag values
CoAP string data definition with const data.
const uint8_t * s
read-only string data
size_t length
length of string
The structure used for returning the underlying (D)TLS library information.
uint64_t built_version
(D)TLS Built against Library Version
coap_tls_library_t type
Library type.
uint64_t version
(D)TLS runtime Library Version
const char * s_byte
signed char ptr
const uint8_t * u_byte
unsigned char ptr