Here's a trivial TLS client program for testing this. David --- /* * TLS-over-TCP send client */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <netdb.h> #include <netinet/in.h> #include <netinet/tcp.h> #include <sys/stat.h> #include <sys/sendfile.h> #include <linux/tls.h> #define OSERROR(X, Y) do { if ((long)(X) == -1) { perror(Y); exit(1); } } while(0) static unsigned char buffer[4096] __attribute__((aligned(4096))); static void set_tls(int sock) { struct tls12_crypto_info_aes_gcm_128 crypto_info; crypto_info.info.version = TLS_1_2_VERSION; crypto_info.info.cipher_type = TLS_CIPHER_AES_GCM_128; memset(crypto_info.iv, 0, TLS_CIPHER_AES_GCM_128_IV_SIZE); memset(crypto_info.rec_seq, 0, TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE); memset(crypto_info.key, 0, TLS_CIPHER_AES_GCM_128_KEY_SIZE); memset(crypto_info.salt, 0, TLS_CIPHER_AES_GCM_128_SALT_SIZE); OSERROR(setsockopt(sock, SOL_TCP, TCP_ULP, "tls", sizeof("tls")), "TCP_ULP"); OSERROR(setsockopt(sock, SOL_TLS, TLS_TX, &crypto_info, sizeof(crypto_info)), "TLS_TX"); OSERROR(setsockopt(sock, SOL_TLS, TLS_RX, &crypto_info, sizeof(crypto_info)), "TLS_RX"); } int main(int argc, char *argv[]) { struct sockaddr_in sin = { .sin_family = AF_INET, .sin_port = htons(5556) }; struct hostent *h; struct stat st; ssize_t r, o; int sf = 0; int cfd, fd; if (argc > 1 && strcmp(argv[1], "-s") == 0) { sf = 1; argc--; argv++; } if (argc != 3) { fprintf(stderr, "tcp-send [-s] <server> <file>\n"); exit(2); } h = gethostbyname(argv[1]); if (!h) { fprintf(stderr, "%s: %s\n", argv[1], hstrerror(h_errno)); exit(3); } if (!h->h_addr_list[0]) { fprintf(stderr, "%s: No addresses\n", argv[1]); exit(3); } memcpy(&sin.sin_addr, h->h_addr_list[0], h->h_length); cfd = socket(AF_INET, SOCK_STREAM, 0); OSERROR(cfd, "socket"); OSERROR(connect(cfd, (struct sockaddr *)&sin, sizeof(sin)), "connect"); set_tls(cfd); fd = open(argv[2], O_RDONLY); OSERROR(fd, argv[2]); OSERROR(fstat(fd, &st), argv[2]); if (!sf) { for (;;) { r = read(fd, buffer, sizeof(buffer)); OSERROR(r, argv[2]); if (r == 0) break; o = 0; do { ssize_t w = write(cfd, buffer + o, r - o); OSERROR(w, "write"); o += w; } while (o < r); } } else { off_t off = 0; r = sendfile(cfd, fd, &off, st.st_size); OSERROR(r, "sendfile"); if (r != st.st_size) { fprintf(stderr, "Short sendfile\n"); exit(1); } } OSERROR(close(cfd), "close/c"); OSERROR(close(fd), "close/f"); return 0; }