Skip to content

Commit

Permalink
Allow objects on uninitialized tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
olszomal authored and mtrojnar committed Dec 13, 2024
1 parent ff98ba6 commit 57abaf5
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 47 deletions.
177 changes: 130 additions & 47 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 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) {

This comment has been minimized.

Copy link
@rafajunio

rafajunio Jan 8, 2025

Could you please, if possible, add the flag CKR_HOST_MEMORY as well? Sometimes the OPTEE shared memory could not allocate anymore and cause an error at C_OpenSession due to ioctl failure. This will return CKR_HOST_MEMORY. So if possible change as follow:

if (rv == CKR_TOKEN_NOT_RECOGNIZED || rv == CKR_HOST_MEMORY) {			

Just to add more information, since you have a pthread_cond_wait without timeout this block all process's that want get a connection. This problem was detected during to boot when several services try to access the HSM for connections

pthread_mutex_unlock(&slot->lock);
return -1;
}

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

0 comments on commit 57abaf5

Please sign in to comment.