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"