summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVesa Jääskeläinen <vesa.jaaskelainen@vaisala.com>2020-10-21 17:57:56 +0300
committerJérôme Forissier <jerome@forissier.org>2021-01-07 17:51:19 +0100
commit1a27b197d8b16ef2d4dab8d205f359627b6f0232 (patch)
tree9f05ba120e99e2975dd7b02f7b277c933201cb31
parent1e497011e77b5e6ec4b8346aa75c750aacba734f (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.mk3
-rw-r--r--ta/pkcs11/include/pkcs11_ta.h41
-rw-r--r--ta/pkcs11/src/persistent_token.c154
-rw-r--r--ta/pkcs11/src/pkcs11_token.c42
-rw-r--r--ta/pkcs11/src/pkcs11_token.h42
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);