static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
{
    MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
    switch (type) {
    case EVP_PKEY_CTRL_CIPHER:
        switch (hctx->type) {
        case MAC_TYPE_RAW:
            return -2;
        case MAC_TYPE_MAC:
            {
                OSSL_PARAM params[3];
                size_t params_n = 0;
                char *ciphname = (char *)OBJ_nid2sn(EVP_CIPHER_nid(p2));
#ifndef OPENSSL_NO_ENGINE
                char *engineid = (char *)ENGINE_get_id(ctx->engine);
                params[params_n++] =
                    OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_ENGINE,
                                                     engineid,
                                                     strlen(engineid) + 1);
#endif
                params[params_n++] =
                    OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER,
                                                     ciphname,
                                                     strlen(ciphname) + 1);
                params[params_n] = OSSL_PARAM_construct_end();
                if (!EVP_MAC_CTX_set_params(hctx->ctx, params)
                    || !EVP_MAC_init(hctx->ctx))
                    return 0;
            }
            break;
        default:
            return 0;
        }
        break;
    case EVP_PKEY_CTRL_MD:
        switch (hctx->type) {
        case MAC_TYPE_RAW:
            hctx->raw_data.md = p2;
            break;
        case MAC_TYPE_MAC: {
                EVP_MAC_CTX *new_mac_ctx;
                if (ctx->pkey == NULL)
                    return 0;
                new_mac_ctx = EVP_MAC_CTX_dup((EVP_MAC_CTX *)ctx->pkey
                                              ->pkey.ptr);
                if (new_mac_ctx == NULL)
                    return 0;
                EVP_MAC_CTX_free(hctx->ctx);
                hctx->ctx = new_mac_ctx;
            }
            break;
        default:
            return 0;
        }
        break;
    case EVP_PKEY_CTRL_SET_DIGEST_SIZE:
        {
            OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
            size_t size = (size_t)p1;
            size_t verify = 0;
            params[0] =
                OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_SIZE, &size);
            if (!EVP_MAC_CTX_set_params(hctx->ctx, params))
                return 0;
            params[0] =
                OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_SIZE, &verify);
            if (!EVP_MAC_CTX_get_params(hctx->ctx, params))
                return 0;
            if (verify != size)
                return -2;
        }
        break;
    case EVP_PKEY_CTRL_SET_MAC_KEY:
        switch (hctx->type) {
        case MAC_TYPE_RAW:
            if ((!p2 && p1 > 0) || (p1 < -1))
                return 0;
            if (!ASN1_OCTET_STRING_set(&hctx->raw_data.ktmp, p2, p1))
                return 0;
            break;
        case MAC_TYPE_MAC:
            {
                OSSL_PARAM params[2];
                size_t params_n = 0;
                params[params_n++] =
                    OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
                                                      p2, p1);
                params[params_n] = OSSL_PARAM_construct_end();
                return EVP_MAC_CTX_set_params(hctx->ctx, params);
            }
            break;
        default:
            return 0;
        }
        break;
    case EVP_PKEY_CTRL_DIGESTINIT:
        switch (hctx->type) {
        case MAC_TYPE_RAW:
            if (!EVP_MAC_init(hctx->ctx))
                return 0;
            {
                ASN1_OCTET_STRING *key =
                    (ASN1_OCTET_STRING *)ctx->pkey->pkey.ptr;
                OSSL_PARAM params[4];
                size_t params_n = 0;
                char *mdname =
                    (char *)OBJ_nid2sn(EVP_MD_nid(hctx->raw_data.md));
#ifndef OPENSSL_NO_ENGINE
                char *engineid = ctx->engine == NULL
                    ? NULL : (char *)ENGINE_get_id(ctx->engine);
                if (engineid != NULL) {
                    size_t engineid_l = strlen(engineid) + 1;
                    params[params_n++] =
                        OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_ENGINE,
                                                         engineid,
                                                         engineid_l);
                }
#endif
                params[params_n++] =
                    OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
                                                     mdname,
                                                     strlen(mdname) + 1);
                params[params_n++] =
                    OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
                                                      key->data, key->length);
                params[params_n] = OSSL_PARAM_construct_end();
                return EVP_MAC_CTX_set_params(hctx->ctx, params);
            }
            break;
        case MAC_TYPE_MAC:
            return -2;
        default:
            return 0;
        }
        break;
    default:
        return -2;
    }
    return 1;
}
['static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)\n{\n    MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);\n    switch (type) {\n    case EVP_PKEY_CTRL_CIPHER:\n        switch (hctx->type) {\n        case MAC_TYPE_RAW:\n            return -2;\n        case MAC_TYPE_MAC:\n            {\n                OSSL_PARAM params[3];\n                size_t params_n = 0;\n                char *ciphname = (char *)OBJ_nid2sn(EVP_CIPHER_nid(p2));\n#ifndef OPENSSL_NO_ENGINE\n                char *engineid = (char *)ENGINE_get_id(ctx->engine);\n                params[params_n++] =\n                    OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_ENGINE,\n                                                     engineid,\n                                                     strlen(engineid) + 1);\n#endif\n                params[params_n++] =\n                    OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER,\n                                                     ciphname,\n                                                     strlen(ciphname) + 1);\n                params[params_n] = OSSL_PARAM_construct_end();\n                if (!EVP_MAC_CTX_set_params(hctx->ctx, params)\n                    || !EVP_MAC_init(hctx->ctx))\n                    return 0;\n            }\n            break;\n        default:\n            return 0;\n        }\n        break;\n    case EVP_PKEY_CTRL_MD:\n        switch (hctx->type) {\n        case MAC_TYPE_RAW:\n            hctx->raw_data.md = p2;\n            break;\n        case MAC_TYPE_MAC: {\n                EVP_MAC_CTX *new_mac_ctx;\n                if (ctx->pkey == NULL)\n                    return 0;\n                new_mac_ctx = EVP_MAC_CTX_dup((EVP_MAC_CTX *)ctx->pkey\n                                              ->pkey.ptr);\n                if (new_mac_ctx == NULL)\n                    return 0;\n                EVP_MAC_CTX_free(hctx->ctx);\n                hctx->ctx = new_mac_ctx;\n            }\n            break;\n        default:\n            return 0;\n        }\n        break;\n    case EVP_PKEY_CTRL_SET_DIGEST_SIZE:\n        {\n            OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };\n            size_t size = (size_t)p1;\n            size_t verify = 0;\n            params[0] =\n                OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_SIZE, &size);\n            if (!EVP_MAC_CTX_set_params(hctx->ctx, params))\n                return 0;\n            params[0] =\n                OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_SIZE, &verify);\n            if (!EVP_MAC_CTX_get_params(hctx->ctx, params))\n                return 0;\n            if (verify != size)\n                return -2;\n        }\n        break;\n    case EVP_PKEY_CTRL_SET_MAC_KEY:\n        switch (hctx->type) {\n        case MAC_TYPE_RAW:\n            if ((!p2 && p1 > 0) || (p1 < -1))\n                return 0;\n            if (!ASN1_OCTET_STRING_set(&hctx->raw_data.ktmp, p2, p1))\n                return 0;\n            break;\n        case MAC_TYPE_MAC:\n            {\n                OSSL_PARAM params[2];\n                size_t params_n = 0;\n                params[params_n++] =\n                    OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,\n                                                      p2, p1);\n                params[params_n] = OSSL_PARAM_construct_end();\n                return EVP_MAC_CTX_set_params(hctx->ctx, params);\n            }\n            break;\n        default:\n            return 0;\n        }\n        break;\n    case EVP_PKEY_CTRL_DIGESTINIT:\n        switch (hctx->type) {\n        case MAC_TYPE_RAW:\n            if (!EVP_MAC_init(hctx->ctx))\n                return 0;\n            {\n                ASN1_OCTET_STRING *key =\n                    (ASN1_OCTET_STRING *)ctx->pkey->pkey.ptr;\n                OSSL_PARAM params[4];\n                size_t params_n = 0;\n                char *mdname =\n                    (char *)OBJ_nid2sn(EVP_MD_nid(hctx->raw_data.md));\n#ifndef OPENSSL_NO_ENGINE\n                char *engineid = ctx->engine == NULL\n                    ? NULL : (char *)ENGINE_get_id(ctx->engine);\n                if (engineid != NULL) {\n                    size_t engineid_l = strlen(engineid) + 1;\n                    params[params_n++] =\n                        OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_ENGINE,\n                                                         engineid,\n                                                         engineid_l);\n                }\n#endif\n                params[params_n++] =\n                    OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,\n                                                     mdname,\n                                                     strlen(mdname) + 1);\n                params[params_n++] =\n                    OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,\n                                                      key->data, key->length);\n                params[params_n] = OSSL_PARAM_construct_end();\n                return EVP_MAC_CTX_set_params(hctx->ctx, params);\n            }\n            break;\n        case MAC_TYPE_MAC:\n            return -2;\n        default:\n            return 0;\n        }\n        break;\n    default:\n        return -2;\n    }\n    return 1;\n}', 'void *EVP_PKEY_CTX_get_data(const EVP_PKEY_CTX *ctx)\n{\n    return ctx->data;\n}', 'int EVP_CIPHER_nid(const EVP_CIPHER *cipher)\n{\n    return cipher->nid;\n}', 'const char *OBJ_nid2sn(int n)\n{\n    ADDED_OBJ ad, *adp;\n    ASN1_OBJECT ob;\n    if ((n >= 0) && (n < NUM_NID)) {\n        if ((n != NID_undef) && (nid_objs[n].nid == NID_undef)) {\n            OBJerr(OBJ_F_OBJ_NID2SN, OBJ_R_UNKNOWN_NID);\n            return NULL;\n        }\n        return nid_objs[n].sn;\n    }\n    OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);\n    if (added == NULL)\n        return NULL;\n    ad.type = ADDED_NID;\n    ad.obj = &ob;\n    ob.nid = n;\n    adp = lh_ADDED_OBJ_retrieve(added, &ad);\n    if (adp != NULL)\n        return adp->obj->sn;\n    OBJerr(OBJ_F_OBJ_NID2SN, OBJ_R_UNKNOWN_NID);\n    return NULL;\n}', 'const char *ENGINE_get_id(const ENGINE *e)\n{\n    return e->id;\n}', 'OSSL_PARAM OSSL_PARAM_construct_utf8_string(const char *key, char *buf,\n                                            size_t bsize)\n{\n    return ossl_param_construct(key, OSSL_PARAM_UTF8_STRING, buf, bsize);\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}']