mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #16179 from leandrolanzieri/dev/net/sock/dtls_multi_cred
net/sock/dtls: allow using multiple credentials
This commit is contained in:
commit
f3482071e1
@ -24,6 +24,9 @@ USEPKG += tinydtls
|
||||
USEMODULE += sock_dtls
|
||||
USEMODULE += sock_udp
|
||||
|
||||
# extra utilities for endpoint printing
|
||||
USEMODULE += sock_util
|
||||
|
||||
# tinydtls needs crypto secure PRNG
|
||||
USEMODULE += prng_sha1prng
|
||||
|
||||
|
@ -40,3 +40,37 @@ constraints that applies specifically to the stack are also applied here.
|
||||
For tinydtls, please refer to [dtls-echo README][1].
|
||||
|
||||
[1]: https://github.com/RIOT-OS/RIOT/blob/master/examples/dtls-echo/README.md
|
||||
|
||||
### Cipher suite
|
||||
You can select between `TLS_PSK_WITH_AES_128_CCM_8` (Pre-Shared Key) and
|
||||
`TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8` (Raw Public Key - ECC) either by setting
|
||||
the correspondent options in `make menuconfig` or via `CFLAGS`. See the `Makefile`
|
||||
for more information.
|
||||
|
||||
## Credentials
|
||||
### Pre-Shared Key
|
||||
When using Pre-Shared Key (PSK), the client registers two keys to `credman` and
|
||||
makes them available to the sock. The client registers a PSK callback function,
|
||||
which allows the application to specify which credential to use with a
|
||||
particular sock and endpoint. In this application the client will print the
|
||||
server's endpoint and the sent hint, if any. As per the sock DTLS documentation,
|
||||
if the application callback fails to determine which credential should be used,
|
||||
an Identity Hint (https://tools.ietf.org/html/rfc4279#section-5.2) match is
|
||||
attempted. `credential1` is assigned an Identity Hint, defined as
|
||||
`PSK_DEFAULT_HINT` in `tinydtls_keys.h`. This hint is used by sock to select the
|
||||
credential, in case the DTLS server sends such a hint. Finally, if none of the
|
||||
above attempts succeed in determining which credential to use, sock DTLS will
|
||||
pick the first valid credential registered in the sock.
|
||||
|
||||
The behaviour above can be tested, for example, by removing the hint from the
|
||||
server (`sock_dtls_set_server_psk_id_hint`). As `credential0` is the first
|
||||
registered credential in the client, it will be chosen. As the server does not
|
||||
have this credential, the handshake will fail.
|
||||
|
||||
### ECC
|
||||
When using ECC Raw Public Key (RPK), the server registers two keys to `credman`
|
||||
and makes them available to the sock. It also registers an RPK callback
|
||||
function, which allows the application to specify which credential to use with a
|
||||
particular sock and endpoint (the client could as well do so). In the particular
|
||||
case of this example the callback always returns the credential with tag
|
||||
`SOCK_DTLS_SERVER_TAG_1`.
|
||||
|
@ -18,10 +18,14 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "kernel_defines.h"
|
||||
|
||||
#include "net/sock/udp.h"
|
||||
#include "net/sock/dtls.h"
|
||||
#include "net/sock/dtls/creds.h"
|
||||
#include "net/ipv6/addr.h"
|
||||
#include "net/credman.h"
|
||||
#include "net/sock/util.h"
|
||||
|
||||
#include "tinydtls_keys.h"
|
||||
|
||||
@ -29,36 +33,41 @@
|
||||
#define DTLS_DEFAULT_PORT 20220 /* DTLS default port */
|
||||
#endif
|
||||
|
||||
#define SOCK_DTLS_CLIENT_TAG (2)
|
||||
#define SOCK_DTLS_CLIENT_TAG_0 (2)
|
||||
#define SOCK_DTLS_CLIENT_TAG_1 (3)
|
||||
|
||||
#ifdef CONFIG_DTLS_ECC
|
||||
static const ecdsa_public_key_t other_pubkeys[] = {
|
||||
{ .x = ecdsa_pub_key_x, .y = ecdsa_pub_key_y },
|
||||
static const ecdsa_public_key_t other_pubkeys0[] = {
|
||||
{ .x = ecdsa_pub_key0_x, .y = ecdsa_pub_key0_y },
|
||||
};
|
||||
|
||||
static const credman_credential_t credential = {
|
||||
static const credman_credential_t credential0 = {
|
||||
.type = CREDMAN_TYPE_ECDSA,
|
||||
.tag = SOCK_DTLS_CLIENT_TAG,
|
||||
.tag = SOCK_DTLS_CLIENT_TAG_0,
|
||||
.params = {
|
||||
.ecdsa = {
|
||||
.private_key = ecdsa_priv_key,
|
||||
.private_key = ecdsa_priv_key0,
|
||||
.public_key = {
|
||||
.x = ecdsa_pub_key_x,
|
||||
.y = ecdsa_pub_key_y,
|
||||
.x = ecdsa_pub_key0_x,
|
||||
.y = ecdsa_pub_key0_y,
|
||||
},
|
||||
.client_keys = (ecdsa_public_key_t *)other_pubkeys,
|
||||
.client_keys_size = ARRAY_SIZE(other_pubkeys),
|
||||
.client_keys = (ecdsa_public_key_t *)other_pubkeys0,
|
||||
.client_keys_size = ARRAY_SIZE(other_pubkeys0),
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
#else /* ifdef CONFIG_DTLS_PSK */
|
||||
static const uint8_t psk_id_0[] = PSK_DEFAULT_IDENTITY;
|
||||
static const uint8_t psk_key_0[] = PSK_DEFAULT_KEY;
|
||||
static const uint8_t psk_id_0[] = PSK_WRONG_IDENTITY;
|
||||
static const uint8_t psk_key_0[] = PSK_WRONG_KEY;
|
||||
|
||||
static const credman_credential_t credential = {
|
||||
static const uint8_t psk_id_1[] = PSK_DEFAULT_IDENTITY;
|
||||
static const uint8_t psk_key_1[] = PSK_DEFAULT_KEY;
|
||||
static const char psk_id_1_hint[] = PSK_DEFAULT_HINT;
|
||||
|
||||
static const credman_credential_t credential0 = {
|
||||
.type = CREDMAN_TYPE_PSK,
|
||||
.tag = SOCK_DTLS_CLIENT_TAG,
|
||||
.tag = SOCK_DTLS_CLIENT_TAG_0,
|
||||
.params = {
|
||||
.psk = {
|
||||
.key = { .s = psk_key_0, .len = sizeof(psk_key_0) - 1, },
|
||||
@ -66,6 +75,39 @@ static const credman_credential_t credential = {
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
static const credman_credential_t credential1 = {
|
||||
.type = CREDMAN_TYPE_PSK,
|
||||
.tag = SOCK_DTLS_CLIENT_TAG_1,
|
||||
.params = {
|
||||
.psk = {
|
||||
.key = { .s = psk_key_1, .len = sizeof(psk_key_1) - 1, },
|
||||
.id = { .s = psk_id_1, .len = sizeof(psk_id_1) - 1, },
|
||||
.hint = { .s = psk_id_1_hint, .len = sizeof(psk_id_1_hint) - 1, },
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
static credman_tag_t _client_psk_cb(sock_dtls_t *sock, sock_udp_ep_t *ep, credman_tag_t tags[],
|
||||
unsigned tags_len, const char *hint, size_t hint_len)
|
||||
{
|
||||
(void) sock;
|
||||
(void) tags;
|
||||
(void) tags_len;
|
||||
|
||||
/* this callback is here just to show the functionality, it only prints the received hint */
|
||||
char addrstr[IPV6_ADDR_MAX_STR_LEN];
|
||||
uint16_t port;
|
||||
|
||||
sock_udp_ep_fmt(ep, addrstr, &port);
|
||||
printf("From [%s]:%d\n", addrstr, port);
|
||||
|
||||
if (hint && hint_len) {
|
||||
printf("Client got hint: %.*s\n", (unsigned)hint_len, hint);
|
||||
}
|
||||
|
||||
return CREDMAN_TAG_EMPTY;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int client_send(char *addr_str, char *data, size_t datalen)
|
||||
@ -108,21 +150,39 @@ static int client_send(char *addr_str, char *data, size_t datalen)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sock_dtls_create(&dtls_sock, &udp_sock,
|
||||
SOCK_DTLS_CLIENT_TAG,
|
||||
res = credman_add(&credential0);
|
||||
if (res < 0 && res != CREDMAN_EXIST) {
|
||||
/* ignore duplicate credentials */
|
||||
printf("Error cannot add credential to system: %d\n", (int)res);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sock_dtls_create(&dtls_sock, &udp_sock, SOCK_DTLS_CLIENT_TAG_0,
|
||||
SOCK_DTLS_1_2, SOCK_DTLS_CLIENT) < 0) {
|
||||
puts("Error creating DTLS sock");
|
||||
sock_udp_close(&udp_sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = credman_add(&credential);
|
||||
#if IS_ACTIVE(CONFIG_DTLS_PSK)
|
||||
/* register a second PSK credential */
|
||||
res = credman_add(&credential1);
|
||||
if (res < 0 && res != CREDMAN_EXIST) {
|
||||
/* ignore duplicate credentials */
|
||||
printf("Error cannot add credential to system: %d\n", (int)res);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* make the new credential available to the sock */
|
||||
if (sock_dtls_add_credential(&dtls_sock, SOCK_DTLS_CLIENT_TAG_1) < 0) {
|
||||
printf("Error cannot add credential to the sock: %d\n", (int)res);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* register a callback for PSK credential selection */
|
||||
sock_dtls_set_client_psk_cb(&dtls_sock, _client_psk_cb);
|
||||
#endif
|
||||
|
||||
res = sock_dtls_session_init(&dtls_sock, &remote, &session);
|
||||
if (res <= 0) {
|
||||
return res;
|
||||
|
@ -20,6 +20,8 @@
|
||||
|
||||
#include "net/sock/udp.h"
|
||||
#include "net/sock/dtls.h"
|
||||
#include "net/sock/dtls/creds.h"
|
||||
#include "net/sock/util.h"
|
||||
#include "net/credman.h"
|
||||
#include "msg.h"
|
||||
#include "thread.h"
|
||||
@ -31,7 +33,8 @@
|
||||
#define DTLS_DEFAULT_PORT (20220) /* DTLS default port */
|
||||
#endif
|
||||
|
||||
#define SOCK_DTLS_SERVER_TAG (10)
|
||||
#define SOCK_DTLS_SERVER_TAG_0 (10)
|
||||
#define SOCK_DTLS_SERVER_TAG_1 (11)
|
||||
#define DTLS_STOP_SERVER_MSG 0x4001 /* Custom IPC type msg. */
|
||||
#define READER_QUEUE_SIZE (8U)
|
||||
|
||||
@ -42,33 +45,73 @@ static kernel_pid_t _dtls_server_pid = KERNEL_PID_UNDEF;
|
||||
|
||||
#ifdef CONFIG_DTLS_ECC
|
||||
static const ecdsa_public_key_t other_pubkeys[] = {
|
||||
{ .x = ecdsa_pub_key_x, .y = ecdsa_pub_key_y },
|
||||
{ .x = ecdsa_pub_key0_x, .y = ecdsa_pub_key0_y },
|
||||
};
|
||||
|
||||
static const credman_credential_t credential = {
|
||||
static const credman_credential_t credential0 = {
|
||||
.type = CREDMAN_TYPE_ECDSA,
|
||||
.tag = SOCK_DTLS_SERVER_TAG,
|
||||
.tag = SOCK_DTLS_SERVER_TAG_0,
|
||||
.params = {
|
||||
.ecdsa = {
|
||||
.private_key = ecdsa_priv_key,
|
||||
.private_key = ecdsa_priv_key0,
|
||||
.public_key = {
|
||||
.x = ecdsa_pub_key_x,
|
||||
.y = ecdsa_pub_key_y,
|
||||
.x = ecdsa_pub_key0_x,
|
||||
.y = ecdsa_pub_key0_y,
|
||||
},
|
||||
.client_keys = (ecdsa_public_key_t *)other_pubkeys,
|
||||
.client_keys_size = ARRAY_SIZE(other_pubkeys),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static const ecdsa_public_key_t other_pubkeys1[] = {
|
||||
{ .x = ecdsa_pub_key1_x, .y = ecdsa_pub_key1_y },
|
||||
};
|
||||
|
||||
static const credman_credential_t credential1 = {
|
||||
.type = CREDMAN_TYPE_ECDSA,
|
||||
.tag = SOCK_DTLS_SERVER_TAG_1,
|
||||
.params = {
|
||||
.ecdsa = {
|
||||
.private_key = ecdsa_priv_key1,
|
||||
.public_key = {
|
||||
.x = ecdsa_pub_key1_x,
|
||||
.y = ecdsa_pub_key1_y,
|
||||
},
|
||||
.client_keys = (ecdsa_public_key_t *)other_pubkeys1,
|
||||
.client_keys_size = ARRAY_SIZE(other_pubkeys1),
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
static credman_tag_t _rpk_cb(sock_dtls_t *sock, sock_udp_ep_t *ep, credman_tag_t tags[],
|
||||
unsigned tags_len)
|
||||
{
|
||||
(void) sock;
|
||||
(void) ep;
|
||||
(void) tags;
|
||||
(void) tags_len;
|
||||
|
||||
char addrstr[IPV6_ADDR_MAX_STR_LEN];
|
||||
uint16_t port;
|
||||
|
||||
sock_udp_ep_fmt(ep, addrstr, &port);
|
||||
printf("From [%s]:%d\n", addrstr, port);
|
||||
|
||||
return SOCK_DTLS_SERVER_TAG_1;
|
||||
}
|
||||
|
||||
#else /* #ifdef CONFIG_DTLS_PSK */
|
||||
static const uint8_t psk_id_0[] = PSK_DEFAULT_IDENTITY;
|
||||
static const uint8_t psk_key_0[] = PSK_DEFAULT_KEY;
|
||||
|
||||
static const credman_credential_t credential = {
|
||||
static const credman_credential_t credential0 = {
|
||||
.type = CREDMAN_TYPE_PSK,
|
||||
.tag = SOCK_DTLS_SERVER_TAG,
|
||||
.tag = SOCK_DTLS_SERVER_TAG_0,
|
||||
.params = {
|
||||
.psk = {
|
||||
.key = { .s = psk_key_0, .len = sizeof(psk_key_0) - 1, },
|
||||
.id = { .s = psk_id_0, .len = sizeof(psk_id_0) - 1, },
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -93,20 +136,47 @@ void *dtls_server_wrapper(void *arg)
|
||||
local.port = DTLS_DEFAULT_PORT;
|
||||
sock_udp_create(&udp_sock, &local, NULL, 0);
|
||||
|
||||
res = sock_dtls_create(&sock, &udp_sock, SOCK_DTLS_SERVER_TAG,
|
||||
res = credman_add(&credential0);
|
||||
if (res < 0 && res != CREDMAN_EXIST) {
|
||||
/* ignore duplicate credentials */
|
||||
printf("Error cannot add credential to system: %d\n", (int)res);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
res = sock_dtls_create(&sock, &udp_sock, SOCK_DTLS_SERVER_TAG_0,
|
||||
SOCK_DTLS_1_2, SOCK_DTLS_SERVER);
|
||||
if (res < 0) {
|
||||
puts("Error creating DTLS sock");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
res = credman_add(&credential);
|
||||
/* set PSK Identity hint, this is optional and application-specific */
|
||||
#if IS_ACTIVE(CONFIG_DTLS_PSK)
|
||||
if (sock_dtls_set_server_psk_id_hint(&sock, PSK_DEFAULT_HINT) < 0) {
|
||||
puts("Error setting PSK Identity hint");
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if IS_ACTIVE(CONFIG_DTLS_ECC)
|
||||
/* register a second RPK */
|
||||
res = credman_add(&credential1);
|
||||
if (res < 0 && res != CREDMAN_EXIST) {
|
||||
/* ignore duplicate credentials */
|
||||
printf("Error cannot add credential to system: %d\n", (int)res);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* make the new credential available to the sock */
|
||||
if (sock_dtls_add_credential(&sock, SOCK_DTLS_SERVER_TAG_1) < 0) {
|
||||
printf("Error cannot add credential to the sock: %d\n", (int)res);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* register a callback for RPK credential selection */
|
||||
sock_dtls_set_rpk_cb(&sock, _rpk_cb);
|
||||
#endif
|
||||
|
||||
while (active) {
|
||||
if ((msg_try_receive(&msg) == 1) &&
|
||||
(msg.type == DTLS_STOP_SERVER_MSG)){
|
||||
|
@ -29,35 +29,57 @@ extern "C" {
|
||||
* Default keys examples for tinyDTLS (for RIOT, Linux and Contiki)
|
||||
*/
|
||||
#ifdef CONFIG_DTLS_PSK
|
||||
#define PSK_WRONG_IDENTITY "Wrong_identity"
|
||||
#define PSK_WRONG_KEY "wrong_secret"
|
||||
#define PSK_DEFAULT_IDENTITY "Client_identity"
|
||||
#define PSK_DEFAULT_KEY "secretPSK"
|
||||
#define PSK_OPTIONS "i:k:"
|
||||
#define PSK_ID_MAXLEN 32
|
||||
#define PSK_MAXLEN 32
|
||||
#define PSK_DEFAULT_HINT "hint"
|
||||
|
||||
#endif /* CONFIG_DTLS_PSK */
|
||||
|
||||
#ifdef CONFIG_DTLS_ECC
|
||||
static const unsigned char ecdsa_priv_key[] = {
|
||||
static const unsigned char ecdsa_priv_key0[] = {
|
||||
0x41, 0xC1, 0xCB, 0x6B, 0x51, 0x24, 0x7A, 0x14,
|
||||
0x43, 0x21, 0x43, 0x5B, 0x7A, 0x80, 0xE7, 0x14,
|
||||
0x89, 0x6A, 0x33, 0xBB, 0xAD, 0x72, 0x94, 0xCA,
|
||||
0x40, 0x14, 0x55, 0xA1, 0x94, 0xA9, 0x49, 0xFA
|
||||
};
|
||||
|
||||
static const unsigned char ecdsa_pub_key_x[] = {
|
||||
static const unsigned char ecdsa_pub_key0_x[] = {
|
||||
0x36, 0xDF, 0xE2, 0xC6, 0xF9, 0xF2, 0xED, 0x29,
|
||||
0xDA, 0x0A, 0x9A, 0x8F, 0x62, 0x68, 0x4E, 0x91,
|
||||
0x63, 0x75, 0xBA, 0x10, 0x30, 0x0C, 0x28, 0xC5,
|
||||
0xE4, 0x7C, 0xFB, 0xF2, 0x5F, 0xA5, 0x8F, 0x52
|
||||
};
|
||||
|
||||
static const unsigned char ecdsa_pub_key_y[] = {
|
||||
static const unsigned char ecdsa_pub_key0_y[] = {
|
||||
0x71, 0xA0, 0xD4, 0xFC, 0xDE, 0x1A, 0xB8, 0x78,
|
||||
0x5A, 0x3C, 0x78, 0x69, 0x35, 0xA7, 0xCF, 0xAB,
|
||||
0xE9, 0x3F, 0x98, 0x72, 0x09, 0xDA, 0xED, 0x0B,
|
||||
0x4F, 0xAB, 0xC3, 0x6F, 0xC7, 0x72, 0xF8, 0x29
|
||||
};
|
||||
|
||||
static const unsigned char ecdsa_priv_key1[] = {
|
||||
0x99, 0x1b, 0x1c, 0xf1, 0x52, 0xa3, 0xf5, 0xac,
|
||||
0xce, 0x58, 0x00, 0x45, 0xdc, 0xa7, 0x45, 0x45,
|
||||
0x9e, 0xc6, 0xd8, 0x68, 0x21, 0xd4, 0x82, 0xb7,
|
||||
0x17, 0x84, 0x0a, 0xdc, 0x1d, 0xf1, 0x09, 0x57
|
||||
};
|
||||
|
||||
static const unsigned char ecdsa_pub_key1_x[] = {
|
||||
0xb7, 0x4e, 0xa0, 0x62, 0x96, 0xc5, 0xb9, 0x09,
|
||||
0xad, 0x36, 0x10, 0xab, 0xb1, 0xd8, 0x54, 0x69,
|
||||
0xef, 0x2b, 0x15, 0x5a, 0xb5, 0x28, 0x21, 0x21,
|
||||
0x9f, 0xa3, 0x9e, 0x6a, 0x02, 0xce, 0xb8, 0xb9
|
||||
};
|
||||
|
||||
static const unsigned char ecdsa_pub_key1_y[] = {
|
||||
0xcc, 0x0e, 0x88, 0x88, 0x91, 0x80, 0x7a, 0xdd,
|
||||
0xf7, 0x4e, 0x2e, 0xe6, 0x6e, 0xd4, 0x22, 0xde,
|
||||
0xbc, 0x68, 0xcd, 0x8f, 0xd9, 0x5a, 0xa0, 0xcd,
|
||||
0x5f, 0x4a, 0x1a, 0xb7, 0x2f, 0x95, 0xfc, 0x76
|
||||
};
|
||||
|
||||
#endif /* CONFIG_DTLS_ECC */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -75,6 +75,19 @@ static dtls_handler_t _dtls_handler = {
|
||||
#endif /* CONFIG_DTLS_ECC */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DTLS_ECC
|
||||
/**
|
||||
* @brief Array of ECDSA keys to convert from credman credentials and send in
|
||||
* the callback.
|
||||
*/
|
||||
typedef struct ecdsa_key_assignment {
|
||||
dtls_ecdsa_key_t key;
|
||||
const session_t *session;
|
||||
} ecdsa_key_assignment_t;
|
||||
|
||||
static ecdsa_key_assignment_t _ecdsa_keys[CONFIG_DTLS_CREDENTIALS_MAX];
|
||||
#endif
|
||||
|
||||
static int _read(struct dtls_context_t *ctx, session_t *session, uint8_t *buf,
|
||||
size_t len)
|
||||
{
|
||||
@ -135,6 +148,18 @@ static int _event(struct dtls_context_t *ctx, session_t *session,
|
||||
if (!level && (code != DTLS_EVENT_CONNECT)) {
|
||||
mbox_put(&sock->mbox, &msg);
|
||||
}
|
||||
|
||||
#if IS_ACTIVE(CONFIG_DTLS_ECC)
|
||||
if (code == DTLS_EVENT_CONNECTED) {
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(_ecdsa_keys); i++) {
|
||||
if (_ecdsa_keys[i].session && dtls_session_equals(session, _ecdsa_keys[i].session)) {
|
||||
_ecdsa_keys[i].session = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SOCK_HAS_ASYNC
|
||||
if (sock->async_cb != NULL) {
|
||||
switch (code) {
|
||||
@ -162,37 +187,103 @@ static int _get_psk_info(struct dtls_context_t *ctx, const session_t *session,
|
||||
const unsigned char *desc, size_t desc_len,
|
||||
unsigned char *result, size_t result_length)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)desc;
|
||||
(void)desc_len;
|
||||
(void)session;
|
||||
int ret;
|
||||
|
||||
sock_dtls_t *sock = dtls_get_app_data(ctx);
|
||||
|
||||
credman_credential_t credential;
|
||||
ret = credman_get(&credential, sock->tag, CREDMAN_TYPE_PSK);
|
||||
if (ret < 0) {
|
||||
DEBUG("sock_dtls: no matching PSK credential found\n");
|
||||
return dtls_alert_fatal_create(DTLS_ALERT_DECRYPT_ERROR);
|
||||
}
|
||||
sock_udp_ep_t ep;
|
||||
sock_dtls_t *sock = dtls_get_app_data(ctx);
|
||||
|
||||
const void *c = NULL;
|
||||
size_t c_len = 0;
|
||||
|
||||
_session_to_ep(session, &ep);
|
||||
|
||||
switch (type) {
|
||||
case DTLS_PSK_HINT:
|
||||
DEBUG("sock_dtls: psk hint request\n");
|
||||
/* Ignored. See https://tools.ietf.org/html/rfc4279#section-5.2 */
|
||||
return 0;
|
||||
/* return a hint to the client if set */
|
||||
c_len = strlen(sock->psk_hint);
|
||||
if (c_len) {
|
||||
c = sock->psk_hint;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
DEBUG("sock_dtls: no hint provided\n");
|
||||
return 0;
|
||||
}
|
||||
case DTLS_PSK_IDENTITY:
|
||||
DEBUG("sock_dtls: psk id request\n");
|
||||
c = credential.params.psk.id.s;
|
||||
c_len = credential.params.psk.id.len;
|
||||
/* if the application set a callback , try to select credential from there */
|
||||
if (sock->client_psk_cb) {
|
||||
DEBUG("sock_dtls: requesting the application\n");
|
||||
credential.tag = sock->client_psk_cb(sock, &ep, sock->tags, sock->tags_len,
|
||||
(const char*)desc, desc_len);
|
||||
if (credential.tag != CREDMAN_TAG_EMPTY) {
|
||||
int ret = credman_get(&credential, credential.tag, CREDMAN_TYPE_PSK);
|
||||
if (ret == CREDMAN_OK) {
|
||||
c = credential.params.psk.id.s;
|
||||
c_len = credential.params.psk.id.len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if no callback set or no valid credential returned, try to find a valid registered one */
|
||||
DEBUG("sock_dtls: trying to get first PSK credential\n");
|
||||
credman_credential_t first = { .tag = CREDMAN_TAG_EMPTY };
|
||||
for (unsigned i = 0; i < sock->tags_len && !c; i++) {
|
||||
if (credman_get(&credential, sock->tags[i], CREDMAN_TYPE_PSK) == CREDMAN_OK) {
|
||||
/* if no hint was provided, settle for the first valid credential */
|
||||
if (!desc) {
|
||||
c = credential.params.psk.id.s;
|
||||
c_len = credential.params.psk.id.len;
|
||||
break;
|
||||
}
|
||||
|
||||
/* save the first valid one in case we don't find the hint */
|
||||
if (first.tag == CREDMAN_TAG_EMPTY) {
|
||||
memcpy(&first, &credential, sizeof(credman_credential_t));
|
||||
}
|
||||
|
||||
if (desc_len == credential.params.psk.hint.len &&
|
||||
!strncmp(credential.params.psk.hint.s, (const char *)desc, desc_len)) {
|
||||
c = credential.params.psk.id.s;
|
||||
c_len = credential.params.psk.id.len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if no credential so far, fallback to the first valid one, return alert otherwise */
|
||||
if (!c) {
|
||||
if (first.tag != CREDMAN_TAG_EMPTY) {
|
||||
c = first.params.psk.id.s;
|
||||
c_len = first.params.psk.id.len;
|
||||
}
|
||||
else {
|
||||
DEBUG("sock_dtls: could not find a valid PSK credential\n");
|
||||
return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DTLS_PSK_KEY:
|
||||
DEBUG("sock_dtls: psk key request\n");
|
||||
c = credential.params.psk.key.s;
|
||||
c_len = credential.params.psk.key.len;
|
||||
|
||||
if (desc) {
|
||||
DEBUG("sock_dtls: looking for key for ID: %.*s\n", (unsigned)desc_len, desc);
|
||||
/* try to find matching ID among the registered credentials */
|
||||
for (unsigned i = 0; i < sock->tags_len; i++) {
|
||||
if (credman_get(&credential, sock->tags[i], CREDMAN_TYPE_PSK) == CREDMAN_OK) {
|
||||
DEBUG("sock_dtls: comparing to tag %d, with ID: %.*s\n", sock->tags[i],
|
||||
(unsigned)credential.params.psk.id.len,
|
||||
(char *)credential.params.psk.id.s);
|
||||
if (desc_len == credential.params.psk.id.len &&
|
||||
!memcmp(desc, credential.params.psk.id.s, desc_len)) {
|
||||
DEBUG("sock_dtls: found\n");
|
||||
c = credential.params.psk.key.s;
|
||||
c_len = credential.params.psk.key.len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEBUG("sock:dtls unsupported request type: %d\n", type);
|
||||
@ -217,22 +308,63 @@ static int _get_ecdsa_key(struct dtls_context_t *ctx, const session_t *session,
|
||||
const dtls_ecdsa_key_t **result)
|
||||
{
|
||||
(void)session;
|
||||
int ret;
|
||||
int ret = CREDMAN_ERROR;
|
||||
sock_dtls_t *sock = (sock_dtls_t *)dtls_get_app_data(ctx);
|
||||
sock_udp_ep_t ep;
|
||||
|
||||
_session_to_ep(session, &ep);
|
||||
|
||||
credman_credential_t credential;
|
||||
ret = credman_get(&credential, sock->tag, CREDMAN_TYPE_ECDSA);
|
||||
if (ret < 0) {
|
||||
DEBUG("sock_dtls: no matching ecdsa credential found\n");
|
||||
return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
|
||||
credential.tag = CREDMAN_TAG_EMPTY;
|
||||
DEBUG("sock_dtls: get ECDSA key\n");
|
||||
|
||||
/* if the application set a callback , try to select credential from there */
|
||||
if (sock->rpk_cb) {
|
||||
DEBUG("sock_dtls: requesting the application\n");
|
||||
credential.tag = sock->rpk_cb(sock, &ep, sock->tags, sock->tags_len);
|
||||
if (credential.tag != CREDMAN_TAG_EMPTY) {
|
||||
ret = credman_get(&credential, credential.tag, CREDMAN_TYPE_ECDSA);
|
||||
if (ret != CREDMAN_OK) {
|
||||
credential.tag = CREDMAN_TAG_EMPTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static dtls_ecdsa_key_t key;
|
||||
key.curve = DTLS_ECDH_CURVE_SECP256R1;
|
||||
key.priv_key = credential.params.ecdsa.private_key;
|
||||
key.pub_key_x = credential.params.ecdsa.public_key.x;
|
||||
key.pub_key_y = credential.params.ecdsa.public_key.y;
|
||||
*result = &key;
|
||||
if (credential.tag == CREDMAN_TYPE_EMPTY) {
|
||||
/* if could not get credential try to fetch the first valid credential */
|
||||
for (unsigned i = 0; i < sock->tags_len; i++) {
|
||||
ret = credman_get(&credential, sock->tags[i], CREDMAN_TYPE_ECDSA);
|
||||
if (ret == CREDMAN_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret != CREDMAN_OK) {
|
||||
DEBUG("sock_dtls: no valid credential registered\n");
|
||||
return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/* try to find a free ECDSA key assignment structure for the handshake. When unused, the session
|
||||
* is not set. */
|
||||
ecdsa_key_assignment_t *key = NULL;
|
||||
for (unsigned i = 0; i < CONFIG_DTLS_CREDENTIALS_MAX; i++) {
|
||||
if (!_ecdsa_keys[i].session) {
|
||||
key = &_ecdsa_keys[i];
|
||||
}
|
||||
}
|
||||
if (!key) {
|
||||
DEBUG("sock_dtls: ECDSA keys are full\n");
|
||||
return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
key->session = session;
|
||||
key->key.curve = DTLS_ECDH_CURVE_SECP256R1;
|
||||
key->key.priv_key = credential.params.ecdsa.private_key;
|
||||
key->key.pub_key_x = credential.params.ecdsa.public_key.x;
|
||||
key->key.pub_key_y = credential.params.ecdsa.public_key.y;
|
||||
|
||||
*result = &key->key;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -279,13 +411,26 @@ int sock_dtls_create(sock_dtls_t *sock, sock_udp_t *udp_sock,
|
||||
|
||||
sock->udp_sock = udp_sock;
|
||||
sock->buffer.data = NULL;
|
||||
sock->psk_hint[0] = '\0';
|
||||
sock->client_psk_cb = NULL;
|
||||
sock->rpk_cb = NULL;
|
||||
#ifdef SOCK_HAS_ASYNC
|
||||
sock->async_cb = NULL;
|
||||
sock->buf_ctx = NULL;
|
||||
memset(&sock->async_cb_session, 0, sizeof(sock->async_cb_session));
|
||||
#endif /* SOCK_HAS_ASYNC */
|
||||
|
||||
memset(sock->tags, CREDMAN_TAG_EMPTY, CONFIG_DTLS_CREDENTIALS_MAX * sizeof(credman_tag_t));
|
||||
|
||||
if (tag != CREDMAN_TAG_EMPTY) {
|
||||
sock->tags_len = 1;
|
||||
sock->tags[0] = tag;
|
||||
}
|
||||
else {
|
||||
sock->tags_len = 0;
|
||||
}
|
||||
|
||||
sock->role = role;
|
||||
sock->tag = tag;
|
||||
sock->dtls_ctx = dtls_new_context(sock);
|
||||
if (!sock->dtls_ctx) {
|
||||
DEBUG("sock_dtls: error getting DTLS context\n");
|
||||
@ -296,6 +441,76 @@ int sock_dtls_create(sock_dtls_t *sock, sock_udp_t *udp_sock,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sock_dtls_set_server_psk_id_hint(sock_dtls_t *sock, const char *hint)
|
||||
{
|
||||
assert(sock);
|
||||
if (strlen(hint) > CONFIG_DTLS_PSK_ID_HINT_MAX_SIZE) {
|
||||
DEBUG("sock_dtls: could not set hint due to buffer size\n");
|
||||
return -1;
|
||||
}
|
||||
strcpy(sock->psk_hint, hint);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sock_dtls_add_credential(sock_dtls_t *sock, credman_tag_t tag)
|
||||
{
|
||||
assert(sock);
|
||||
if (sock->tags_len < CONFIG_DTLS_CREDENTIALS_MAX) {
|
||||
DEBUG("sock_dtls: credential added in position %d\n", sock->tags_len);
|
||||
sock->tags[sock->tags_len] = tag;
|
||||
sock->tags_len++;
|
||||
return 0;
|
||||
}
|
||||
DEBUG("sock_dtls: could not add new credential\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int sock_dtls_remove_credential(sock_dtls_t *sock, credman_tag_t tag)
|
||||
{
|
||||
assert(sock);
|
||||
int pos = -1;
|
||||
for (unsigned i = 0; i < sock->tags_len; i++) {
|
||||
if (sock->tags[i] == tag) {
|
||||
pos = i;
|
||||
DEBUG("sock_dtls: found credential to remove in position %i\n", pos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pos >= 0) {
|
||||
sock->tags_len--;
|
||||
for (; (unsigned)pos < sock->tags_len; pos++) {
|
||||
sock->tags[pos] = sock->tags[pos + 1];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
DEBUG("sock_dtls: could not find credential to remove\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
size_t sock_dtls_get_credentials(sock_dtls_t *sock, const credman_tag_t **out)
|
||||
{
|
||||
assert(sock);
|
||||
assert(out);
|
||||
|
||||
*out = sock->tags;
|
||||
return sock->tags_len;
|
||||
}
|
||||
|
||||
void sock_dtls_set_client_psk_cb(sock_dtls_t *sock, sock_dtls_client_psk_cb_t cb)
|
||||
{
|
||||
assert(sock);
|
||||
sock->client_psk_cb = cb;
|
||||
}
|
||||
|
||||
void sock_dtls_set_rpk_cb(sock_dtls_t *sock, sock_dtls_rpk_cb_t cb)
|
||||
{
|
||||
assert(sock);
|
||||
sock->rpk_cb = cb;
|
||||
}
|
||||
|
||||
sock_udp_t *sock_dtls_get_udp_sock(sock_dtls_t *sock)
|
||||
{
|
||||
assert(sock);
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "dtls.h"
|
||||
#include "net/sock/udp.h"
|
||||
#include "net/credman.h"
|
||||
#include "net/sock/dtls/creds.h"
|
||||
#ifdef SOCK_HAS_ASYNC
|
||||
#include "net/sock/async/types.h"
|
||||
#endif
|
||||
@ -74,9 +75,12 @@ struct sock_dtls {
|
||||
size_t datalen; /**< data length */
|
||||
session_t *session; /**< Session information */
|
||||
} buffer;
|
||||
credman_tag_t tag; /**< Credential tag of a registered
|
||||
(D)TLS credential */
|
||||
char psk_hint[CONFIG_DTLS_PSK_ID_HINT_MAX_SIZE]; /**< PSK Identity hint */
|
||||
credman_tag_t tags[CONFIG_DTLS_CREDENTIALS_MAX]; /**< Tags of the available credentials */
|
||||
unsigned tags_len; /**< Number of tags in the list 'tags' */
|
||||
dtls_peer_type role; /**< DTLS role of the socket */
|
||||
sock_dtls_client_psk_cb_t client_psk_cb;/**< Callback to determine PSK credential for session */
|
||||
sock_dtls_rpk_cb_t rpk_cb; /**< Callback to determine RPK credential for session */
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -30,15 +30,26 @@
|
||||
* - Server operation
|
||||
* 1. Create UDP sock @ref sock_udp_create()
|
||||
* 2. Create DTLS sock @ref sock_dtls_create() using role
|
||||
* @ref SOCK_DTLS_SERVER
|
||||
* 3. Start listening with @ref sock_dtls_recv()
|
||||
* @ref SOCK_DTLS_SERVER.
|
||||
* 3. Optionally:
|
||||
* - when using PSK ciphersuites, set a hint @ref sock_dtls_set_server_psk_id_hint()
|
||||
* - add extra credentials @ref sock_dtls_add_credential()
|
||||
* - when using ECC ciphersuites, set a callback for credential selection
|
||||
* @ref sock_dtls_set_rpk_cb()
|
||||
* 4. Start listening with @ref sock_dtls_recv()
|
||||
* - Client operation
|
||||
* 1. Create UDP sock @ref sock_udp_create()
|
||||
* 2. Create DTLS sock @ref sock_dtls_create() using role
|
||||
* @ref SOCK_DTLS_CLIENT
|
||||
* 3. Start handshake session to server @ref sock_dtls_session_init()
|
||||
* 4. Handle incoming handshake packets with @ref sock_dtls_recv()
|
||||
* 5. Send packet to server @ref sock_dtls_send()
|
||||
* 3. Optionally:
|
||||
* - add extra credentials @ref sock_dtls_add_credential()
|
||||
* - when using PSK ciphersuites, set a callback for hint reception and credential
|
||||
* selection @ref sock_dtls_set_client_psk_cb()
|
||||
* - when using ECC ciphersuites, set a callback for credential selection
|
||||
* @ref sock_dtls_set_rpk_cb()
|
||||
* 4. Start handshake session to server @ref sock_dtls_session_init()
|
||||
* 5. Handle incoming handshake packets with @ref sock_dtls_recv()
|
||||
* 6. Send packet to server @ref sock_dtls_send()
|
||||
*
|
||||
* ## Makefile Includes
|
||||
*
|
||||
@ -156,10 +167,10 @@
|
||||
* [type](@ref credman_credential_t::type).
|
||||
*
|
||||
* Next, we must assign a [tag](@ref credman_tag_t) for the credential. Tags
|
||||
* are unsigned integer value that is used to identify which DTLS sock has
|
||||
* access to which credential. Each DTLS sock will also be assigned a tag.
|
||||
* are unsigned integer values used to identify which DTLS sock has
|
||||
* access to which credentials. Each DTLS sock will also be assigned a list of tags.
|
||||
* As a result, a sock can only use credentials that have the same tag as
|
||||
* its assigned tag.
|
||||
* the ones in the list.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
|
||||
* if (credman_add(&psk_credential) < 0) {
|
||||
@ -468,6 +479,34 @@
|
||||
* return 0;
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* ### Multi-credential handling
|
||||
*
|
||||
* Each sock needs at least one credential tag to operate. `sock_dtls_create` allows to optionally
|
||||
* assign an initial credential. Extra credentials can be added and removed using
|
||||
* @ref sock_dtls_add_credential and @ref sock_dtls_remove_credential respectively (found in
|
||||
* `net/sock/dtls/creds.h`).
|
||||
*
|
||||
* #### Pre-shared Keys Cipher Suites
|
||||
* In the case of PSK, a server can optionally indicate a hint to help the client to decide which
|
||||
* PSK Identity to use, using @ref sock_dtls_set_server_psk_id_hint
|
||||
* (see https://tools.ietf.org/html/rfc4279#section-5.2). The client application can
|
||||
* decide which credential to use based on the sent hint and/or the session information, by
|
||||
* registering a callback with @ref sock_dtls_set_client_psk_cb. If no callback is registered, or
|
||||
* fails to chose a tag (i.e. it returns @ref CREDMAN_TAG_EMPTY), the credential is chosen as
|
||||
* follows: if a hint is sent by the server, all credentials registered to the sock are checked for
|
||||
* a matching @ref psk_params_t::hint "hint". A credential is selected on matching hint. If no
|
||||
* credential matches the hint or no hint is provided, the first PSK credential registered in the
|
||||
* sock is used.
|
||||
*
|
||||
* #### Elliptic Curve Cryptography Cipher Suites
|
||||
* When using ECC both client and server applications can register a callback to decide which of
|
||||
* the registered credentials should be used, based on the session information. This is done using
|
||||
* @ref sock_dtls_set_rpk_cb.
|
||||
*
|
||||
* In both cases, if no callbacks are registered, the sock implementation will try to find a
|
||||
* registered credential in the Sock's credential list, that matches the needed type. The first
|
||||
* one that matches is used.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
@ -613,7 +652,9 @@ void sock_dtls_init(void);
|
||||
* @param[in] udp_sock Existing UDP sock initialized with
|
||||
* @ref sock_udp_create() to be used underneath.
|
||||
* @param[in] tag Credential tag of @p sock. The sock will only use
|
||||
* credentials with the same tag given here.
|
||||
* credentials with the tags registered to it
|
||||
* (see @ref sock_dtls_add_credential). Set to @ref CREDMAN_TAG_EMPTY to
|
||||
* create a sock with an empty tag list.
|
||||
* @param[in] version [DTLS version](@ref sock_dtls_prot_version) to use.
|
||||
* @param[in] role [Role](@ref sock_dtls_role) of the endpoint.
|
||||
*
|
||||
|
152
sys/include/net/sock/dtls/creds.h
Normal file
152
sys/include/net/sock/dtls/creds.h
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (C) 2021 HAW Hamburg
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup net_sock_dtls_creds DTLS sock credentials API
|
||||
* @ingroup net_sock_dtls
|
||||
* @brief Credential handling for DTLS sock
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief DTLS sock definitions
|
||||
*
|
||||
* @author Leandro Lanzieri <leandro.lanzieri@haw-hamburg.de>
|
||||
*/
|
||||
|
||||
#ifndef NET_SOCK_DTLS_CREDS_H
|
||||
#define NET_SOCK_DTLS_CREDS_H
|
||||
|
||||
#include "net/sock/udp.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @ingroup net_sock_dtls_conf
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief Default maximum size for the PSK Identity hint string
|
||||
*/
|
||||
#ifndef CONFIG_DTLS_PSK_ID_HINT_MAX_SIZE
|
||||
#define CONFIG_DTLS_PSK_ID_HINT_MAX_SIZE 32
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Default buffer size for TLS credential tags
|
||||
*/
|
||||
#ifndef CONFIG_DTLS_CREDENTIALS_MAX
|
||||
#define CONFIG_DTLS_CREDENTIALS_MAX 4
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Pre-Shared Key client callback. Called during handshake to determine session credential.
|
||||
*
|
||||
* @param[in] sock DTLS sock object
|
||||
* @param[in] ep Remove UDP endpoint representing the session
|
||||
* @param[in] tags List of credential tags available for @p sock
|
||||
* @param[in] tags_len Number of credentials in @p tags
|
||||
* @param[in] hint Hint sent by the server. May be NULL
|
||||
* @param[in] hint_len Length of @p hint
|
||||
*
|
||||
* @return Tag of the credential to use when a suitable one is found
|
||||
* @retval CREDMAN_TAG_EMPTY otherwise
|
||||
*/
|
||||
typedef credman_tag_t (*sock_dtls_client_psk_cb_t)(sock_dtls_t *sock, sock_udp_ep_t *ep,
|
||||
credman_tag_t tags[], unsigned tags_len,
|
||||
const char* hint, size_t hint_len);
|
||||
|
||||
/**
|
||||
* @brief Raw Public Key callback. Called during handshake to determine the session credential.
|
||||
*
|
||||
* @param[in] sock DTLS sock object
|
||||
* @param[in] ep Remote UDP endpoint representing the session
|
||||
* @param[in] tags List of credential tags available for @p sock
|
||||
* @param[in] tags_len Number of credentials in @p tags
|
||||
*
|
||||
* @return Tag of the credential to use when a suitable one is found
|
||||
* @retval CREDMAN_TAG_EMPTY otherwise
|
||||
*/
|
||||
typedef credman_tag_t (*sock_dtls_rpk_cb_t)(sock_dtls_t *sock, sock_udp_ep_t *ep,
|
||||
credman_tag_t tags[], unsigned tags_len);
|
||||
|
||||
/**
|
||||
* @brief Sets the PSK Identity hint to be sent to clients during handshake.
|
||||
*
|
||||
* This hint is optional. It helps clients to decide which PSK Identity to use.
|
||||
*
|
||||
* @param[in, out] sock The DTLS sock object to set the hint to.
|
||||
* @param[in] hint PSK Identity hint as NULL-terminated string.
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -1 on error
|
||||
*/
|
||||
int sock_dtls_set_server_psk_id_hint(sock_dtls_t *sock, const char *hint);
|
||||
|
||||
/**
|
||||
* @brief Adds a credential tag to list of available credentials for @p sock.
|
||||
*
|
||||
* @pre sock != NULL
|
||||
*
|
||||
* @param[in] sock DTLS sock object
|
||||
* @param[in] tag Tag of the credential to add
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -1 otherwise
|
||||
*/
|
||||
int sock_dtls_add_credential(sock_dtls_t *sock, credman_tag_t tag);
|
||||
|
||||
/**
|
||||
* @brief Removes a credential tag of the list of available credentials for @p sock.
|
||||
*
|
||||
* @pre sock != NULL
|
||||
*
|
||||
* @param[in] sock DTLS sock object
|
||||
* @param[in] tag Tag of the credential to remove
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -1 otherwise
|
||||
*/
|
||||
int sock_dtls_remove_credential(sock_dtls_t *sock, credman_tag_t tag);
|
||||
|
||||
/**
|
||||
* @brief Returns an array of tags of the registered credentials in @p sock.
|
||||
*
|
||||
* @param[in] sock DTLS sock object
|
||||
* @param[out] out Pointer to place the reference to a read-only array of @ref credman_tag_t
|
||||
*
|
||||
* @return Number of registered credentials
|
||||
*/
|
||||
size_t sock_dtls_get_credentials(sock_dtls_t *sock, const credman_tag_t **out);
|
||||
|
||||
/**
|
||||
* @brief Sets the callback function for clients to specify a credential to use
|
||||
* for a given connection.
|
||||
*
|
||||
* @param[in] sock The DTLS sock object to set the callback to.
|
||||
* @param[in] cb Callback to set.
|
||||
*/
|
||||
void sock_dtls_set_client_psk_cb(sock_dtls_t *sock, sock_dtls_client_psk_cb_t cb);
|
||||
|
||||
/**
|
||||
* @brief Sets the callback function to specify a credential to use for a given connection,
|
||||
* when using Raw Public Keys.
|
||||
*
|
||||
* @param[in] sock The DTLS sock object to set the callback to.
|
||||
* @param[in] cb Callback to set.
|
||||
*/
|
||||
void sock_dtls_set_rpk_cb(sock_dtls_t *sock, sock_dtls_rpk_cb_t cb);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NET_SOCK_DTLS_CREDS_H */
|
||||
/** @} */
|
@ -44,4 +44,12 @@ config DTLS_HANDSHAKE_BUFSIZE_EXP
|
||||
represents the exponent of 2^n, which will be used as the size of the
|
||||
buffer. The buffer is used to hold credentials during DTLS handshakes.
|
||||
|
||||
config DTLS_CREDENTIALS_MAX
|
||||
int "Buffer size for TLS credential tags"
|
||||
default 4
|
||||
|
||||
config DTLS_PSK_ID_HINT_MAX_SIZE
|
||||
int "Maximum size for a PSK Identity hint string"
|
||||
default 32
|
||||
|
||||
endif # KCONFIG_USEMODULE_SOCK_DTLS
|
||||
|
@ -59,6 +59,7 @@ static const credman_credential_t credential = {
|
||||
};
|
||||
#else /* #ifdef CONFIG_DTLS_PSK */
|
||||
static const uint8_t psk_key_0[] = PSK_DEFAULT_KEY;
|
||||
static const uint8_t psk_id_0[] = PSK_DEFAULT_IDENTITY;
|
||||
|
||||
static const credman_credential_t credential = {
|
||||
.type = CREDMAN_TYPE_PSK,
|
||||
@ -66,6 +67,7 @@ static const credman_credential_t credential = {
|
||||
.params = {
|
||||
.psk = {
|
||||
.key = { .s = psk_key_0, .len = sizeof(psk_key_0) - 1, },
|
||||
.id = { .s = psk_id_0, .len = sizeof(psk_id_0) - 1, },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user