Skip to content

TLS manager (TLSMAN) module#9066

Closed
rfuentess wants to merge 4 commits intoRIOT-OS:masterfrom
rfuentess:module/tlsman
Closed

TLS manager (TLSMAN) module#9066
rfuentess wants to merge 4 commits intoRIOT-OS:masterfrom
rfuentess:module/tlsman

Conversation

@rfuentess
Copy link
Contributor

@rfuentess rfuentess commented May 3, 2018

Contribution description

This WIP PR is the first step for achieving the modules proposed in #7649 (TLSMAN) and #7397 (sock_secure). TLSMAN has as objective to binding all the SSL/TLS protocols available (tinyDTLS, WolfSSL, etc.) with the intention of making their use invisible to the user.

Currently this PR adds the following:

  • TLS Manager module (TLSMAN)
  • A test for sock_udp synchronous communication for tinyDTLS

So far, I have tested it with SAMR21-XPRO boards and native.

Working in Progress

The following are the steps intended to be achieved for this PR:

  • (PoC) Test for sock_udp asynchronous communication for tinyDTLS (See [WIP] TLSMAN: Support for sock_async #9446).
  • Adding test cases for handling the sending and reception of data of high sizes, such as CoAP's payload with blockwise transfer.
  • Support for socket communication for tinyDTLS (can be useful for mitigating the integration of packages such as waakama to RIOT)
  • Integrate WolfSSL once the work in PR wolfSSL pkg addition with examples #7348 is mature.

I had achieved partial success for sock_udp asynchronous communication on the initial steps.

Known issues

Two test cases are disabled because of a well identified bug on tinyDTLS (affecting implementations on Linux, RIOT and Contiki) and an issue that is affecting the implementation for RIOT, but I need to research it a little more before to be able to fix it.

The cases affected by the previous issues are for scenarios where a renegotiation without losing the current session is wished. This is why the current dtls-echo example is not affected by it.

The SAMR21 board is having (random) issues with by the call of sock_udp_close() and sock_udp_open() of one specific test case. It's seems to be related more to a timing issue with gnrc than with this PR.

Issues/PRs references

Discussed on:

Depends on:

See also #9446

@rfuentess
Copy link
Contributor Author

rfuentess commented May 16, 2018

Small update for supporting better a server side.

Also, I'm putting here a minimum example for running both sides with synchronous behavior. I'll add them to the module documentation later.

Please, reminds that this module is not intended to be used directly by the user, but by means of another module. These examples are just to show the simplicity in relation to the client/server sides on the dtls-echo example.

P.S. Those codes are also tested with iotlab-m3 boards.


The following is the client side

 #include <stdio.h>

 #include "msg.h"
 #include "net/sock/udp.h"
 #include "net/tlsman.h"

#ifndef SERVER_PORT
#define SERVER_PORT 20220
#endif

#ifndef REMOTE_SERVER
#define REMOTE_SERVER "fd00:dead:beef::1"
#endif

/* List of acceptable cipher suites (T) */
#define SECURE_CIPHER_PSK_IDS (0xC0A8)
#define SECURE_CIPHER_RPK_IDS (0xC0AE)
#define SECURE_CIPHER_LIST { SECURE_CIPHER_PSK_IDS, SECURE_CIPHER_RPK_IDS }

#define MAIN_QUEUE_SIZE     (8)
static msg_t _main_msg_queue[MAIN_QUEUE_SIZE];

static void _resp_handler(uint8_t *data, size_t data_size, void *sock)
{
    (void) sock;
    printf("Answer (%i bytes): --%s--\n", data_size, data);
}

int main(void)
{
    sock_udp_t udp_sock;
    sock_udp_ep_t local = SOCK_IPV6_EP_ANY;
    sock_udp_ep_t remote = SOCK_IPV6_EP_ANY;
    uint8_t tlsman_flags =  TLSMAN_FLAG_STACK_DTLS |
                            TLSMAN_FLAG_SIDE_CLIENT;

    tlsman_session_t dtls_session;
    uint8_t packet_rcvd[DTLS_MAX_BUF];

    msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE);
    puts("Client example implementation with TLSMAN");

    /* The Cipher(s) the application must use (Hardcoded) */
    int chipers[] = SECURE_CIPHER_LIST;
    ssize_t res = tlsman_load_stack(chipers, sizeof(chipers), tlsman_flags);

    local.port = (unsigned short) SERVER_PORT + 10;
    remote.port = (unsigned short) SERVER_PORT;
    ipv6_addr_from_str((ipv6_addr_t *)&remote.addr.ipv6, REMOTE_SERVER);
    sock_udp_create(&udp_sock, &local, &remote, 0);

    res = tlsman_init_context((tlsman_ep_t *) &local,
                                     (tlsman_ep_t *) &remote,
                                    &dtls_session, &udp_sock,
                                    _resp_handler, tlsman_flags);

    if (res != 0) {
        puts("ERROR: Unable to init tlsman context!");
        return -1;
    }

    res = tlsman_create_channel(&dtls_session, tlsman_flags,
                          packet_rcvd, DTLS_MAX_BUF);

    if (tlsman_process_is_error_code_nonfatal(res)) {
        puts("ERROR: Unable to start (D)TLS handhsake process!");
        return -1;
    }
    else if (res == TLSMAN_ERROR_HANDSHAKE_TIMEOUT) {
        puts("ERROR: (D)TLS handshake timeout!");
    }

    while(tlsman_is_channel_ready(&dtls_session)) {
        printf("Send (%i bytes): --%s--\n", sizeof("Ping"), "Ping");
        tlsman_send_data_app(&dtls_session, "Ping", sizeof("Ping"));
        xtimer_usleep(100); /* Simulating other operations */
        tlsman_retrieve_data_app(&dtls_session, packet_rcvd, DTLS_MAX_BUF);
        xtimer_sleep(5);
    }

    return 0;
}

