3 /* This is needed for apple */
4 #define __APPLE_USE_RFC_3542
11 #include <netinet/in.h>
12 #include <sys/types.h>
13 #include <sys/socket.h>
15 #include <arpa/inet.h>
26 * General purpose byte array structure.
28 * Contains pointer to array of bytes and it's length.
33 uint8_t *data; /**< Pointer to the byte array */
34 size_t len; /**< Data size */
38 /**@def BYTE_ARRAY_INITIALIZER
40 * Initializes of existing byte array pointer to \a NULL.
42 #undef BYTE_ARRAY_INITIALIZER
43 #define BYTE_ARRAY_INITIALIZER {NULL, 0}
45 #define DTLS_PRIVATE_KEY_SIZE (32)
46 #define DTLS_PUBLIC_KEY_SIZE (64)
48 #define DEFAULT_PORT 20220
50 #define PSK_CLIENT_IDENTITY "Client_identity"
51 #define PSK_SERVER_IDENTITY "Server_identity"
52 #define PSK_DEFAULT_KEY "secretPSK"
53 #define PSK_OPTIONS "i:s:k:"
54 #define X509_OPTIONS "x:r:u:"
57 #define UNUSED_PARAM __attribute__((unused))
63 static size_t len = 0;
66 size_t length; /* length of string */
67 unsigned char *s; /* string data */
70 static dtls_str output_file = { 0, NULL }; /* output file name */
72 static dtls_context_t *dtls_context = NULL;
73 static dtls_context_t *orig_dtls_context = NULL;
76 #define CLIENT_CRT_LEN 293
77 static const unsigned char g_client_certificate[CLIENT_CRT_LEN] = {
79 0x30, 0x82, 0x01, 0x1e, 0x30, 0x81, 0xc4, 0xa0,
80 0x03, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x38,
81 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce,
82 0x3d, 0x04, 0x03, 0x02, 0x05, 0x00, 0x30, 0x17,
83 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04,
84 0x03, 0x0c, 0x0c, 0x4c, 0x6f, 0x63, 0x61, 0x6c,
85 0x20, 0x49, 0x53, 0x53, 0x55, 0x45, 0x52, 0x30,
86 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x31, 0x30,
87 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
88 0x17, 0x0d, 0x34, 0x39, 0x30, 0x31, 0x30, 0x31,
89 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
90 0x17, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55,
91 0x04, 0x03, 0x0c, 0x0c, 0x4c, 0x6f, 0x63, 0x61,
92 0x6c, 0x20, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54,
93 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
94 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
95 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
96 0x42, 0x00, 0x04, 0xe3, 0xd1, 0x67, 0x1e, 0xdc,
97 0x46, 0xf4, 0x19, 0x50, 0x15, 0x2e, 0x3a, 0x2f,
98 0xd8, 0x68, 0x6b, 0x37, 0x32, 0x84, 0x9e, 0x83,
99 0x81, 0xbf, 0x25, 0x5d, 0xbb, 0x18, 0x07, 0x3c,
100 0xbd, 0xf3, 0xab, 0xd3, 0xbf, 0x53, 0x59, 0xc9,
101 0x1e, 0xce, 0x5b, 0x39, 0x6a, 0xe5, 0x60, 0xf3,
102 0x70, 0xdb, 0x66, 0xb6, 0x80, 0xcb, 0x65, 0x0b,
103 0x35, 0x2a, 0x62, 0x44, 0x89, 0x63, 0x64, 0x6f,
104 0x6f, 0xbd, 0xf0, 0x30, 0x0c, 0x06, 0x08, 0x2a,
105 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x05,
106 0x00, 0x03, 0x47, 0x00, 0x30, 0x44, 0x02, 0x20,
107 0x60, 0xdc, 0x45, 0x77, 0x7d, 0xcb, 0xc3, 0xb4,
108 0xba, 0x60, 0x5a, 0x2e, 0xe5, 0x4e, 0x19, 0x8b,
109 0x48, 0x8a, 0x87, 0xd4, 0x66, 0xb4, 0x1a, 0x86,
110 0x23, 0x67, 0xb8, 0xb6, 0x50, 0xfe, 0x4d, 0xde,
111 0x02, 0x20, 0x60, 0x68, 0x46, 0xff, 0x74, 0x11,
112 0xfb, 0x36, 0x13, 0xf4, 0xa7, 0x3d, 0xb7, 0x35,
113 0x79, 0x23, 0x29, 0x14, 0x6a, 0x28, 0x09, 0xff,
114 0x8c, 0x19, 0x26, 0xe3, 0x41, 0xc8, 0xe4, 0x13,
116 //default client's key pair
117 static const unsigned char x509_priv_key[] = {
118 0xf9, 0x42, 0xb4, 0x16, 0x89, 0x10, 0xf4, 0x07,
119 0x99, 0xb2, 0xe2, 0x9a, 0xed, 0xd4, 0x39, 0xb8,
120 0xca, 0xd4, 0x9d, 0x76, 0x11, 0x43, 0x3a, 0xac,
121 0x14, 0xba, 0x17, 0x9d, 0x3e, 0xbb, 0xbf, 0xbc};
123 static const unsigned char x509_pub_key_x[] = {
124 0xe3, 0xd1, 0x67, 0x1e, 0xdc, 0x46, 0xf4, 0x19,
125 0x50, 0x15, 0x2e, 0x3a, 0x2f, 0xd8, 0x68, 0x6b,
126 0x37, 0x32, 0x84, 0x9e, 0x83, 0x81, 0xbf, 0x25,
127 0x5d, 0xbb, 0x18, 0x07, 0x3c, 0xbd, 0xf3, 0xab};
129 static const unsigned char x509_pub_key_y[] = {
130 0xd3, 0xbf, 0x53, 0x59, 0xc9, 0x1e, 0xce, 0x5b,
131 0x39, 0x6a, 0xe5, 0x60, 0xf3, 0x70, 0xdb, 0x66,
132 0xb6, 0x80, 0xcb, 0x65, 0x0b, 0x35, 0x2a, 0x62,
133 0x44, 0x89, 0x63, 0x64, 0x6f, 0x6f, 0xbd, 0xf0};
136 static const unsigned char x509_ca_pub_x[] = {
137 0x57, 0x94, 0x7f, 0x98, 0x7a, 0x02, 0x67, 0x09,
138 0x25, 0xc1, 0xcb, 0x5a, 0xf5, 0x46, 0xfb, 0xad,
139 0xf7, 0x68, 0x94, 0x8c, 0xa7, 0xe3, 0xf0, 0x5b,
140 0xc3, 0x6b, 0x5c, 0x9b, 0xd3, 0x7d, 0x74, 0x12
143 static const unsigned char x509_ca_pub_y[] = {
144 0xce, 0x68, 0xbc, 0x55, 0xf5, 0xf8, 0x1b, 0x3d,
145 0xef, 0xed, 0x1f, 0x2b, 0xd2, 0x69, 0x5d, 0xcf,
146 0x79, 0x16, 0xa6, 0xbd, 0x97, 0x96, 0x27, 0x60,
147 0x5d, 0xd1, 0xb7, 0x93, 0xa2, 0x4a, 0x62, 0x4d
150 //default server's key pair
151 static const unsigned char serv_pub_key_x[] = {
152 0x07, 0x88, 0x10, 0xdc, 0x62, 0xd7, 0xe6, 0x9b,
153 0x7c, 0xad, 0x6e, 0x78, 0xb0, 0x5f, 0x9a, 0x00,
154 0x11, 0x74, 0x2c, 0x8b, 0xaf, 0x09, 0x65, 0x7c,
155 0x86, 0x8e, 0x55, 0xcb, 0x39, 0x55, 0x72, 0xc6};
157 static const unsigned char serv_pub_key_y[] = {
158 0x65, 0x71, 0xcd, 0x03, 0xdc, 0x2a, 0x4f, 0x46,
159 0x5b, 0x14, 0xc8, 0x27, 0x74, 0xab, 0xf4, 0x1f,
160 0xc1, 0x35, 0x0d, 0x42, 0xbc, 0xc2, 0x9f, 0xb5,
161 0xc1, 0x79, 0xb6, 0x8b, 0xca, 0xdb, 0xff, 0x82};
164 static unsigned char x509_client_cert[DTLS_MAX_CERT_SIZE];
165 static size_t x509_client_cert_len = 0;
166 static unsigned char x509_client_priv[DTLS_PRIVATE_KEY_SIZE+1];
167 static size_t x509_client_priv_is_set = 0;
168 static unsigned char x509_ca_pub[DTLS_PUBLIC_KEY_SIZE+1];
169 static size_t x509_ca_pub_is_set = 0;
171 static int x509_info_from_file = 0;
174 static const unsigned char ecdsa_priv_key[] = {
175 0x41, 0xC1, 0xCB, 0x6B, 0x51, 0x24, 0x7A, 0x14,
176 0x43, 0x21, 0x43, 0x5B, 0x7A, 0x80, 0xE7, 0x14,
177 0x89, 0x6A, 0x33, 0xBB, 0xAD, 0x72, 0x94, 0xCA,
178 0x40, 0x14, 0x55, 0xA1, 0x94, 0xA9, 0x49, 0xFA};
180 static const unsigned char ecdsa_pub_key_x[] = {
181 0x36, 0xDF, 0xE2, 0xC6, 0xF9, 0xF2, 0xED, 0x29,
182 0xDA, 0x0A, 0x9A, 0x8F, 0x62, 0x68, 0x4E, 0x91,
183 0x63, 0x75, 0xBA, 0x10, 0x30, 0x0C, 0x28, 0xC5,
184 0xE4, 0x7C, 0xFB, 0xF2, 0x5F, 0xA5, 0x8F, 0x52};
186 static const unsigned char ecdsa_pub_key_y[] = {
187 0x71, 0xA0, 0xD4, 0xFC, 0xDE, 0x1A, 0xB8, 0x78,
188 0x5A, 0x3C, 0x78, 0x69, 0x35, 0xA7, 0xCF, 0xAB,
189 0xE9, 0x3F, 0x98, 0x72, 0x09, 0xDA, 0xED, 0x0B,
190 0x4F, 0xAB, 0xC3, 0x6F, 0xC7, 0x72, 0xF8, 0x29};
193 #if defined(DTLS_PSK) || defined(DTLS_X509)
195 read_from_file(char *arg, unsigned char *buf, size_t max_buf_len) {
205 bytes_read = fread(buf, 1, max_buf_len, f);
212 result += bytes_read;
213 max_buf_len -= bytes_read;
218 #endif /*DTLS_PSK||DTLS_X509*/
220 /* The PSK information for DTLS */
221 #define PSK_ID_MAXLEN 256
222 #define PSK_MAXLEN 256
223 static unsigned char psk_client_id[PSK_ID_MAXLEN];
224 static size_t psk_client_id_length = 0;
225 static unsigned char psk_server_id[PSK_ID_MAXLEN];
226 static size_t psk_server_id_length = 0;
227 static unsigned char psk_key[PSK_MAXLEN];
228 static size_t psk_key_length = 0;
230 /* This function is the "key store" for tinyDTLS. It is called to
231 * retrieve a key for the given identity within this particular
234 get_psk_info(struct dtls_context_t *ctx UNUSED_PARAM,
235 const session_t *session UNUSED_PARAM,
236 dtls_credentials_type_t type,
237 const unsigned char *id, size_t id_len,
238 unsigned char *result, size_t result_length) {
241 case DTLS_PSK_IDENTITY:
243 dtls_debug("got psk_identity_hint: '%.*s'\n", id_len, id);
246 if (result_length < psk_client_id_length) {
247 dtls_warn("cannot set psk_identity -- buffer too small\n");
248 return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
251 memcpy(result, psk_client_id, psk_client_id_length);
252 return psk_client_id_length;
254 if (id_len != psk_server_id_length || memcmp(psk_server_id, id, id_len) != 0) {
255 dtls_debug("PSK for unknown id requested\n");
257 if (result_length < psk_key_length) {
258 dtls_warn("cannot set psk -- buffer too small\n");
259 return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
262 memcpy(result, psk_key, psk_key_length);
263 return psk_key_length;
265 dtls_warn("unsupported request type: %d\n", type);
268 return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
270 #endif /* DTLS_PSK */
274 get_ecdsa_key(struct dtls_context_t *ctx,
275 const session_t *session,
276 const dtls_ecc_key_t **result) {
279 static const dtls_ecc_key_t ecdsa_key = {
280 .curve = DTLS_ECDH_CURVE_SECP256R1,
281 .priv_key = ecdsa_priv_key,
282 .pub_key_x = ecdsa_pub_key_x,
283 .pub_key_y = ecdsa_pub_key_y
285 *result = &ecdsa_key;
290 verify_ecdsa_key(struct dtls_context_t *ctx,
291 const session_t *session,
292 const unsigned char *other_pub_x,
293 const unsigned char *other_pub_y,
303 #endif /* DTLS_ECC */
307 get_x509_key(struct dtls_context_t *ctx,
308 const session_t *session,
309 const dtls_ecc_key_t **result) {
312 static dtls_ecc_key_t ecdsa_key = {
313 .curve = DTLS_ECDH_CURVE_SECP256R1,
314 .priv_key = x509_priv_key,
315 .pub_key_x = x509_pub_key_x,
316 .pub_key_y = x509_pub_key_y
318 if (x509_info_from_file)
319 ecdsa_key.priv_key = x509_client_priv;
320 *result = &ecdsa_key;
325 get_x509_cert(struct dtls_context_t *ctx,
326 const session_t *session,
327 const unsigned char **cert,
332 if (x509_info_from_file)
334 *cert = x509_client_cert;
335 *cert_size = x509_client_cert_len;
339 *cert = g_client_certificate;
340 *cert_size = CLIENT_CRT_LEN;
346 int check_certificate(byte_array cert_der_code, byte_array ca_public_key)
353 static int verify_x509_cert(struct dtls_context_t *ctx, const session_t *session,
354 const unsigned char *cert, size_t cert_size,
361 const unsigned char *ca_pub_x;
362 const unsigned char *ca_pub_y;
363 byte_array cert_der_code = BYTE_ARRAY_INITIALIZER;
364 byte_array ca_public_key = BYTE_ARRAY_INITIALIZER;
365 unsigned char ca_pub_key[DTLS_PUBLIC_KEY_SIZE];
369 if (x509_info_from_file)
371 ca_pub_x = x509_ca_pub;
372 ca_pub_y = x509_ca_pub + DTLS_PUBLIC_KEY_SIZE/2;
376 ca_pub_x = x509_ca_pub_x;
377 ca_pub_y = x509_ca_pub_y;
380 cert_der_code.data = (uint8_t *)cert;
381 cert_der_code.len = cert_size;
383 ca_public_key.len = DTLS_PUBLIC_KEY_SIZE;
384 ca_public_key.data = ca_pub_key;
385 memcpy(ca_public_key.data, ca_pub_x, DTLS_PUBLIC_KEY_SIZE/2);
386 memcpy(ca_public_key.data + DTLS_PUBLIC_KEY_SIZE/2, ca_pub_y, DTLS_PUBLIC_KEY_SIZE/2);
388 memcpy(x, serv_pub_key_x, x_size);
389 memcpy(y, serv_pub_key_y, y_size);
391 ret = (int) check_certificate(cert_der_code, ca_public_key);
396 static int is_x509_active(struct dtls_context_t *ctx)
402 #endif /* DTLS_X509 */
405 try_send(struct dtls_context_t *ctx, session_t *dst) {
407 res = dtls_write(ctx, dst, (uint8 *)buf, len);
409 memmove(buf, buf + res, len - res);
416 if (fgets(buf + len, sizeof(buf) - len, stdin))
417 len += strlen(buf + len);
421 read_from_peer(struct dtls_context_t *ctx,
422 session_t *session, uint8 *data, size_t len) {
426 for (i = 0; i < len; i++)
427 printf("%c", data[i]);
432 send_to_peer(struct dtls_context_t *ctx,
433 session_t *session, uint8 *data, size_t len) {
435 int fd = *(int *)dtls_get_app_data(ctx);
436 return sendto(fd, data, len, MSG_DONTWAIT,
437 &session->addr.sa, session->size);
441 dtls_handle_read(struct dtls_context_t *ctx) {
444 #define MAX_READ_BUF 2000
445 static uint8 buf[MAX_READ_BUF];
448 fd = *(int *)dtls_get_app_data(ctx);
453 memset(&session, 0, sizeof(session_t));
454 session.size = sizeof(session.addr);
455 len = recvfrom(fd, buf, MAX_READ_BUF, 0,
456 &session.addr.sa, &session.size);
462 dtls_dsrv_log_addr(DTLS_LOG_DEBUG, "peer", &session);
463 dtls_debug_dump("bytes from peer", buf, len);
466 return dtls_handle_message(ctx, &session, buf, len);
469 static void dtls_handle_signal(int sig)
471 dtls_free_context(dtls_context);
472 dtls_free_context(orig_dtls_context);
473 signal(sig, SIG_DFL);
477 /* stolen from libcoap: */
479 resolve_address(const char *server, struct sockaddr *dst) {
481 struct addrinfo *res, *ainfo;
482 struct addrinfo hints;
483 static char addrstr[256];
486 memset(addrstr, 0, sizeof(addrstr));
487 if (server && strlen(server) > 0)
488 memcpy(addrstr, server, strlen(server));
490 memcpy(addrstr, "localhost", 9);
492 memset ((char *)&hints, 0, sizeof(hints));
493 hints.ai_socktype = SOCK_DGRAM;
494 hints.ai_family = AF_UNSPEC;
496 error = getaddrinfo(addrstr, "", &hints, &res);
499 fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error));
503 for (ainfo = res; ainfo != NULL; ainfo = ainfo->ai_next) {
505 switch (ainfo->ai_family) {
509 memcpy(dst, ainfo->ai_addr, ainfo->ai_addrlen);
510 return ainfo->ai_addrlen;
520 /*---------------------------------------------------------------------------*/
522 usage( const char *program, const char *version) {
525 p = strrchr( program, '/' );
529 fprintf(stderr, "%s v%s -- DTLS client implementation\n"
530 "(c) 2011-2014 Olaf Bergmann <bergmann@tzi.org>\n\n"
533 " [-i file] [-s file] [-k file]"
534 #endif /* DTLS_PSK */
536 " [-x file] [-r file] [-u file]"
537 #endif /* DTLS_X509 */
538 " [-o file] [-p port] [-v num] [-c num] addr [port]\n"
540 "\t-i file\t\tread PSK Client identity from file\n"
541 "\t-s file\t\tread PSK Server identity from file\n"
542 "\t-k file\t\tread pre-shared key from file\n"
543 #endif /* DTLS_PSK */
545 "\t-x file\tread Client certificate from file\n"
546 "\t-r file\tread Client private key from file\n"
547 "\t-u file\tread CA public key from file\n"
548 #endif /* DTLS_X509 */
549 "\t-o file\t\toutput received data to this file (use '-' for STDOUT)\n"
550 "\t-p port\t\tlisten on specified port (default is %d)\n"
551 "\t-v num\t\tverbosity level (default: 3)\n"
552 "\t-c num\t\tcipher suite (default: 1)\n"
553 "\t\t\t1: TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 \n"
554 "\t\t\t2: TLS_PSK_WITH_AES_128_CCM_8\n"
555 "\t\t\t3: TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8\n"
556 "\t\t\t4: TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256\n",
557 program, version, program, DEFAULT_PORT);
560 static dtls_handler_t cb = {
561 .write = send_to_peer,
562 .read = read_from_peer,
565 .get_psk_info = get_psk_info,
566 #endif /* DTLS_PSK */
568 .get_ecdsa_key = get_ecdsa_key,
569 .verify_ecdsa_key = verify_ecdsa_key,
570 #endif /* DTLS_ECC */
572 .get_x509_key = get_x509_key,
573 .verify_x509_cert = verify_x509_cert,
574 .get_x509_cert = get_x509_cert,
575 .is_x509_active = is_x509_active,
576 #endif /* DTLS_X509 */
580 #define DTLS_CLIENT_CMD_CLOSE "client:close"
581 #define DTLS_CLIENT_CMD_RENEGOTIATE "client:renegotiate"
583 /* As per RFC 6347 section 4.2.8, DTLS Server should support requests
584 * from clients who have silently abandoned the existing association
585 * and initiated a new handshake request by sending a ClientHello.
586 * Below command tests this feature.
588 #define DTLS_CLIENT_CMD_REHANDSHAKE "client:rehandshake"
591 main(int argc, char **argv) {
593 struct timeval timeout;
594 unsigned short port = DEFAULT_PORT;
595 char port_str[NI_MAXSERV] = "0";
596 log_t log_level = DTLS_LOG_WARN;
599 dtls_cipher_t selected_cipher = TLS_NULL_WITH_NULL_NULL;
600 dtls_cipher_enable_t ecdh_anon_enalbe = DTLS_CIPHER_ENABLE;
605 snprintf(port_str, sizeof(port_str), "%d", port);
608 psk_client_id_length = strlen(PSK_CLIENT_IDENTITY);
609 psk_server_id_length = strlen(PSK_SERVER_IDENTITY);
610 psk_key_length = strlen(PSK_DEFAULT_KEY);
611 memcpy(psk_client_id, PSK_CLIENT_IDENTITY, psk_client_id_length);
612 memcpy(psk_server_id, PSK_SERVER_IDENTITY, psk_server_id_length);
613 memcpy(psk_key, PSK_DEFAULT_KEY, psk_key_length);
614 #endif /* DTLS_PSK */
616 while ((opt = getopt(argc, argv, "p:o:v:c:" PSK_OPTIONS X509_OPTIONS)) != -1) {
620 ssize_t result = read_from_file(optarg, psk_client_id, PSK_ID_MAXLEN);
622 dtls_warn("cannot read Client PSK identity\n");
624 psk_client_id_length = result;
629 ssize_t result = read_from_file(optarg, psk_server_id, PSK_ID_MAXLEN);
631 dtls_warn("cannot read Server PSK identity\n");
633 psk_server_id_length = result;
638 ssize_t result = read_from_file(optarg, psk_key, PSK_MAXLEN);
640 dtls_warn("cannot read PSK\n");
642 psk_key_length = result;
646 #endif /* DTLS_PSK */
650 ssize_t result = read_from_file(optarg, x509_client_cert, DTLS_MAX_CERT_SIZE);
653 dtls_warn("Cannot read Client certificate. Using default\n");
657 x509_client_cert_len = result;
663 ssize_t result = read_from_file(optarg, x509_client_priv, DTLS_PRIVATE_KEY_SIZE+1);
666 dtls_warn("Cannot read Client private key. Using default\n");
670 x509_client_priv_is_set = result;
676 ssize_t result = read_from_file(optarg, x509_ca_pub, DTLS_PUBLIC_KEY_SIZE+1);
679 dtls_warn("Cannot read CA public key. Using default\n");
683 x509_ca_pub_is_set = result;
687 #endif /* DTLS_X509 */
689 strncpy(port_str, optarg, NI_MAXSERV-1);
690 port_str[NI_MAXSERV - 1] = '\0';
693 output_file.length = strlen(optarg);
694 output_file.s = (unsigned char *)malloc(output_file.length + 1);
696 if (!output_file.s) {
697 dtls_crit("cannot set output file: insufficient memory\n");
700 /* copy filename including trailing zero */
701 memcpy(output_file.s, optarg, output_file.length + 1);
705 log_level = strtol(optarg, NULL, 10);
708 if( strcmp(optarg, "1") == 0)
710 selected_cipher = TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256;
711 ecdh_anon_enalbe = DTLS_CIPHER_ENABLE;
713 else if( strcmp(optarg, "2") == 0)
715 selected_cipher = TLS_PSK_WITH_AES_128_CCM_8 ;
716 ecdh_anon_enalbe = DTLS_CIPHER_DISABLE;
718 else if( strcmp(optarg, "3") == 0)
720 selected_cipher = TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 ;
721 ecdh_anon_enalbe = DTLS_CIPHER_DISABLE;
723 else if( strcmp(optarg, "4") == 0)
725 selected_cipher = TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256;
726 ecdh_anon_enalbe = DTLS_CIPHER_DISABLE;
730 usage(argv[0], dtls_package_version());
735 dtls_set_log_level(log_level);
737 if (argc <= optind) {
738 usage(argv[0], dtls_package_version());
743 if (x509_client_cert_len && x509_client_priv_is_set && x509_ca_pub_is_set)
745 x509_info_from_file = 1;
747 else if(!(x509_client_cert_len || x509_client_priv_is_set || x509_ca_pub_is_set))
749 x509_info_from_file = 0;
753 fprintf(stderr,"please set -x, -r, -u options simultaneously");
754 usage(argv[0], dtls_package_version());
757 #endif /* DTLS_X509 */
759 memset(&dst, 0, sizeof(session_t));
760 /* resolve destination address where server should be sent */
761 res = resolve_address(argv[optind++], &dst.addr.sa);
763 dtls_emerg("failed to resolve address\n");
768 /* use port number from command line when specified or the listen
770 dst.addr.sin.sin_port = htons(atoi(optind < argc ? argv[optind++] : port_str));
773 /* init socket and set it to non-blocking */
774 fd = socket(dst.addr.sa.sa_family, SOCK_DGRAM, 0);
777 dtls_alert("socket: %s\n", strerror(errno));
781 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) ) < 0) {
782 dtls_alert("setsockopt SO_REUSEADDR: %s\n", strerror(errno));
785 flags = fcntl(fd, F_GETFL, 0);
786 if (flags < 0 || fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
787 dtls_alert("fcntl: %s\n", strerror(errno));
792 #ifdef IPV6_RECVPKTINFO
793 if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on) ) < 0) {
794 #else /* IPV6_RECVPKTINFO */
795 if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &on, sizeof(on) ) < 0) {
796 #endif /* IPV6_RECVPKTINFO */
797 dtls_alert("setsockopt IPV6_PKTINFO: %s\n", strerror(errno));
800 if (signal(SIGINT, dtls_handle_signal) == SIG_ERR) {
801 dtls_alert("An error occurred while setting a signal handler.\n");
805 dtls_context = dtls_new_context(&fd);
807 dtls_emerg("cannot create context\n");
812 /* select cipher suite */
813 dtls_select_cipher(dtls_context, selected_cipher);
815 /* enable/disable tls_ecdh_anon_with_aes_128_cbc_sha_256 */
816 dtls_enables_anon_ecdh(dtls_context, ecdh_anon_enalbe);
818 dtls_set_handler(dtls_context, &cb);
820 dtls_connect(dtls_context, &dst);
826 FD_SET(fileno(stdin), &rfds);
828 /* FD_SET(fd, &wfds); */
833 result = select(fd+1, &rfds, &wfds, 0, &timeout);
835 if (result < 0) { /* error */
838 } else if (result == 0) { /* timeout */
840 if (FD_ISSET(fd, &wfds))
842 else if (FD_ISSET(fd, &rfds))
843 dtls_handle_read(dtls_context);
844 else if (FD_ISSET(fileno(stdin), &rfds))
849 if (len >= strlen(DTLS_CLIENT_CMD_CLOSE) &&
850 !memcmp(buf, DTLS_CLIENT_CMD_CLOSE, strlen(DTLS_CLIENT_CMD_CLOSE))) {
851 printf("client: closing connection\n");
852 dtls_close(dtls_context, &dst);
854 } else if (len >= strlen(DTLS_CLIENT_CMD_RENEGOTIATE) &&
855 !memcmp(buf, DTLS_CLIENT_CMD_RENEGOTIATE, strlen(DTLS_CLIENT_CMD_RENEGOTIATE))) {
856 printf("client: renegotiate connection\n");
857 dtls_renegotiate(dtls_context, &dst);
859 } else if (len >= strlen(DTLS_CLIENT_CMD_REHANDSHAKE) &&
860 !memcmp(buf, DTLS_CLIENT_CMD_REHANDSHAKE, strlen(DTLS_CLIENT_CMD_REHANDSHAKE))) {
861 printf("client: rehandshake connection\n");
862 if (orig_dtls_context == NULL) {
863 /* Cache the current context. We cannot free the current context as it will notify
864 * the Server to close the connection (which we do not want).
866 orig_dtls_context = dtls_context;
867 /* Now, Create a new context and attempt to initiate a handshake. */
868 dtls_context = dtls_new_context(&fd);
870 dtls_emerg("cannot create context\n");
873 dtls_set_handler(dtls_context, &cb);
874 dtls_connect(dtls_context, &dst);
878 try_send(dtls_context, &dst);
883 dtls_free_context(dtls_context);
884 dtls_free_context(orig_dtls_context);