diff --git a/ykcs11/obj_types.h b/ykcs11/obj_types.h index 1f0913f..38bf018 100644 --- a/ykcs11/obj_types.h +++ b/ykcs11/obj_types.h @@ -90,6 +90,8 @@ typedef enum { } piv_obj_id_t; +#define OBJECT_INVALID (PIV_PUBK_OBJ_LAST + 1) + typedef CK_RV (*get_attr_f)(CK_OBJECT_HANDLE, CK_ATTRIBUTE_PTR); typedef struct { @@ -120,7 +122,7 @@ typedef struct { CK_BBOOL copyable; // TODO: Optional, not used so far (default TRUE) CK_BBOOL destroyable; // TODO: Optional, not used so far (default TRUE) get_attr_f get_attribute; - CK_ULONG sub_id; // Sub-object id + CK_BYTE sub_id; // Sub-object id } piv_obj_t; #endif diff --git a/ykcs11/objects.c b/ykcs11/objects.c index c21e48b..5f5630b 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -612,7 +612,7 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_ID: fprintf(stderr, "ID\n"); - len = sizeof(CK_ULONG); + len = sizeof(CK_BYTE); ul_tmp = piv_objects[obj].sub_id; data = (CK_BYTE_PTR) &ul_tmp; break; @@ -922,6 +922,48 @@ CK_RV get_attribute(ykcs11_session_t *s, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR return CKR_OBJECT_HANDLE_INVALID; } +CK_BBOOL attribute_match(ykcs11_session_t *s, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR attribute) { + + CK_ATTRIBUTE to_match; + CK_BYTE_PTR data; + + // Get the size first + to_match.type = attribute->type; + to_match.pValue = NULL; + to_match.ulValueLen = 0; + + if (get_attribute(s, obj, &to_match) != CKR_OK) + return CK_FALSE; + + if (to_match.ulValueLen != attribute->ulValueLen) + return CK_FALSE; + + // Allocate space for the attribute + data = malloc(to_match.ulValueLen); + if (data == NULL) + return CK_FALSE; + + // Retrieve the attribute + to_match.pValue = data; + if (get_attribute(s, obj, &to_match) != CKR_OK) { + free(data); + data = NULL; + return CK_FALSE; + } + + // Compare the attributes + if (memcmp(attribute->pValue, to_match.pValue, to_match.ulValueLen) != 0) { + free(data); + data = NULL; + return CK_FALSE; + } + + free(data); + data = NULL; + + return CK_TRUE; +} + CK_RV get_available_certificate_ids(ykcs11_session_t *s, piv_obj_id_t *cert_ids, CK_ULONG n_certs) { CK_ULONG i, j; diff --git a/ykcs11/objects.h b/ykcs11/objects.h index df0a60f..801923d 100644 --- a/ykcs11/objects.h +++ b/ykcs11/objects.h @@ -7,8 +7,10 @@ CK_ULONG piv_2_ykpiv(piv_obj_id_t id); -CK_RV get_attribute(ykcs11_session_t *s, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template); -CK_RV get_available_certificate_ids(ykcs11_session_t *s, piv_obj_id_t *cert_ids, CK_ULONG n_certs); -CK_RV store_cert(piv_obj_id_t cert_id, CK_BYTE_PTR data, CK_ULONG len); +CK_RV get_attribute(ykcs11_session_t *s, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template); +CK_BBOOL attribute_match(ykcs11_session_t *s, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR attribute); + +CK_RV get_available_certificate_ids(ykcs11_session_t *s, piv_obj_id_t *cert_ids, CK_ULONG n_certs); +CK_RV store_cert(piv_obj_id_t cert_id, CK_BYTE_PTR data, CK_ULONG len); #endif diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 45937cd..d994b8b 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -581,7 +581,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CloseSession)( } if (session.handle == CK_INVALID_HANDLE) { - DBG(("There is no existing session")); + DBG(("Trying to close a session, but there is no existing one")); return CKR_SESSION_CLOSED; } @@ -697,8 +697,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( DBG(("user %lu, pin %s, pinlen %lu", userType, pPin, ulPinLen)); - if (session.handle == CK_INVALID_HANDLE) + if (session.handle != YKCS11_SESSION_ID) { + DBG(("Session is not open")); return CKR_SESSION_CLOSED; + } if (hSession != session.handle) return CKR_SESSION_HANDLE_INVALID; @@ -814,8 +816,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)( return CKR_CRYPTOKI_NOT_INITIALIZED; } - if (session.handle != YKCS11_SESSION_ID) + if (session.handle != YKCS11_SESSION_ID) { + DBG(("Session is not open")); return CKR_SESSION_CLOSED; + } if (hSession != session.handle) return CKR_SESSION_HANDLE_INVALID; @@ -867,14 +871,19 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( { DIN; CK_ULONG i; + CK_ULONG j; + CK_ULONG total; + if (piv_state == NULL) { DBG(("libykpiv is not initialized or already finalized")); return CKR_CRYPTOKI_NOT_INITIALIZED; } - if (session.handle != YKCS11_SESSION_ID) + if (session.handle != YKCS11_SESSION_ID) { + DBG(("Session is not open")); return CKR_SESSION_CLOSED; + } if (hSession != session.handle) return CKR_SESSION_HANDLE_INVALID; @@ -885,6 +894,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( find_obj.idx = 0; find_obj.num = session.slot->token->n_objects; + // TODO: remove private objects if needed + find_obj.objects = malloc(sizeof(piv_obj_id_t) * find_obj.num); if (find_obj.objects == NULL) { DBG(("Unable to allocate memory for finding objects")); @@ -892,31 +903,46 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( } memcpy(find_obj.objects, session.slot->token->objects, sizeof(piv_obj_id_t) * find_obj.num); // TODO: add another 'num' field for then objects have to be excluded because of attribute matching; - find_obj.active = CK_TRUE; - if (ulCount == 0) { - DBG(("Find ALL the objects!")); + DBG(("Find ALL the objects! Got %lu", find_obj.num)); + find_obj.active = CK_TRUE; DOUT; return CKR_OK; } DBG(("Initialized search with %lu parameters", ulCount)); - if (pTemplate == NULL_PTR) { - find_obj.active = CK_FALSE; + if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD; - } + // Match parameters + total = find_obj.num; for (i = 0; i < ulCount; i++) { DBG(("Parameter %lu\nType: %lu Value: %lu Len: %lu", i, pTemplate[i].type, *((CK_ULONG_PTR)pTemplate[i].pValue), pTemplate[i].ulValueLen)); - // TODO: remove objects that don't match + + for (j = 0; j < find_obj.num; j++) { + if (find_obj.objects[j] == OBJECT_INVALID) + continue; // Object already discarded, keep going + + if (attribute_match(&session, find_obj.objects[j], pTemplate + i) == CK_FALSE) { + DBG(("Removing object %u from the list", find_obj.objects[j])); + find_obj.objects[j] = OBJECT_INVALID; // Object not matching, mark it + total--; + } + else + DBG(("Keeping object %u in the list", find_obj.objects[j])); + } } + DBG(("%lu object(s) left after attribute matching", total)); + // TODO: do it properly here, just a test now //find_obj.objects = session.slot->token->objects + 3; - memmove(find_obj.objects, find_obj.objects + 13, sizeof(piv_obj_id_t) * (find_obj.num - 13)); - find_obj.num = 1; + /*memmove(find_obj.objects, find_obj.objects + 12, sizeof(piv_obj_id_t) * (find_obj.num - 12)); + find_obj.num = 1;*/ + find_obj.active = CK_TRUE; + DOUT; return CKR_OK; } @@ -935,8 +961,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)( return CKR_CRYPTOKI_NOT_INITIALIZED; } - if (session.handle != YKCS11_SESSION_ID) + if (session.handle != YKCS11_SESSION_ID) { + DBG(("Session is not open")); return CKR_SESSION_CLOSED; + } if (hSession != session.handle) return CKR_SESSION_HANDLE_INVALID; @@ -951,7 +979,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)( DBG(("Can return %lu object(s)", ulMaxObjectCount)); - // Return the next object + // Return the next object, if any + while(find_obj.idx < find_obj.num && + find_obj.objects[find_obj.idx] == OBJECT_INVALID) + find_obj.idx++; + if (find_obj.idx == find_obj.num) { *pulObjectCount = 0; DOUT; @@ -977,8 +1009,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsFinal)( return CKR_CRYPTOKI_NOT_INITIALIZED; } - if (session.handle != YKCS11_SESSION_ID) + if (session.handle != YKCS11_SESSION_ID) { + DBG(("Session is not open")); return CKR_SESSION_CLOSED; + } if (hSession != session.handle) return CKR_SESSION_HANDLE_INVALID; @@ -1180,8 +1214,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( return CKR_CRYPTOKI_NOT_INITIALIZED; } - if (session.handle != YKCS11_SESSION_ID) + if (session.handle != YKCS11_SESSION_ID) { + DBG(("Session is not open")); return CKR_SESSION_CLOSED; + } if (hSession != session.handle) return CKR_SESSION_HANDLE_INVALID; @@ -1241,8 +1277,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( } DBG(("Key length is %lu bit", sign_info.key_len)); - //sign_info.key_len /= 8; - + sign_info.key = piv_2_ykpiv(hKey); if (sign_info.key == 0) { DBG(("Incorrect key %lu", hKey));