/* * Copyright (C) 2019 Daniele Lacamera * * 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. */ /** * @ingroup examples * @{ * * @file * @brief Demonstrating DTLS 1.2 client using wolfSSL * * @author Daniele Lacamera * @} */ #include #include #include #include #include #include #include #include "net/gnrc/netif.h" #include "log.h" #define SERVER_PORT 11111 #define APP_DTLS_BUF_SIZE 64 extern const unsigned char server_cert[]; extern const unsigned long server_cert_len; static sock_tls_t skv; static sock_tls_t *sk = &skv; static void usage(const char *cmd_name) { LOG(LOG_ERROR, "Usage: %s \n", cmd_name); } #ifdef MODULE_WOLFSSL_PSK /* identity is OpenSSL testing default for openssl s_client, keep same */ static const char* kIdentityStr = "Client_identity"; static inline unsigned int my_psk_client_cb(WOLFSSL* ssl, const char* hint, char* identity, unsigned int id_max_len, unsigned char* key, unsigned int key_max_len) { (void)ssl; (void)hint; (void)key_max_len; /* see internal.h MAX_PSK_ID_LEN for PSK identity limit */ strncpy(identity, kIdentityStr, id_max_len); if (wolfSSL_GetVersion(ssl) < WOLFSSL_TLSV1_3) { /* test key in hex is 0x1a2b3c4d , in decimal 439,041,101 , we're using unsigned binary */ key[0] = 0x1a; key[1] = 0x2b; key[2] = 0x3c; key[3] = 0x4d; return 4; /* length of key in octets or 0 for error */ } else { int i; int b = 0x01; for (i = 0; i < 32; i++, b += 0x22) { if (b >= 0x100) b = 0x01; key[i] = b; } return 32; /* length of key in octets or 0 for error */ } } #endif int dtls_client(int argc, char **argv) { int ret = 0; char buf[APP_DTLS_BUF_SIZE] = "Hello from DTLS client!"; char *iface; char *addr_str; int connect_timeout = 0; const int max_connect_timeouts = 5; if (argc != 2) { usage(argv[0]); return -1; } addr_str = argv[1]; sock_udp_ep_t local = SOCK_IPV6_EP_ANY; sock_udp_ep_t remote = SOCK_IPV6_EP_ANY; /* Parsing
*/ iface = ipv6_addr_split_iface(addr_str); if (!iface) { if (gnrc_netif_numof() == 1) { /* assign the single interface found in gnrc_netif_numof() */ remote.netif = (uint16_t)gnrc_netif_iter(NULL)->pid; } } else { gnrc_netif_t *netif = gnrc_netif_get_by_pid(atoi(iface)); if (netif == NULL) { LOG(LOG_ERROR, "ERROR: interface not valid\n"); usage(argv[0]); return -1; } remote.netif = (uint16_t)netif->pid; } if (ipv6_addr_from_str((ipv6_addr_t *)remote.addr.ipv6, addr_str) == NULL) { LOG(LOG_ERROR, "ERROR: unable to parse destination address\n"); usage(argv[0]); return -1; } remote.port = SERVER_PORT; if (sock_dtls_create(sk, &local, &remote, 0, wolfDTLSv1_2_client_method()) != 0) { LOG(LOG_ERROR, "ERROR: Unable to create DTLS sock\n"); return -1; } #ifndef MODULE_WOLFSSL_PSK /* Disable certificate validation from the client side */ wolfSSL_CTX_set_verify(sk->ctx, SSL_VERIFY_NONE, 0); /* Load certificate file for the DTLS client */ if (wolfSSL_CTX_use_certificate_buffer(sk->ctx, server_cert, server_cert_len, SSL_FILETYPE_ASN1 ) != SSL_SUCCESS) { LOG(LOG_ERROR, "Error loading cert buffer\n"); return -1; } #else /* !def MODULE_WOLFSSL_PSK */ wolfSSL_CTX_set_psk_client_callback(sk->ctx, my_psk_client_cb); #endif if (sock_dtls_session_create(sk) < 0) return -1; wolfSSL_dtls_set_timeout_init(sk->ssl, 5); LOG(LOG_INFO, "connecting to server...\n"); /* attempt to connect until the connection is successful */ do { ret = wolfSSL_connect(sk->ssl); if ((ret != SSL_SUCCESS)) { if(wolfSSL_get_error(sk->ssl, ret) == SOCKET_ERROR_E) { LOG(LOG_WARNING, "Socket error: reconnecting...\n"); sock_dtls_session_destroy(sk); connect_timeout = 0; if (sock_dtls_session_create(sk) < 0) return -1; } if ((wolfSSL_get_error(sk->ssl, ret) == WOLFSSL_ERROR_WANT_READ) && (connect_timeout++ >= max_connect_timeouts)) { LOG(LOG_WARNING, "Server not responding: reconnecting...\n"); sock_dtls_session_destroy(sk); connect_timeout = 0; if (sock_dtls_session_create(sk) < 0) return -1; } } } while(ret != SSL_SUCCESS); /* set remote endpoint */ sock_dtls_set_endpoint(sk, &remote); /* send the hello message */ wolfSSL_write(sk->ssl, buf, strlen(buf)); /* wait for a reply, indefinitely */ do { ret = wolfSSL_read(sk->ssl, buf, APP_DTLS_BUF_SIZE - 1); LOG(LOG_INFO, "wolfSSL_read returned %d\n", ret); } while (ret <= 0); buf[ret] = (char)0; LOG(LOG_INFO, "Received: '%s'\n", buf); /* Clean up and exit. */ LOG(LOG_INFO, "Closing connection.\n"); sock_dtls_session_destroy(sk); sock_dtls_close(sk); return 0; }