# Simple TLS Server contributed by < `OscarShiang` > ## Requirements To write a TLS server using OpenSSL library, we must install the packages by entering the following commands: ```shell $ sudo apt install libssl-dev ``` ## Create CA Before starting our server, we need key and cerification to configure the SSL sesssion. Using the following commands to generate key and certification: ```shell $ openssl ecparam -out key.pem -genkey -name prime256v1 $ openssl req -x509 -new -key key.pem -out cert.pem ``` ## Workflow of the server 1. initialize OpenSSL library and add algorithm in 2. create and configure SSL_ctx 3. create SSL session and set the session using SSL_ctx 4. create server socket and bind the information 5. listen on the port 6. accept the connection from client 7. do TLS handshake by calling `SSL_accept()` 8. sending data using `SSL_write()` and receive data using `SSL_read()` the implementation is much like this ```c #include <arpa/inet.h> #include <openssl/err.h> #include <openssl/ssl.h> #include <stdio.h> #include <string.h> #include <sys/socket.h> #include <unistd.h> #define OPENSSL_CERT "certs/cert.pem" #define OPENSSL_KEY "certs/key.pem" int create_socket(int port) { int s; struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = htonl(INADDR_ANY); s = socket(AF_INET, SOCK_STREAM, 0); if (s < 0) { perror("Unable to create socket"); exit(EXIT_FAILURE); } if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { perror("Unable to bind"); exit(EXIT_FAILURE); } if (listen(s, 1) < 0) { perror("Unable to listen"); exit(EXIT_FAILURE); } return s; } void init_openssl() { SSL_load_error_strings(); OpenSSL_add_ssl_algorithms(); } void cleanup_openssl() { EVP_cleanup(); } SSL_CTX *create_context() { SSL_CTX *ctx; ctx = SSL_CTX_new(TLS_method()); if (!ctx) { perror("Unable to create SSL context"); ERR_print_errors_fp(stderr); exit(EXIT_FAILURE); } return ctx; } void configure_context(SSL_CTX *ctx) { SSL_CTX_set_ecdh_auto(ctx, 1); /* Set the key and cert */ if (SSL_CTX_use_certificate_file(ctx, OPENSSL_CERT, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); exit(EXIT_FAILURE); } if (SSL_CTX_use_PrivateKey_file(ctx, OPENSSL_KEY, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); exit(EXIT_FAILURE); } } #define PORT 8081 int main(int argc, char **argv) { int sock; SSL_CTX *ctx; init_openssl(); ctx = create_context(); configure_context(ctx); sock = create_socket(PORT); puts("Start to handle connections"); /* Handle connections */ while (1) { struct sockaddr_in addr; uint len = sizeof(addr); SSL *ssl; const char reply[] = "test\n"; int client = accept(sock, (struct sockaddr *) &addr, &len); if (client < 0) { perror("Unable to accept"); exit(EXIT_FAILURE); } ssl = SSL_new(ctx); SSL_set_fd(ssl, client); if (SSL_accept(ssl) <= 0) { ERR_print_errors_fp(stderr); } else { SSL_write(ssl, reply, strlen(reply)); } SSL_shutdown(ssl); SSL_free(ssl); close(client); } close(sock); SSL_CTX_free(ctx); cleanup_openssl(); } ``` ## Compile the source file Because we are using OpenSSL library to perform TLS handshake, we must link the ssl and crypto libraries when compiling the server. ```makefile EXE = tls_server OBJ = tls_server.o CFLAGS = -std=gnu99 -lssl -lcrypto # add these link parameters all: ${EXE} ${EXE}: ${OBJ} ${CC} $< -o $@ ${CFLAGS} %.o: %.c ${CC} -c $< format: @clang-format -i *.c clean: ${RM} ${EXE} *.o .PHONY: all format clean ``` ###### tags: `linux2020`