X-Git-Url: http://wagner.pp.ru/gitweb/?a=blobdiff_plain;f=test_tls.c;h=77e62815826d98039e6fdcb38a2ad31b5df0f885;hb=021a2b61b5d904caaf4ceb26ff3163f1f0e4219f;hp=fa4048c7afd844a9e4fcd9731536a6b478fb1d27;hpb=7ed64cd58e3f90e7a7229b0a504816e54f9444dc;p=openssl-gost%2Fengine.git diff --git a/test_tls.c b/test_tls.c index fa4048c..77e6281 100644 --- a/test_tls.c +++ b/test_tls.c @@ -8,6 +8,11 @@ * See https://www.openssl.org/source/license.html for details */ +#ifdef _MSC_VER +# pragma warning(push, 3) +# include +# pragma warning(pop) +#endif #include "e_gost_err.h" #include "gost_lcl.h" #include @@ -22,28 +27,24 @@ #include #include #include -#include -#include #include -#include -#include -#include -#include +#ifdef __GNUC__ /* For X509_NAME_add_entry_by_txt */ -#pragma GCC diagnostic ignored "-Wpointer-sign" - -#define T(e) ({ if (!(e)) { \ - ERR_print_errors_fp(stderr); \ - OpenSSLDie(__FILE__, __LINE__, #e); \ - } \ - }) -#define TE(e) ({ if (!(e)) { \ - ERR_print_errors_fp(stderr); \ - fprintf(stderr, "Error at %s:%d %s\n", __FILE__, __LINE__, #e); \ - return -1; \ - } \ - }) +# pragma GCC diagnostic ignored "-Wpointer-sign" +#endif + +#define T(e) \ + if (!(e)) { \ + ERR_print_errors_fp(stderr); \ + OpenSSLDie(__FILE__, __LINE__, #e); \ + } +#define TE(e) \ + if (!(e)) { \ + ERR_print_errors_fp(stderr); \ + fprintf(stderr, "Error at %s:%d %s\n", __FILE__, __LINE__, #e); \ + return -1; \ + } #define cRED "\033[1;31m" #define cDRED "\033[0;31m" @@ -62,154 +63,18 @@ struct certkey { X509 *cert; }; -/* How much K to transfer between client and server. */ -#define KTRANSFER (1 * 1024) +static int verbose; +static const char *cipher_list; -/* - * Simple TLS Server code is based on - * https://wiki.openssl.org/index.php/Simple_TLS_Server - */ -static int s_server(EVP_PKEY *pkey, X509 *cert, int pipewr) -{ - SSL_CTX *ctx; - T(ctx = SSL_CTX_new(TLS_server_method())); - T(SSL_CTX_use_certificate(ctx, cert)); - T(SSL_CTX_use_PrivateKey(ctx, pkey)); - T(SSL_CTX_check_private_key(ctx)); - - struct sockaddr_in addr = { .sin_family = AF_INET }; - socklen_t len; - int sock; - sock = socket(AF_INET, SOCK_STREAM, 0); - if (sock < 0) - err(1, "socket"); - if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) < 0) - err(1, "setsockopt"); - if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) - err(1, "bind"); - len = sizeof(addr); - if (getsockname(sock, (struct sockaddr *)&addr, &len) < 0) - err(1, "getsockname"); - int port = ntohs(addr.sin_port); - if (listen(sock, 1) < 0) - err(1, "listen"); - /* Signal to client that server is ready. */ - if (write(pipewr, &port, sizeof(port)) != sizeof(port)) - err(1, "write pipe"); - len = sizeof(addr); - alarm(1); - int client = accept(sock, (struct sockaddr *)&addr, &len); - if (client < 0) - err(1, "accept"); - alarm(0); - SSL *ssl; - ssl = SSL_new(ctx); - SSL_set_fd(ssl, client); - T(SSL_accept(ssl) == 1); - - /* Receive data from client */ - char buf[1024]; - int i; - for (i = 0; i < KTRANSFER; i++) { - int k; - - T(SSL_read(ssl, buf, sizeof(buf)) == sizeof(buf)); - for (k = 0; k < sizeof(buf); k++) - if (buf[k] != 'c') - err(1, "corruption from client"); - } - /* Send data to client. */ - memset(buf, 's', sizeof(buf)); - for (i = 0; i < KTRANSFER; i++) { - T(SSL_write(ssl, buf, sizeof(buf)) == sizeof(buf)); - } - SSL_shutdown(ssl); - SSL_free(ssl); - close(client); - - close(sock); - SSL_CTX_free(ctx); - return 0; -} - -/* - * Simple TLC Client code is based on man BIO_f_ssl and - * https://wiki.openssl.org/index.php/SSL/TLS_Client - */ -static int s_client(int piperd) +static void err(int eval, const char *fmt, ...) { - SSL_CTX *ctx; - T(ctx = SSL_CTX_new(TLS_client_method())); - - BIO *sbio; - T(sbio = BIO_new_ssl_connect(ctx)); - SSL *ssl; - T(BIO_get_ssl(sbio, &ssl)); - T(SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY)); -#if 0 - /* Does not work with reneg. */ - BIO_set_ssl_renegotiate_bytes(sbio, 100 * 1024); -#endif - int port; - alarm(1); - /* Wait for server to be ready. */ - if (read(piperd, &port, sizeof(port)) != sizeof(port)) - err(1, "read pipe"); - char tport[8]; - snprintf(tport, sizeof(tport), "%d", port); - T(BIO_set_conn_port(sbio, tport)); - T(BIO_do_connect(sbio) == 1); - T(BIO_do_handshake(sbio) == 1); - alarm(0); - - printf("Protocol: %s\n", SSL_get_version(ssl)); - printf("Cipher: %s\n", SSL_get_cipher_name(ssl)); -#if 0 - SSL_SESSION *sess = SSL_get0_session(ssl); - SSL_SESSION_print_fp(stdout, sess); -#endif - - X509 *cert; - T(cert = SSL_get_peer_certificate(ssl)); - X509_free(cert); - int verify = SSL_get_verify_result(ssl); - printf("Verify: %s\n", X509_verify_cert_error_string(verify)); - if (verify != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) - err(1, "invalid SSL_get_verify_result"); - - /* Send data to server. */ - char buf[1024]; - int i; - memset(buf, 'c', sizeof(buf)); - for (i = 0; i < KTRANSFER; i++) { - T(BIO_write(sbio, buf, sizeof(buf)) == sizeof(buf)); - } - (void)BIO_shutdown_wr(sbio); - - /* Receive data from server. */ - for (i = 0; i < KTRANSFER; i++) { - int k; - int n = BIO_read(sbio, buf, sizeof(buf)); - - if (n != sizeof(buf)) { - printf("i:%d BIO_read:%d SSL_get_error:%d\n", i, n, - SSL_get_error(ssl, n)); - ERR_print_errors_fp(stderr); - err(1, "BIO_read"); - } - - for (k = 0; k < sizeof(buf); k++) - if (buf[k] != 's') - err(1, "corruption from server"); - } + va_list ap; - i = BIO_get_num_renegotiates(sbio); - if (i) - printf("Renegs: %d\n", i); - BIO_free_all(sbio); - SSL_CTX_free(ctx); - - return 0; + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + printf(": %s\n", strerror(errno)); + exit(eval); } /* Generate simple cert+key pair. Based on req.c */ @@ -235,8 +100,8 @@ static struct certkey certgen(const char *algname, const char *paramset) T(X509_REQ_set_version(req, 0L)); X509_NAME *name; T(name = X509_NAME_new()); - T(X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, "Test CA", -1, -1, 0)); - T(X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, "Test Key", -1, -1, 0)); + T(X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (unsigned char *)"Test CA", -1, -1, 0)); + T(X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char *)"Test Key", -1, -1, 0)); T(X509_REQ_set_subject_name(req, name)); T(X509_REQ_set_pubkey(req, pkey)); X509_NAME_free(name); @@ -288,6 +153,7 @@ static struct certkey certgen(const char *algname, const char *paramset) return (struct certkey){ .pkey = pkey, .cert = x509ss }; } +/* Non-blocking BIO test mechanic is based on sslapitest.c */ int test(const char *algname, const char *paramset) { int ret = 0; @@ -300,29 +166,105 @@ int test(const char *algname, const char *paramset) struct certkey ck; ck = certgen(algname, paramset); - int pipefd[2]; - if (pipe(pipefd)) - err(1, "pipe"); - - pid_t pid = fork(); - if (pid < 0) - err(1, "fork"); - - if (pid > 0) { - int status; - - ret = s_client(pipefd[0]); - wait(&status); - ret |= WIFEXITED(status) && WEXITSTATUS(status); - X509_free(ck.cert); - EVP_PKEY_free(ck.pkey); - } else if (pid == 0) { - ret = s_server(ck.pkey, ck.cert, pipefd[1]); - X509_free(ck.cert); - EVP_PKEY_free(ck.pkey); - exit(ret); + SSL_CTX *cctx, *sctx; + + T(sctx = SSL_CTX_new(TLS_server_method())); + T(SSL_CTX_use_certificate(sctx, ck.cert)); + T(SSL_CTX_use_PrivateKey(sctx, ck.pkey)); + T(SSL_CTX_check_private_key(sctx)); + + T(cctx = SSL_CTX_new(TLS_client_method())); + + /* create_ssl_objects */ + SSL *serverssl, *clientssl; + T(serverssl = SSL_new(sctx)); + T(clientssl = SSL_new(cctx)); + BIO *s_to_c_bio, *c_to_s_bio; + T(s_to_c_bio = BIO_new(BIO_s_mem())); + T(c_to_s_bio = BIO_new(BIO_s_mem())); + /* Non-blocking IO. */ + BIO_set_mem_eof_return(s_to_c_bio, -1); + BIO_set_mem_eof_return(c_to_s_bio, -1); + /* Transfer BIOs to SSL objects. */ + SSL_set_bio(serverssl, c_to_s_bio, s_to_c_bio); + BIO_up_ref(s_to_c_bio); + BIO_up_ref(c_to_s_bio); + SSL_set_bio(clientssl, s_to_c_bio, c_to_s_bio); + c_to_s_bio = NULL; + c_to_s_bio = NULL; + + /* create_ssl_connection */ + int retc = -1, rets = -1, err; + do { + err = SSL_ERROR_WANT_WRITE; + while (retc <= 0 && err == SSL_ERROR_WANT_WRITE) { + retc = SSL_connect(clientssl); + if (retc <= 0) + err = SSL_get_error(clientssl, retc); + if (verbose) + printf("SSL_connect: %d %d\n", retc, err); + } + if (retc <= 0 && err != SSL_ERROR_WANT_READ) { + ERR_print_errors_fp(stderr); + OpenSSLDie(__FILE__, __LINE__, "SSL_connect"); + } + err = SSL_ERROR_WANT_WRITE; + while (rets <= 0 && err == SSL_ERROR_WANT_WRITE) { + rets = SSL_accept(serverssl); + if (rets <= 0) + err = SSL_get_error(serverssl, rets); + if (verbose) + printf("SSL_accept: %d %d\n", rets, err); + } + if (rets <= 0 && err != SSL_ERROR_WANT_READ && + err != SSL_ERROR_WANT_X509_LOOKUP) { + ERR_print_errors_fp(stderr); + OpenSSLDie(__FILE__, __LINE__, "SSL_accept"); + } + } while (retc <=0 || rets <= 0); + + /* Two SSL_read_ex should fail. */ + unsigned char buf; + size_t readbytes; + T(!SSL_read_ex(clientssl, &buf, sizeof(buf), &readbytes)); + T(!SSL_read_ex(clientssl, &buf, sizeof(buf), &readbytes)); + + /* Connect client to the server. */ + T(SSL_do_handshake(clientssl) == 1); + printf("Protocol: %s\n", SSL_get_version(clientssl)); + printf("Cipher: %s\n", SSL_get_cipher_name(clientssl)); + if (verbose) { + SSL_SESSION *sess = SSL_get0_session(clientssl); + SSL_SESSION_print_fp(stdout, sess); + } + + /* Transfer some data. */ + int i; + for (i = 0; i < 16; i++) { + char pbuf[512], lbuf[512]; + + memset(pbuf, 'c' + i, sizeof(pbuf)); + T(SSL_write(serverssl, pbuf, sizeof(pbuf)) == sizeof(pbuf)); + T(SSL_read(clientssl, lbuf, sizeof(lbuf)) == sizeof(lbuf)); + T(memcmp(pbuf, lbuf, sizeof(pbuf)) == 0); + + memset(lbuf, 's' + i, sizeof(lbuf)); + T(SSL_write(clientssl, lbuf, sizeof(lbuf)) == sizeof(lbuf)); + T(SSL_read(serverssl, pbuf, sizeof(pbuf)) == sizeof(pbuf)); + T(memcmp(pbuf, lbuf, sizeof(pbuf)) == 0); } + SSL_shutdown(clientssl); + SSL_shutdown(serverssl); + + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + + /* Every responsible process should free this. */ + X509_free(ck.cert); + EVP_PKEY_free(ck.pkey); return ret; } @@ -330,15 +272,14 @@ int main(int argc, char **argv) { int ret = 0; - setenv("OPENSSL_ENGINES", ENGINE_DIR, 0); OPENSSL_add_all_algorithms_conf(); - ERR_load_crypto_strings(); - ENGINE *eng; - T(eng = ENGINE_by_id("gost")); - T(ENGINE_init(eng)); - T(ENGINE_set_default(eng, ENGINE_METHOD_ALL)); + + char *p; + if ((p = getenv("VERBOSE"))) + verbose = atoi(p); ret |= test("rsa", NULL); + cipher_list = "LEGACY-GOST2012-GOST8912-GOST8912"; ret |= test("gost2012_256", "A"); ret |= test("gost2012_256", "B"); ret |= test("gost2012_256", "C"); @@ -347,9 +288,6 @@ int main(int argc, char **argv) ret |= test("gost2012_512", "B"); ret |= test("gost2012_512", "C"); - ENGINE_finish(eng); - ENGINE_free(eng); - if (ret) printf(cDRED "= Some tests FAILED!\n" cNORM); else