diff options
author | Vesa Jääskeläinen <vesa.jaaskelainen@vaisala.com> | 2020-10-21 17:57:56 +0300 |
---|---|---|
committer | Jérôme Forissier <jerome@forissier.org> | 2021-01-07 17:51:19 +0100 |
commit | 1a27b197d8b16ef2d4dab8d205f359627b6f0232 (patch) | |
tree | 9f05ba120e99e2975dd7b02f7b277c933201cb31 | |
parent | 1e497011e77b5e6ec4b8346aa75c750aacba734f (diff) |
ta: pkcs11: Add TEE Identity based authentication support
In C_InitToken() if PIN is NULL_PTR then it will activate TEE Identity
based authentication support for token.
Once activated:
- When ever PIN is required client's TEE Identity will be used for
authentication
- PIN failure counters are disabled
- If new PIN is given as input it is in form of PIN ACL string
- It can be disabled with C_InitToken with non-zero PIN
Internally protected authentication path will be used for mode
determination.
Acked-by: Ruchika Gupta <ruchika.gupta@linaro.org>
Reviewed-by: Etienne Carriere <etienne.carriere@linaro.org>
Signed-off-by: Vesa Jääskeläinen <vesa.jaaskelainen@vaisala.com>
-rw-r--r-- | mk/config.mk | 3 | ||||
-rw-r--r-- | ta/pkcs11/include/pkcs11_ta.h | 41 | ||||
-rw-r--r-- | ta/pkcs11/src/persistent_token.c | 154 | ||||
-rw-r--r-- | ta/pkcs11/src/pkcs11_token.c | 42 | ||||
-rw-r--r-- | ta/pkcs11/src/pkcs11_token.h | 42 |
5 files changed, 280 insertions, 2 deletions
diff --git a/mk/config.mk b/mk/config.mk index c4836a08..e0127b21 100644 --- a/mk/config.mk +++ b/mk/config.mk @@ -578,6 +578,9 @@ CFG_CRYPTOLIB_DIR ?= core/lib/libtomcrypt # that would set = n. $(call force,CFG_CORE_MBEDTLS_MPI,y) +# Enable PKCS#11 TA's TEE Identity based authentication support +CFG_PKCS11_TA_AUTH_TEE_IDENTITY ?= y + # Enable virtualization support. OP-TEE will not work without compatible # hypervisor if this option is enabled. CFG_VIRTUALIZATION ?= n diff --git a/ta/pkcs11/include/pkcs11_ta.h b/ta/pkcs11/include/pkcs11_ta.h index e3f52cc5..fb5fae5a 100644 --- a/ta/pkcs11/include/pkcs11_ta.h +++ b/ta/pkcs11/include/pkcs11_ta.h @@ -599,6 +599,47 @@ enum pkcs11_user_type { }; /* + * TEE Identity based authentication for tokens + * + * When configuration CFG_PKCS11_TA_AUTH_TEE_IDENTITY is enabled TEE Identity + * based authentication scheme is enabled. + * + * Feature enablement per token basis is controlled by token flag: + * pkcs11_token_info->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH + * + * When calling C_InitToken() mode is determined based on SO PIN value. + * - If the PIN is empty (or NULL_PTR) then active client TEE Identity will be + * used as SO TEE Identity + * - If the PIN is given then normal PIN behavior is used + * + * Once TEE Identity based authentication is activated following operational + * changes happen: + * - PIN failure counters are disabled to prevent token authentication lockups + * - Switching to different authentication mode needs C_InitToken() + * - When C_Login() or so is performed actual PIN value is ignored and active + * client TEE Identity will be used + * + * Different types of TEE Identity authentication methods can be configured: + * - Configured with C_InitToken(), C_InitPIN() or by C_SetPIN() + * - PIN value follows below PIN syntax + * + * TEE Identity based authenticate PIN syntax: + * - PIN value: NULL_PTR or empty + * - Use active client TEE Identity + * - PIN value: public + * - TEE public login + * - PIN value: user:<client UUID string> + * - TEE user login with client UUID matching user credentials + * - PIN value: group:<client UUID string> + * - TEE group login with client UUID matching group credentials + */ + +/* Keywords for protected authenticated path PIN parser */ +#define PKCS11_AUTH_TEE_IDENTITY_PUBLIC "public" +#define PKCS11_AUTH_TEE_IDENTITY_USER "user:" +#define PKCS11_AUTH_TEE_IDENTITY_GROUP "group:" + +/* * Values for 32bit session flags argument to PKCS11_CMD_OPEN_SESSION * and pkcs11_session_info::flags. * PKCS11_CKFSS_<x> reflects CryptoKi client API session flags CKF_<x>. diff --git a/ta/pkcs11/src/persistent_token.c b/ta/pkcs11/src/persistent_token.c index b8bd15c4..e6cfbc9b 100644 --- a/ta/pkcs11/src/persistent_token.c +++ b/ta/pkcs11/src/persistent_token.c @@ -128,6 +128,160 @@ enum pkcs11_rc verify_pin(enum pkcs11_user_type user, const uint8_t *pin, return rc; } +#if defined(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) +enum pkcs11_rc setup_so_identity_auth_from_client(struct ck_token *token) +{ + TEE_Identity identity = { }; + TEE_Result res = TEE_SUCCESS; + + res = TEE_GetPropertyAsIdentity(TEE_PROPSET_CURRENT_CLIENT, + "gpd.client.identity", &identity); + if (res != TEE_SUCCESS) { + EMSG("TEE_GetPropertyAsIdentity: returned %#"PRIx32, res); + return PKCS11_CKR_PIN_INVALID; + } + + TEE_MemMove(&token->db_main->so_identity, &identity, sizeof(identity)); + token->db_main->flags |= PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH; + + token->db_main->so_pin_salt = 0; + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc setup_identity_auth_from_pin(struct ck_token *token, + enum pkcs11_user_type user_type, + const uint8_t *pin, + size_t pin_size) +{ + TEE_Identity identity = { }; + TEE_Result res = TEE_SUCCESS; + uint32_t flags_clear = 0; + uint32_t flags_set = 0; + char *acl_string = NULL; + char *uuid_str = NULL; + + assert(token->db_main->flags & + PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH); + + if (!pin) { + /* Use client identity */ + res = TEE_GetPropertyAsIdentity(TEE_PROPSET_CURRENT_CLIENT, + "gpd.client.identity", + &identity); + if (res != TEE_SUCCESS) { + EMSG("TEE_GetPropertyAsIdentity: returned %#"PRIx32, + res); + return PKCS11_CKR_PIN_INVALID; + } + } else { + /* Parse PIN ACL string: <login type>:<client id> */ + acl_string = TEE_Malloc(pin_size + 1, TEE_MALLOC_FILL_ZERO); + if (!acl_string) + return PKCS11_CKR_DEVICE_MEMORY; + TEE_MemMove(acl_string, pin, pin_size); + + uuid_str = strstr(acl_string, ":"); + if (uuid_str) + uuid_str++; + if (strcmp(PKCS11_AUTH_TEE_IDENTITY_PUBLIC, acl_string) == 0) { + identity.login = TEE_LOGIN_PUBLIC; + } else if (strstr(acl_string, PKCS11_AUTH_TEE_IDENTITY_USER) == + acl_string) { + identity.login = TEE_LOGIN_USER; + } else if (strstr(acl_string, PKCS11_AUTH_TEE_IDENTITY_GROUP) == + acl_string) { + identity.login = TEE_LOGIN_GROUP; + } else { + EMSG("Invalid PIN ACL string - login"); + TEE_Free(acl_string); + return PKCS11_CKR_PIN_INVALID; + } + + if (identity.login != TEE_LOGIN_PUBLIC) { + if (!uuid_str) { + EMSG("Invalid PIN ACL string - colon"); + TEE_Free(acl_string); + return PKCS11_CKR_PIN_INVALID; + } + + res = tee_uuid_from_str(&identity.uuid, uuid_str); + if (res) { + EMSG("Invalid PIN ACL string - client id"); + TEE_Free(acl_string); + return PKCS11_CKR_PIN_INVALID; + } + } + + TEE_Free(acl_string); + } + + switch (user_type) { + case PKCS11_CKU_SO: + token->db_main->so_pin_count = 0; + token->db_main->so_pin_salt = 0; + flags_clear = PKCS11_CKFT_SO_PIN_COUNT_LOW | + PKCS11_CKFT_SO_PIN_FINAL_TRY | + PKCS11_CKFT_SO_PIN_LOCKED | + PKCS11_CKFT_SO_PIN_TO_BE_CHANGED; + + TEE_MemMove(&token->db_main->so_identity, &identity, + sizeof(identity)); + break; + case PKCS11_CKU_USER: + token->db_main->user_pin_count = 0; + token->db_main->user_pin_salt = 0; + flags_clear = PKCS11_CKFT_USER_PIN_COUNT_LOW | + PKCS11_CKFT_USER_PIN_FINAL_TRY | + PKCS11_CKFT_USER_PIN_LOCKED | + PKCS11_CKFT_USER_PIN_TO_BE_CHANGED; + flags_set = PKCS11_CKFT_USER_PIN_INITIALIZED; + + TEE_MemMove(&token->db_main->user_identity, &identity, + sizeof(identity)); + break; + default: + return PKCS11_CKR_FUNCTION_FAILED; + } + + token->db_main->flags &= ~flags_clear; + token->db_main->flags |= flags_set; + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc verify_identity_auth(struct ck_token *token, + enum pkcs11_user_type user_type) +{ + TEE_Identity identity = { }; + TEE_Result res = TEE_SUCCESS; + + assert(token->db_main->flags & + PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH); + + res = TEE_GetPropertyAsIdentity(TEE_PROPSET_CURRENT_CLIENT, + "gpd.client.identity", &identity); + if (res != TEE_SUCCESS) { + EMSG("TEE_GetPropertyAsIdentity: returned %#"PRIx32, res); + return PKCS11_CKR_PIN_INVALID; + } + + if (user_type == PKCS11_CKU_SO) { + if (TEE_MemCompare(&token->db_main->so_identity, &identity, + sizeof(identity))) + return PKCS11_CKR_PIN_INCORRECT; + } else if (user_type == PKCS11_CKU_USER) { + if (TEE_MemCompare(&token->db_main->user_identity, &identity, + sizeof(identity))) + return PKCS11_CKR_PIN_INCORRECT; + } else { + return PKCS11_CKR_PIN_INCORRECT; + } + + return PKCS11_CKR_OK; +} +#endif /* CFG_PKCS11_TA_AUTH_TEE_IDENTITY */ + /* * Release resources relate to persistent database */ diff --git a/ta/pkcs11/src/pkcs11_token.c b/ta/pkcs11/src/pkcs11_token.c index 97b0dee1..f29d03e1 100644 --- a/ta/pkcs11/src/pkcs11_token.c +++ b/ta/pkcs11/src/pkcs11_token.c @@ -4,6 +4,7 @@ */ #include <assert.h> +#include <config.h> #include <confine_array_index.h> #include <pkcs11_ta.h> #include <printk.h> @@ -839,6 +840,28 @@ enum pkcs11_rc entry_ck_token_initialize(uint32_t ptypes, TEE_Param *params) if (sess->token == token) return PKCS11_CKR_SESSION_EXISTS; +#if defined(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) + /* Check TEE Identity based authentication if enabled */ + if (token->db_main->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH) { + rc = verify_identity_auth(ck_token, PKCS11_CKU_SO); + if (rc) + return rc; + } + + /* Detect TEE Identity based ACL usage activation with NULL PIN */ + if (!pin) { + rc = setup_so_identity_auth_from_client(token); + if (rc) + return rc; + + goto inited; + } else { + /* De-activate TEE Identity based authentication */ + token->db_main->flags &= + ~PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH; + } +#endif /* CFG_PKCS11_TA_AUTH_TEE_IDENTITY */ + if (!token->db_main->so_pin_salt) { /* * The spec doesn't permit returning @@ -921,6 +944,16 @@ static enum pkcs11_rc set_pin(struct pkcs11_session *session, if (!pkcs11_session_is_read_write(session)) return PKCS11_CKR_SESSION_READ_ONLY; + if (IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) && + token->db_main->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH) { + rc = setup_identity_auth_from_pin(token, user_type, new_pin, + new_pin_size); + if (rc) + return rc; + + goto update_db; + } + if (new_pin_size < PKCS11_TOKEN_PIN_SIZE_MIN || new_pin_size > PKCS11_TOKEN_PIN_SIZE_MAX) return PKCS11_CKR_PIN_LEN_RANGE; @@ -955,6 +988,7 @@ static enum pkcs11_rc set_pin(struct pkcs11_session *session, return PKCS11_CKR_FUNCTION_FAILED; } +update_db: token->db_main->flags &= ~flags_clear; token->db_main->flags |= flags_set; @@ -1015,6 +1049,10 @@ static enum pkcs11_rc check_so_pin(struct pkcs11_session *session, assert(token->db_main->flags & PKCS11_CKFT_TOKEN_INITIALIZED); + if (IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) && + token->db_main->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH) + return verify_identity_auth(token, PKCS11_CKU_SO); + if (token->db_main->flags & PKCS11_CKFT_SO_PIN_LOCKED) return PKCS11_CKR_PIN_LOCKED; @@ -1067,6 +1105,10 @@ static enum pkcs11_rc check_user_pin(struct pkcs11_session *session, struct ck_token *token = session->token; 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) + return verify_identity_auth(token, PKCS11_CKU_USER); + if (!token->db_main->user_pin_salt) return PKCS11_CKR_USER_PIN_NOT_INITIALIZED; diff --git a/ta/pkcs11/src/pkcs11_token.h b/ta/pkcs11/src/pkcs11_token.h index d9550353..b201e33e 100644 --- a/ta/pkcs11/src/pkcs11_token.h +++ b/ta/pkcs11/src/pkcs11_token.h @@ -63,10 +63,16 @@ struct token_persistent_main { uint32_t flags; uint32_t so_pin_count; uint32_t so_pin_salt; - uint8_t so_pin_hash[TEE_MAX_HASH_SIZE]; + union { + uint8_t so_pin_hash[TEE_MAX_HASH_SIZE]; + TEE_Identity so_identity; + }; uint32_t user_pin_count; uint32_t user_pin_salt; - uint8_t user_pin_hash[TEE_MAX_HASH_SIZE]; + union { + uint8_t user_pin_hash[TEE_MAX_HASH_SIZE]; + TEE_Identity user_identity; + }; }; /* @@ -187,6 +193,38 @@ 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]); +#if defined(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) +enum pkcs11_rc setup_so_identity_auth_from_client(struct ck_token *token); +enum pkcs11_rc setup_identity_auth_from_pin(struct ck_token *token, + enum pkcs11_user_type user_type, + const uint8_t *pin, + size_t pin_size); +enum pkcs11_rc verify_identity_auth(struct ck_token *token, + enum pkcs11_user_type user_type); +#else +static inline enum pkcs11_rc +setup_so_identity_auth_from_client(struct ck_token *token __unused) +{ + return PKCS11_CKR_PIN_INVALID; +} + +static inline enum pkcs11_rc +setup_identity_auth_from_pin(struct ck_token *token __unused, + enum pkcs11_user_type user_type __unused, + const uint8_t *pin __unused, + size_t pin_size __unused) +{ + return PKCS11_CKR_PIN_INVALID; +} + +static inline enum pkcs11_rc +verify_identity_auth(struct ck_token *token __unused, + enum pkcs11_user_type user_type __unused) +{ + return PKCS11_CKR_PIN_INCORRECT; +} +#endif /* CFG_PKCS11_TA_AUTH_TEE_IDENTITY */ + /* Token persistent objects */ enum pkcs11_rc create_object_uuid(struct ck_token *token, struct pkcs11_object *obj); |