コード例 #1
0
/* Test of EVP_PKEY_ASN1_METHOD ordering */
static int test_asn1_meths(void)
{
    int i;
    int prev = -1;
    int good = 1;
    int pkey_id;
    const EVP_PKEY_ASN1_METHOD *ameth;

    for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) {
        ameth = EVP_PKEY_asn1_get0(i);
        EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth);
        if (pkey_id < prev)
            good = 0;
        prev = pkey_id;

    }
    if (!good) {
        TEST_error("EVP_PKEY_ASN1_METHOD table out of order");
        for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) {
            const char *info;

            ameth = EVP_PKEY_asn1_get0(i);
            EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, &info, NULL, ameth);
            if (info == NULL)
                info = "<NO NAME>";
            TEST_note("%d : %s : %s", pkey_id, OBJ_nid2ln(pkey_id), info);
        }
    }
    return good;
}
コード例 #2
0
/* Test of EVP_PKEY_METHOD ordering */
static int test_pkey_meths(void)
{
    size_t i;
    int prev = -1;
    int good = 1;
    int pkey_id;
    const EVP_PKEY_METHOD *pmeth;

    for (i = 0; i < EVP_PKEY_meth_get_count(); i++) {
        pmeth = EVP_PKEY_meth_get0(i);
        EVP_PKEY_meth_get0_info(&pkey_id, NULL, pmeth);
        if (pkey_id < prev)
            good = 0;
        prev = pkey_id;

    }
    if (!good) {
        TEST_error("EVP_PKEY_METHOD table out of order");
        for (i = 0; i < EVP_PKEY_meth_get_count(); i++) {
            pmeth = EVP_PKEY_meth_get0(i);
            EVP_PKEY_meth_get0_info(&pkey_id, NULL, pmeth);
            TEST_note("%d : %s", pkey_id, OBJ_nid2ln(pkey_id));
        }
    }
    return good;
}
コード例 #3
0
static int test_tbl_standard(void)
{
    const ASN1_STRING_TABLE *tmp;
    int last_nid = -1;
    size_t i;

    for (tmp = tbl_standard, i = 0; i < OSSL_NELEM(tbl_standard); i++, tmp++) {
        if (tmp->nid < last_nid) {
            last_nid = 0;
            break;
        }
        last_nid = tmp->nid;
    }

    if (TEST_int_ne(last_nid, 0)) {
        TEST_info("asn1 tbl_standard: Table order OK");
        return 1;
    }

    TEST_info("asn1 tbl_standard: out of order");
    for (tmp = tbl_standard, i = 0; i < OSSL_NELEM(tbl_standard); i++, tmp++)
        TEST_note("asn1 tbl_standard: Index %zu, NID %d, Name=%s",
                  i, tmp->nid, OBJ_nid2ln(tmp->nid));

    return 0;
}
コード例 #4
0
static int do_test_cert_table(int nid, uint32_t amask, size_t idx,
                              const char *idxname)
{
    const SSL_CERT_LOOKUP *clu = &ssl_cert_info[idx];

    if (clu->nid == nid && clu->amask == amask)
        return 1;

    TEST_error("Invalid table entry for certificate type %s, index %zu",
               idxname, idx);
    if (clu->nid != nid)
        TEST_note("Expected %s, got %s\n", OBJ_nid2sn(nid),
                  OBJ_nid2sn(clu->nid));
    if (clu->amask != amask)
        TEST_note("Expected auth mask 0x%x, got 0x%x\n", amask, clu->amask);
    return 0;
}
コード例 #5
0
ファイル: property_test.c プロジェクト: opensignature/openssl
static int test_register_deregister(void)
{
    static const struct {
        int nid;
        const char *prop;
        char *impl;
    } impls[] = {
        { 6, "position=1", "a" },
        { 6, "position=2", "b" },
        { 6, "position=3", "c" },
        { 6, "position=4", "d" },
    };
    size_t i;
    int ret = 0;
    OSSL_METHOD_STORE *store;

    if (!TEST_ptr(store = ossl_method_store_new(NULL))
        || !add_property_names("position", NULL))
        goto err;

    for (i = 0; i < OSSL_NELEM(impls); i++)
        if (!TEST_true(ossl_method_store_add(store, impls[i].nid, impls[i].prop,
                                             impls[i].impl, NULL))) {
            TEST_note("iteration %zd", i + 1);
            goto err;
        }

    /* Deregister in a different order to registration */
    for (i = 0; i < OSSL_NELEM(impls); i++) {
        const size_t j = (1 + i * 3) % OSSL_NELEM(impls);
        int nid = impls[j].nid;
        void *impl = impls[j].impl;

        if (!TEST_true(ossl_method_store_remove(store, nid, impl))
            || !TEST_false(ossl_method_store_remove(store, nid, impl))) {
            TEST_note("iteration %zd, position %zd", i + 1, j + 1);
            goto err;
        }
    }

    if (TEST_false(ossl_method_store_remove(store, impls[0].nid, impls[0].impl)))
        ret = 1;
err:
    ossl_method_store_free(store);
    return ret;
}
コード例 #6
0
static int test_standard_methods(void)
{
    const EVP_PKEY_ASN1_METHOD **tmp;
    int last_pkey_id = -1;
    size_t i;
    int ok = 1;

    for (tmp = standard_methods, i = 0; i < OSSL_NELEM(standard_methods);
         i++, tmp++) {
        if ((*tmp)->pkey_id < last_pkey_id) {
            last_pkey_id = 0;
            break;
        }
        last_pkey_id = (*tmp)->pkey_id;

        /*
         * One of the following must be true:
         *
         * pem_str == NULL AND ASN1_PKEY_ALIAS is set
         * pem_str != NULL AND ASN1_PKEY_ALIAS is clear
         *
         * Anything else is an error and may lead to a corrupt ASN1 method table
         */
        if (!TEST_true(((*tmp)->pem_str == NULL && ((*tmp)->pkey_flags & ASN1_PKEY_ALIAS) != 0)
                       || ((*tmp)->pem_str != NULL && ((*tmp)->pkey_flags & ASN1_PKEY_ALIAS) == 0))) {
            TEST_note("asn1 standard methods: Index %zu, pkey ID %d, Name=%s",
                      i, (*tmp)->pkey_id, OBJ_nid2sn((*tmp)->pkey_id));
            ok = 0;
        }
    }

    if (TEST_int_ne(last_pkey_id, 0)) {
        TEST_info("asn1 standard methods: Table order OK");
        return ok;
    }

    TEST_note("asn1 standard methods: out of order");
    for (tmp = standard_methods, i = 0; i < OSSL_NELEM(standard_methods);
         i++, tmp++)
        TEST_note("asn1 standard methods: Index %zu, pkey ID %d, Name=%s",
                  i, (*tmp)->pkey_id, OBJ_nid2sn((*tmp)->pkey_id));

    return 0;
}
コード例 #7
0
ファイル: ecdsatest.c プロジェクト: Vonage/openssl
int setup_tests(void)
{
#ifdef OPENSSL_NO_EC
    TEST_note("Elliptic curves are disabled.");
#else
    ADD_TEST(x9_62_tests);
    ADD_TEST(test_builtin);
#endif
    return 1;
}
コード例 #8
0
int setup_tests(void)
{
    size_t n = test_get_argument_count();

    if (!TEST_int_gt(n, 0)) {
        TEST_note("usage: x509_dup_cert_test cert.pem...");
        return 0;
    }

    ADD_ALL_TESTS(test_509_dup_cert, n);
    return 1;
}
コード例 #9
0
int setup_tests(void)
{
    if (!TEST_ptr(c = test_get_argument(0))
            || !TEST_ptr(k = test_get_argument(1))
            || !TEST_ptr(t = test_get_argument(2))
            || !TEST_ptr(e = test_get_argument(3))) {
        TEST_note("usage: x509_check_cert_pkey cert.pem|cert.req"
                  " key.pem cert|req <expected>");
        return 0;
    }

    ADD_TEST(test_x509_check_cert_pkey);
    return 1;
}
コード例 #10
0
ファイル: sparse_array_test.c プロジェクト: romen/openssl
static int test_sparse_array(void)
{
    static const struct {
        size_t n;
        char *v;
    } cases[] = {
        { 22, "a" }, { 0, "z" }, { 1, "b" }, { 290, "c" },
        { INT_MAX, "m" }, { 6666666, "d" }, { (size_t)-1, "H" },
        { 99, "e" }
    };
    SPARSE_ARRAY_OF(char) *sa;
    size_t i, j;
    int res = 0;

    if (!TEST_ptr(sa = ossl_sa_char_new())
            || !TEST_ptr_null(ossl_sa_char_get(sa, 3))
            || !TEST_ptr_null(ossl_sa_char_get(sa, 0))
            || !TEST_ptr_null(ossl_sa_char_get(sa, UINT_MAX)))
        goto err;

    for (i = 0; i < OSSL_NELEM(cases); i++) {
        if (!TEST_true(ossl_sa_char_set(sa, cases[i].n, cases[i].v))) {
            TEST_note("iteration %zu", i + 1);
            goto err;
        }
        for (j = 0; j <= i; j++)
            if (!TEST_str_eq(ossl_sa_char_get(sa, cases[j].n), cases[j].v)) {
                TEST_note("iteration %zu / %zu", i + 1, j + 1);
                goto err;
            }
    }

    res = 1;
err:
    ossl_sa_char_free(sa);
    return res;
}
コード例 #11
0
ファイル: ecdsatest.c プロジェクト: tiran/openssl
int setup_tests(void)
{
#ifdef OPENSSL_NO_EC
    TEST_note("Elliptic curves are disabled.");
#else
    /* get a list of all internal curves */
    crv_len = EC_get_builtin_curves(NULL, 0);
    if (!TEST_ptr(curves = OPENSSL_malloc(sizeof(*curves) * crv_len))
        || !TEST_true(EC_get_builtin_curves(curves, crv_len)))
        return 0;
    ADD_ALL_TESTS(test_builtin, crv_len);
    ADD_ALL_TESTS(x9_62_tests, OSSL_NELEM(ecdsa_cavs_kats));
#endif
    return 1;
}
コード例 #12
0
ファイル: x509_internal_test.c プロジェクト: akamai/openssl
static int test_standard_exts(void)
{
    size_t i;
    int prev = -1, good = 1;
    const X509V3_EXT_METHOD **tmp;

    tmp = standard_exts;
    for (i = 0; i < OSSL_NELEM(standard_exts); i++, tmp++) {
        if ((*tmp)->ext_nid < prev)
            good = 0;
        prev = (*tmp)->ext_nid;

    }
    if (!good) {
        tmp = standard_exts;
        TEST_error("Extensions out of order!");
        for (i = 0; i < STANDARD_EXTENSION_COUNT; i++, tmp++)
            TEST_note("%d : %s", (*tmp)->ext_nid, OBJ_nid2sn((*tmp)->ext_nid));
    }
    return good;
}
コード例 #13
0
ファイル: property_test.c プロジェクト: opensignature/openssl
static int test_query_cache_stochastic(void)
{
    const int max = 10000, tail = 10;
    OSSL_METHOD_STORE *store;
    int i, res = 0;
    char buf[50];
    void *result;
    int errors = 0;
    int v[10001];

    if (!TEST_ptr(store = ossl_method_store_new(NULL))
        || !add_property_names("n", NULL))
        goto err;

    for (i = 1; i <= max; i++) {
        v[i] = 2 * i;
        BIO_snprintf(buf, sizeof(buf), "n=%d\n", i);
        if (!TEST_true(ossl_method_store_add(store, i, buf, "abc", NULL))
                || !TEST_true(ossl_method_store_cache_set(store, i, buf, v + i))
                || !TEST_true(ossl_method_store_cache_set(store, i, "n=1234",
                                                          "miss"))) {
            TEST_note("iteration %d", i);
            goto err;
        }
    }
    for (i = 1; i <= max; i++) {
        BIO_snprintf(buf, sizeof(buf), "n=%d\n", i);
        if (!ossl_method_store_cache_get(store, i, buf, &result)
            || result != v + i)
            errors++;
    }
    /* There is a tiny probability that this will fail when it shouldn't */
    res = TEST_int_gt(errors, tail) && TEST_int_lt(errors, max - tail);

err:
    ossl_method_store_free(store);
    return res;
}
コード例 #14
0
static int test_tls13_encryption(void)
{
    SSL_CTX *ctx = NULL;
    SSL *s = NULL;
    SSL3_RECORD rec;
    unsigned char *key = NULL, *iv = NULL, *seq = NULL;
    const EVP_CIPHER *ciph = EVP_aes_128_gcm();
    int ret = 0;
    size_t ivlen, ctr;

    /*
     * Encrypted TLSv1.3 records always have an outer content type of
     * application data, and a record version of TLSv1.2.
     */
    rec.data = NULL;
    rec.type = SSL3_RT_APPLICATION_DATA;
    rec.rec_version = TLS1_2_VERSION;

    ctx = SSL_CTX_new(TLS_method());
    if (!TEST_ptr(ctx)) {
        TEST_info("Failed creating SSL_CTX");
        goto err;
    }

    s = SSL_new(ctx);
    if (!TEST_ptr(s)) {
        TEST_info("Failed creating SSL");
        goto err;
    }

    s->enc_read_ctx = EVP_CIPHER_CTX_new();
    if (!TEST_ptr(s->enc_read_ctx))
        goto err;

    s->enc_write_ctx = EVP_CIPHER_CTX_new();
    if (!TEST_ptr(s->enc_write_ctx))
        goto err;

    s->s3->tmp.new_cipher = SSL_CIPHER_find(s, TLS13_AES_128_GCM_SHA256_BYTES);
    if (!TEST_ptr(s->s3->tmp.new_cipher)) {
        TEST_info("Failed to find cipher");
        goto err;
    }

    for (ctr = 0; ctr < OSSL_NELEM(refdata); ctr++) {
        /* Load the record */
        ivlen = EVP_CIPHER_iv_length(ciph);
        if (!load_record(&rec, &refdata[ctr], &key, s->read_iv, ivlen,
                         RECORD_LAYER_get_read_sequence(&s->rlayer))) {
            TEST_error("Failed loading key into EVP_CIPHER_CTX");
            goto err;
        }

        /* Set up the read/write sequences */
        memcpy(RECORD_LAYER_get_write_sequence(&s->rlayer),
               RECORD_LAYER_get_read_sequence(&s->rlayer), SEQ_NUM_SIZE);
        memcpy(s->write_iv, s->read_iv, ivlen);

        /* Load the key into the EVP_CIPHER_CTXs */
        if (EVP_CipherInit_ex(s->enc_write_ctx, ciph, NULL, key, NULL, 1) <= 0
                || EVP_CipherInit_ex(s->enc_read_ctx, ciph, NULL, key, NULL, 0)
                   <= 0) {
            TEST_error("Failed loading key into EVP_CIPHER_CTX\n");
            goto err;
        }

        /* Encrypt it */
        if (!TEST_size_t_eq(tls13_enc(s, &rec, 1, 1), 1)) {
            TEST_info("Failed to encrypt record %zu", ctr);
            goto err;
        }
        if (!TEST_true(test_record(&rec, &refdata[ctr], 1))) {
            TEST_info("Record %zu encryption test failed", ctr);
            goto err;
        }

        /* Decrypt it */
        if (!TEST_int_eq(tls13_enc(s, &rec, 1, 0), 1)) {
            TEST_info("Failed to decrypt record %zu", ctr);
            goto err;
        }
        if (!TEST_true(test_record(&rec, &refdata[ctr], 0))) {
            TEST_info("Record %zu decryption test failed", ctr);
            goto err;
        }

        OPENSSL_free(rec.data);
        OPENSSL_free(key);
        OPENSSL_free(iv);
        OPENSSL_free(seq);
        rec.data = NULL;
        key = NULL;
        iv = NULL;
        seq = NULL;
    }

    TEST_note("PASS: %zu records tested", ctr);
    ret = 1;

 err:
    OPENSSL_free(rec.data);
    OPENSSL_free(key);
    OPENSSL_free(iv);
    OPENSSL_free(seq);
    SSL_free(s);
    SSL_CTX_free(ctx);
    return ret;
}
コード例 #15
0
ファイル: params_api_test.c プロジェクト: dgalaxy/openssl
static int test_param_construct(void)
{
    static const char *int_names[] = {
        "int", "long", "int32", "int64"
    };
    static const char *uint_names[] = {
        "uint", "ulong", "uint32", "uint64", "size_t"
    };
    static const unsigned char bn_val[16] = {
        0xac, 0x75, 0x22, 0x7d, 0x81, 0x06, 0x7a, 0x23,
        0xa6, 0xed, 0x87, 0xc7, 0xab, 0xf4, 0x73, 0x22
    };
    OSSL_PARAM params[20];
    char buf[100], buf2[100], *bufp, *bufp2;
    unsigned char ubuf[100];
    void *vp, *vpn = NULL, *vp2;
    OSSL_PARAM *p;
    const OSSL_PARAM *cp;
    static const OSSL_PARAM pend = OSSL_PARAM_END;
    int i, n = 0, ret = 0;
    unsigned int u;
    long int l;
    unsigned long int ul;
    int32_t i32;
    uint32_t u32;
    int64_t i64;
    uint64_t u64;
    size_t j, k, s, sz;
    double d, d2;
    BIGNUM *bn = NULL, *bn2 = NULL;

    params[n++] = OSSL_PARAM_construct_int("int", &i, &sz);
    params[n++] = OSSL_PARAM_construct_uint("uint", &u, &sz);
    params[n++] = OSSL_PARAM_construct_long("long", &l, &sz);
    params[n++] = OSSL_PARAM_construct_ulong("ulong", &ul, &sz);
    params[n++] = OSSL_PARAM_construct_int32("int32", &i32, &sz);
    params[n++] = OSSL_PARAM_construct_int64("int64", &i64, &sz);
    params[n++] = OSSL_PARAM_construct_uint32("uint32", &u32, &sz);
    params[n++] = OSSL_PARAM_construct_uint64("uint64", &u64, &sz);
    params[n++] = OSSL_PARAM_construct_size_t("size_t", &s, &sz);
    params[n++] = OSSL_PARAM_construct_double("double", &d, &sz);
    params[n++] = OSSL_PARAM_construct_BN("bignum", ubuf, sizeof(ubuf), &sz);
    params[n++] = OSSL_PARAM_construct_utf8_string("utf8str", buf, sizeof(buf),
                                                   &sz);
    params[n++] = OSSL_PARAM_construct_octet_string("octstr", buf, sizeof(buf),
                                                    &sz);
    params[n++] = OSSL_PARAM_construct_utf8_ptr("utf8ptr", &bufp, &sz);
    params[n++] = OSSL_PARAM_construct_octet_ptr("octptr", &vp, &sz);
    params[n] = pend;

    /* Search failure */
    if (!TEST_ptr_null(OSSL_PARAM_locate(params, "fnord")))
        goto err;

    /* All signed integral types */
    for (j = 0; j < OSSL_NELEM(int_names); j++) {
        if (!TEST_ptr(cp = OSSL_PARAM_locate(params, int_names[j]))
            || !TEST_true(OSSL_PARAM_set_int32(cp, (int32_t)(3 + j)))
            || !TEST_true(OSSL_PARAM_get_int64(cp, &i64))
            || !TEST_size_t_eq(cp->data_size, sz)
            || !TEST_size_t_eq((size_t)i64, 3 + j)) {
            TEST_note("iteration %zu var %s", j + 1, int_names[j]);
            goto err;
        }
    }
    /* All unsigned integral types */
    for (j = 0; j < OSSL_NELEM(uint_names); j++) {
        if (!TEST_ptr(cp = OSSL_PARAM_locate(params, uint_names[j]))
            || !TEST_true(OSSL_PARAM_set_uint32(cp, (uint32_t)(3 + j)))
            || !TEST_true(OSSL_PARAM_get_uint64(cp, &u64))
            || !TEST_size_t_eq(cp->data_size, sz)
            || !TEST_size_t_eq((size_t)u64, 3 + j)) {
            TEST_note("iteration %zu var %s", j + 1, uint_names[j]);
            goto err;
        }
    }
    /* Real */
    if (!TEST_ptr(cp = OSSL_PARAM_locate(params, "double"))
        || !TEST_true(OSSL_PARAM_set_double(cp, 3.14))
        || !TEST_true(OSSL_PARAM_get_double(cp, &d2))
        || !TEST_size_t_eq(sz, sizeof(double))
        || !TEST_double_eq(d, d2))
        goto err;
    /* UTF8 string */
    bufp = NULL;
    if (!TEST_ptr(cp = OSSL_PARAM_locate(params, "utf8str"))
        || !TEST_true(OSSL_PARAM_set_utf8_string(cp, "abcdef"))
        || !TEST_size_t_eq(sz, sizeof("abcdef"))
        || !TEST_true(OSSL_PARAM_get_utf8_string(cp, &bufp, 0))
        || !TEST_str_eq(bufp, "abcdef"))
        goto err;
    OPENSSL_free(bufp);
    bufp = buf2;
    if (!TEST_true(OSSL_PARAM_get_utf8_string(cp, &bufp, sizeof(buf2)))
        || !TEST_str_eq(buf2, "abcdef"))
        goto err;
    /* UTF8 pointer */
    bufp = buf;
    sz = 0;
    if (!TEST_ptr(cp = OSSL_PARAM_locate(params, "utf8ptr"))
        || !TEST_true(OSSL_PARAM_set_utf8_ptr(cp, "tuvwxyz"))
        || !TEST_size_t_eq(sz, sizeof("tuvwxyz"))
        || !TEST_str_eq(bufp, "tuvwxyz")
        || !TEST_true(OSSL_PARAM_get_utf8_ptr(cp, (const char **)&bufp2))
        || !TEST_ptr_eq(bufp2, bufp))
        goto err;
    /* OCTET string */
    if (!TEST_ptr(p = locate(params, "octstr"))
        || !TEST_true(OSSL_PARAM_set_octet_string(p, "abcdefghi",
                                                  sizeof("abcdefghi")))
        || !TEST_size_t_eq(sz, sizeof("abcdefghi")))
        goto err;
    /* Match the return size to avoid trailing garbage bytes */
    p->data_size = *p->return_size;
    if (!TEST_true(OSSL_PARAM_get_octet_string(p, &vpn, 0, &s))
        || !TEST_size_t_eq(s, sizeof("abcdefghi"))
        || !TEST_mem_eq(vpn, sizeof("abcdefghi"),
                        "abcdefghi", sizeof("abcdefghi")))
        goto err;
    vp = buf2;
    if (!TEST_true(OSSL_PARAM_get_octet_string(p, &vp, sizeof(buf2), &s))
        || !TEST_size_t_eq(s, sizeof("abcdefghi"))
        || !TEST_mem_eq(vp, sizeof("abcdefghi"),
                        "abcdefghi", sizeof("abcdefghi")))
        goto err;
    /* OCTET pointer */
    vp = &l;
    sz = 0;
    if (!TEST_ptr(p = locate(params, "octptr"))
        || !TEST_true(OSSL_PARAM_set_octet_ptr(p, &ul, sizeof(ul)))
        || !TEST_size_t_eq(sz, sizeof(ul))
        || !TEST_ptr_eq(vp, &ul))
        goto err;
    /* Match the return size to avoid trailing garbage bytes */
    p->data_size = *p->return_size;
    if (!TEST_true(OSSL_PARAM_get_octet_ptr(p, (const void **)&vp2, &k))
        || !TEST_size_t_eq(k, sizeof(ul))
        || !TEST_ptr_eq(vp2, vp))
        goto err;
    /* BIGNUM */
    if (!TEST_ptr(p = locate(params, "bignum"))
        || !TEST_ptr(bn = BN_lebin2bn(bn_val, (int)sizeof(bn_val), NULL))
        || !TEST_true(OSSL_PARAM_set_BN(p, bn))
        || !TEST_size_t_eq(sz, sizeof(bn_val)))
        goto err;
    /* Match the return size to avoid trailing garbage bytes */
    p->data_size = *p->return_size;
    if(!TEST_true(OSSL_PARAM_get_BN(p, &bn2))
        || !TEST_BN_eq(bn, bn2))
        goto err;
    ret = 1;
err:
    OPENSSL_free(vpn);
    BN_free(bn);
    BN_free(bn2);
    return ret;
}
コード例 #16
0
ファイル: property_test.c プロジェクト: opensignature/openssl
static int test_property(void)
{
    static const struct {
        int nid;
        const char *prop;
        char *impl;
    } impls[] = {
        { 1, "fast=no, colour=green", "a" },
        { 1, "fast, colour=blue", "b" },
        { 1, "", "-" },
        { 9, "sky=blue, furry", "c" },
        { 3, NULL, "d" },
        { 6, "sky.colour=blue, sky=green, old.data", "e" },
    };
    static struct {
        int nid;
        const char *prop;
        char *expected;
    } queries[] = {
        { 1, "fast", "b" },
        { 1, "fast=yes", "b" },
        { 1, "fast=no, colour=green", "a" },
        { 1, "colour=blue, fast", "b" },
        { 1, "colour=blue", "b" },
        { 9, "furry", "c" },
        { 6, "sky.colour=blue", "e" },
        { 6, "old.data", "e" },
        { 9, "furry=yes, sky=blue", "c" },
        { 1, "", "a" },
        { 3, "", "d" },
    };
    OSSL_METHOD_STORE *store;
    size_t i;
    int ret = 0;
    void *result;

    if (!TEST_ptr(store = ossl_method_store_new(NULL))
        || !add_property_names("fast", "colour", "sky", "furry", NULL))
        goto err;

    for (i = 0; i < OSSL_NELEM(impls); i++)
        if (!TEST_true(ossl_method_store_add(store, impls[i].nid, impls[i].prop,
                                             impls[i].impl, NULL))) {
            TEST_note("iteration %zd", i + 1);
            goto err;
        }
    for (i = 0; i < OSSL_NELEM(queries); i++) {
        OSSL_PROPERTY_LIST *pq = NULL;

        if (!TEST_true(ossl_method_store_fetch(store, queries[i].nid,
                                               queries[i].prop, &result))
            || !TEST_str_eq((char *)result, queries[i].expected)) {
            TEST_note("iteration %zd", i + 1);
            ossl_property_free(pq);
            goto err;
        }
        ossl_property_free(pq);
    }
    ret = 1;
err:
    ossl_method_store_free(store);
    return ret;
}