diff options
author | Jens Wiklander <jens.wiklander@linaro.org> | 2020-04-09 12:30:03 +0200 |
---|---|---|
committer | Jérôme Forissier <jerome@forissier.org> | 2020-04-16 15:42:19 +0200 |
commit | bef8bc684207124e10d768c25fdf398db52610cf (patch) | |
tree | bb02c334597ad093839879f1e478bf7e7db6b712 | |
parent | 8e03579eea6477af3dfb4597cb0d5983318a3a77 (diff) |
ta: pkcs11: helpers for PIN hashing
Adds helpers to hash PIN and to verify the hash of a PIN. The PIN is
hashed together with user type and a generated salt. A used salt never
takes the value 0 so that can be used to tell if a PIN is set.
Acked-by: Rouven Czerwinski <r.czerwinski@pengutronix.de>
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
-rw-r--r-- | ta/pkcs11/src/persistent_token.c | 58 | ||||
-rw-r--r-- | ta/pkcs11/src/pkcs11_token.h | 7 |
2 files changed, 65 insertions, 0 deletions
diff --git a/ta/pkcs11/src/persistent_token.c b/ta/pkcs11/src/persistent_token.c index b68c0399..29c701e7 100644 --- a/ta/pkcs11/src/persistent_token.c +++ b/ta/pkcs11/src/persistent_token.c @@ -73,6 +73,64 @@ static TEE_Result open_pin_file(struct ck_token *token, 0, out_hdl); } +static enum pkcs11_rc do_hash(uint32_t user, const uint8_t *pin, + size_t pin_size, uint32_t salt, + uint8_t hash[TEE_MAX_HASH_SIZE]) +{ + TEE_Result res = TEE_SUCCESS; + TEE_OperationHandle oh = TEE_HANDLE_NULL; + uint32_t sz = TEE_MAX_HASH_SIZE; + + res = TEE_AllocateOperation(&oh, TEE_ALG_SHA256, TEE_MODE_DIGEST, 0); + if (res) + return tee2pkcs_error(res); + + TEE_DigestUpdate(oh, &user, sizeof(user)); + TEE_DigestUpdate(oh, &salt, sizeof(salt)); + res = TEE_DigestDoFinal(oh, pin, pin_size, hash, &sz); + TEE_FreeOperation(oh); + + if (res) + return PKCS11_CKR_GENERAL_ERROR; + + memset(hash + sz, 0, TEE_MAX_HASH_SIZE - sz); + return PKCS11_CKR_OK; +} + +enum pkcs11_rc hash_pin(enum pkcs11_user_type user, const uint8_t *pin, + size_t pin_size, uint32_t *salt, + uint8_t hash[TEE_MAX_HASH_SIZE]) +{ + enum pkcs11_rc rc = PKCS11_CKR_OK; + uint32_t s = 0; + + TEE_GenerateRandom(&s, sizeof(s)); + if (!s) + s++; + + rc = do_hash(user, pin, pin_size, s, hash); + if (!rc) + *salt = s; + return rc; +} + +enum pkcs11_rc verify_pin(enum pkcs11_user_type user, const uint8_t *pin, + size_t pin_size, uint32_t salt, + const uint8_t hash[TEE_MAX_HASH_SIZE]) +{ + uint8_t tmp_hash[TEE_MAX_HASH_SIZE] = { 0 }; + enum pkcs11_rc rc = PKCS11_CKR_OK; + + rc = do_hash(user, pin, pin_size, salt, tmp_hash); + if (rc) + return rc; + + if (buf_compare_ct(tmp_hash, hash, TEE_MAX_HASH_SIZE)) + rc = PKCS11_CKR_PIN_INCORRECT; + + return rc; +} + static void init_pin_keys(struct ck_token *token, enum pkcs11_user_type user) { TEE_Result res = TEE_ERROR_GENERIC; diff --git a/ta/pkcs11/src/pkcs11_token.h b/ta/pkcs11/src/pkcs11_token.h index 4c8b7afc..8d442a12 100644 --- a/ta/pkcs11/src/pkcs11_token.h +++ b/ta/pkcs11/src/pkcs11_token.h @@ -112,6 +112,13 @@ unsigned int get_token_id(struct ck_token *token); struct ck_token *init_persistent_db(unsigned int token_id); void close_persistent_db(struct ck_token *token); +enum pkcs11_rc hash_pin(enum pkcs11_user_type user, const uint8_t *pin, + size_t pin_size, uint32_t *salt, + uint8_t hash[TEE_MAX_HASH_SIZE]); +enum pkcs11_rc verify_pin(enum pkcs11_user_type user, const uint8_t *pin, + size_t pin_size, uint32_t salt, + const uint8_t hash[TEE_MAX_HASH_SIZE]); + /* * Pkcs11 session support */ |