Skip to main content
  • Home
  • login
  • Browse the archive

    swh mirror partner logo
swh logo
SoftwareHeritage
Software
Heritage
Mirror
Features
  • Search

  • Downloads

  • Save code now

  • Add forge now

  • Help

  • fe7dd1a
  • /
  • test
  • /
  • tlstest_helpers.c
Raw File
Permalinks

To reference or cite the objects present in the Software Heritage archive, permalinks based on SoftWare Hash IDentifiers (SWHIDs) must be used.
Select below a type of object currently browsed in order to display its associated SWHID and permalink.

  • content
  • directory
content badge Iframe embedding
swh:1:cnt:16dce8df552e7749f0b4339a2f6ad3e7c54237cf
directory badge Iframe embedding
swh:1:dir:afd609aa2aed1298dc68e73d964aeceb47031ec2
tlstest_helpers.c
// SPDX-License-Identifier: Apache-2.0 AND MIT
#include <openssl/ssl.h>
#include <openssl/err.h>


#define MAXLOOPS    1000000

int create_tls1_3_ctx_pair(OSSL_LIB_CTX *libctx, SSL_CTX **sctx, SSL_CTX **cctx,
                        char *certfile, char *privkeyfile) {
    SSL_CTX *serverctx = NULL, *clientctx = NULL;

    if (sctx == NULL || cctx == NULL)
        goto err;

    serverctx = SSL_CTX_new_ex(libctx, NULL, TLS_server_method());
    clientctx = SSL_CTX_new_ex(libctx, NULL, TLS_client_method());

    if (serverctx == NULL || clientctx == NULL)
        goto err;

    SSL_CTX_set_options(serverctx,SSL_OP_ALLOW_CLIENT_RENEGOTIATION);
    SSL_CTX_set_min_proto_version(serverctx,TLS1_3_VERSION);
    SSL_CTX_set_max_proto_version(serverctx,TLS1_3_VERSION);
    SSL_CTX_set_min_proto_version(clientctx,TLS1_3_VERSION);
    SSL_CTX_set_max_proto_version(clientctx,TLS1_3_VERSION);

    if (!SSL_CTX_use_certificate_file(serverctx, certfile,
        SSL_FILETYPE_PEM) )
        goto err;

    if (!SSL_CTX_use_PrivateKey_file(serverctx,privkeyfile,
        SSL_FILETYPE_PEM))
        goto err;

    if (!SSL_CTX_check_private_key(serverctx))
        goto err;

    *sctx = serverctx;
    *cctx = clientctx;
    return 1;

    err:
    SSL_CTX_free(serverctx);
    SSL_CTX_free(clientctx);
    return 0;
}

int create_tls_objects(SSL_CTX *serverctx, SSL_CTX *clientctx, SSL **sssl,
                       SSL **cssl) {
    SSL *serverssl = NULL, *clientssl = NULL;
    BIO *s_to_c_bio = NULL, *c_to_s_bio = NULL;

    if(serverctx == NULL || clientctx == NULL)
        goto err;

    serverssl = SSL_new(serverctx);
    clientssl = SSL_new(clientctx);

    if (serverssl == NULL || clientssl == NULL)
        goto err;

    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)
        goto err;

    /* 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 */
    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);

    *sssl = serverssl;
    *cssl = clientssl;

    return 1;

    err:
    SSL_free(serverssl);
    SSL_free(clientssl);
    BIO_free(s_to_c_bio);
    BIO_free(c_to_s_bio);

    return 0;
}

/* Create an SSL connection, but does not read any post-handshake
* NewSessionTicket messages.
* We stop the connection attempt (and return a failure value) if either peer
* has SSL_get_error() return the value in the |want| parameter. The connection
* attempt could be restarted by a subsequent call to this function.
*/
int create_bare_tls_connection(SSL *serverssl, SSL *clientssl, int want,
                               int read)
{
    int retc = -1, rets = -1, err, abortctr = 0;
    int clienterr = 0, servererr = 0;


    do {
        err = SSL_ERROR_WANT_WRITE;
        while (!clienterr && retc <= 0 && err == SSL_ERROR_WANT_WRITE) {
            retc = SSL_connect(clientssl);
            if (retc <= 0)
                err = SSL_get_error(clientssl, retc);
        }

        if (!clienterr && retc <= 0 && err != SSL_ERROR_WANT_READ) {
            fprintf(stderr, "SSL_connect() failed %d, %d", retc, err);
            if (want != SSL_ERROR_SSL)
                ERR_clear_error();
            clienterr = 1;
        }
        if (want != SSL_ERROR_NONE && err == want)
            return 0;

        err = SSL_ERROR_WANT_WRITE;
        while (!servererr && rets <= 0 && err == SSL_ERROR_WANT_WRITE) {
            rets = SSL_accept(serverssl);
            if (rets <= 0)
                err = SSL_get_error(serverssl, rets);
        }

        if (!servererr && rets <= 0
            && err != SSL_ERROR_WANT_READ
            && err != SSL_ERROR_WANT_X509_LOOKUP) {
            fprintf(stderr, "SSL_accept() failed %d, %d", rets, err);
            if (want != SSL_ERROR_SSL)
                ERR_clear_error();
            servererr = 1;
        }
        if (want != SSL_ERROR_NONE && err == want)
            return 0;
        if (clienterr && servererr)
            return 0;

        if (++abortctr == MAXLOOPS) {
            fprintf(stderr, "No progress made");
            return 0;
        }

    } while (retc <=0 || rets <= 0);

    return 1;
}

/*
 * Create an SSL connection including any post handshake NewSessionTicket
 * messages.
 */
int create_tls_connection(SSL *serverssl, SSL *clientssl, int want)
{
    int i;
    unsigned char buf;
    size_t readbytes;

    if (!create_bare_tls_connection(serverssl, clientssl, want, 1))
        return 0;

    /*
     * We attempt to read some data on the client side which we expect to fail.
     * This will ensure we have received the NewSessionTicket in TLSv1.3 where
     * appropriate. We do this twice because there are 2 NewSessionTickets.
     */
    for (i = 0; i < 2; i++) {
        if (SSL_read_ex(clientssl, &buf, sizeof(buf), &readbytes) > 0) {
            if (readbytes !=0)
                return 0;
        } else if (SSL_get_error(clientssl, 0) != SSL_ERROR_WANT_READ) {
            return 0;
        }
    }

    return 1;
}

ENEA — Copyright (C), ENEA. License: GNU AGPLv3+.
Legal notes  ::  JavaScript license information ::  Web API

back to top