tls

tls.git
git clone git://git.lenczewski.org/tls.git
Log | Files | Refs

test-client.c (2936B)


      1 #define _GNU_SOURCE 1
      2 
      3 #include "tls.h"
      4 
      5 #include "common.h"
      6 
      7 int
      8 main(int argc, char **argv)
      9 {
     10 	if (argc < 3) {
     11 		fprintf(stderr, "Usage: %s <host> <port>\n", argv[0]);
     12 		exit(EXIT_FAILURE);
     13 	}
     14 
     15 	char *host = argv[1], *port = argv[2];
     16 
     17 	int sock = get_client_socket(host, port, SOCK_STREAM, IPPROTO_TCP);
     18 	if (sock < 0) {
     19 		fprintf(stderr, "Failed to connect to %s:%s\n", host, port);
     20 		exit(EXIT_FAILURE);
     21 	}
     22 
     23 	// plaintext buffer
     24 	char buf[4096];
     25 	size_t buf_cap = sizeof buf, buf_cur = 0, buf_len = 0;
     26 
     27 	// ciphertext buffer
     28 	char tlsbuf[TLS_RECORD_MAX_SIZE];
     29 	size_t tlsbuf_cap = sizeof tlsbuf, tlsbuf_len = 0;
     30 
     31 	// setup client tls session state
     32 	struct tls_session session;
     33 	tls_session_init(&session, TLS_VERSION_1_3, tlsbuf, sizeof tlsbuf);
     34 
     35 	struct x25519_point client_privkey, client_pubkey;
     36 	getrandom(&client_privkey.vs, sizeof client_privkey.vs, 0);
     37 	x25519_genpubkey(&client_pubkey, &client_privkey);
     38 
     39 	// TODO: generate keys using x25519
     40 
     41 	tls_session_set_keys(&session, TLS_NAMED_GROUP_X25519,
     42 			     client_privkey.vs, sizeof client_privkey.vs,
     43 			     client_pubkey.vs, sizeof client_pubkey.vs);
     44 
     45 #if 0
     46 	char client_certificate[8192];
     47 	// TODO: generate certificate
     48 	tls_session_set_cert(&session,
     49 			     client_certificate, sizeof client_certificate);
     50 #endif
     51 
     52 	// start client tls handshake
     53 	tls_session_client_handshake(&session);
     54 
     55 	int run = 1;
     56 	while (run) {
     57 		enum tls_step step = tls_session_step(&session);
     58 
     59 		switch (step) {
     60 		case TLS_STEP_WANT_RECV: { // need to fetch data from remote
     61 			size_t cap;
     62 			void *tlsbuf = tls_session_recv(&session, &cap);
     63 
     64 			int res;
     65 			if ((res = recv(sock, tlsbuf, cap, 0)) < 0)
     66 				__builtin_trap();
     67 
     68 			tls_session_recv_commit(&session, res);
     69 		} break;
     70 
     71 		case TLS_STEP_WANT_SEND: { // need to flush data to remote
     72 			size_t len;
     73 			void *tlsbuf = tls_session_send(&session, &len);
     74 			if (sendall(sock, tlsbuf, len) < 0)
     75 				__builtin_trap();
     76 
     77 			tls_session_send_commit(&session, &len);
     78 		} break;
     79 
     80 		case TLS_STEP_HANDSHAKE: { // need to progress handshake fsm
     81 			tls_session_client_handshake(&session);
     82 		} break;
     83 
     84 		case TLS_STEP_HANDSHAKE_UPDATE_KEYS: { // reached key limits, need update
     85 			tls_session_update_keys();
     86 		} break;
     87 
     88 		case TLS_STEP_HANDSHAKE_ALERT: { // received alert (warning or error)
     89 			__builtin_trap();
     90 		} break;
     91 
     92 		case TLS_STEP_HANDSHAKE_FINISHED: {
     93 			buf_len = sprintf(buf, "ping\n");
     94 
     95 			// TODO: how to signal to start a write?
     96 		} break;
     97 
     98 		case TLS_STEP_HAVE_RECORD: { // received complete tls record
     99 			tls_session_pull(&session, buf, sizeof buf, &buf_len);
    100 			printf("read msg: %.*s\n", (int) buf_len, buf);
    101 		} break;
    102 
    103 		case TLS_STEP_WANT_RECORD: { // want data to fill tls record
    104 			buf_cur += tls_session_push(&session, buf, buf_len - buf_cur);
    105 			if (buf_cur == buf_cap)
    106 				tls_session_flush(&session);
    107 		} break;
    108 
    109 		case TLS_STEP_END: {
    110 			run = 0;
    111 		} break;
    112 		}
    113 	}
    114 
    115 	close(sock);
    116 
    117 	exit(EXIT_SUCCESS);
    118 }
    119 
    120 #include "tls.c"