Beispiel #1
0
static int test_fatalerr(void)
{
    SSL_CTX *sctx = NULL, *cctx = NULL;
    SSL *sssl = NULL, *cssl = NULL;
    const char *msg = "Dummy";
    BIO *wbio = NULL;
    int ret = 0, len;
    char buf[80];
    unsigned char dummyrec[] = {
        0x17, 0x03, 0x03, 0x00, 0x05, 'D', 'u', 'm', 'm', 'y'
    };

    if (!TEST_true(create_ssl_ctx_pair(TLS_method(), TLS_method(), &sctx, &cctx,
                                       cert, privkey)))
        goto err;

    /*
     * Deliberately set the cipher lists for client and server to be different
     * to force a handshake failure.
     */
    if (!TEST_true(SSL_CTX_set_cipher_list(sctx, "AES128-SHA"))
            || !TEST_true(SSL_CTX_set_cipher_list(cctx, "AES256-SHA"))
            || !TEST_true(create_ssl_objects(sctx, cctx, &sssl, &cssl, NULL,
                          NULL)))
        goto err;

    wbio = SSL_get_wbio(cssl);
    if (!TEST_ptr(wbio)) {
        printf("Unexpected NULL bio received\n");
        goto err;
    }

    /* Connection should fail */
    if (!TEST_false(create_ssl_connection(sssl, cssl, SSL_ERROR_NONE)))
        goto err;

    ERR_clear_error();

    /* Inject a plaintext record from client to server */
    if (!TEST_int_gt(BIO_write(wbio, dummyrec, sizeof(dummyrec)), 0))
        goto err;

    /* SSL_read()/SSL_write should fail because of a previous fatal error */
    if (!TEST_int_le(len = SSL_read(sssl, buf, sizeof(buf - 1)), 0)) {
        buf[len] = '\0';
        TEST_error("Unexpected success reading data: %s\n", buf);
        goto err;
    }
    if (!TEST_int_le(SSL_write(sssl, msg, strlen(msg)), 0))
        goto err;

    ret = 1;
 err:
    SSL_free(sssl);
    SSL_free(cssl);
    SSL_CTX_free(sctx);
    SSL_CTX_free(cctx);

    return ret;
}
Beispiel #2
0
static int check_alerts(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx)
{
    if (!TEST_int_eq(result->client_alert_sent,
                     result->client_alert_received)) {
        TEST_info("Client sent alert %s but server received %s.",
                  print_alert(result->client_alert_sent),
                  print_alert(result->client_alert_received));
        /*
         * We can't bail here because the peer doesn't always get far enough
         * to process a received alert. Specifically, in protocol version
         * negotiation tests, we have the following scenario.
         * Client supports TLS v1.2 only; Server supports TLS v1.1.
         * Client proposes TLS v1.2; server responds with 1.1;
         * Client now sends a protocol alert, using TLS v1.2 in the header.
         * The server, however, rejects the alert because of version mismatch
         * in the record layer; therefore, the server appears to never
         * receive the alert.
         */
        /* return 0; */
    }

    if (!TEST_int_eq(result->server_alert_sent,
                     result->server_alert_received)) {
        TEST_info("Server sent alert %s but client received %s.",
                  print_alert(result->server_alert_sent),
                  print_alert(result->server_alert_received));
        /* return 0; */
    }

    /* Tolerate an alert if one wasn't explicitly specified in the test. */
    if (test_ctx->expected_client_alert
        /*
         * The info callback alert value is computed as
         * (s->s3->send_alert[0] << 8) | s->s3->send_alert[1]
         * where the low byte is the alert code and the high byte is other stuff.
         */
        && (result->client_alert_sent & 0xff) != test_ctx->expected_client_alert) {
        TEST_error("ClientAlert mismatch: expected %s, got %s.",
                   print_alert(test_ctx->expected_client_alert),
                   print_alert(result->client_alert_sent));
        return 0;
    }

    if (test_ctx->expected_server_alert
        && (result->server_alert_sent & 0xff) != test_ctx->expected_server_alert) {
        TEST_error("ServerAlert mismatch: expected %s, got %s.",
                   print_alert(test_ctx->expected_server_alert),
                   print_alert(result->server_alert_sent));
        return 0;
    }

    if (!TEST_int_le(result->client_num_fatal_alerts_sent, 1))
        return 0;
    if (!TEST_int_le(result->server_num_fatal_alerts_sent, 1))
        return 0;
    return 1;
}
Beispiel #3
0
static int fbytes(unsigned char *buf, int num)
{
    int ret = 0;
    static int fbytes_counter = 0;
    BIGNUM *tmp = NULL;

    if (use_fake == 0)
        return old_rand->bytes(buf, num);

    use_fake = 0;

    if (!TEST_ptr(tmp = BN_new())
        || !TEST_int_lt(fbytes_counter, OSSL_NELEM(numbers))
        || !TEST_true(BN_hex2bn(&tmp, numbers[fbytes_counter]))
        /* tmp might need leading zeros so pad it out */
        || !TEST_int_le(BN_num_bytes(tmp), num)
        || !TEST_true(BN_bn2binpad(tmp, buf, num)))
        goto err;

    fbytes_counter = (fbytes_counter + 1) % OSSL_NELEM(numbers);
    ret = 1;
 err:
    BN_free(tmp);
    return ret;
}
Beispiel #4
0
static int sanity_check_bytes(size_t (*rng)(unsigned char *, size_t), 
    int rounds, int min_failures, int max_retries, int max_zero_words)
{
    int testresult = 0;
    unsigned char prior[31] = {0}, buf[31] = {0}, check[7];
    int failures = 0, zero_words = 0;

    int i;
    for (i = 0; i < rounds; i++) {
        size_t generated = 0;

        int retry;
        for (retry = 0; retry < max_retries; retry++) {
            generated = rng(buf, sizeof(buf));
            if (generated == sizeof(buf))
                break;
            failures++;
        }

        /*-
         * Verify that we don't have too many unexpected runs of zeroes,
         * implying that we might be accidentally using the 32-bit RDRAND
         * instead of the 64-bit one on 64-bit systems.
         */
        size_t j;
        for (j = 0; j < sizeof(buf) - 1; j++) {
            if (buf[j] == 0 && buf[j+1] == 0) {
                zero_words++;
            }
        }

        if (!TEST_int_eq(generated, sizeof(buf)))
            goto end;
        if (!TEST_false(!memcmp(prior, buf, sizeof(buf))))
            goto end;

        /* Verify that the last 7 bytes of buf aren't all the same value */
        unsigned char *tail = &buf[sizeof(buf) - sizeof(check)];
        memset(check, tail[0], 7);
        if (!TEST_false(!memcmp(check, tail, sizeof(check))))
            goto end;

        /* Save the result and make sure it's different next time */
        memcpy(prior, buf, sizeof(buf));
    }

    if (!TEST_int_le(zero_words, max_zero_words))
        goto end;

    if (!TEST_int_ge(failures, min_failures))
        goto end;

    testresult = 1;
end:
    return testresult;
}
Beispiel #5
0
static int client_setup_sni_after_state(void)
{
    SSL_CTX *ctx;
    SSL *con = NULL;
    BIO *rbio;
    BIO *wbio;
    char *hostname = NULL;
    int ret = 0;

    /* use TLS_method to blur 'side' */
    ctx = SSL_CTX_new(TLS_method());
    if (!TEST_ptr(ctx))
        goto end;

    con = SSL_new(ctx);
    if (!TEST_ptr(con))
        goto end;

    rbio = BIO_new(BIO_s_mem());
    wbio = BIO_new(BIO_s_mem());
    if (!TEST_ptr(rbio)|| !TEST_ptr(wbio)) {
        BIO_free(rbio);
        BIO_free(wbio);
        goto end;
    }

    SSL_set_bio(con, rbio, wbio);
    SSL_set_connect_state(con);

    /* set SNI after 'client side' is set */
    SSL_set_tlsext_host_name(con, host);

    if (!TEST_int_le(SSL_connect(con), 0))
        /* This shouldn't succeed because we don't have a server! */
        goto end;
    if (!TEST_true(get_sni_from_client_hello(wbio, &hostname)))
        /* no SNI in client hello */
        goto end;
    if (!TEST_str_eq(hostname, host))
        /* incorrect SNI value */
        goto end;
    ret = 1;
end:
    OPENSSL_free(hostname);
    SSL_free(con);
    SSL_CTX_free(ctx);
    return ret;
}
Beispiel #6
0
/*
 * Perform extensive error checking as required by SP800-90.
 * Induce several failure modes and check an error condition is set.
 */
static int error_check(DRBG_SELFTEST_DATA *td)
{
    static char zero[sizeof(RAND_DRBG)];
    RAND_DRBG *drbg = NULL;
    TEST_CTX t;
    unsigned char buff[1024];
    unsigned int generate_counter_tmp;
    int ret = 0;

    if (!TEST_ptr(drbg = RAND_DRBG_new(0, 0, NULL)))
        goto err;

    /*
     * Personalisation string tests
     */

    /* Test detection of too large personlisation string */
    if (!init(drbg, td, &t)
            || RAND_DRBG_instantiate(drbg, td->pers, drbg->max_perslen + 1) > 0)
        goto err;

    /*
     * Entropy source tests
     */

    /* Test entropy source failure detecion: i.e. returns no data */
    t.entropylen = 0;
    if (TEST_int_le(RAND_DRBG_instantiate(drbg, td->pers, td->perslen), 0))
        goto err;

    /* Try to generate output from uninstantiated DRBG */
    if (!TEST_false(RAND_DRBG_generate(drbg, buff, td->exlen, 0,
                                       td->adin, td->adinlen))
            || !uninstantiate(drbg))
        goto err;

    /* Test insufficient entropy */
    t.entropylen = drbg->min_entropylen - 1;
    if (!init(drbg, td, &t)
            || RAND_DRBG_instantiate(drbg, td->pers, td->perslen) > 0
            || !uninstantiate(drbg))
        goto err;

    /* Test too much entropy */
    t.entropylen = drbg->max_entropylen + 1;
    if (!init(drbg, td, &t)
            || RAND_DRBG_instantiate(drbg, td->pers, td->perslen) > 0
            || !uninstantiate(drbg))
        goto err;

    /*
     * Nonce tests
     */

    /* Test too small nonce */
    if (drbg->min_noncelen) {
        t.noncelen = drbg->min_noncelen - 1;
        if (!init(drbg, td, &t)
                || RAND_DRBG_instantiate(drbg, td->pers, td->perslen) > 0
                || !uninstantiate(drbg))
            goto err;
    }

    /* Test too large nonce */
    if (drbg->max_noncelen) {
        t.noncelen = drbg->max_noncelen + 1;
        if (!init(drbg, td, &t)
                || RAND_DRBG_instantiate(drbg, td->pers, td->perslen) > 0
                || !uninstantiate(drbg))
            goto err;
    }

    /* Instantiate with valid data, Check generation is now OK */
    if (!instantiate(drbg, td, &t)
            || !TEST_true(RAND_DRBG_generate(drbg, buff, td->exlen, 0,
                                             td->adin, td->adinlen)))
        goto err;

    /* Request too much data for one request */
    if (!TEST_false(RAND_DRBG_generate(drbg, buff, drbg->max_request + 1, 0,
                                       td->adin, td->adinlen)))
        goto err;

    /* Try too large additional input */
    if (!TEST_false(RAND_DRBG_generate(drbg, buff, td->exlen, 0,
                                       td->adin, drbg->max_adinlen + 1)))
        goto err;

    /*
     * Check prediction resistance request fails if entropy source
     * failure.
     */
    t.entropylen = 0;
    if (TEST_false(RAND_DRBG_generate(drbg, buff, td->exlen, 1,
                                      td->adin, td->adinlen))
            || !uninstantiate(drbg))
        goto err;

    /* Instantiate again with valid data */
    if (!instantiate(drbg, td, &t))
        goto err;
    generate_counter_tmp = drbg->generate_counter;
    drbg->generate_counter = drbg->reseed_interval;

    /* Generate output and check entropy has been requested for reseed */
    t.entropycnt = 0;
    if (!TEST_true(RAND_DRBG_generate(drbg, buff, td->exlen, 0,
                                      td->adin, td->adinlen))
            || !TEST_int_eq(t.entropycnt, 1)
            || !TEST_int_eq(drbg->generate_counter, generate_counter_tmp + 1)
            || !uninstantiate(drbg))
        goto err;

    /*
     * Check prediction resistance request fails if entropy source
     * failure.
     */
    t.entropylen = 0;
    if (!TEST_false(RAND_DRBG_generate(drbg, buff, td->exlen, 1,
                                       td->adin, td->adinlen))
            || !uninstantiate(drbg))
        goto err;

    /* Test reseed counter works */
    if (!instantiate(drbg, td, &t))
        goto err;
    generate_counter_tmp = drbg->generate_counter;
    drbg->generate_counter = drbg->reseed_interval;

    /* Generate output and check entropy has been requested for reseed */
    t.entropycnt = 0;
    if (!TEST_true(RAND_DRBG_generate(drbg, buff, td->exlen, 0,
                                      td->adin, td->adinlen))
            || !TEST_int_eq(t.entropycnt, 1)
            || !TEST_int_eq(drbg->generate_counter, generate_counter_tmp + 1)
            || !uninstantiate(drbg))
        goto err;

    /*
     * Explicit reseed tests
     */

    /* Test explicit reseed with too large additional input */
    if (!init(drbg, td, &t)
            || RAND_DRBG_reseed(drbg, td->adin, drbg->max_adinlen + 1, 0) > 0)
        goto err;

    /* Test explicit reseed with entropy source failure */
    t.entropylen = 0;
    if (!TEST_int_le(RAND_DRBG_reseed(drbg, td->adin, td->adinlen, 0), 0)
            || !uninstantiate(drbg))
        goto err;

    /* Test explicit reseed with too much entropy */
    if (!init(drbg, td, &t))
        goto err;
    t.entropylen = drbg->max_entropylen + 1;
    if (!TEST_int_le(RAND_DRBG_reseed(drbg, td->adin, td->adinlen, 0), 0)
            || !uninstantiate(drbg))
        goto err;

    /* Test explicit reseed with too little entropy */
    if (!init(drbg, td, &t))
        goto err;
    t.entropylen = drbg->min_entropylen - 1;
    if (!TEST_int_le(RAND_DRBG_reseed(drbg, td->adin, td->adinlen, 0), 0)
            || !uninstantiate(drbg))
        goto err;

    /* Standard says we have to check uninstantiate really zeroes */
    if (!TEST_mem_eq(zero, sizeof(drbg->data), &drbg->data, sizeof(drbg->data)))
        goto err;

    ret = 1;

err:
    uninstantiate(drbg);
    RAND_DRBG_free(drbg);
    return ret;
}
static int test_siphash(int idx)
{
    SIPHASH siphash;
    TESTDATA test = tests[idx];
    unsigned char key[SIPHASH_KEY_SIZE];
    unsigned char in[64];
    size_t inlen = test.idx;
    unsigned char *expected = test.expected.data;
    size_t expectedlen = test.expected.size;
    unsigned char out[SIPHASH_MAX_DIGEST_SIZE];
    size_t i;

    if (expectedlen != SIPHASH_MIN_DIGEST_SIZE &&
        expectedlen != SIPHASH_MAX_DIGEST_SIZE) {
        TEST_info("size %zu vs %d and %d", expectedlen,
                  SIPHASH_MIN_DIGEST_SIZE, SIPHASH_MAX_DIGEST_SIZE);
        return 0;
    }

    if (!TEST_int_le(inlen, sizeof(in)))
        return 0;

    /* key and in data are 00 01 02 ... */
    for (i = 0; i < sizeof(key); i++)
        key[i] = (unsigned char)i;

    for (i = 0; i < inlen; i++)
        in[i] = (unsigned char)i;

    if (!TEST_true(SipHash_Init(&siphash, key, expectedlen, 0, 0)))
        return 0;
    SipHash_Update(&siphash, in, inlen);
    if (!TEST_true(SipHash_Final(&siphash, out, expectedlen))
        || !TEST_mem_eq(out, expectedlen, expected, expectedlen))
        return 0;

    if (inlen > 16) {
        if (!TEST_true(SipHash_Init(&siphash, key, expectedlen, 0, 0)))
            return 0;
        SipHash_Update(&siphash, in, 1);
        SipHash_Update(&siphash, in+1, inlen-1);
        if (!TEST_true(SipHash_Final(&siphash, out, expectedlen)))
            return 0;

        if (!TEST_mem_eq(out, expectedlen, expected, expectedlen)) {
            TEST_info("SipHash test #%d/1+(N-1) failed.", idx);
            return 0;
        }
    }

    if (inlen > 32) {
        size_t half = inlen / 2;

        if (!TEST_true(SipHash_Init(&siphash, key, expectedlen, 0, 0)))
            return 0;
        SipHash_Update(&siphash, in, half);
        SipHash_Update(&siphash, in+half, inlen-half);
        if (!TEST_true(SipHash_Final(&siphash, out, expectedlen)))
            return 0;

        if (!TEST_mem_eq(out, expectedlen, expected, expectedlen)) {
            TEST_info("SipHash test #%d/2 failed.", idx);
            return 0;
        }

        for (half = 16; half < inlen; half += 16) {
            if (!TEST_true(SipHash_Init(&siphash, key, expectedlen, 0, 0)))
                return 0;
            SipHash_Update(&siphash, in, half);
            SipHash_Update(&siphash, in+half, inlen-half);
            if (!TEST_true(SipHash_Final(&siphash, out, expectedlen)))
                return 0;

            if (!TEST_mem_eq(out, expectedlen, expected, expectedlen)) {
                TEST_info("SipHash test #%d/%zu+%zu failed.",
                          idx, half, inlen-half);
                return 0;
            }
        }
    }

    return 1;
}
Beispiel #8
0
static int test_client_hello(int currtest)
{
    SSL_CTX *ctx;
    SSL *con = NULL;
    BIO *rbio;
    BIO *wbio;
    long len;
    unsigned char *data;
    PACKET pkt = {0}, pkt2 = {0}, pkt3 = {0};
    char *dummytick = "Hello World!";
    unsigned int type = 0;
    int testresult = 0;
    size_t msglen;
    BIO *sessbio = NULL;
    SSL_SESSION *sess = NULL;

#ifdef OPENSSL_NO_TLS1_3
    if (currtest == TEST_ADD_PADDING_AND_PSK)
        return 1;
#endif

    /*
     * For each test set up an SSL_CTX and SSL and see what ClientHello gets
     * produced when we try to connect
     */
    ctx = SSL_CTX_new(TLS_method());
    if (!TEST_ptr(ctx))
        goto end;

    switch(currtest) {
    case TEST_SET_SESSION_TICK_DATA_VER_NEG:
        /* Testing for session tickets <= TLS1.2; not relevant for 1.3 */
        if (!TEST_true(SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)))
            goto end;
        break;

    case TEST_ADD_PADDING_AND_PSK:
    case TEST_ADD_PADDING:
    case TEST_PADDING_NOT_NEEDED:
        SSL_CTX_set_options(ctx, SSL_OP_TLSEXT_PADDING);
        /*
         * Add lots of ciphersuites so that the ClientHello is at least
         * F5_WORKAROUND_MIN_MSG_LEN bytes long - meaning padding will be
         * needed. Also add some dummy ALPN protocols in case we still don't
         * have enough.
         */
        if (currtest == TEST_ADD_PADDING
                && (!TEST_true(SSL_CTX_set_cipher_list(ctx, "ALL"))
                    || !TEST_false(SSL_CTX_set_alpn_protos(ctx,
                                               (unsigned char *)alpn_prots,
                                               sizeof(alpn_prots) - 1))))
            goto end;

        break;

    default:
        goto end;
    }

    con = SSL_new(ctx);
    if (!TEST_ptr(con))
        goto end;

    if (currtest == TEST_ADD_PADDING_AND_PSK) {
        sessbio = BIO_new_file(sessionfile, "r");
        if (!TEST_ptr(sessbio)) {
            TEST_info("Unable to open session.pem");
            goto end;
        }
        sess = PEM_read_bio_SSL_SESSION(sessbio, NULL, NULL, NULL);
        if (!TEST_ptr(sess)) {
            TEST_info("Unable to load SSL_SESSION");
            goto end;
        }
        /*
         * We reset the creation time so that we don't discard the session as
         * too old.
         */
        if (!TEST_true(SSL_SESSION_set_time(sess, time(NULL)))
                || !TEST_true(SSL_set_session(con, sess)))
            goto end;
    }

    rbio = BIO_new(BIO_s_mem());
    wbio = BIO_new(BIO_s_mem());
    if (!TEST_ptr(rbio)|| !TEST_ptr(wbio)) {
        BIO_free(rbio);
        BIO_free(wbio);
        goto end;
    }

    SSL_set_bio(con, rbio, wbio);
    SSL_set_connect_state(con);

    if (currtest == TEST_SET_SESSION_TICK_DATA_VER_NEG) {
        if (!TEST_true(SSL_set_session_ticket_ext(con, dummytick,
                                                  strlen(dummytick))))
            goto end;
    }

    if (!TEST_int_le(SSL_connect(con), 0)) {
        /* This shouldn't succeed because we don't have a server! */
        goto end;
    }

    len = BIO_get_mem_data(wbio, (char **)&data);
    if (!TEST_true(PACKET_buf_init(&pkt, data, len))
               /* Skip the record header */
            || !PACKET_forward(&pkt, SSL3_RT_HEADER_LENGTH))
        goto end;

    msglen = PACKET_remaining(&pkt);

    /* Skip the handshake message header */
    if (!TEST_true(PACKET_forward(&pkt, SSL3_HM_HEADER_LENGTH))
               /* Skip client version and random */
            || !TEST_true(PACKET_forward(&pkt, CLIENT_VERSION_LEN
                                               + SSL3_RANDOM_SIZE))
               /* Skip session id */
            || !TEST_true(PACKET_get_length_prefixed_1(&pkt, &pkt2))
               /* Skip ciphers */
            || !TEST_true(PACKET_get_length_prefixed_2(&pkt, &pkt2))
               /* Skip compression */
            || !TEST_true(PACKET_get_length_prefixed_1(&pkt, &pkt2))
               /* Extensions len */
            || !TEST_true(PACKET_as_length_prefixed_2(&pkt, &pkt2)))
        goto end;

    /* Loop through all extensions */
    while (PACKET_remaining(&pkt2)) {

        if (!TEST_true(PACKET_get_net_2(&pkt2, &type))
                || !TEST_true(PACKET_get_length_prefixed_2(&pkt2, &pkt3)))
            goto end;

        if (type == TLSEXT_TYPE_session_ticket) {
            if (currtest == TEST_SET_SESSION_TICK_DATA_VER_NEG) {
                if (TEST_true(PACKET_equal(&pkt3, dummytick,
                                           strlen(dummytick)))) {
                    /* Ticket data is as we expected */
                    testresult = 1;
                }
                goto end;
            }
        }
        if (type == TLSEXT_TYPE_padding) {
            if (!TEST_false(currtest == TEST_PADDING_NOT_NEEDED))
                goto end;
            else if (TEST_true(currtest == TEST_ADD_PADDING
                    || currtest == TEST_ADD_PADDING_AND_PSK))
                testresult = TEST_true(msglen == F5_WORKAROUND_MAX_MSG_LEN);
        }
    }

    if (currtest == TEST_PADDING_NOT_NEEDED)
        testresult = 1;

