Skip to content
sslapitest.c 28.4 KiB
Newer Older
Matt Caswell's avatar
Matt Caswell committed
/*
 * 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
 */

Matt Caswell's avatar
Matt Caswell committed
#include <string.h>

Matt Caswell's avatar
Matt Caswell committed
#include <openssl/opensslconf.h>
#include <openssl/bio.h>
#include <openssl/crypto.h>
#include <openssl/ssl.h>
Matt Caswell's avatar
Matt Caswell committed
#include <openssl/ocsp.h>
Matt Caswell's avatar
Matt Caswell committed

#include "ssltestlib.h"
#include "testutil.h"
#include "test_main_custom.h"
#include "e_os.h"
Matt Caswell's avatar
Matt Caswell committed

static char *cert = NULL;
static char *privkey = NULL;

#ifndef OPENSSL_NO_OCSP
Matt Caswell's avatar
Matt Caswell committed
static const unsigned char orespder[] = "Dummy OCSP Response";
static int ocsp_server_called = 0;
static int ocsp_client_called = 0;

static int cdummyarg = 1;
static X509 *ocspcert = NULL;
#define NUM_EXTRA_CERTS 40

static int execute_test_large_message(const SSL_METHOD *smeth,
Matt Caswell's avatar
Matt Caswell committed
                                      const SSL_METHOD *cmeth, int read_ahead)
{
    SSL_CTX *cctx = NULL, *sctx = NULL;
    SSL *clientssl = NULL, *serverssl = NULL;
    int testresult = 0;
    int i;
    BIO *certbio = BIO_new_file(cert, "r");
    X509 *chaincert = NULL;
    int certlen;

    if (certbio == NULL) {
        printf("Can't load the certficate file\n");
        goto end;
    }
    chaincert = PEM_read_bio_X509(certbio, NULL, NULL, NULL);
    BIO_free(certbio);
    certbio = NULL;
    if (chaincert == NULL) {
        printf("Unable to load certificate for chain\n");
        goto end;
    }

    if (!create_ssl_ctx_pair(smeth, cmeth, &sctx,
                             &cctx, cert, privkey)) {
        printf("Unable to create SSL_CTX pair\n");
        goto end;
    }

Matt Caswell's avatar
Matt Caswell committed
    if(read_ahead) {
        /*
         * Test that read_ahead works correctly when dealing with large
         * records
         */
        SSL_CTX_set_read_ahead(cctx, 1);
    }

    /*
     * We assume the supplied certificate is big enough so that if we add
     * NUM_EXTRA_CERTS it will make the overall message large enough. The
     * default buffer size is requested to be 16k, but due to the way BUF_MEM
     * works, it ends up allocing a little over 21k (16 * 4/3). So, in this test
     * we need to have a message larger than that.
     */
    certlen = i2d_X509(chaincert, NULL);
    OPENSSL_assert((certlen * NUM_EXTRA_CERTS)
                   > ((SSL3_RT_MAX_PLAIN_LENGTH * 4) / 3));
    for (i = 0; i < NUM_EXTRA_CERTS; i++) {
        if (!X509_up_ref(chaincert)) {
            printf("Unable to up ref cert\n");
            goto end;
        }
        if (!SSL_CTX_add_extra_chain_cert(sctx, chaincert)) {
            printf("Unable to add extra chain cert %d\n", i);
            X509_free(chaincert);
            goto end;
        }
    }

    if (!create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, NULL)) {
        printf("Unable to create SSL objects\n");
        goto end;
    }

    if (!create_ssl_connection(serverssl, clientssl)) {
        printf("Unable to create SSL connection\n");
        goto end;
    }

Matt Caswell's avatar
Matt Caswell committed
    /*
     * Calling SSL_clear() first is not required but this tests that SSL_clear()
     * doesn't leak (when using enable-crypto-mdebug).
     */
    if (!SSL_clear(serverssl)) {
        printf("Unexpected failure from SSL_clear()\n");
        goto end;
    }
Matt Caswell's avatar
Matt Caswell committed
    testresult = 1;
 end:
    X509_free(chaincert);
    SSL_free(serverssl);
    SSL_free(clientssl);
    SSL_CTX_free(sctx);
    SSL_CTX_free(cctx);

    return testresult;
}

static int test_large_message_tls(void)
{
Matt Caswell's avatar
Matt Caswell committed
    return execute_test_large_message(TLS_server_method(), TLS_client_method(),
                                      0);
}

static int test_large_message_tls_read_ahead(void)
{
    return execute_test_large_message(TLS_server_method(), TLS_client_method(),
                                      1);
Matt Caswell's avatar
Matt Caswell committed
#ifndef OPENSSL_NO_DTLS
static int test_large_message_dtls(void)
{
Matt Caswell's avatar
Matt Caswell committed
    /*
     * read_ahead is not relevant to DTLS because DTLS always acts as if
     * read_ahead is set.
     */
    return execute_test_large_message(DTLS_server_method(),
Matt Caswell's avatar
Matt Caswell committed
                                      DTLS_client_method(), 0);
Matt Caswell's avatar
Matt Caswell committed
#endif
#ifndef OPENSSL_NO_OCSP
Matt Caswell's avatar
Matt Caswell committed
static int ocsp_server_cb(SSL *s, void *arg)
{
    int *argi = (int *)arg;
    unsigned char *orespdercopy = NULL;
    STACK_OF(OCSP_RESPID) *ids = NULL;
    OCSP_RESPID *id = NULL;

    if (*argi == 2) {
        /* In this test we are expecting exactly 1 OCSP_RESPID */
        SSL_get_tlsext_status_ids(s, &ids);
        if (ids == NULL || sk_OCSP_RESPID_num(ids) != 1)
            return SSL_TLSEXT_ERR_ALERT_FATAL;

        id = sk_OCSP_RESPID_value(ids, 0);
        if (id == NULL || !OCSP_RESPID_match(id, ocspcert))
            return SSL_TLSEXT_ERR_ALERT_FATAL;
    } else if (*argi != 1) {
        return SSL_TLSEXT_ERR_ALERT_FATAL;
    }


    orespdercopy = OPENSSL_memdup(orespder, sizeof(orespder));
    if (orespdercopy == NULL)
        return SSL_TLSEXT_ERR_ALERT_FATAL;

    SSL_set_tlsext_status_ocsp_resp(s, orespdercopy, sizeof(orespder));

    ocsp_server_called = 1;

    return SSL_TLSEXT_ERR_OK;
}

static int ocsp_client_cb(SSL *s, void *arg)
{
    int *argi = (int *)arg;
    const unsigned char *respderin;
    size_t len;

    if (*argi != 1 && *argi != 2)
        return 0;

    len = SSL_get_tlsext_status_ocsp_resp(s, &respderin);

    if (memcmp(orespder, respderin, len) != 0)
        return 0;

    ocsp_client_called = 1;

    return 1;
}
Loading
Loading full blame…