From 1d60161a9eae18e339232bed879f0525925e10cb Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Tue, 16 Aug 2016 00:02:34 -0400 Subject: More pkcs11test fixes: nuanced read-only, error code proliferation. PKCS #11's notion of a "read-only" session is odd: read-only sessions can still create/modify/destroy objects, just not "token" objects. C_SeedRandom() has its own special "nope, didn't implement that" error code, apparently the one everything else uses wasn't good enough. C_Login() has different error codes for "you're already logged in" and "you're already logged in as somebody else". --- pkcs11.c | 121 +++++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 83 insertions(+), 38 deletions(-) diff --git a/pkcs11.c b/pkcs11.c index 15d3572..cf354e6 100644 --- a/pkcs11.c +++ b/pkcs11.c @@ -1186,22 +1186,36 @@ static CK_RV p11_object_check_rights(const p11_session_t *session, static const char session_object_query[] = " SELECT session_handle FROM session NATURAL JOIN object WHERE object_handle = ?1"; - CK_BBOOL object_is_private; sqlite3_stmt *q = NULL; + CK_BBOOL cka_private; + CK_BBOOL cka_token; CK_RV rv; if (session == NULL) lose(CKR_SESSION_HANDLE_INVALID); + if (!p11_attribute_get_bbool(object_handle, CKA_PRIVATE, &cka_private)) + cka_private = CK_TRUE; + + if (!p11_attribute_get_bbool(object_handle, CKA_TOKEN, &cka_token)) + cka_token = CK_FALSE; + /* - * Read-only sessions are, um, read-only. + * Read-only sessions are, um, read-only. Well, except, in PKCS #11, + * read-only only sort of means what you might expect. */ - switch (session->state) { - case CKS_RO_PUBLIC_SESSION: - case CKS_RO_USER_FUNCTIONS: - if (rights == p11_object_access_write) - lose(CKR_SESSION_READ_ONLY); + if (rights == p11_object_access_write) { + switch (session->state) { + case CKS_RO_PUBLIC_SESSION: + if (cka_private) + lose(CKR_SESSION_READ_ONLY); + /* Fall through */ + case CKS_RO_USER_FUNCTIONS: + if (cka_token) + lose(CKR_SESSION_READ_ONLY); + /* Fall through */ + } } /* @@ -1212,7 +1226,7 @@ static CK_RV p11_object_check_rights(const p11_session_t *session, case CKS_RO_PUBLIC_SESSION: case CKS_RW_PUBLIC_SESSION: case CKS_RW_SO_FUNCTIONS: - if (!p11_attribute_get_bbool(object_handle, CKA_PRIVATE, &object_is_private) || object_is_private) + if (cka_private) lose(CKR_OBJECT_HANDLE_INVALID); } @@ -2177,15 +2191,8 @@ static CK_RV p11_check_keypair_attributes(const p11_session_t *session, *public_flags = *private_flags = 0; - /* - * Read-only sessions can't create keys, doh. - */ - - switch (session->state) { - case CKS_RO_PUBLIC_SESSION: - case CKS_RO_USER_FUNCTIONS: - lose(CKR_SESSION_READ_ONLY); - } + const CK_BBOOL * public_cka_private = NULL, * public_cka_token = NULL; + const CK_BBOOL *private_cka_private = NULL, *private_cka_token = NULL; /* * Check values provided in the public and private templates. @@ -2200,6 +2207,12 @@ static CK_RV p11_check_keypair_attributes(const p11_session_t *session, P11_DESCRIPTOR_FORBIDDEN_BY_GENERATE)) != CKR_OK) goto fail; + if (type == CKA_TOKEN) + public_cka_token = val; + + if (type == CKA_PRIVATE) + public_cka_private = val; + p11_attribute_apply_keyusage(public_flags, type, val); } @@ -2212,6 +2225,12 @@ static CK_RV p11_check_keypair_attributes(const p11_session_t *session, P11_DESCRIPTOR_FORBIDDEN_BY_GENERATE)) != CKR_OK) goto fail; + if (type == CKA_TOKEN) + public_cka_token = val; + + if (type == CKA_PRIVATE) + public_cka_private = val; + p11_attribute_apply_keyusage(private_flags, type, val); } @@ -2241,6 +2260,25 @@ static CK_RV p11_check_keypair_attributes(const p11_session_t *session, P11_DESCRIPTOR_FORBIDDEN_BY_GENERATE)) != CKR_OK) goto fail; + /* + * Read-only sessions can't create objects, doh. + * Well, except when they can, thanks, PKCS #11. + */ + + switch (session->state) { + case CKS_RO_PUBLIC_SESSION: + if ((public_cka_private == NULL || *public_cka_private) || + (private_cka_private == NULL || *private_cka_private)) + lose(CKR_SESSION_READ_ONLY); + /* Fall through */ + + case CKS_RO_USER_FUNCTIONS: + if ((public_cka_token != NULL && *public_cka_token) || + (private_cka_token != NULL && *private_cka_token)) + lose(CKR_SESSION_READ_ONLY); + /* Fall through */ + } + /* * If we get this far, we're happy. Maybe. */ @@ -2569,14 +2607,11 @@ static CK_RV p11_check_create_attributes(const p11_session_t *session, P11_DESCRIPTOR_FORBIDDEN_BY_CREATEOBJECT)) != CKR_OK) goto fail; - switch (type) { - case CKA_TOKEN: + if (type == CKA_TOKEN) cka_token = val; - break; - case CKA_PRIVATE: + + if (type == CKA_PRIVATE) cka_private = val; - break; - } } /* @@ -3223,27 +3258,32 @@ CK_RV C_Login(CK_SESSION_HANDLE hSession, if (p11_session_find(hSession) == NULL) lose(CKR_SESSION_HANDLE_INVALID); - /* - * We don't currently support re-login without an intervening - * logout, so reject the login attempt if we're already logged in. - */ - - if (logged_in_as != not_logged_in) - lose(CKR_USER_ALREADY_LOGGED_IN); - /* * Figure out which PIN we're checking. * We don't (yet?) support CKU_CONTEXT_SPECIFIC. * + * We don't currently support re-login without an intervening + * logout, so reject the login attempt if we're already logged in. + * * Read-only SO is an illegal state, so reject the login attempt if * we have any read-only sessions and we're trying to log in as SO. */ switch (userType) { case CKU_USER: + switch (logged_in_as) { + case not_logged_in: break; + case logged_in_as_user: lose(CKR_USER_ALREADY_LOGGED_IN); + case logged_in_as_so: lose(CKR_USER_ANOTHER_ALREADY_LOGGED_IN); + } user = HAL_USER_NORMAL; break; case CKU_SO: + switch (logged_in_as) { + case not_logged_in: break; + case logged_in_as_so: lose(CKR_USER_ALREADY_LOGGED_IN); + case logged_in_as_user: lose(CKR_USER_ANOTHER_ALREADY_LOGGED_IN); + } for (session = p11_sessions; session != NULL; session = session->link) if (session->state == CKS_RO_PUBLIC_SESSION) lose(CKR_SESSION_READ_ONLY_EXISTS); @@ -4829,6 +4869,18 @@ CK_RV C_GetMechanismList(CK_SLOT_ID slotID, return rv; } +CK_RV C_SeedRandom(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSeed, + CK_ULONG ulSeedLen) +{ + ENTER_PUBLIC_FUNCTION(C_SeedRandom); + + if (p11_uninitialized()) + return CKR_CRYPTOKI_NOT_INITIALIZED; + + return CKR_RANDOM_SEED_NOT_SUPPORTED; +} + /* @@ -5114,13 +5166,6 @@ CK_RV C_DeriveKey(CK_SESSION_HANDLE hSession, UNSUPPORTED_FUNCTION(C_DeriveKey); } -CK_RV C_SeedRandom(CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pSeed, - CK_ULONG ulSeedLen) -{ - UNSUPPORTED_FUNCTION(C_SeedRandom); -} - CK_RV C_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pRserved) -- cgit v1.2.3