Skip to content

Commit

Permalink
ta: pkcs11: Add TEE Identity based authentication support
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-by: Etienne Carriere <[email protected]>
Signed-off-by: Vesa Jääskeläinen <[email protected]>
  • Loading branch information
vesajaaskelainen authored and jforissier committed Jan 7, 2021
1 parent 1e49701 commit 1a27b19
Show file tree
Hide file tree
Showing 5 changed files with 280 additions and 2 deletions.
3 changes: 3 additions & 0 deletions mk/config.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
41 changes: 41 additions & 0 deletions ta/pkcs11/include/pkcs11_ta.h
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,47 @@ enum pkcs11_user_type {
PKCS11_CKU_CONTEXT_SPECIFIC = 0x002,
};

/*
* 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.
Expand Down
154 changes: 154 additions & 0 deletions ta/pkcs11/src/persistent_token.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down
42 changes: 42 additions & 0 deletions ta/pkcs11/src/pkcs11_token.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/

#include <assert.h>
#include <config.h>
#include <confine_array_index.h>
#include <pkcs11_ta.h>
#include <printk.h>
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;

Expand Down
42 changes: 40 additions & 2 deletions ta/pkcs11/src/pkcs11_token.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
};

/*
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 1a27b19

Please sign in to comment.