@@ -222,15 +222,21 @@ struct collect_data_st {
222222 int total; /* number of matching results */
223223 char error_occurred;
224224 char keytype_resolved;
225+ OSSL_PROPERTY_LIST *pq;
225226
226227 STACK_OF(EVP_KEYMGMT) *keymgmts;
227228};
228229
229- static void collect_decoder_keymgmt(EVP_KEYMGMT *keymgmt, OSSL_DECODER *decoder,
230- void *provctx, struct collect_data_st *data)
230+ /*
231+ * Add decoder instance to the decoder context if it is compatible. Returns 1
232+ * if a decoder was added, 0 otherwise.
233+ */
234+ static int collect_decoder_keymgmt(EVP_KEYMGMT *keymgmt, OSSL_DECODER *decoder,
235+ void *provctx, struct collect_data_st *data)
231236{
232237 void *decoderctx = NULL;
233238 OSSL_DECODER_INSTANCE *di = NULL;
239+ const OSSL_PROPERTY_LIST *props;
234240
235241 /*
236242 * We already checked the EVP_KEYMGMT is applicable in check_keymgmt so we
@@ -239,17 +245,17 @@ static void collect_decoder_keymgmt(EVP_KEYMGMT *keymgmt, OSSL_DECODER *decoder,
239245
240246 if (keymgmt->name_id != decoder->base.id)
241247 /* Mismatch is not an error, continue. */
242- return;
248+ return 0 ;
243249
244250 if ((decoderctx = decoder->newctx(provctx)) == NULL) {
245251 data->error_occurred = 1;
246- return;
252+ return 0 ;
247253 }
248254
249255 if ((di = ossl_decoder_instance_new(decoder, decoderctx)) == NULL) {
250256 decoder->freectx(decoderctx);
251257 data->error_occurred = 1;
252- return;
258+ return 0 ;
253259 }
254260
255261 /*
@@ -263,7 +269,7 @@ static void collect_decoder_keymgmt(EVP_KEYMGMT *keymgmt, OSSL_DECODER *decoder,
263269 || OPENSSL_strcasecmp(data->ctx->start_input_type, "PEM") != 0)) {
264270 /* Mismatch is not an error, continue. */
265271 ossl_decoder_instance_free(di);
266- return;
272+ return 0 ;
267273 }
268274
269275 OSSL_TRACE_BEGIN(DECODER) {
@@ -275,13 +281,30 @@ static void collect_decoder_keymgmt(EVP_KEYMGMT *keymgmt, OSSL_DECODER *decoder,
275281 OSSL_DECODER_get0_properties(decoder));
276282 } OSSL_TRACE_END(DECODER);
277283
284+ /*
285+ * Get the property match score so the decoders can be prioritized later.
286+ */
287+ props = ossl_decoder_parsed_properties(decoder);
288+ if (data->pq != NULL && props != NULL) {
289+ di->score = ossl_property_match_count(data->pq, props);
290+ /*
291+ * Mismatch of mandatory properties is not an error, the decoder is just
292+ * ignored, continue.
293+ */
294+ if (di->score < 0) {
295+ ossl_decoder_instance_free(di);
296+ return 0;
297+ }
298+ }
299+
278300 if (!ossl_decoder_ctx_add_decoder_inst(data->ctx, di)) {
279301 ossl_decoder_instance_free(di);
280302 data->error_occurred = 1;
281- return;
303+ return 0 ;
282304 }
283305
284306 ++data->total;
307+ return 1;
285308}
286309
287310static void collect_decoder(OSSL_DECODER *decoder, void *arg)
@@ -321,7 +344,9 @@ static void collect_decoder(OSSL_DECODER *decoder, void *arg)
321344 for (i = 0; i < end_i; ++i) {
322345 keymgmt = sk_EVP_KEYMGMT_value(keymgmts, i);
323346
324- collect_decoder_keymgmt(keymgmt, decoder, provctx, data);
347+ /* Only add this decoder once */
348+ if (collect_decoder_keymgmt(keymgmt, decoder, provctx, data))
349+ break;
325350 if (data->error_occurred)
326351 return;
327352 }
@@ -407,6 +432,8 @@ static int ossl_decoder_ctx_setup_for_pkey(OSSL_DECODER_CTX *ctx,
407432 struct decoder_pkey_data_st *process_data = NULL;
408433 struct collect_data_st collect_data = { NULL };
409434 STACK_OF(EVP_KEYMGMT) *keymgmts = NULL;
435+ OSSL_PROPERTY_LIST **plp;
436+ OSSL_PROPERTY_LIST *pq = NULL, *p2 = NULL;
410437
411438 OSSL_TRACE_BEGIN(DECODER) {
412439 const char *input_type = ctx->start_input_type;
@@ -442,6 +469,25 @@ static int ossl_decoder_ctx_setup_for_pkey(OSSL_DECODER_CTX *ctx,
442469 process_data->selection = ctx->selection;
443470 process_data->keymgmts = keymgmts;
444471
472+ /*
473+ * Collect passed and default properties to prioritize the decoders.
474+ */
475+ if (propquery != NULL)
476+ p2 = pq = ossl_parse_query(libctx, propquery, 1);
477+
478+ plp = ossl_ctx_global_properties(libctx, 0);
479+ if (plp != NULL && *plp != NULL) {
480+ if (pq == NULL) {
481+ pq = *plp;
482+ } else {
483+ p2 = ossl_property_merge(pq, *plp);
484+ ossl_property_free(pq);
485+ if (p2 == NULL)
486+ goto err;
487+ pq = p2;
488+ }
489+ }
490+
445491 /*
446492 * Enumerate all keymgmts into a stack.
447493 *
@@ -457,10 +503,11 @@ static int ossl_decoder_ctx_setup_for_pkey(OSSL_DECODER_CTX *ctx,
457503 * upfront, as this ensures that the names for all loaded providers have
458504 * been registered by the time we try to resolve the keytype string.
459505 */
460- collect_data.ctx = ctx;
461- collect_data.libctx = libctx;
462- collect_data.keymgmts = keymgmts;
463- collect_data.keytype = keytype;
506+ collect_data.ctx = ctx;
507+ collect_data.libctx = libctx;
508+ collect_data.keymgmts = keymgmts;
509+ collect_data.keytype = keytype;
510+ collect_data.pq = pq;
464511 EVP_KEYMGMT_do_all_provided(libctx, collect_keymgmt, &collect_data);
465512
466513 if (collect_data.error_occurred)
@@ -496,6 +543,7 @@ static int ossl_decoder_ctx_setup_for_pkey(OSSL_DECODER_CTX *ctx,
496543 ok = 1;
497544 err:
498545 decoder_clean_pkey_construct_arg(process_data);
546+ ossl_property_free(p2);
499547 return ok;
500548}
501549
0 commit comments