@@ -391,7 +391,7 @@ static void *ctx_try_load_object(ENGINE_CTX *ctx,
391391{
392392 PKCS11_SLOT * slot ;
393393 PKCS11_SLOT * found_slot = NULL , * * matched_slots = NULL ;
394- PKCS11_TOKEN * tok , * match_tok = NULL ;
394+ PKCS11_TOKEN * match_tok = NULL ;
395395 unsigned int n , m ;
396396 char * obj_id = NULL ;
397397 size_t obj_id_len = 0 ;
@@ -406,6 +406,10 @@ static void *ctx_try_load_object(ENGINE_CTX *ctx,
406406 if (object_uri && * object_uri ) {
407407 obj_id_len = strlen (object_uri ) + 1 ;
408408 obj_id = OPENSSL_malloc (obj_id_len );
409+ if (!obj_id ) {
410+ ctx_log (ctx , 0 , "Could not allocate memory for ID\n" );
411+ goto cleanup ;
412+ }
409413 if (!strncasecmp (object_uri , "pkcs11:" , 7 )) {
410414 n = parse_pkcs11_uri (ctx , object_uri , & match_tok ,
411415 obj_id , & obj_id_len , tmp_pin , & tmp_pin_len , & obj_label );
@@ -415,12 +419,12 @@ static void *ctx_try_load_object(ENGINE_CTX *ctx,
415419 "The PKCS#11 URI format is defined by RFC7512\n" ,
416420 object_typestr );
417421 ENGerr (ENG_F_CTX_LOAD_OBJECT , ENG_R_INVALID_ID );
418- goto error ;
422+ goto cleanup ;
419423 }
420424 if (tmp_pin_len > 0 && tmp_pin [0 ] != 0 ) {
421425 tmp_pin [tmp_pin_len ] = 0 ;
422426 if (!ctx_ctrl_set_pin (ctx , tmp_pin )) {
423- goto error ;
427+ goto cleanup ;
424428 }
425429 }
426430 ctx_log (ctx , 1 , "Looking in slots for %s %s login: " ,
@@ -436,7 +440,7 @@ static void *ctx_try_load_object(ENGINE_CTX *ctx,
436440 "still accepted for now\n" ,
437441 object_typestr );
438442 ENGerr (ENG_F_CTX_LOAD_OBJECT , ENG_R_INVALID_ID );
439- goto error ;
443+ goto cleanup ;
440444 }
441445 ctx_log (ctx , 1 , "Looking in slot %d for %s %s login: " ,
442446 slot_nr , object_typestr , login ? "with" : "without" );
@@ -455,8 +459,8 @@ static void *ctx_try_load_object(ENGINE_CTX *ctx,
455459 matched_slots = (PKCS11_SLOT * * )calloc (ctx -> slot_count ,
456460 sizeof (PKCS11_SLOT * ));
457461 if (!matched_slots ) {
458- ctx_log (ctx , 0 , "Could not allocate memory for matched slots\n" );
459- goto error ;
462+ ctx_log (ctx , 0 , "Could not allocate memory for slots\n" );
463+ goto cleanup ;
460464 }
461465
462466 for (n = 0 ; n < ctx -> slot_count ; n ++ ) {
@@ -504,8 +508,9 @@ static void *ctx_try_load_object(ENGINE_CTX *ctx,
504508 }
505509 ctx_log (ctx , 1 , "\n" );
506510
507- /* Ignore slots without tokens or with uninitialized token */
508- if (found_slot && found_slot -> token && found_slot -> token -> initialized ) {
511+ /* Ignore slots without tokens. Thales HSM (and potentially
512+ * other modules) allow objects on uninitialized tokens. */
513+ if (found_slot && found_slot -> token ) {
509514 matched_slots [matched_count ] = found_slot ;
510515 matched_count ++ ;
511516 }
@@ -516,73 +521,151 @@ static void *ctx_try_load_object(ENGINE_CTX *ctx,
516521 if (match_tok ) {
517522 ctx_log (ctx , 0 , "No matching initialized token was found for %s\n" ,
518523 object_typestr );
519- goto error ;
524+ goto cleanup ;
520525 }
521526
522527 /* If the legacy slot ID format was used */
523528 if (slot_nr != -1 ) {
524529 ctx_log (ctx , 0 , "The %s was not found on slot %d\n" , object_typestr , slot_nr );
525- goto error ;
530+ goto cleanup ;
526531 } else {
527532 found_slot = PKCS11_find_token (ctx -> pkcs11_ctx ,
528533 ctx -> slot_list , ctx -> slot_count );
529- /* Ignore if the the token is not initialized */
530- if ( found_slot && found_slot -> token &&
531- found_slot -> token -> initialized ) {
534+ /* Ignore slots without tokens. Thales HSM (and potentially
535+ * other modules) allow objects on uninitialized tokens. */
536+ if ( found_slot && found_slot -> token ) {
532537 matched_slots [matched_count ] = found_slot ;
533538 matched_count ++ ;
534539 } else {
535540 ctx_log (ctx , 0 , "No tokens found\n" );
536- goto error ;
541+ goto cleanup ;
537542 }
538543 }
539544 }
540545
541- for (n = 0 ; n < matched_count ; n ++ ) {
542- slot = matched_slots [n ];
543- tok = slot -> token ;
544- if (!tok ) {
545- ctx_log (ctx , 0 , "Empty slot found\n" );
546- break ;
547- }
546+ /* In several tokens certificates are marked as private */
547+ if (login ) {
548+ /* Only try to login if a single slot matched to avoiding trying
549+ * the PIN against all matching slots */
548550
549- ctx_log (ctx , 1 , "Found slot: %s\n" , slot -> description );
550- ctx_log (ctx , 1 , "Found token: %s\n" , slot -> token -> label );
551+ if (matched_count == 1 ) {
552+ slot = matched_slots [0 ];
553+ if (!slot -> token ) {
554+ ctx_log (ctx , 0 , "Empty slot found: %s\n" , slot -> description );
555+ goto cleanup ; /* failed */
556+ }
557+ ctx_log (ctx , 1 , "Found slot: %s\n" , slot -> description );
558+ ctx_log (ctx , 1 , "Found token: %s\n" , slot -> token -> label [0 ]?
559+ slot -> token -> label : "no label" );
551560
552- /* In several tokens certificates are marked as private */
553- if (login ) {
554561 /* Only try to login if login is required */
555- if (tok -> loginRequired || ctx -> force_login ) {
556- /* Only try to login if a single slot matched to avoiding trying
557- * the PIN against all matching slots */
558- if (matched_count == 1 ) {
559- if (!ctx_login (ctx , slot , tok ,
560- ui_method , callback_data )) {
562+ if (slot -> token -> loginRequired || ctx -> force_login ) {
563+ if (!ctx_login (ctx , slot , slot -> token , ui_method , callback_data )) {
564+ ctx_log (ctx , 0 , "Login to token failed, returning NULL...\n" );
565+ goto cleanup ; /* failed */
566+ }
567+ }
568+ } else {
569+ /* Multiple matching slots */
570+ size_t init_count = 0 ;
571+ size_t uninit_count = 0 ;
572+ PKCS11_SLOT * * init_slots = NULL , * * uninit_slots = NULL ;
573+
574+ init_slots = (PKCS11_SLOT * * )calloc (ctx -> slot_count , sizeof (PKCS11_SLOT * ));
575+ if (!init_slots ) {
576+ ctx_log (ctx , 0 , "Could not allocate memory for slots\n" );
577+ goto cleanup ; /* failed */
578+ }
579+ uninit_slots = (PKCS11_SLOT * * )calloc (ctx -> slot_count , sizeof (PKCS11_SLOT * ));
580+ if (!uninit_slots ) {
581+ ctx_log (ctx , 0 , "Could not allocate memory for slots\n" );
582+ free (init_slots );
583+ goto cleanup ; /* failed */
584+ }
585+
586+ for (m = 0 ; m < matched_count ; m ++ ) {
587+ slot = matched_slots [m ];
588+ if (!slot -> token ) {
589+ ctx_log (ctx , 0 , "Empty slot found: %s\n" , slot -> description );
590+ continue ; /* skipped */
591+ }
592+ if (slot -> token -> initialized ) {
593+ init_slots [init_count ] = slot ;
594+ init_count ++ ;
595+ } else {
596+ uninit_slots [uninit_count ] = slot ;
597+ uninit_count ++ ;
598+ }
599+ }
600+
601+ /* Initialized tokens */
602+ if (init_count == 1 ) {
603+ slot = init_slots [0 ];
604+ ctx_log (ctx , 1 , "Found slot: %s\n" , slot -> description );
605+ ctx_log (ctx , 1 , "Found token: %s\n" , slot -> token -> label [0 ]?
606+ slot -> token -> label : "no label" );
607+
608+ /* Only try to login if login is required */
609+ if (slot -> token -> loginRequired || ctx -> force_login ) {
610+ if (!ctx_login (ctx , slot , slot -> token , ui_method , callback_data )) {
561611 ctx_log (ctx , 0 , "Login to token failed, returning NULL...\n" );
562- goto error ;
612+ free (init_slots );
613+ free (uninit_slots );
614+ goto cleanup ; /* failed */
563615 }
564- } else {
565- ctx_log (ctx , 0 , "Multiple matching slots (%zu); will not try to"
566- " login\n" , matched_count );
567- for (m = 0 ; m < matched_count ; m ++ ){
568- slot = matched_slots [m ];
569- ctx_log (ctx , 0 , "- [%u] %s: %s\n" , m + 1 ,
570- slot -> description ? slot -> description :
571- "(no description)" ,
572- (slot -> token && slot -> token -> label )?
573- slot -> token -> label : "no label" );
616+ }
617+ } else {
618+ /* Multiple slots with initialized token */
619+ if (init_count > 1 ) {
620+ ctx_log (ctx , 0 , "Multiple matching slots (%zu);"
621+ " will not try to login\n" , init_count );
622+ }
623+ for (m = 0 ; m < init_count ; m ++ ) {
624+ slot = init_slots [m ];
625+ ctx_log (ctx , 0 , "- [%u] %s: %s\n" , m + 1 ,
626+ slot -> description ? slot -> description :
627+ "(no description)" ,
628+ (slot -> token && slot -> token -> label )?
629+ slot -> token -> label : "no label" );
630+ }
631+ free (init_slots );
632+
633+ /* Uninitialized tokens, user PIN is unset */
634+ for (m = 0 ; m < uninit_count ; m ++ ) {
635+ slot = uninit_slots [m ];
636+ ctx_log (ctx , 1 , "Found slot: %s\n" , slot -> description );
637+ ctx_log (ctx , 1 , "Found token: %s\n" , slot -> token -> label [0 ]?
638+ slot -> token -> label : "no label" );
639+ object = match_func (ctx , slot -> token , obj_id , obj_id_len , obj_label );
640+ if (object ) {
641+ free (uninit_slots );
642+ goto cleanup ; /* success */
574643 }
575- goto error ;
576644 }
645+ free (uninit_slots );
646+ goto cleanup ; /* failed */
577647 }
578648 }
649+ object = match_func (ctx , slot -> token , obj_id , obj_id_len , obj_label );
579650
580- object = match_func (ctx , tok , obj_id , obj_id_len , obj_label );
581- if (object )
582- break ;
651+ } else {
652+ /* Find public object */
653+ for (n = 0 ; n < matched_count ; n ++ ) {
654+ slot = matched_slots [n ];
655+ if (!slot -> token ) {
656+ ctx_log (ctx , 0 , "Empty slot found: %s\n" , slot -> description );
657+ break ;
658+ }
659+ ctx_log (ctx , 1 , "Found slot: %s\n" , slot -> description );
660+ ctx_log (ctx , 1 , "Found token: %s\n" , slot -> token -> label [0 ]?
661+ slot -> token -> label : "no label" );
662+ object = match_func (ctx , slot -> token , obj_id , obj_id_len , obj_label );
663+ if (object )
664+ break ; /* success */
665+ }
583666 }
584667
585- error :
668+ cleanup :
586669 /* Free the searched token data */
587670 if (match_tok ) {
588671 OPENSSL_free (match_tok -> model );
0 commit comments