@@ -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