OpenSSL:TLS
OpenSSL을 사용하여 TLS를 구현하는 방법에 대하여 정리한다.
Implementation
#define HOST_NAME "www.random.org"
#define HOST_PORT "443"
#define HOST_RESOURCE "/cgi-bin/randbyte?nbytes=32&format=h"
long res = 1;
SSL_CTX* ctx = NULL;
BIO *web = NULL, *out = NULL;
SSL *ssl = NULL;
init_openssl_library();
const SSL_METHOD* method = SSLv23_method();
if(!(NULL != method)) handleFailure();
ctx = SSL_CTX_new(method);
if(!(ctx != NULL)) handleFailure();
/* Cannot fail ??? */
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback);
/* Cannot fail ??? */
SSL_CTX_set_verify_depth(ctx, 4);
/* Cannot fail ??? */
const long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
SSL_CTX_set_options(ctx, flags);
res = SSL_CTX_load_verify_locations(ctx, "random-org-chain.pem", NULL);
if(!(1 == res)) handleFailure();
web = BIO_new_ssl_connect(ctx);
if(!(web != NULL)) handleFailure();
res = BIO_set_conn_hostname(web, HOST_NAME ":" HOST_PORT);
if(!(1 == res)) handleFailure();
BIO_get_ssl(web, &ssl);
if(!(ssl != NULL)) handleFailure();
const char* const PREFERRED_CIPHERS = "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4";
res = SSL_set_cipher_list(ssl, PREFERRED_CIPHERS);
if(!(1 == res)) handleFailure();
res = SSL_set_tlsext_host_name(ssl, HOST_NAME);
if(!(1 == res)) handleFailure();
out = BIO_new_fp(stdout, BIO_NOCLOSE);
if(!(NULL != out)) handleFailure();
res = BIO_do_connect(web);
if(!(1 == res)) handleFailure();
res = BIO_do_handshake(web);
if(!(1 == res)) handleFailure();
/* Step 1: verify a server certificate was presented during the negotiation */
X509* cert = SSL_get_peer_certificate(ssl);
if(cert) { X509_free(cert); } /* Free immediately */
if(NULL == cert) handleFailure();
/* Step 2: verify the result of chain verification */
/* Verification performed according to RFC 4158 */
res = SSL_get_verify_result(ssl);
if(!(X509_V_OK == res)) handleFailure();
/* Step 3: hostname verification */
/* An exercise left to the reader */
BIO_puts(web, "GET " HOST_RESOURCE " HTTP/1.1\r\n"
"Host: " HOST_NAME "\r\n"
"Connection: close\r\n\r\n");
BIO_puts(out, "\n");
int len = 0;
do
{
char buff[1536] = {};
len = BIO_read(web, buff, sizeof(buff));
if(len > 0)
BIO_write(out, buff, len);
} while (len > 0 || BIO_should_retry(web));
if(out)
BIO_free(out);
if(web != NULL)
BIO_free_all(web);
if(NULL != ctx)
SSL_CTX_free(ctx);
Documentation
- libuv-tls
- https://github.com/deleisha/libuv-tls
See also
Favorite site
- Example 'C' code demonstrating a basic SSL/TLS connection The example 'C' program sslconnect.c demonstrates how to make a basic SSL/TLS connection, using the OpenSSL library functions.
- OpenSSL Programming Tutorial
- [추천] Openssl을 이용한 암호화 통신 2
- SSL/TLS Programming - sslClient.c & sslServer.c
- Simple SSL Client Program
- sslconnect.c - example 'C' code demonstrating a basic SSL/TLS connection
- non-blocking socket에 OpenSSL 적용하기 : TOAST Meetup
- [추천] Stackoverflow - Directly Read/Write Handshake data with Memory BIO
- [추천] SSL Handshake 과정
- [추천] 패킷 분석 이용한 프로토콜 분석 - 06_3 - SSL 연결과정 캡처 (handshake)
Example
- Github - examples of using OpenSSL
- [추천] Using OpenSSL with memory BIOs 3
- Github Gist - ZumZoom/OpenSSL BIO_s_mem example