Server side:

  #include <stdio.h>

 #include "msg.h"
 #include "net/tlsman.h"

#ifndef DTLS_DEFAULT_PORT
#define DTLS_DEFAULT_PORT 20220 /* DTLS default port */
#endif

/* List of acceptable cipher suites (T) */
/* NOTE: For now, only CoAP Secure candidates (RFC 7252 9.1.3) */
#define SECURE_CIPHER_PSK_IDS (0xC0A8)
#define SECURE_CIPHER_RPK_IDS (0xC0AE)
#define SECURE_CIPHER_LIST { SECURE_CIPHER_PSK_IDS, SECURE_CIPHER_RPK_IDS }

#define MAIN_QUEUE_SIZE     (8)
static msg_t _main_msg_queue[MAIN_QUEUE_SIZE];

static tlsman_session_t dtls_session;

static void _resp_handler(uint8_t *data, size_t data_size, void *sock)
{
    (void) sock;
    (void) data;
    (void) data_size;
    tlsman_send_data_app(&dtls_session, "Pong", sizeof("Pong"));
}

int main(void)
{

    msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE);
    puts("Sever example implementation with TLSMAN");

    uint8_t pckt_rcvd[DTLS_MAX_BUF];

    sock_udp_t udp_sock;
    sock_udp_ep_t local = SOCK_IPV6_EP_ANY;
    sock_udp_ep_t remote = SOCK_IPV6_EP_ANY;

    uint8_t tlsman_flags =  TLSMAN_FLAG_STACK_DTLS |
                            TLSMAN_FLAG_SIDE_SERVER;

    int chipers[] = SECURE_CIPHER_LIST;
    ssize_t res;

    ipv6_addr_t addrs[GNRC_NETIF_IPV6_ADDRS_NUMOF];
    gnrc_netif_t *netif = gnrc_netif_iter(NULL);
    if ((netif != NULL) &&
        ((res = gnrc_netif_ipv6_addrs_get(netif, addrs, sizeof(addrs))) > 0)) {
        printf("Listening (D)TLS request in: ");
        for (unsigned i = 0; i < (res / sizeof(ipv6_addr_t)); i++) {
            printf("[");
            ipv6_addr_print(&addrs[i]);
            printf("]:%u\n", DTLS_DEFAULT_PORT);
        }
    }

    res = tlsman_load_stack(chipers, sizeof(chipers), tlsman_flags);

    local.port = DTLS_DEFAULT_PORT;
    if (sock_udp_create(&udp_sock, &local, NULL, 0) < 0) {
        puts("ERROR: Unable create sock.");
        return -1;
    }

    res = tlsman_init_context((tlsman_ep_t *) &local,
                                     (tlsman_ep_t *) &remote,
                                    &dtls_session, &udp_sock,
                                    _resp_handler, tlsman_flags);

    if (res != 0) {
        puts("ERROR: Unable to init tlsman context!");
        return -1;
    }

    while(tlsman_listening(&dtls_session, tlsman_flags,
                            pckt_rcvd, DTLS_MAX_BUF)) {
        xtimer_usleep(500);
    }

    return 0;
}

@rfuentess
Copy link
Contributor Author

Part of the work done in the last Paris Hackathon was a redo of the API for TALISMAN.

@rfuentess
Copy link
Contributor Author

A new test case was added for testing sock_async.

Also, I'll do a rebase in the following days.

@miri64
Copy link
Member

miri64 commented Jun 13, 2018

A new test case was added for testing sock_async.

Is it a good idea to base this PR upon a staled WIP API?

@rfuentess
Copy link
Contributor Author

Is it a good idea to base this PR upon a staled WIP API?

For a quickly merge, not at all. However, because this PR and the work for sock_secure are aimed for a single sock (see #7397 comment) I started to integrate it with #8236.

This is converting the PR into a proof of concept instead of a WIP. However, I'm still trying to be agnostic, as much as possible, with the current, and future, sock. So, one alternative would be breaking the PR into two.

@tcschmidt tcschmidt added the State: WIP State: The PR is still work-in-progress and its code is not in its final presentable form yet label Jun 21, 2018
@rfuentess
Copy link
Contributor Author

After thinking a little more, I opted to be more practical for this WIP PR.
Any further work with TLSMAN and sock_async will be done over #9446.

OP was edited according to this change.

@rfuentess rfuentess mentioned this pull request Jun 28, 2018
5 tasks
Raul Fuentes added 4 commits July 4, 2018 14:32
@rfuentess
Copy link
Contributor Author

rfuentess commented Jul 4, 2018

Rebased with master now that #7615 is merged.

@miri64 miri64 added Area: network Area: Networking Area: security Area: Security-related libraries and subsystems Process: API change Integration Process: PR contains or issue proposes an API change. Should be handled with care. Type: new feature The issue requests / The PR implemements a new feature for RIOT labels Oct 17, 2018
@miri64
Copy link
Member

miri64 commented Feb 1, 2019

See #9450 (comment)

@miri64 miri64 closed this Feb 1, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: network Area: Networking Area: security Area: Security-related libraries and subsystems Process: API change Integration Process: PR contains or issue proposes an API change. Should be handled with care. State: WIP State: The PR is still work-in-progress and its code is not in its final presentable form yet Type: new feature The issue requests / The PR implemements a new feature for RIOT

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants