Commit 7f5f35af authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

Add options to check certificate types.

parent 50718243
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -89,6 +89,9 @@ handshake.

* ExpectedTmpKeyType - the expected algorithm or curve of server temp key

* ExpectedServerKeyType, ExpectedClientKeyType - the expected algorithm or
  curve of server or client certificate

## Configuring the client and server

The client and server configurations can be any valid `SSL_CTX`
+30 −9
Original line number Diff line number Diff line
@@ -847,6 +847,32 @@ static char *dup_str(const unsigned char *in, size_t len)
    return ret;
}

static int pkey_type(EVP_PKEY *pkey)
{
    int nid = EVP_PKEY_id(pkey);

#ifndef OPENSSL_NO_EC
    if (nid == EVP_PKEY_EC) {
        const EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey);
        return EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
    }
#endif
    return nid;
}

static int peer_pkey_type(SSL *s)
{
    X509 *x = SSL_get_peer_certificate(s);

    if (x != NULL) {
        int nid = pkey_type(X509_get0_pubkey(x));

        X509_free(x);
        return nid;
    }
    return NID_undef;
}

/*
 * Note that |extra| points to the correct client/server configuration
 * within |test_ctx|. When configuring the handshake, general mode settings
@@ -1040,18 +1066,13 @@ static HANDSHAKE_RESULT *do_handshake_internal(
        *session_out = SSL_get1_session(client.ssl);

    if (SSL_get_server_tmp_key(client.ssl, &tmp_key)) {
        int nid = EVP_PKEY_id(tmp_key);

#ifndef OPENSSL_NO_EC
        if (nid == EVP_PKEY_EC) {
            EC_KEY *ec = EVP_PKEY_get0_EC_KEY(tmp_key);
            nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
        }
#endif
        ret->tmp_key_type = pkey_type(tmp_key);
        EVP_PKEY_free(tmp_key);
        ret->tmp_key_type = nid;
    }

    ret->server_cert_type = peer_pkey_type(client.ssl);
    ret->client_cert_type = peer_pkey_type(server.ssl);

    ctx_data_free_data(&server_ctx_data);
    ctx_data_free_data(&server2_ctx_data);
    ctx_data_free_data(&client_ctx_data);
+4 −0
Original line number Diff line number Diff line
@@ -45,6 +45,10 @@ typedef struct handshake_result {
    int server_resumed;
    /* Temporary key type */
    int tmp_key_type;
    /* server certificate key type */
    int server_cert_type;
    /* client certificate key type */
    int client_cert_type;
} HANDSHAKE_RESULT;

HANDSHAKE_RESULT *HANDSHAKE_RESULT_new(void);
+29 −6
Original line number Diff line number Diff line
@@ -187,17 +187,38 @@ static int check_resumption(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx)
    return 1;
}

static int check_tmp_key(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx)
static int check_key_type(const char *name,int expected_key_type, int key_type)
{
    if (test_ctx->expected_tmp_key_type == 0
        || test_ctx->expected_tmp_key_type == result->tmp_key_type)
    if (expected_key_type == 0 || expected_key_type == key_type)
        return 1;
    fprintf(stderr, "Tmp key type mismatch, %s vs %s\n",
            OBJ_nid2ln(test_ctx->expected_tmp_key_type),
            OBJ_nid2ln(result->tmp_key_type));
    fprintf(stderr, "%s type mismatch, %s vs %s\n",
            name, OBJ_nid2ln(expected_key_type),
            key_type == NID_undef ? "absent" : OBJ_nid2ln(key_type));
    return 0;
}

static int check_tmp_key(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx)
{
    return check_key_type("Tmp key", test_ctx->expected_tmp_key_type,
                          result->tmp_key_type);
}

static int check_server_cert_type(HANDSHAKE_RESULT *result,
                                  SSL_TEST_CTX *test_ctx)
{
    return check_key_type("Server certificate",
                          test_ctx->expected_server_cert_type,
                          result->server_cert_type);
}

static int check_client_cert_type(HANDSHAKE_RESULT *result,
                                  SSL_TEST_CTX *test_ctx)
{
    return check_key_type("Client certificate",
                          test_ctx->expected_client_cert_type,
                          result->client_cert_type);
}

/*
 * This could be further simplified by constructing an expected
 * HANDSHAKE_RESULT, and implementing comparison methods for
@@ -219,6 +240,8 @@ static int check_test(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx)
        ret &= check_alpn(result, test_ctx);
        ret &= check_resumption(result, test_ctx);
        ret &= check_tmp_key(result, test_ctx);
        ret &= check_server_cert_type(result, test_ctx);
        ret &= check_client_cert_type(result, test_ctx);
    }
    return ret;
}
+31 −5
Original line number Diff line number Diff line
@@ -433,16 +433,20 @@ IMPLEMENT_SSL_TEST_INT_OPTION(SSL_TEST_CTX, test, app_data_size)
IMPLEMENT_SSL_TEST_INT_OPTION(SSL_TEST_CTX, test, max_fragment_size)

/***********************/
/* ExpectedTmpKeyType  */
/* Expected key types  */
/***********************/

__owur static int parse_expected_tmp_key_type(SSL_TEST_CTX *test_ctx,
                                              const char *value)
__owur static int parse_expected_key_type(int *ptype, const char *value)
{
    int nid;
    const EVP_PKEY_ASN1_METHOD *ameth;

    if (value == NULL)
        return 0;
    ameth = EVP_PKEY_asn1_find_str(NULL, value, -1);
    if (ameth != NULL)
        EVP_PKEY_asn1_get0_info(&nid, NULL, NULL, NULL, NULL, ameth);
    else
        nid = OBJ_sn2nid(value);
    if (nid == NID_undef)
        nid = OBJ_ln2nid(value);
@@ -452,10 +456,30 @@ __owur static int parse_expected_tmp_key_type(SSL_TEST_CTX *test_ctx,
#endif
    if (nid == NID_undef)
        return 0;
    test_ctx->expected_tmp_key_type = nid;
    *ptype = nid;
    return 1;
}

__owur static int parse_expected_tmp_key_type(SSL_TEST_CTX *test_ctx,
                                              const char *value)
{
    return parse_expected_key_type(&test_ctx->expected_tmp_key_type, value);
}

__owur static int parse_expected_server_cert_type(SSL_TEST_CTX *test_ctx,
                                                  const char *value)
{
    return parse_expected_key_type(&test_ctx->expected_server_cert_type,
                                   value);
}

__owur static int parse_expected_client_cert_type(SSL_TEST_CTX *test_ctx,
                                                  const char *value)
{
    return parse_expected_key_type(&test_ctx->expected_client_cert_type,
                                   value);
}

/*************************************************************/
/* Known test options and their corresponding parse methods. */
/*************************************************************/
@@ -481,6 +505,8 @@ static const ssl_test_ctx_option ssl_test_ctx_options[] = {
    { "ApplicationData", &parse_test_app_data_size },
    { "MaxFragmentSize", &parse_test_max_fragment_size },
    { "ExpectedTmpKeyType", &parse_expected_tmp_key_type },
    { "ExpectedServerCertType", &parse_expected_server_cert_type },
    { "ExpectedClientCertType", &parse_expected_client_cert_type },
};

/* Nested client options. */
Loading