Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
179 changes: 131 additions & 48 deletions src/eng_back.c
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ static void *ctx_try_load_object(ENGINE_CTX *ctx,
{
PKCS11_SLOT *slot;
PKCS11_SLOT *found_slot = NULL, **matched_slots = NULL;
PKCS11_TOKEN *tok, *match_tok = NULL;
PKCS11_TOKEN *match_tok = NULL;
unsigned int n, m;
char *obj_id = NULL;
size_t obj_id_len = 0;
Expand All @@ -406,6 +406,10 @@ static void *ctx_try_load_object(ENGINE_CTX *ctx,
if (object_uri && *object_uri) {
obj_id_len = strlen(object_uri) + 1;
obj_id = OPENSSL_malloc(obj_id_len);
if (!obj_id) {
ctx_log(ctx, 0, "Could not allocate memory for ID\n");
goto cleanup;
}
if (!strncasecmp(object_uri, "pkcs11:", 7)) {
n = parse_pkcs11_uri(ctx, object_uri, &match_tok,
obj_id, &obj_id_len, tmp_pin, &tmp_pin_len, &obj_label);
Expand All @@ -415,12 +419,12 @@ static void *ctx_try_load_object(ENGINE_CTX *ctx,
"The PKCS#11 URI format is defined by RFC7512\n",
object_typestr);
ENGerr(ENG_F_CTX_LOAD_OBJECT, ENG_R_INVALID_ID);
goto error;
goto cleanup;
}
if (tmp_pin_len > 0 && tmp_pin[0] != 0) {
tmp_pin[tmp_pin_len] = 0;
if (!ctx_ctrl_set_pin(ctx, tmp_pin)) {
goto error;
goto cleanup;
}
}
ctx_log(ctx, 1, "Looking in slots for %s %s login: ",
Expand All @@ -436,7 +440,7 @@ static void *ctx_try_load_object(ENGINE_CTX *ctx,
"still accepted for now\n",
object_typestr);
ENGerr(ENG_F_CTX_LOAD_OBJECT, ENG_R_INVALID_ID);
goto error;
goto cleanup;
}
ctx_log(ctx, 1, "Looking in slot %d for %s %s login: ",
slot_nr, object_typestr, login ? "with" : "without");
Expand All @@ -455,8 +459,8 @@ static void *ctx_try_load_object(ENGINE_CTX *ctx,
matched_slots = (PKCS11_SLOT **)calloc(ctx->slot_count,
sizeof(PKCS11_SLOT *));
if (!matched_slots) {
ctx_log(ctx, 0, "Could not allocate memory for matched slots\n");
goto error;
ctx_log(ctx, 0, "Could not allocate memory for slots\n");
goto cleanup;
}

for (n = 0; n < ctx->slot_count; n++) {
Expand All @@ -472,7 +476,7 @@ static void *ctx_try_load_object(ENGINE_CTX *ctx,
if (slot->token->readOnly)
strcat(flags, "ro, ");
} else {
strcpy(flags, "no token");
strcpy(flags, "no token, ");
}
if ((m = strlen(flags)) != 0) {
flags[m - 2] = '\0';
Expand Down Expand Up @@ -504,8 +508,9 @@ static void *ctx_try_load_object(ENGINE_CTX *ctx,
}
ctx_log(ctx, 1, "\n");

/* Ignore slots without tokens or with uninitialized token */
if (found_slot && found_slot->token && found_slot->token->initialized) {
/* Ignore slots without tokens. Thales HSM (and potentially
* other modules) allow objects on uninitialized tokens. */
if (found_slot && found_slot->token) {
matched_slots[matched_count] = found_slot;
matched_count++;
}
Expand All @@ -516,73 +521,151 @@ static void *ctx_try_load_object(ENGINE_CTX *ctx,
if (match_tok) {
ctx_log(ctx, 0, "No matching initialized token was found for %s\n",
object_typestr);
goto error;
goto cleanup;
}

/* If the legacy slot ID format was used */
if (slot_nr != -1) {
ctx_log(ctx, 0, "The %s was not found on slot %d\n", object_typestr, slot_nr);
goto error;
goto cleanup;
} else {
found_slot = PKCS11_find_token(ctx->pkcs11_ctx,
ctx->slot_list, ctx->slot_count);
/* Ignore if the the token is not initialized */
if (found_slot && found_slot->token &&
found_slot->token->initialized) {
/* Ignore slots without tokens. Thales HSM (and potentially
* other modules) allow objects on uninitialized tokens. */
if (found_slot && found_slot->token) {
matched_slots[matched_count] = found_slot;
matched_count++;
} else {
ctx_log(ctx, 0, "No tokens found\n");
goto error;
goto cleanup;
}
}
}

for (n = 0; n < matched_count; n++) {
slot = matched_slots[n];
tok = slot->token;
if (!tok) {
ctx_log(ctx, 0, "Empty slot found\n");
break;
}
/* In several tokens certificates are marked as private */
if (login) {
/* Only try to login if a single slot matched to avoiding trying
* the PIN against all matching slots */

ctx_log(ctx, 1, "Found slot: %s\n", slot->description);
ctx_log(ctx, 1, "Found token: %s\n", slot->token->label);
if (matched_count == 1) {
slot = matched_slots[0];
if (!slot->token) {
ctx_log(ctx, 0, "Empty slot found: %s\n", slot->description);
goto cleanup; /* failed */
}
ctx_log(ctx, 1, "Found slot: %s\n", slot->description);
ctx_log(ctx, 1, "Found token: %s\n", slot->token->label[0]?
slot->token->label : "no label");

/* In several tokens certificates are marked as private */
if (login) {
/* Only try to login if login is required */
if (tok->loginRequired || ctx->force_login) {
/* Only try to login if a single slot matched to avoiding trying
* the PIN against all matching slots */
if (matched_count == 1) {
if (!ctx_login(ctx, slot, tok,
ui_method, callback_data)) {
if (slot->token->loginRequired || ctx->force_login) {
if (!ctx_login(ctx, slot, slot->token, ui_method, callback_data)) {
ctx_log(ctx, 0, "Login to token failed, returning NULL...\n");
goto cleanup; /* failed */
}
}
} else {
/* Multiple matching slots */
size_t init_count = 0;
size_t uninit_count = 0;
PKCS11_SLOT **init_slots = NULL, **uninit_slots = NULL;

init_slots = (PKCS11_SLOT **)calloc(ctx->slot_count, sizeof(PKCS11_SLOT *));
if (!init_slots) {
ctx_log(ctx, 0, "Could not allocate memory for slots\n");
goto cleanup; /* failed */
}
uninit_slots = (PKCS11_SLOT **)calloc(ctx->slot_count, sizeof(PKCS11_SLOT *));
if (!uninit_slots) {
ctx_log(ctx, 0, "Could not allocate memory for slots\n");
free(init_slots);
goto cleanup; /* failed */
}

for (m = 0; m < matched_count; m++) {
slot = matched_slots[m];
if (!slot->token) {
ctx_log(ctx, 0, "Empty slot found: %s\n", slot->description);
continue; /* skipped */
}
if (slot->token->initialized) {
init_slots[init_count] = slot;
init_count++;
} else {
uninit_slots[uninit_count] = slot;
uninit_count++;
}
}

/* Initialized tokens */
if (init_count == 1) {
slot = init_slots[0];
ctx_log(ctx, 1, "Found slot: %s\n", slot->description);
ctx_log(ctx, 1, "Found token: %s\n", slot->token->label[0]?
slot->token->label : "no label");

/* Only try to login if login is required */
if (slot->token->loginRequired || ctx->force_login) {
if (!ctx_login(ctx, slot, slot->token, ui_method, callback_data)) {
ctx_log(ctx, 0, "Login to token failed, returning NULL...\n");
goto error;
free(init_slots);
free(uninit_slots);
goto cleanup; /* failed */
}
} else {
ctx_log(ctx, 0, "Multiple matching slots (%zu); will not try to"
" login\n", matched_count);
for (m = 0; m < matched_count; m++){
slot = matched_slots[m];
ctx_log(ctx, 0, "- [%u] %s: %s\n", m + 1,
slot->description? slot->description:
"(no description)",
(slot->token && slot->token->label)?
slot->token->label: "no label");
}
} else {
/* Multiple slots with initialized token */
if (init_count > 1) {
ctx_log(ctx, 0, "Multiple matching slots (%zu);"
" will not try to login\n", init_count);
}
for (m = 0; m < init_count; m++) {
slot = init_slots[m];
ctx_log(ctx, 0, "- [%u] %s: %s\n", m + 1,
slot->description? slot->description:
"(no description)",
(slot->token && slot->token->label)?
slot->token->label: "no label");
}
free(init_slots);

/* Uninitialized tokens, user PIN is unset */
for (m = 0; m < uninit_count; m++) {
slot = uninit_slots[m];
ctx_log(ctx, 1, "Found slot: %s\n", slot->description);
ctx_log(ctx, 1, "Found token: %s\n", slot->token->label[0]?
slot->token->label : "no label");
object = match_func(ctx, slot->token, obj_id, obj_id_len, obj_label);
if (object) {
free(uninit_slots);
goto cleanup; /* success */
}
goto error;
}
free(uninit_slots);
goto cleanup; /* failed */
}
}
object = match_func(ctx, slot->token, obj_id, obj_id_len, obj_label);

object = match_func(ctx, tok, obj_id, obj_id_len, obj_label);
if (object)
break;
} else {
/* Find public object */
for (n = 0; n < matched_count; n++) {
slot = matched_slots[n];
if (!slot->token) {
ctx_log(ctx, 0, "Empty slot found: %s\n", slot->description);
break;
}
ctx_log(ctx, 1, "Found slot: %s\n", slot->description);
ctx_log(ctx, 1, "Found token: %s\n", slot->token->label[0]?
slot->token->label : "no label");
object = match_func(ctx, slot->token, obj_id, obj_id_len, obj_label);
if (object)
break; /* success */
}
}

error:
cleanup:
/* Free the searched token data */
if (match_tok) {
OPENSSL_free(match_tok->model);
Expand Down
4 changes: 4 additions & 0 deletions src/p11_slot.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,10 @@ int pkcs11_get_session(PKCS11_SLOT_private *slot, int rw, CK_SESSION_HANDLE *ses
slot->num_sessions++;
break;
}
if (rv == CKR_TOKEN_NOT_RECOGNIZED) {
pthread_mutex_unlock(&slot->lock);
return -1;
}

/* Remember the maximum session count */
if (rv == CKR_SESSION_COUNT)
Expand Down
Loading