aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pkcs11.c121
1 files 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);
}
@@ -2242,6 +2261,25 @@ static CK_RV p11_check_keypair_attributes(const p11_session_t *session,
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;
- }
}
/*
@@ -3224,26 +3259,31 @@ CK_RV C_Login(CK_SESSION_HANDLE hSession,
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)