-
-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathdtls-client.c
182 lines (156 loc) · 5.22 KB
/
dtls-client.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/*
* Copyright (C) 2020 Dyne.org foundation
*
* This file is subject to the terms and conditions of the Affero GNU
* General Public License (AGPL) version 3. See the file LICENSE for
* more details.
*
*/
#include <wolfssl/ssl.h>
#include <wolfssl/error-ssl.h>
#include <sock_tls.h>
#include <net/sock.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.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 <server-address>\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 <address> */
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;
}