+
+ if (keytype != -1) {
+ switch (evp_pkey_ctx_state(ctx)) {
+ case EVP_PKEY_STATE_PROVIDER:
+ if (ctx->keymgmt == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ return -2;
+ }
+ if (!EVP_KEYMGMT_is_a(ctx->keymgmt,
+ evp_pkey_type2name(keytype))) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION);
+ return -1;
+ }
+ break;
+ case EVP_PKEY_STATE_UNKNOWN:
+ case EVP_PKEY_STATE_LEGACY:
+ if (ctx->pmeth == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+ return -2;
+ }
+ if (EVP_PKEY_type(ctx->pmeth->pkey_id) != EVP_PKEY_type(keytype)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION);
+ return -1;
+ }
+ break;
+ }
+ }
+ if (optype != -1 && (ctx->operation & optype) == 0) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION);
+ return -1;
+ }
+
+ switch (cmd) {
+ case EVP_PKEY_CTRL_SET1_ID:
+ evp_pkey_ctx_free_cached_data(ctx, cmd, name);
+ if (name != NULL) {
+ ctx->cached_parameters.dist_id_name = OPENSSL_strdup(name);
+ if (ctx->cached_parameters.dist_id_name == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ }
+ if (data_len > 0) {
+ ctx->cached_parameters.dist_id = OPENSSL_memdup(data, data_len);
+ if (ctx->cached_parameters.dist_id == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ }
+ ctx->cached_parameters.dist_id_set = 1;
+ ctx->cached_parameters.dist_id_len = data_len;
+ break;
+ }
+ return 1;
+}
+
+static void evp_pkey_ctx_free_cached_data(EVP_PKEY_CTX *ctx,
+ int cmd, const char *name)
+{
+ cmd = decode_cmd(cmd, name);
+ switch (cmd) {
+ case EVP_PKEY_CTRL_SET1_ID:
+ OPENSSL_free(ctx->cached_parameters.dist_id);
+ OPENSSL_free(ctx->cached_parameters.dist_id_name);
+ ctx->cached_parameters.dist_id = NULL;
+ ctx->cached_parameters.dist_id_name = NULL;
+ break;
+ }
+}
+
+static void evp_pkey_ctx_free_all_cached_data(EVP_PKEY_CTX *ctx)
+{
+ evp_pkey_ctx_free_cached_data(ctx, EVP_PKEY_CTRL_SET1_ID, NULL);
+}
+
+int evp_pkey_ctx_use_cached_data(EVP_PKEY_CTX *ctx)
+{
+ int ret = 1;
+
+ if (ret && ctx->cached_parameters.dist_id_set) {
+ const char *name = ctx->cached_parameters.dist_id_name;
+ const void *val = ctx->cached_parameters.dist_id;
+ size_t len = ctx->cached_parameters.dist_id_len;
+
+ if (name != NULL)
+ ret = evp_pkey_ctx_ctrl_str_int(ctx, name, val);
+ else
+ ret = evp_pkey_ctx_ctrl_int(ctx, -1, ctx->operation,
+ EVP_PKEY_CTRL_SET1_ID,
+ (int)len, (void *)val);
+ }
+
+ return ret;
+}
+
+OSSL_LIB_CTX *EVP_PKEY_CTX_get0_libctx(EVP_PKEY_CTX *ctx)
+{
+ return ctx->libctx;
+}
+
+const char *EVP_PKEY_CTX_get0_propq(EVP_PKEY_CTX *ctx)
+{
+ return ctx->propquery;