@@ -222,15 +222,21 @@ struct collect_data_st {
222
222
int total ; /* number of matching results */
223
223
char error_occurred ;
224
224
char keytype_resolved ;
225
+ OSSL_PROPERTY_LIST * pq ;
225
226
226
227
STACK_OF (EVP_KEYMGMT ) * keymgmts ;
227
228
};
228
229
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 )
231
236
{
232
237
void * decoderctx = NULL ;
233
238
OSSL_DECODER_INSTANCE * di = NULL ;
239
+ const OSSL_PROPERTY_LIST * props ;
234
240
235
241
/*
236
242
* 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,
239
245
240
246
if (keymgmt -> name_id != decoder -> base .id )
241
247
/* Mismatch is not an error, continue. */
242
- return ;
248
+ return 0 ;
243
249
244
250
if ((decoderctx = decoder -> newctx (provctx )) == NULL ) {
245
251
data -> error_occurred = 1 ;
246
- return ;
252
+ return 0 ;
247
253
}
248
254
249
255
if ((di = ossl_decoder_instance_new (decoder , decoderctx )) == NULL ) {
250
256
decoder -> freectx (decoderctx );
251
257
data -> error_occurred = 1 ;
252
- return ;
258
+ return 0 ;
253
259
}
254
260
255
261
/*
@@ -263,7 +269,7 @@ static void collect_decoder_keymgmt(EVP_KEYMGMT *keymgmt, OSSL_DECODER *decoder,
263
269
|| OPENSSL_strcasecmp (data -> ctx -> start_input_type , "PEM" ) != 0 )) {
264
270
/* Mismatch is not an error, continue. */
265
271
ossl_decoder_instance_free (di );
266
- return ;
272
+ return 0 ;
267
273
}
268
274
269
275
OSSL_TRACE_BEGIN (DECODER ) {
@@ -275,13 +281,30 @@ static void collect_decoder_keymgmt(EVP_KEYMGMT *keymgmt, OSSL_DECODER *decoder,
275
281
OSSL_DECODER_get0_properties (decoder ));
276
282
} OSSL_TRACE_END (DECODER );
277
283
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
+
278
300
if (!ossl_decoder_ctx_add_decoder_inst (data -> ctx , di )) {
279
301
ossl_decoder_instance_free (di );
280
302
data -> error_occurred = 1 ;
281
- return ;
303
+ return 0 ;
282
304
}
283
305
284
306
++ data -> total ;
307
+ return 1 ;
285
308
}
286
309
287
310
static void collect_decoder (OSSL_DECODER * decoder , void * arg )
@@ -321,7 +344,9 @@ static void collect_decoder(OSSL_DECODER *decoder, void *arg)
321
344
for (i = 0 ; i < end_i ; ++ i ) {
322
345
keymgmt = sk_EVP_KEYMGMT_value (keymgmts , i );
323
346
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 ;
325
350
if (data -> error_occurred )
326
351
return ;
327
352
}
@@ -407,6 +432,8 @@ static int ossl_decoder_ctx_setup_for_pkey(OSSL_DECODER_CTX *ctx,
407
432
struct decoder_pkey_data_st * process_data = NULL ;
408
433
struct collect_data_st collect_data = { NULL };
409
434
STACK_OF (EVP_KEYMGMT ) * keymgmts = NULL ;
435
+ OSSL_PROPERTY_LIST * * plp ;
436
+ OSSL_PROPERTY_LIST * pq = NULL , * p2 = NULL ;
410
437
411
438
OSSL_TRACE_BEGIN (DECODER ) {
412
439
const char * input_type = ctx -> start_input_type ;
@@ -442,6 +469,25 @@ static int ossl_decoder_ctx_setup_for_pkey(OSSL_DECODER_CTX *ctx,
442
469
process_data -> selection = ctx -> selection ;
443
470
process_data -> keymgmts = keymgmts ;
444
471
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
+
445
491
/*
446
492
* Enumerate all keymgmts into a stack.
447
493
*
@@ -457,10 +503,11 @@ static int ossl_decoder_ctx_setup_for_pkey(OSSL_DECODER_CTX *ctx,
457
503
* upfront, as this ensures that the names for all loaded providers have
458
504
* been registered by the time we try to resolve the keytype string.
459
505
*/
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 ;
464
511
EVP_KEYMGMT_do_all_provided (libctx , collect_keymgmt , & collect_data );
465
512
466
513
if (collect_data .error_occurred )
@@ -496,6 +543,7 @@ static int ossl_decoder_ctx_setup_for_pkey(OSSL_DECODER_CTX *ctx,
496
543
ok = 1 ;
497
544
err :
498
545
decoder_clean_pkey_construct_arg (process_data );
546
+ ossl_property_free (p2 );
499
547
return ok ;
500
548
}
501
549
0 commit comments