Skip to content

Commit

Permalink
ta: pkcs11: Improve PIN counter handling robustness
Browse files Browse the repository at this point in the history
Make sure PIN check attempt is saved persistently before continuing with
the actual PIN verification, improving counter and flags coherency in
case of subsequent failure with persistent saving.

Signed-off-by: Loic Poulain <[email protected]>
  • Loading branch information
Loic Poulain committed Nov 9, 2023
1 parent c41ef45 commit 5d59bbf
Showing 1 changed file with 50 additions and 54 deletions.
104 changes: 50 additions & 54 deletions ta/pkcs11/src/pkcs11_token.c
Original file line number Diff line number Diff line change
Expand Up @@ -1143,47 +1143,45 @@ static enum pkcs11_rc check_so_pin(struct pkcs11_session *session,
if (token->db_main->flags & PKCS11_CKFT_SO_PIN_LOCKED)
return PKCS11_CKR_PIN_LOCKED;

rc = verify_pin(PKCS11_CKU_SO, pin, pin_size,
token->db_main->so_pin_salt,
token->db_main->so_pin_hash);
if (rc) {
unsigned int pin_count = 0;

if (rc != PKCS11_CKR_PIN_INCORRECT)
return rc;

token->db_main->flags |= PKCS11_CKFT_SO_PIN_COUNT_LOW;
token->db_main->so_pin_count++;
/*
* Preset the counter and flags conservatively in the database so that
* the tentative is saved whatever happens next.
*/
token->db_main->flags |= PKCS11_CKFT_SO_PIN_COUNT_LOW;
token->db_main->so_pin_count++;

pin_count = token->db_main->so_pin_count;
if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX - 1)
token->db_main->flags |= PKCS11_CKFT_SO_PIN_FINAL_TRY;
if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX)
token->db_main->flags |= PKCS11_CKFT_SO_PIN_LOCKED;
if (token->db_main->so_pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX - 1)
token->db_main->flags |= PKCS11_CKFT_SO_PIN_FINAL_TRY;
else if (token->db_main->so_pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX)
token->db_main->flags |= PKCS11_CKFT_SO_PIN_LOCKED;

update_persistent_db(token);
update_persistent_db(token);

rc = verify_pin(PKCS11_CKU_SO, pin, pin_size,
token->db_main->so_pin_salt,
token->db_main->so_pin_hash);
if (rc == PKCS11_CKR_PIN_INCORRECT) {
if (token->db_main->flags & PKCS11_CKFT_SO_PIN_LOCKED)
return PKCS11_CKR_PIN_LOCKED;

return PKCS11_CKR_PIN_INCORRECT;
}

if (token->db_main->so_pin_count) {
if (rc)
token->db_main->so_pin_count--;
else
token->db_main->so_pin_count = 0;

update_persistent_db(token);
token->db_main->flags &= ~PKCS11_CKFT_SO_PIN_LOCKED;
if (token->db_main->so_pin_count < PKCS11_TOKEN_SO_PIN_COUNT_MAX - 1) {
token->db_main->flags &= ~PKCS11_CKFT_SO_PIN_FINAL_TRY;
if (!token->db_main->so_pin_count)
token->db_main->flags &= ~PKCS11_CKFT_SO_PIN_COUNT_LOW;
}

if (token->db_main->flags & (PKCS11_CKFT_SO_PIN_COUNT_LOW |
PKCS11_CKFT_SO_PIN_FINAL_TRY)) {
token->db_main->flags &= ~(PKCS11_CKFT_SO_PIN_COUNT_LOW |
PKCS11_CKFT_SO_PIN_FINAL_TRY);

update_persistent_db(token);
}
update_persistent_db(token);

return PKCS11_CKR_OK;
return rc;
}

static enum pkcs11_rc check_user_pin(struct pkcs11_session *session,
Expand All @@ -1202,47 +1200,45 @@ static enum pkcs11_rc check_user_pin(struct pkcs11_session *session,
if (token->db_main->flags & PKCS11_CKFT_USER_PIN_LOCKED)
return PKCS11_CKR_PIN_LOCKED;

rc = verify_pin(PKCS11_CKU_USER, pin, pin_size,
token->db_main->user_pin_salt,
token->db_main->user_pin_hash);
if (rc) {
unsigned int pin_count = 0;

if (rc != PKCS11_CKR_PIN_INCORRECT)
return rc;

token->db_main->flags |= PKCS11_CKFT_USER_PIN_COUNT_LOW;
token->db_main->user_pin_count++;
/*
* Preset the counter and flags conservatively in the database so that
* the tentative is saved whatever happens next.
*/
token->db_main->flags |= PKCS11_CKFT_USER_PIN_COUNT_LOW;
token->db_main->user_pin_count++;

pin_count = token->db_main->user_pin_count;
if (pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX - 1)
token->db_main->flags |= PKCS11_CKFT_USER_PIN_FINAL_TRY;
if (pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX)
token->db_main->flags |= PKCS11_CKFT_USER_PIN_LOCKED;
if (token->db_main->user_pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX - 1)
token->db_main->flags |= PKCS11_CKFT_USER_PIN_FINAL_TRY;
else if (token->db_main->user_pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX)
token->db_main->flags |= PKCS11_CKFT_USER_PIN_LOCKED;

update_persistent_db(token);
update_persistent_db(token);

rc = verify_pin(PKCS11_CKU_USER, pin, pin_size,
token->db_main->user_pin_salt,
token->db_main->user_pin_hash);
if (rc == PKCS11_CKR_PIN_INCORRECT) {
if (token->db_main->flags & PKCS11_CKFT_USER_PIN_LOCKED)
return PKCS11_CKR_PIN_LOCKED;

return PKCS11_CKR_PIN_INCORRECT;
}

if (token->db_main->user_pin_count) {
if (rc)
token->db_main->user_pin_count--;
else
token->db_main->user_pin_count = 0;

update_persistent_db(token);
token->db_main->flags &= ~PKCS11_CKFT_USER_PIN_LOCKED;
if (token->db_main->user_pin_count < PKCS11_TOKEN_USER_PIN_COUNT_MAX - 1) {
token->db_main->flags &= ~PKCS11_CKFT_USER_PIN_FINAL_TRY;
if (!token->db_main->user_pin_count)
token->db_main->flags &= ~PKCS11_CKFT_USER_PIN_COUNT_LOW;
}

if (token->db_main->flags & (PKCS11_CKFT_USER_PIN_COUNT_LOW |
PKCS11_CKFT_USER_PIN_FINAL_TRY)) {
token->db_main->flags &= ~(PKCS11_CKFT_USER_PIN_COUNT_LOW |
PKCS11_CKFT_USER_PIN_FINAL_TRY);

update_persistent_db(token);
}
update_persistent_db(token);

return PKCS11_CKR_OK;
return rc;
}

enum pkcs11_rc entry_ck_set_pin(struct pkcs11_client *client,
Expand Down

0 comments on commit 5d59bbf

Please sign in to comment.