Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ta: pkcs11: Improve PIN counter handling robustness #6445

Merged
merged 1 commit into from
Nov 10, 2023
Merged
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
126 changes: 62 additions & 64 deletions ta/pkcs11/src/pkcs11_token.c
Original file line number Diff line number Diff line change
Expand Up @@ -1132,117 +1132,115 @@ static enum pkcs11_rc check_so_pin(struct pkcs11_session *session,
uint8_t *pin, size_t pin_size)
{
struct ck_token *token = session->token;
struct token_persistent_main *db = token->db_main;
enum pkcs11_rc rc = PKCS11_CKR_OK;

assert(token->db_main->flags & PKCS11_CKFT_TOKEN_INITIALIZED);
assert(db->flags & PKCS11_CKFT_TOKEN_INITIALIZED);

if (IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) &&
token->db_main->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH)
db->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH)
return verify_identity_auth(token, PKCS11_CKU_SO);

if (token->db_main->flags & PKCS11_CKFT_SO_PIN_LOCKED)
if (db->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;
/*
* Preset the counter and flags conservatively in the database so that
* the tentative is saved whatever happens next.
*/
db->flags |= PKCS11_CKFT_SO_PIN_COUNT_LOW;
db->so_pin_count++;

if (rc != PKCS11_CKR_PIN_INCORRECT)
return rc;
if (db->so_pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX - 1)
db->flags |= PKCS11_CKFT_SO_PIN_FINAL_TRY;
else if (db->so_pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX)
db->flags |= PKCS11_CKFT_SO_PIN_LOCKED;

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;

update_persistent_db(token);
update_persistent_db(token);

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

return PKCS11_CKR_PIN_INCORRECT;
}

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

update_persistent_db(token);
db->flags &= ~PKCS11_CKFT_SO_PIN_LOCKED;
if (db->so_pin_count < PKCS11_TOKEN_SO_PIN_COUNT_MAX - 1) {
db->flags &= ~PKCS11_CKFT_SO_PIN_FINAL_TRY;
if (!db->so_pin_count)
db->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,
uint8_t *pin, size_t pin_size)
{
struct ck_token *token = session->token;
struct token_persistent_main *db = token->db_main;
enum pkcs11_rc rc = PKCS11_CKR_OK;

if (IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) &&
token->db_main->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH)
db->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH)
return verify_identity_auth(token, PKCS11_CKU_USER);

if (!token->db_main->user_pin_salt)
if (!db->user_pin_salt)
return PKCS11_CKR_USER_PIN_NOT_INITIALIZED;

if (token->db_main->flags & PKCS11_CKFT_USER_PIN_LOCKED)
if (db->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.
*/
db->flags |= PKCS11_CKFT_USER_PIN_COUNT_LOW;
db->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 (db->user_pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX - 1)
db->flags |= PKCS11_CKFT_USER_PIN_FINAL_TRY;
else if (db->user_pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX)
db->flags |= PKCS11_CKFT_USER_PIN_LOCKED;

update_persistent_db(token);
update_persistent_db(token);

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

return PKCS11_CKR_PIN_INCORRECT;
}

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

update_persistent_db(token);
db->flags &= ~PKCS11_CKFT_USER_PIN_LOCKED;
if (db->user_pin_count < PKCS11_TOKEN_USER_PIN_COUNT_MAX - 1) {
db->flags &= ~PKCS11_CKFT_USER_PIN_FINAL_TRY;
if (!db->user_pin_count)
db->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