diff --git a/ykcs11/token_vendors.c b/ykcs11/token_vendors.c index 6d0c2bd..4cd4bf7 100644 --- a/ykcs11/token_vendors.c +++ b/ykcs11/token_vendors.c @@ -4,6 +4,33 @@ #include #include "debug.h" +static CK_RV COMMON_token_login(ykpiv_state *state, CK_USER_TYPE user, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len) { + + int tries = 0; // TODO: this is effectively disregarded, should we add a better value in ykpiv_verify? + unsigned char key[24]; + size_t key_len = sizeof(key); + + if (user == CKU_USER) { + if (ykpiv_verify(state, (char *)pin, &tries) != YKPIV_OK) { + DBG(("Failed to login")); + return CKR_PIN_INCORRECT; + } + } + else if (user == CKU_SO) { + if(ykpiv_hex_decode((char *)pin, pin_len, key, &key_len) != YKPIV_OK) { + DBG(("Failed decoding key")); + return CKR_FUNCTION_FAILED; + } + + if(ykpiv_authenticate(state, key) != YKPIV_OK) { + DBG(("Failed to authenticate")); + return CKR_PIN_INCORRECT; + } + } + + return CKR_OK; +} + static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE key, CK_ULONG key_len) { // TODO: make a function in ykpiv for this unsigned char in_data[5]; @@ -200,6 +227,7 @@ token_vendor_t get_token_vendor(vendor_id_t vid) { v.get_token_objects_num = YUBICO_get_token_objects_num; v.get_token_object_list = YUBICO_get_token_object_list; v.get_token_raw_certificate = YUBICO_get_token_raw_certificate; + v.token_login = COMMON_token_login; v.token_generate_key = COMMON_token_generate_key; v.token_import_cert = COMMON_token_import_cert; v.token_import_private_key = COMMON_token_import_private_key; @@ -219,6 +247,7 @@ token_vendor_t get_token_vendor(vendor_id_t vid) { v.get_token_objects_num = NULL; v.get_token_object_list = NULL; v.get_token_raw_certificate = NULL; + v.token_login = NULL; v.token_generate_key = NULL; v.token_import_cert = NULL; v.token_import_private_key = NULL; diff --git a/ykcs11/token_vendors.h b/ykcs11/token_vendors.h index 791dc91..ed555b9 100644 --- a/ykcs11/token_vendors.h +++ b/ykcs11/token_vendors.h @@ -20,6 +20,7 @@ typedef CK_RV (*get_t_object_list_f)(ykpiv_state *, piv_obj_id_t *, CK_ULONG); typedef CK_RV (*get_t_raw_certificate_f)(ykpiv_state *, piv_obj_id_t, CK_BYTE_PTR, CK_ULONG_PTR); // Common token functions below +typedef CK_RV (*t_login_f)(ykpiv_state *, CK_USER_TYPE, CK_UTF8CHAR_PTR, CK_ULONG); typedef CK_RV (*t_generate_key_f)(ykpiv_state *, CK_BBOOL, CK_BYTE, CK_ULONG); typedef CK_RV (*t_import_cert_f)(ykpiv_state *, CK_ULONG, CK_BYTE_PTR); typedef CK_RV (*t_import_private_key_f)(ykpiv_state *, CK_BYTE, CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, @@ -40,6 +41,7 @@ typedef struct { get_t_objects_num_f get_token_objects_num; get_t_object_list_f get_token_object_list; get_t_raw_certificate_f get_token_raw_certificate; + t_login_f token_login; t_generate_key_f token_generate_key; t_import_cert_f token_import_cert; t_import_private_key_f token_import_private_key; diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 66f2569..fa67b6c 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -698,7 +698,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( ) { DIN; - CK_ULONG tries = 0; + CK_RV rv; + token_vendor_t token; if (piv_state == NULL) { DBG(("libykpiv is not initialized or already finalized")); @@ -727,6 +728,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( return CKR_SESSION_READ_ONLY_EXISTS; } + token = get_token_vendor(session.slot->token->vid); + switch (userType) { case CKU_USER: if (ulPinLen < PIV_MIN_PIN_LEN || ulPinLen > PIV_MAX_PIN_LEN) @@ -742,13 +745,13 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( return CKR_USER_ANOTHER_ALREADY_LOGGED_IN; } - tries = 0; - if (ykpiv_verify(piv_state, pPin, (int *)&tries) != YKPIV_OK) { // TODO: call this from vendors.c - DBG(("You loose! %lu", tries)); - return CKR_PIN_INCORRECT; + rv = token.token_login(piv_state, CKU_USER, pPin, ulPinLen); + if (rv != CKR_OK) { + DBG(("Unable to login as regular user")); + return rv; } - if ((session.info.flags & CKF_RW_SESSION) == 0) // TODO: double check with the if line 678 for R/O + if ((session.info.flags & CKF_RW_SESSION) == 0) session.info.state = CKS_RO_USER_FUNCTIONS; else session.info.state = CKS_RW_USER_FUNCTIONS; @@ -763,20 +766,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( session.info.state == CKS_RW_USER_FUNCTIONS) return CKR_USER_ANOTHER_ALREADY_LOGGED_IN; - /***** TODO: replace this with a token function *****/ - unsigned char key[24]; - size_t key_len = sizeof(key); - if(ykpiv_hex_decode(pPin, ulPinLen, key, &key_len) != YKPIV_OK) { - DBG(("Failed decoding key")); - return CKR_FUNCTION_FAILED; + rv = token.token_login(piv_state, CKU_SO, pPin, ulPinLen); + if (rv != CKR_OK) { + DBG(("Unable to login as SO")); + return rv; } - if(ykpiv_authenticate(piv_state, key) != YKPIV_OK) { - DBG(("Failed to authenticate")); - return CKR_PIN_INCORRECT; - } - /***************************************************/ - session.info.state = CKS_RW_SO_FUNCTIONS; break; @@ -795,7 +790,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( return CKR_USER_TYPE_INVALID; } - DBG(("You win! %lu", tries)); + DBG(("Successfully logged in")); DOUT; return CKR_OK;