static int tls1_prf_P_hash(const EVP_MD *md,
                           const unsigned char *sec, size_t sec_len,
                           const unsigned char *seed, size_t seed_len,
                           unsigned char *out, size_t olen)
{
    size_t chunk;
    EVP_MAC *mac = NULL;
    EVP_MAC_CTX *ctx = NULL, *ctx_Ai = NULL, *ctx_init = NULL;
    unsigned char Ai[EVP_MAX_MD_SIZE];
    size_t Ai_len;
    int ret = 0;
    OSSL_PARAM params[4];
    int mac_flags;
    const char *mdname = EVP_MD_name(md);
    mac = EVP_MAC_fetch(NULL, OSSL_MAC_NAME_HMAC, NULL);
    ctx_init = EVP_MAC_CTX_new(mac);
    if (ctx_init == NULL)
        goto err;
    mac_flags = EVP_MD_CTX_FLAG_NON_FIPS_ALLOW;
    params[0] = OSSL_PARAM_construct_int(OSSL_MAC_PARAM_FLAGS, &mac_flags);
    params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_ALGORITHM,
                                                 (char *)mdname,
                                                 strlen(mdname) + 1);
    params[2] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
                                                  (void *)sec, sec_len);
    params[3] = OSSL_PARAM_construct_end();
    if (!EVP_MAC_CTX_set_params(ctx_init, params))
        goto err;
    if (!EVP_MAC_init(ctx_init))
        goto err;
    chunk = EVP_MAC_size(ctx_init);
    if (chunk == 0)
        goto err;
    ctx_Ai = EVP_MAC_CTX_dup(ctx_init);
    if (ctx_Ai == NULL)
        goto err;
    if (seed != NULL && !EVP_MAC_update(ctx_Ai, seed, seed_len))
        goto err;
    for (;;) {
        if (!EVP_MAC_final(ctx_Ai, Ai, &Ai_len, sizeof(Ai)))
            goto err;
        EVP_MAC_CTX_free(ctx_Ai);
        ctx_Ai = NULL;
        ctx = EVP_MAC_CTX_dup(ctx_init);
        if (ctx == NULL)
            goto err;
        if (!EVP_MAC_update(ctx, Ai, Ai_len))
            goto err;
        if (olen > chunk) {
            ctx_Ai = EVP_MAC_CTX_dup(ctx);
            if (ctx_Ai == NULL)
                goto err;
        }
        if (seed != NULL && !EVP_MAC_update(ctx, seed, seed_len))
            goto err;
        if (olen <= chunk) {
            if (!EVP_MAC_final(ctx, Ai, &Ai_len, sizeof(Ai)))
                goto err;
            memcpy(out, Ai, olen);
            break;
        }
        if (!EVP_MAC_final(ctx, out, NULL, olen))
            goto err;
        EVP_MAC_CTX_free(ctx);
        ctx = NULL;
        out += chunk;
        olen -= chunk;
    }
    ret = 1;
 err:
    EVP_MAC_CTX_free(ctx);
    EVP_MAC_CTX_free(ctx_Ai);
    EVP_MAC_CTX_free(ctx_init);
    EVP_MAC_free(mac);
    OPENSSL_cleanse(Ai, sizeof(Ai));
    return ret;
}
['static int tls1_prf_P_hash(const EVP_MD *md,\n                           const unsigned char *sec, size_t sec_len,\n                           const unsigned char *seed, size_t seed_len,\n                           unsigned char *out, size_t olen)\n{\n    size_t chunk;\n    EVP_MAC *mac = NULL;\n    EVP_MAC_CTX *ctx = NULL, *ctx_Ai = NULL, *ctx_init = NULL;\n    unsigned char Ai[EVP_MAX_MD_SIZE];\n    size_t Ai_len;\n    int ret = 0;\n    OSSL_PARAM params[4];\n    int mac_flags;\n    const char *mdname = EVP_MD_name(md);\n    mac = EVP_MAC_fetch(NULL, OSSL_MAC_NAME_HMAC, NULL);\n    ctx_init = EVP_MAC_CTX_new(mac);\n    if (ctx_init == NULL)\n        goto err;\n    mac_flags = EVP_MD_CTX_FLAG_NON_FIPS_ALLOW;\n    params[0] = OSSL_PARAM_construct_int(OSSL_MAC_PARAM_FLAGS, &mac_flags);\n    params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_ALGORITHM,\n                                                 (char *)mdname,\n                                                 strlen(mdname) + 1);\n    params[2] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,\n                                                  (void *)sec, sec_len);\n    params[3] = OSSL_PARAM_construct_end();\n    if (!EVP_MAC_CTX_set_params(ctx_init, params))\n        goto err;\n    if (!EVP_MAC_init(ctx_init))\n        goto err;\n    chunk = EVP_MAC_size(ctx_init);\n    if (chunk == 0)\n        goto err;\n    ctx_Ai = EVP_MAC_CTX_dup(ctx_init);\n    if (ctx_Ai == NULL)\n        goto err;\n    if (seed != NULL && !EVP_MAC_update(ctx_Ai, seed, seed_len))\n        goto err;\n    for (;;) {\n        if (!EVP_MAC_final(ctx_Ai, Ai, &Ai_len, sizeof(Ai)))\n            goto err;\n        EVP_MAC_CTX_free(ctx_Ai);\n        ctx_Ai = NULL;\n        ctx = EVP_MAC_CTX_dup(ctx_init);\n        if (ctx == NULL)\n            goto err;\n        if (!EVP_MAC_update(ctx, Ai, Ai_len))\n            goto err;\n        if (olen > chunk) {\n            ctx_Ai = EVP_MAC_CTX_dup(ctx);\n            if (ctx_Ai == NULL)\n                goto err;\n        }\n        if (seed != NULL && !EVP_MAC_update(ctx, seed, seed_len))\n            goto err;\n        if (olen <= chunk) {\n            if (!EVP_MAC_final(ctx, Ai, &Ai_len, sizeof(Ai)))\n                goto err;\n            memcpy(out, Ai, olen);\n            break;\n        }\n        if (!EVP_MAC_final(ctx, out, NULL, olen))\n            goto err;\n        EVP_MAC_CTX_free(ctx);\n        ctx = NULL;\n        out += chunk;\n        olen -= chunk;\n    }\n    ret = 1;\n err:\n    EVP_MAC_CTX_free(ctx);\n    EVP_MAC_CTX_free(ctx_Ai);\n    EVP_MAC_CTX_free(ctx_init);\n    EVP_MAC_free(mac);\n    OPENSSL_cleanse(Ai, sizeof(Ai));\n    return ret;\n}', 'const char *EVP_MD_name(const EVP_MD *md)\n{\n    if (md->prov != NULL)\n        return md->name;\n#ifndef FIPS_MODE\n    return OBJ_nid2sn(EVP_MD_nid(md));\n#else\n    return NULL;\n#endif\n}', 'EVP_MAC *EVP_MAC_fetch(OPENSSL_CTX *libctx, const char *algorithm,\n                       const char *properties)\n{\n    return evp_generic_fetch(libctx, OSSL_OP_MAC, algorithm, properties,\n                             evp_mac_from_dispatch, evp_mac_up_ref,\n                             evp_mac_free);\n}', 'void *evp_generic_fetch(OPENSSL_CTX *libctx, int operation_id,\n                        const char *name, const char *properties,\n                        void *(*new_method)(const char *name,\n                                            const OSSL_DISPATCH *fns,\n                                            OSSL_PROVIDER *prov),\n                        int (*up_ref_method)(void *),\n                        void (*free_method)(void *))\n{\n    OSSL_METHOD_STORE *store = get_default_method_store(libctx);\n    OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);\n    int nameid = 0;\n    uint32_t methid = 0;\n    void *method = NULL;\n    if (store == NULL || namemap == NULL)\n        return NULL;\n    if (!ossl_assert(operation_id > 0))\n        return NULL;\n    if ((nameid = ossl_namemap_name2num(namemap, name)) != 0\n        && (methid = method_id(operation_id, nameid)) == 0)\n        return NULL;\n    if (nameid == 0\n        || !ossl_method_store_cache_get(store, methid, properties,\n                                        &method)) {\n        OSSL_METHOD_CONSTRUCT_METHOD mcm = {\n            alloc_tmp_method_store,\n            dealloc_tmp_method_store,\n            get_method_from_store,\n            put_method_in_store,\n            construct_method,\n            destruct_method\n        };\n        struct method_data_st mcmdata;\n        mcmdata.mcm = &mcm;\n        mcmdata.libctx = libctx;\n        mcmdata.name = name;\n        mcmdata.method_from_dispatch = new_method;\n        mcmdata.destruct_method = free_method;\n        mcmdata.refcnt_up_method = up_ref_method;\n        mcmdata.destruct_method = free_method;\n        if ((method = ossl_method_construct(libctx, operation_id, name,\n                                            properties, 0  ,\n                                            &mcm, &mcmdata)) != NULL) {\n            nameid = ossl_namemap_name2num(namemap, name);\n            methid = method_id(operation_id, nameid);\n            ossl_method_store_cache_set(store, methid, properties, method);\n        }\n    } else {\n        up_ref_method(method);\n    }\n    return method;\n}', 'static OSSL_METHOD_STORE *get_default_method_store(OPENSSL_CTX *libctx)\n{\n    return openssl_ctx_get_data(libctx, OPENSSL_CTX_DEFAULT_METHOD_STORE_INDEX,\n                                &default_method_store_method);\n}', 'void *openssl_ctx_get_data(OPENSSL_CTX *ctx, int index,\n                           const OPENSSL_CTX_METHOD *meth)\n{\n    void *data = NULL;\n    ctx = openssl_ctx_get_concrete(ctx);\n    if (ctx == NULL)\n        return NULL;\n    CRYPTO_THREAD_read_lock(ctx->lock);\n    if (ctx->dyn_indexes[index] == -1\n            && !openssl_ctx_init_index(ctx, index, meth)) {\n        CRYPTO_THREAD_unlock(ctx->lock);\n        return NULL;\n    }\n    if (CRYPTO_alloc_ex_data(CRYPTO_EX_INDEX_OPENSSL_CTX, NULL,\n                             &ctx->data, ctx->dyn_indexes[index]))\n        data = CRYPTO_get_ex_data(&ctx->data, ctx->dyn_indexes[index]);\n    CRYPTO_THREAD_unlock(ctx->lock);\n    return data;\n}', 'OPENSSL_CTX *openssl_ctx_get_concrete(OPENSSL_CTX *ctx)\n{\n#ifndef FIPS_MODE\n    if (ctx == NULL) {\n        if (!RUN_ONCE(&default_context_init, do_default_context_init))\n            return 0;\n        return default_context;\n    }\n#endif\n    return ctx;\n}', 'OSSL_NAMEMAP *ossl_namemap_stored(OPENSSL_CTX *libctx)\n{\n    return openssl_ctx_get_data(libctx, OPENSSL_CTX_NAMEMAP_INDEX,\n                                &stored_namemap_method);\n}', 'OSSL_PARAM OSSL_PARAM_construct_int(const char *key, int *buf)\n{\n    return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf, sizeof(int));\n}', 'static OSSL_PARAM ossl_param_construct(const char *key, unsigned int data_type,\n                                       void *data, size_t data_size)\n{\n    OSSL_PARAM res;\n    res.key = key;\n    res.data_type = data_type;\n    res.data = data;\n    res.data_size = data_size;\n    res.return_size = 0;\n    return res;\n}']