|  | /* | 
|  | * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. | 
|  | * | 
|  | * Licensed under the OpenSSL license (the "License").  You may not use | 
|  | * this file except in compliance with the License.  You can obtain a copy | 
|  | * in the file LICENSE in the source distribution or at | 
|  | * https://www.openssl.org/source/license.html | 
|  | */ | 
|  |  | 
|  | #include "ssltestlib.h" | 
|  |  | 
|  | int create_ssl_ctx_pair(const SSL_METHOD *sm, const SSL_METHOD *cm, | 
|  | SSL_CTX **sctx, SSL_CTX **cctx, char *certfile, | 
|  | char *privkeyfile) | 
|  | { | 
|  | SSL_CTX *serverctx = NULL; | 
|  | SSL_CTX *clientctx = NULL; | 
|  |  | 
|  | serverctx = SSL_CTX_new(sm); | 
|  | clientctx = SSL_CTX_new(cm); | 
|  | if (serverctx == NULL || clientctx == NULL) { | 
|  | printf("Failed to create SSL_CTX\n"); | 
|  | goto err; | 
|  | } | 
|  |  | 
|  | if (SSL_CTX_use_certificate_file(serverctx, certfile, | 
|  | SSL_FILETYPE_PEM) <= 0) { | 
|  | printf("Failed to load server certificate\n"); | 
|  | goto err; | 
|  | } | 
|  | if (SSL_CTX_use_PrivateKey_file(serverctx, privkeyfile, | 
|  | SSL_FILETYPE_PEM) <= 0) { | 
|  | printf("Failed to load server private key\n"); | 
|  | } | 
|  | if (SSL_CTX_check_private_key(serverctx) <= 0) { | 
|  | printf("Failed to check private key\n"); | 
|  | goto err; | 
|  | } | 
|  |  | 
|  | *sctx = serverctx; | 
|  | *cctx = clientctx; | 
|  |  | 
|  | return 1; | 
|  | err: | 
|  | SSL_CTX_free(serverctx); | 
|  | SSL_CTX_free(clientctx); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | #define MAXLOOPS    100000 | 
|  |  | 
|  | /* | 
|  | * NOTE: Transfers control of the BIOs - this function will free them on error | 
|  | */ | 
|  | int create_ssl_connection(SSL_CTX *serverctx, SSL_CTX *clientctx, SSL **sssl, | 
|  | SSL **cssl, BIO *s_to_c_fbio, BIO *c_to_s_fbio) | 
|  | { | 
|  | int retc = -1, rets = -1, err, abortctr = 0; | 
|  | SSL *serverssl, *clientssl; | 
|  | BIO *s_to_c_bio = NULL, *c_to_s_bio = NULL; | 
|  |  | 
|  | serverssl = SSL_new(serverctx); | 
|  | clientssl = SSL_new(clientctx); | 
|  |  | 
|  | if (serverssl == NULL || clientssl == NULL) { | 
|  | printf("Failed to create SSL object\n"); | 
|  | goto error; | 
|  | } | 
|  |  | 
|  | s_to_c_bio = BIO_new(BIO_s_mem()); | 
|  | c_to_s_bio = BIO_new(BIO_s_mem()); | 
|  | if (s_to_c_bio == NULL || c_to_s_bio == NULL) { | 
|  | printf("Failed to create mem BIOs\n"); | 
|  | goto error; | 
|  | } | 
|  |  | 
|  | if (s_to_c_fbio != NULL) | 
|  | s_to_c_bio = BIO_push(s_to_c_fbio, s_to_c_bio); | 
|  | if (c_to_s_fbio != NULL) | 
|  | c_to_s_bio = BIO_push(c_to_s_fbio, c_to_s_bio); | 
|  | if (s_to_c_bio == NULL || c_to_s_bio == NULL) { | 
|  | printf("Failed to create chained BIOs\n"); | 
|  | goto error; | 
|  | } | 
|  |  | 
|  | /* Set Non-blocking IO behaviour */ | 
|  | BIO_set_mem_eof_return(s_to_c_bio, -1); | 
|  | BIO_set_mem_eof_return(c_to_s_bio, -1); | 
|  |  | 
|  | /* Up ref these as we are passing them to two SSL objects */ | 
|  | BIO_up_ref(s_to_c_bio); | 
|  | BIO_up_ref(c_to_s_bio); | 
|  |  | 
|  | SSL_set_bio(serverssl, c_to_s_bio, s_to_c_bio); | 
|  | SSL_set_bio(clientssl, s_to_c_bio, c_to_s_bio); | 
|  |  | 
|  | /* BIOs will now be freed when SSL objects are freed */ | 
|  | s_to_c_bio = c_to_s_bio = NULL; | 
|  | s_to_c_fbio = c_to_s_fbio = NULL; | 
|  |  | 
|  | 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 (retc <= 0 && err != SSL_ERROR_WANT_READ) { | 
|  | printf("SSL_connect() failed %d, %d\n", retc, err); | 
|  | goto error; | 
|  | } | 
|  |  | 
|  | 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 (rets <= 0 && err != SSL_ERROR_WANT_READ) { | 
|  | printf("SSL_accept() failed %d, %d\n", retc, err); | 
|  | goto error; | 
|  | } | 
|  | if (++abortctr == MAXLOOPS) { | 
|  | printf("No progress made\n"); | 
|  | goto error; | 
|  | } | 
|  | } while (retc <=0 || rets <= 0); | 
|  |  | 
|  | *sssl = serverssl; | 
|  | *cssl = clientssl; | 
|  |  | 
|  | return 1; | 
|  |  | 
|  | error: | 
|  | SSL_free(serverssl); | 
|  | SSL_free(clientssl); | 
|  | BIO_free(s_to_c_bio); | 
|  | BIO_free(c_to_s_bio); | 
|  | BIO_free(s_to_c_fbio); | 
|  | BIO_free(c_to_s_fbio); | 
|  |  | 
|  | return 0; | 
|  | } |