end:
    SSL_free(con);
    SSL_CTX_free(ctx);
    SSL_SESSION_free(sess);
    BIO_free(sessbio);

    return testresult;
}
Beispiel #9
0
/*-
 * Positive and negative ECDSA testing through EVP interface:
 * - EVP_DigestSign (this is the one-shot version)
 * - EVP_DigestVerify
 *
 * Tests the library can successfully:
 * - create a key
 * - create a signature
 * - accept that signature
 * - reject that signature with a different public key
 * - reject that signature if its length is not correct
 * - reject that signature after modifying the message
 * - accept that signature after un-modifying the message
 * - reject that signature after modifying the signature
 * - accept that signature after un-modifying the signature
 */
static int test_builtin(int n)
{
    EC_KEY *eckey_neg = NULL, *eckey = NULL;
    unsigned char dirt, offset, tbs[128];
    unsigned char *sig = NULL;
    EVP_PKEY *pkey_neg = NULL, *pkey = NULL;
    EVP_MD_CTX *mctx = NULL;
    size_t sig_len;
    int nid, ret = 0;

    nid = curves[n].nid;

    /* skip built-in curves where ord(G) is not prime */
    if (nid == NID_ipsec4 || nid == NID_ipsec3) {
        TEST_info("skipped: ECDSA unsupported for curve %s", OBJ_nid2sn(nid));
        return 1;
    }

    TEST_info("testing ECDSA for curve %s", OBJ_nid2sn(nid));

    if (!TEST_ptr(mctx = EVP_MD_CTX_new())
        /* get some random message data */
        || !TEST_true(RAND_bytes(tbs, sizeof(tbs)))
        /* real key */
        || !TEST_ptr(eckey = EC_KEY_new_by_curve_name(nid))
        || !TEST_true(EC_KEY_generate_key(eckey))
        || !TEST_ptr(pkey = EVP_PKEY_new())
        || !TEST_true(EVP_PKEY_assign_EC_KEY(pkey, eckey))
        /* fake key for negative testing */
        || !TEST_ptr(eckey_neg = EC_KEY_new_by_curve_name(nid))
        || !TEST_true(EC_KEY_generate_key(eckey_neg))
        || !TEST_ptr(pkey_neg = EVP_PKEY_new())
        || !TEST_true(EVP_PKEY_assign_EC_KEY(pkey_neg, eckey_neg)))
        goto err;

    sig_len = ECDSA_size(eckey);

    if (!TEST_ptr(sig = OPENSSL_malloc(sig_len))
        /* create a signature */
        || !TEST_true(EVP_DigestSignInit(mctx, NULL, NULL, NULL, pkey))
        || !TEST_true(EVP_DigestSign(mctx, sig, &sig_len, tbs, sizeof(tbs)))
        || !TEST_int_le(sig_len, ECDSA_size(eckey))
        /* negative test, verify with wrong key, 0 return */
        || !TEST_true(EVP_MD_CTX_reset(mctx))
        || !TEST_true(EVP_DigestVerifyInit(mctx, NULL, NULL, NULL, pkey_neg))
        || !TEST_int_eq(EVP_DigestVerify(mctx, sig, sig_len, tbs, sizeof(tbs)), 0)
        /* negative test, verify with wrong signature length, -1 return */
        || !TEST_true(EVP_MD_CTX_reset(mctx))
        || !TEST_true(EVP_DigestVerifyInit(mctx, NULL, NULL, NULL, pkey))
        || !TEST_int_eq(EVP_DigestVerify(mctx, sig, sig_len - 1, tbs, sizeof(tbs)), -1)
        /* positive test, verify with correct key, 1 return */
        || !TEST_true(EVP_MD_CTX_reset(mctx))
        || !TEST_true(EVP_DigestVerifyInit(mctx, NULL, NULL, NULL, pkey))
        || !TEST_int_eq(EVP_DigestVerify(mctx, sig, sig_len, tbs, sizeof(tbs)), 1))
        goto err;

    /* muck with the message, test it fails with 0 return */
    tbs[0] ^= 1;
    if (!TEST_true(EVP_MD_CTX_reset(mctx))
        || !TEST_true(EVP_DigestVerifyInit(mctx, NULL, NULL, NULL, pkey))
        || !TEST_int_eq(EVP_DigestVerify(mctx, sig, sig_len, tbs, sizeof(tbs)), 0))
        goto err;
    /* un-muck and test it verifies */
    tbs[0] ^= 1;
    if (!TEST_true(EVP_MD_CTX_reset(mctx))
        || !TEST_true(EVP_DigestVerifyInit(mctx, NULL, NULL, NULL, pkey))
        || !TEST_int_eq(EVP_DigestVerify(mctx, sig, sig_len, tbs, sizeof(tbs)), 1))
        goto err;

    /*-
     * Muck with the ECDSA signature. The DER encoding is one of:
     * - 30 LL 02 ..
     * - 30 81 LL 02 ..
     *
     * - Sometimes this mucks with the high level DER sequence wrapper:
     *   in that case, DER-parsing of the whole signature should fail.
     *
     * - Sometimes this mucks with the DER-encoding of ECDSA.r:
     *   in that case, DER-parsing of ECDSA.r should fail.
     *
     * - Sometimes this mucks with the DER-encoding of ECDSA.s:
     *   in that case, DER-parsing of ECDSA.s should fail.
     *
     * - Sometimes this mucks with ECDSA.r:
     *   in that case, the signature verification should fail.
     *
     * - Sometimes this mucks with ECDSA.s:
     *   in that case, the signature verification should fail.
     *
     * The usual case is changing the integer value of ECDSA.r or ECDSA.s.
     * Because the ratio of DER overhead to signature bytes is small.
     * So most of the time it will be one of the last two cases.
     *
     * In any case, EVP_PKEY_verify should not return 1 for valid.
     */
    offset = tbs[0] % sig_len;
    dirt = tbs[1] ? tbs[1] : 1;
    sig[offset] ^= dirt;
    if (!TEST_true(EVP_MD_CTX_reset(mctx))
        || !TEST_true(EVP_DigestVerifyInit(mctx, NULL, NULL, NULL, pkey))
        || !TEST_int_ne(EVP_DigestVerify(mctx, sig, sig_len, tbs, sizeof(tbs)), 1))
        goto err;
    /* un-muck and test it verifies */
    sig[offset] ^= dirt;
    if (!TEST_true(EVP_MD_CTX_reset(mctx))
        || !TEST_true(EVP_DigestVerifyInit(mctx, NULL, NULL, NULL, pkey))
        || !TEST_int_eq(EVP_DigestVerify(mctx, sig, sig_len, tbs, sizeof(tbs)), 1))
        goto err;

    ret = 1;
 err:
    EVP_PKEY_free(pkey);
    EVP_PKEY_free(pkey_neg);
    EVP_MD_CTX_free(mctx);
    OPENSSL_free(sig);
    return ret;
}
Beispiel #10
0
static int test_tls13ccs(int tst)
{
    SSL_CTX *sctx = NULL, *cctx = NULL;
    SSL *sssl = NULL, *cssl = NULL;
    int ret = 0;
    const char msg[] = "Dummy data";
    char buf[80];
    size_t written, readbytes;
    SSL_SESSION *sess = NULL;

    chseen = shseen = sccsseen = ccsaftersh = ccsbeforesh = 0;
    sappdataseen = cappdataseen = badccs = badvers = badsessid = 0;
    chsessidlen = 0;

    if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(),
                                       TLS1_VERSION, 0,
                                       &sctx, &cctx, cert, privkey))
        || !TEST_true(SSL_CTX_set_max_early_data(sctx,
                                                 SSL3_RT_MAX_PLAIN_LENGTH)))
        goto err;

    /*
     * Test 0: Simple Handshake
     * Test 1: Simple Handshake, client middlebox compat mode disabled
     * Test 2: Simple Handshake, server middlebox compat mode disabled
     * Test 3: HRR Handshake
     * Test 4: HRR Handshake, client middlebox compat mode disabled
     * Test 5: HRR Handshake, server middlebox compat mode disabled
     * Test 6: Early data handshake
     * Test 7: Early data handshake, client middlebox compat mode disabled
     * Test 8: Early data handshake, server middlebox compat mode disabled
     * Test 9: Early data then HRR
     * Test 10: Early data then HRR, client middlebox compat mode disabled
     * Test 11: Early data then HRR, server middlebox compat mode disabled
     */
    switch (tst) {
    case 0:
    case 3:
    case 6:
    case 9:
        break;
    case 1:
    case 4:
    case 7:
    case 10:
        SSL_CTX_clear_options(cctx, SSL_OP_ENABLE_MIDDLEBOX_COMPAT);
        break;
    case 2:
    case 5:
    case 8:
    case 11:
        SSL_CTX_clear_options(sctx, SSL_OP_ENABLE_MIDDLEBOX_COMPAT);
        break;
    default:
        TEST_error("Invalid test value");
        goto err;
    }

    if (tst >= 6) {
        /* Get a session suitable for early_data */
        if (!TEST_true(create_ssl_objects(sctx, cctx, &sssl, &cssl, NULL, NULL))
                || !TEST_true(create_ssl_connection(sssl, cssl, SSL_ERROR_NONE)))
            goto err;
        sess = SSL_get1_session(cssl);
        if (!TEST_ptr(sess))
            goto err;
        SSL_shutdown(cssl);
        SSL_shutdown(sssl);
        SSL_free(sssl);
        SSL_free(cssl);
        sssl = cssl = NULL;
    }

    if ((tst >= 3 && tst <= 5) || tst >= 9) {
        /* HRR handshake */
        if (!TEST_true(SSL_CTX_set1_groups_list(sctx, "P-256")))
            goto err;
    }

    s_to_c_fbio = BIO_new(bio_f_watchccs_filter());
    c_to_s_fbio = BIO_new(bio_f_watchccs_filter());
    if (!TEST_ptr(s_to_c_fbio)
            || !TEST_ptr(c_to_s_fbio)) {
        BIO_free(s_to_c_fbio);
        BIO_free(c_to_s_fbio);
        goto err;
    }

    /* BIOs get freed on error */
    if (!TEST_true(create_ssl_objects(sctx, cctx, &sssl, &cssl, s_to_c_fbio,
                                      c_to_s_fbio)))
        goto err;

    if (tst >= 6) {
        /* Early data */
        if (!TEST_true(SSL_set_session(cssl, sess))
                || !TEST_true(SSL_write_early_data(cssl, msg, strlen(msg),
                                                   &written))
                || (tst <= 8
                    && !TEST_int_eq(SSL_read_early_data(sssl, buf,  sizeof(buf),
                                                &readbytes),
                                                SSL_READ_EARLY_DATA_SUCCESS)))
            goto err;
        if (tst <= 8) {
            if (!TEST_int_gt(SSL_connect(cssl), 0))
                goto err;
        } else {
            if (!TEST_int_le(SSL_connect(cssl), 0))
                goto err;
        }
        if (!TEST_int_eq(SSL_read_early_data(sssl, buf,  sizeof(buf),
                                             &readbytes),
                         SSL_READ_EARLY_DATA_FINISH))
            goto err;
    }

    /* Perform handshake (or complete it if doing early data ) */
    if (!TEST_true(create_ssl_connection(sssl, cssl, SSL_ERROR_NONE)))
        goto err;

    /*
     * Check there were no unexpected CCS messages, all record versions
     * were as expected, and that the session ids were reflected by the server
     * correctly.
     */
    if (!TEST_false(badccs) || !TEST_false(badvers) || !TEST_false(badsessid))
        goto err;

    switch (tst) {
    case 0:
        if (!TEST_true(sccsseen)
                || !TEST_true(ccsaftersh)
                || !TEST_false(ccsbeforesh)
                || !TEST_size_t_gt(chsessidlen, 0))
            goto err;
        break;

    case 1:
        if (!TEST_true(sccsseen)
                || !TEST_false(ccsaftersh)
                || !TEST_false(ccsbeforesh)
                || !TEST_size_t_eq(chsessidlen, 0))
            goto err;
        break;

    case 2:
        if (!TEST_false(sccsseen)
                || !TEST_true(ccsaftersh)
                || !TEST_false(ccsbeforesh)
                || !TEST_size_t_gt(chsessidlen, 0))
            goto err;
        break;

    case 3:
        if (!TEST_true(sccsseen)
                || !TEST_true(ccsaftersh)
                || !TEST_false(ccsbeforesh)
                || !TEST_size_t_gt(chsessidlen, 0))
            goto err;
        break;

    case 4:
        if (!TEST_true(sccsseen)
                || !TEST_false(ccsaftersh)
                || !TEST_false(ccsbeforesh)
                || !TEST_size_t_eq(chsessidlen, 0))
            goto err;
        break;

    case 5:
        if (!TEST_false(sccsseen)
                || !TEST_true(ccsaftersh)
                || !TEST_false(ccsbeforesh)
                || !TEST_size_t_gt(chsessidlen, 0))
            goto err;
        break;

    case 6:
        if (!TEST_true(sccsseen)
                || !TEST_false(ccsaftersh)
                || !TEST_true(ccsbeforesh)
                || !TEST_size_t_gt(chsessidlen, 0))
            goto err;
        break;

    case 7:
        if (!TEST_true(sccsseen)
                || !TEST_false(ccsaftersh)
                || !TEST_false(ccsbeforesh)
                || !TEST_size_t_eq(chsessidlen, 0))
            goto err;
        break;

    case 8:
        if (!TEST_false(sccsseen)
                || !TEST_false(ccsaftersh)
                || !TEST_true(ccsbeforesh)
                || !TEST_size_t_gt(chsessidlen, 0))
            goto err;
        break;

    case 9:
        if (!TEST_true(sccsseen)
                || !TEST_false(ccsaftersh)
                || !TEST_true(ccsbeforesh)
                || !TEST_size_t_gt(chsessidlen, 0))
            goto err;
        break;

    case 10:
        if (!TEST_true(sccsseen)
                || !TEST_false(ccsaftersh)
                || !TEST_false(ccsbeforesh)
                || !TEST_size_t_eq(chsessidlen, 0))
            goto err;
        break;

    case 11:
        if (!TEST_false(sccsseen)
                || !TEST_false(ccsaftersh)
                || !TEST_true(ccsbeforesh)
                || !TEST_size_t_gt(chsessidlen, 0))
            goto err;
        break;

    default:
        TEST_error("Invalid test value");
        goto err;
    }

    ret = 1;
 err:
    SSL_SESSION_free(sess);
    SSL_free(sssl);
    SSL_free(cssl);
    SSL_CTX_free(sctx);
    SSL_CTX_free(cctx);

    return ret;
}