More object handling.
This commit is contained in:
+2
-2
@@ -77,8 +77,8 @@ typedef enum {
|
||||
typedef struct {
|
||||
//const CK_OBJECT_CLASS class;
|
||||
piv_obj_id_t type;
|
||||
const CK_CHAR_PTR name; // TODO: or utf8
|
||||
const CK_CHAR_PTR oid;
|
||||
const char *name; // TODO: or utf8
|
||||
const char *oid;
|
||||
CK_BYTE tag_len; // TODO: or ulong?
|
||||
CK_BYTE tag_value[3];
|
||||
CK_BYTE containerid[2]; /* will use as relative paths for simulation */ // TODO: needed?
|
||||
|
||||
+166
-67
@@ -1,10 +1,11 @@
|
||||
#include "objects.h"
|
||||
#include <ykpiv.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
//TODO: this is mostly a snippet from OpenSC how to give credit?
|
||||
/* Must be in order, and one per enumerated PIV_OBJ */
|
||||
static const piv_obj_t objects[] = {
|
||||
static piv_obj_t objects[] = {
|
||||
{PIV_OBJ_CCC, "Card Capability Container",
|
||||
"2.16.840.1.101.3.7.1.219.0", 3, "\x5F\xC1\x07", "\xDB\x00", 0},
|
||||
{PIV_OBJ_CHUI, "Card Holder Unique Identifier",
|
||||
@@ -95,11 +96,11 @@ static const piv_obj_t objects[] = {
|
||||
{PIV_OBJ_IRIS_IMAGE, "Cardholder Iris Images",
|
||||
"2.16.840.1.101.3.7.2.16.21", 3, "\x5F\xC1\x21", "\x10\x15", 0},
|
||||
{PIV_OBJ_BITGT, "Biometric Information Templates Group Template",
|
||||
"2.16.840.1.101.3.7.2.16.22", 2, "\x7F\x61", "\x10\x16" },
|
||||
"2.16.840.1.101.3.7.2.16.22", 2, "\x7F\x61", "\x10\x16", 0},
|
||||
{PIV_OBJ_SM_SIGNER, "Secure Messaging Certificate Signer",
|
||||
"2.16.840.1.101.3.7.2.16.23", 3, "\x5F\xC1\x22", "\x10\x17"},
|
||||
"2.16.840.1.101.3.7.2.16.23", 3, "\x5F\xC1\x22", "\x10\x17", 0},
|
||||
{PIV_OBJ_PC_REF_DATA, "Pairing Code Reference Data Container",
|
||||
"2.16.840.1.101.3.7.2.16.24", 3, "\x5F\xC1\x23", "\x10\x18"},
|
||||
"2.16.840.1.101.3.7.2.16.24", 3, "\x5F\xC1\x23", "\x10\x18", 0},
|
||||
|
||||
/* following not standard , to be used by piv-tool only for testing */
|
||||
{PIV_OBJ_9B03, "3DES-ECB ADM",
|
||||
@@ -163,115 +164,213 @@ static const piv_obj_t objects[] = {
|
||||
|
||||
static const CK_ULONG n_objects = sizeof(objects) / sizeof(piv_obj_t);
|
||||
|
||||
static CK_RV get_object_class(CK_OBJECT_HANDLE obj, CK_OBJECT_CLASS_PTR class) {
|
||||
static void get_object_class(CK_OBJECT_HANDLE obj, CK_OBJECT_CLASS_PTR class) {
|
||||
if ((objects[obj].flags & PIV_OBJECT_TYPE_PUBKEY))
|
||||
*class = CKO_PUBLIC_KEY;
|
||||
else if ((objects[obj].flags & PIV_OBJECT_TYPE_CERT))
|
||||
*class = CKO_CERTIFICATE;
|
||||
else
|
||||
*class - CKO_DATA; // TODO: other possibilities?
|
||||
return CKR_OK;
|
||||
*class = CKO_DATA; // TODO: other possibilities?
|
||||
}
|
||||
|
||||
static CK_RV get_object_label(CK_OBJECT_HANDLE obj, CK_UTF8CHAR_PTR label) {
|
||||
strcpy(label, objects[obj].name);
|
||||
static void get_object_label(CK_OBJECT_HANDLE obj, CK_UTF8CHAR_PTR label) {
|
||||
strcpy((char *)label, objects[obj].name);
|
||||
}
|
||||
|
||||
static CK_RV get_object_oid(CK_OBJECT_HANDLE obj, CK_UTF8CHAR_PTR oid) {
|
||||
// strcpy(oid, objects[obj].oid);
|
||||
oid[0] = 0x2b;
|
||||
oid[1] = 0x06;
|
||||
oid[2] = 0x01;
|
||||
oid[3] = 0x04;
|
||||
oid[4] = 0x01;
|
||||
oid[5] = 0x82;
|
||||
oid[6] = 0x37;
|
||||
oid[7] = 0x15;
|
||||
oid[8] = 0x14;
|
||||
// Next two functions based off the code at
|
||||
// https://github.com/m9aertner/oidConverter/blob/master/oid.c
|
||||
// TODO: how to give credit?
|
||||
static void make_base128(unsigned long l, int first, CK_BYTE_PTR buf, CK_ULONG_PTR n) {
|
||||
if (l > 127)
|
||||
make_base128(l / 128, 0, buf, n);
|
||||
|
||||
l %= 128;
|
||||
|
||||
if (first)
|
||||
buf[(*n)++] = (CK_BYTE)l;
|
||||
else
|
||||
buf[(*n)++] = 0x80 | (CK_BYTE)l;
|
||||
}
|
||||
|
||||
static void asn1_encode_oid(CK_CHAR_PTR oid, CK_BYTE_PTR asn1_oid, CK_ULONG_PTR len) {
|
||||
CK_CHAR_PTR tmp = strdup((char *)oid);
|
||||
CK_CHAR_PTR p = tmp;
|
||||
CK_BYTE_PTR q = NULL;
|
||||
CK_ULONG n = 0;
|
||||
CK_BYTE b = 0;
|
||||
CK_ULONG l = 0;
|
||||
CK_ULONG nodes;
|
||||
|
||||
q = p;
|
||||
*len = 0;
|
||||
nodes = 1;
|
||||
while (*p != 0) {
|
||||
if (*p == '.')
|
||||
nodes++;
|
||||
p++;
|
||||
}
|
||||
|
||||
n = 0;
|
||||
b = 0;
|
||||
p = q;
|
||||
while (n < nodes) {
|
||||
q = p;
|
||||
while (*p != 0) {
|
||||
if (*p == '.')
|
||||
break;
|
||||
p++;
|
||||
}
|
||||
|
||||
l = 0;
|
||||
if (*p == '.') {
|
||||
*p = 0;
|
||||
l = (CK_ULONG) atoi((char *)q);
|
||||
q = p + 1;
|
||||
p = q;
|
||||
}
|
||||
else {
|
||||
l = (CK_ULONG) atoi((char *)q);
|
||||
q = p;
|
||||
}
|
||||
|
||||
/* Digit is in l. */
|
||||
if (n == 0)
|
||||
b = 40 * ((CK_BYTE)l);
|
||||
else if (n == 1) {
|
||||
b += (CK_BYTE) l;
|
||||
asn1_oid[(*len)++] = b;
|
||||
}
|
||||
else {
|
||||
make_base128(l, 1, asn1_oid, len);
|
||||
}
|
||||
n++;
|
||||
}
|
||||
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
static void get_object_oid(CK_OBJECT_HANDLE obj, CK_UTF8CHAR_PTR oid) {
|
||||
strcpy((char *)oid, objects[obj].oid);
|
||||
}
|
||||
|
||||
static void get_object_certificate_type(CK_OBJECT_HANDLE obj, CK_CERTIFICATE_TYPE_PTR type) {
|
||||
if ((objects[obj].flags & PIV_OBJECT_TYPE_CERT))
|
||||
*type = CKC_X_509;
|
||||
}
|
||||
|
||||
static void get_object_key_id(CK_OBJECT_HANDLE obj, CK_UTF8CHAR_PTR key_id) {
|
||||
memcpy((char *)key_id, objects[obj].containerid, 2);
|
||||
}
|
||||
|
||||
CK_RV get_attribute(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
|
||||
fprintf(stderr, "FOR OBJECT %lu, I WANT ", obj);
|
||||
CK_ULONG i;
|
||||
|
||||
switch (template->type) {
|
||||
case CKA_CLASS:
|
||||
fprintf(stderr, "CLASS\n");
|
||||
if (template->pValue == NULL_PTR) // TODO: just don't use functions, break and check return later?
|
||||
template->ulValueLen = 1;
|
||||
else
|
||||
get_object_class(obj, template->pValue);
|
||||
|
||||
return CKR_OK;
|
||||
|
||||
case CKA_TOKEN:
|
||||
//get_object
|
||||
// case CKA_TOKEN:
|
||||
case CKA_PRIVATE:
|
||||
fprintf(stderr, "PRIVATE\n"); // TODO: check more
|
||||
template->ulValueLen = CK_UNAVAILABLE_INFORMATION;
|
||||
return CKR_OK;
|
||||
|
||||
case CKA_LABEL:
|
||||
fprintf(stderr, "LABEL\n");
|
||||
get_object_label(obj, template->pValue);
|
||||
if (template->pValue == NULL_PTR)
|
||||
template->ulValueLen = strlen(objects[obj].name);
|
||||
else
|
||||
strcpy((char *)template->pValue, objects[obj].name);
|
||||
return CKR_OK;
|
||||
|
||||
case CKA_APPLICATION:
|
||||
fprintf(stderr, "APPLICATION\n");
|
||||
get_object_label(obj, template->pValue);
|
||||
if (template->pValue == NULL_PTR)
|
||||
template->ulValueLen = strlen(objects[obj].name);
|
||||
else
|
||||
strcpy((char *)template->pValue, objects[obj].name);
|
||||
return CKR_OK;
|
||||
|
||||
case CKA_VALUE:
|
||||
case CKA_OBJECT_ID:
|
||||
fprintf(stderr, "OID\n!!!"); // TODO: this is a DER encoded byte array
|
||||
|
||||
get_object_oid(obj, template->pValue);
|
||||
template->ulValueLen = 9;
|
||||
// case CKA_VALUE:
|
||||
case CKA_OBJECT_ID: // TODO: how about just storing the OID in DER ?
|
||||
fprintf(stderr, "OID\n");
|
||||
if (template->pValue == NULL_PTR)
|
||||
template->ulValueLen = strlen(objects[obj].oid) * 2; // Slightly oversized
|
||||
else {
|
||||
strcpy((char *)template->pValue, objects[obj].oid);
|
||||
asn1_encode_oid(template->pValue, template->pValue, &template->ulValueLen);
|
||||
}
|
||||
return CKR_OK;
|
||||
|
||||
case CKA_CERTIFICATE_TYPE:
|
||||
case CKA_ISSUER:
|
||||
case CKA_SERIAL_NUMBER:
|
||||
fprintf(stderr, "CERTIFICATE TYPE\n");
|
||||
if (template->pValue == NULL_PTR)
|
||||
template->ulValueLen = 1;
|
||||
else
|
||||
*((CK_ULONG_PTR)template->pValue) = CKC_X_509; // Support only X.509 certs
|
||||
return CKR_OK;
|
||||
// case CKA_ISSUER:
|
||||
// case CKA_SERIAL_NUMBER:
|
||||
case CKA_KEY_TYPE:
|
||||
fprintf(stderr, "Return the key type\n");
|
||||
fprintf(stderr, "Return the key type TODO!!!\n");
|
||||
return CKR_OK;
|
||||
|
||||
case CKA_SUBJECT:
|
||||
/* case CKA_SUBJECT: */
|
||||
case CKA_ID:
|
||||
case CKA_SENSITIVE:
|
||||
case CKA_ENCRYPT:
|
||||
case CKA_DECRYPT:
|
||||
case CKA_WRAP:
|
||||
case CKA_UNWRAP:
|
||||
case CKA_SIGN:
|
||||
case CKA_SIGN_RECOVER:
|
||||
case CKA_VERIFY:
|
||||
case CKA_VERIFY_RECOVER:
|
||||
case CKA_DERIVE:
|
||||
case CKA_START_DATE:
|
||||
case CKA_END_DATE:
|
||||
case CKA_MODULUS:
|
||||
case CKA_MODULUS_BITS:
|
||||
case CKA_PUBLIC_EXPONENT:
|
||||
case CKA_PRIVATE_EXPONENT:
|
||||
case CKA_PRIME_1:
|
||||
case CKA_PRIME_2:
|
||||
case CKA_EXPONENT_1:
|
||||
case CKA_EXPONENT_2:
|
||||
case CKA_COEFFICIENT:
|
||||
case CKA_PRIME:
|
||||
case CKA_SUBPRIME:
|
||||
case CKA_BASE:
|
||||
case CKA_VALUE_BITS:
|
||||
case CKA_VALUE_LEN:
|
||||
case CKA_EXTRACTABLE:
|
||||
case CKA_LOCAL:
|
||||
case CKA_NEVER_EXTRACTABLE:
|
||||
case CKA_ALWAYS_SENSITIVE:
|
||||
fprintf(stderr, "KEY ID\n");
|
||||
if (template->pValue == NULL_PTR)
|
||||
template->ulValueLen = 2;
|
||||
else
|
||||
memcpy((char *)template->pValue, objects[obj].containerid, 2);
|
||||
return CKR_OK;
|
||||
/* case CKA_SENSITIVE: */
|
||||
/* case CKA_ENCRYPT: */
|
||||
/* case CKA_DECRYPT: */
|
||||
/* case CKA_WRAP: */
|
||||
/* case CKA_UNWRAP: */
|
||||
/* case CKA_SIGN: */
|
||||
/* case CKA_SIGN_RECOVER: */
|
||||
/* case CKA_VERIFY: */
|
||||
/* case CKA_VERIFY_RECOVER: */
|
||||
/* case CKA_DERIVE: */
|
||||
/* case CKA_START_DATE: */
|
||||
/* case CKA_END_DATE: */
|
||||
/* case CKA_MODULUS: */
|
||||
/* case CKA_MODULUS_BITS: */
|
||||
/* case CKA_PUBLIC_EXPONENT: */
|
||||
/* case CKA_PRIVATE_EXPONENT: */
|
||||
/* case CKA_PRIME_1: */
|
||||
/* case CKA_PRIME_2: */
|
||||
/* case CKA_EXPONENT_1: */
|
||||
/* case CKA_EXPONENT_2: */
|
||||
/* case CKA_COEFFICIENT: */
|
||||
/* case CKA_PRIME: */
|
||||
/* case CKA_SUBPRIME: */
|
||||
/* case CKA_BASE: */
|
||||
/* case CKA_VALUE_BITS: */
|
||||
/* case CKA_VALUE_LEN: */
|
||||
/* case CKA_EXTRACTABLE: */
|
||||
/* case CKA_LOCAL: */
|
||||
/* case CKA_NEVER_EXTRACTABLE: */
|
||||
/* case CKA_ALWAYS_SENSITIVE: */
|
||||
case CKA_MODIFIABLE:
|
||||
fprintf(stderr, "MODIFIABLE\n");
|
||||
if (template->pValue == NULL_PTR)
|
||||
template->ulValueLen = 1;
|
||||
else
|
||||
*((CK_ULONG_PTR)template->pValue) = CK_FALSE;
|
||||
return CKR_OK;
|
||||
|
||||
case CKA_VENDOR_DEFINED:
|
||||
default:
|
||||
fprintf(stderr, "UNKNOWN ATTRIBUTE!!!!! %lu\n", template[0].type);
|
||||
|
||||
fprintf(stderr, "UNKNOWN ATTRIBUTE!!!!! %lx\n", template[0].type);
|
||||
template->ulValueLen = CK_UNAVAILABLE_INFORMATION;
|
||||
return CKR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
|
||||
@@ -356,6 +356,7 @@ typedef CK_ULONG CK_KEY_TYPE;
|
||||
/* CK_CERTIFICATE_TYPE was changed from CK_USHORT to CK_ULONG
|
||||
* for v2.0 */
|
||||
typedef CK_ULONG CK_CERTIFICATE_TYPE;
|
||||
typedef CK_CERTIFICATE_TYPE CK_PTR CK_CERTIFICATE_TYPE_PTR;
|
||||
|
||||
/* The following certificate types are defined: */
|
||||
#define CKC_X_509 0x00000000
|
||||
|
||||
+23
-10
@@ -11,7 +11,7 @@
|
||||
printf ("\n"); \
|
||||
} while (0)
|
||||
|
||||
#define YKCS11_DBG 1 // General debug, must be either 1 or 0
|
||||
#define YKCS11_DBG 0 // General debug, must be either 1 or 0
|
||||
#define YKCS11_DINOUT 0 // Function in/out debug, must be either 1 or 0
|
||||
|
||||
#define YKCS11_MANUFACTURER "Yubico (www.yubico.com)"
|
||||
@@ -49,6 +49,7 @@ static CK_SESSION_INFO session_info;
|
||||
|
||||
static struct {
|
||||
CK_BBOOL active;
|
||||
CK_ULONG num;
|
||||
CK_ULONG idx;
|
||||
CK_BBOOL all;
|
||||
CK_OBJECT_CLASS class;
|
||||
@@ -750,7 +751,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)(
|
||||
|
||||
if (pTemplate[0].pValue == NULL_PTR) {
|
||||
DBG(("Just get size"));
|
||||
pTemplate[0].ulValueLen = 1024; // TODO: get attribute size
|
||||
get_attribute(hObject, pTemplate); // TODO: get attribute size
|
||||
DOUT;
|
||||
return CKR_OK;
|
||||
}
|
||||
@@ -784,6 +785,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)(
|
||||
{
|
||||
DIN;
|
||||
CK_ULONG i;
|
||||
vendor_t vendor;
|
||||
|
||||
if (piv_state == NULL)
|
||||
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
||||
@@ -792,16 +794,23 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)(
|
||||
return CKR_SESSION_CLOSED;
|
||||
|
||||
if (hSession != session)
|
||||
return CKR_SESSION_HANDLE_INVALID;
|
||||
return CKR_SESSION_HANDLE_INVALID; // TODO: or session closed?
|
||||
|
||||
if (find_obj.active == CK_TRUE)
|
||||
return CKR_OPERATION_ACTIVE;
|
||||
|
||||
if (slots[session_info.slotID].vid == UNKNOWN) {
|
||||
DBG(("Slot %lu is tokenless/unsupported", slotID));
|
||||
return CKR_SLOT_ID_INVALID;
|
||||
}
|
||||
vendor = get_vendor(slots[session_info.slotID].vid); // TODO: make a token field in slot_t ?;
|
||||
|
||||
if (ulCount == 0) {
|
||||
DBG(("Find ALL the objects!"));
|
||||
find_obj.active = CK_TRUE;
|
||||
find_obj.all = CK_TRUE;
|
||||
vendor.get_token_objects_num(&find_obj.num);
|
||||
find_obj.idx = 0;
|
||||
find_obj.all = CK_TRUE;
|
||||
DOUT;
|
||||
return CKR_OK;
|
||||
}
|
||||
@@ -824,7 +833,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)(
|
||||
DOUT;
|
||||
return CKR_OK;
|
||||
}
|
||||
CK_ULONG bla = 1; // TODO: delete
|
||||
|
||||
CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)(
|
||||
CK_SESSION_HANDLE hSession,
|
||||
CK_OBJECT_HANDLE_PTR phObject,
|
||||
@@ -853,11 +862,15 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)(
|
||||
|
||||
DBG(("Can return %lu object(s)", ulMaxObjectCount));
|
||||
if (find_obj.all == CK_TRUE) {
|
||||
// Trying to get all the objects, just return the next
|
||||
//*phObject = piv_objects[find_obj.idx++];
|
||||
//*pulObjectCount = 1;
|
||||
*phObject = piv_objects[bla];
|
||||
*pulObjectCount = bla--;
|
||||
// Trying to get all the objects, just return the next one
|
||||
if (find_obj.idx == find_obj.num) {
|
||||
*pulObjectCount = 0;
|
||||
DOUT;
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
*phObject = piv_objects[find_obj.idx++];
|
||||
*pulObjectCount = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+38
-2
@@ -67,8 +67,43 @@ static const CK_MECHANISM_INFO token_mechanism_infos[] = { // KEEP ALIGNED WITH
|
||||
{0, 0, CKF_DIGEST} // CKM_SHA512
|
||||
};
|
||||
|
||||
static const piv_obj_id_t token_objects[] = {
|
||||
|
||||
static const piv_obj_id_t token_objects[] = { // TODO: is there a way to get this from the token?
|
||||
PIV_OBJ_CCC, // Card capability container
|
||||
PIV_OBJ_CHUI, // Cardholder unique id
|
||||
PIV_OBJ_X509_PIV_AUTH, // PIV authentication
|
||||
PIV_OBJ_CHF, // Cardholder fingerprints
|
||||
PIV_OBJ_SEC_OBJ, // Security object
|
||||
PIV_OBJ_CHFI, // Cardholder facial images
|
||||
PIV_OBJ_X509_CARD_AUTH, // Certificate for card authentication
|
||||
PIV_OBJ_X509_DS, // Certificate for digital signature
|
||||
PIV_OBJ_X509_KM, // Certificate for key management
|
||||
//PIV_OBJ_PI, // Cardholder printed information
|
||||
//PIV_OBJ_DISCOVERY, // Discovery object
|
||||
//PIV_OBJ_HISTORY, // History object
|
||||
/* PIV_OBJ_RETIRED_X509_1, // Retired certificate for KM 1
|
||||
PIV_OBJ_RETIRED_X509_2, // Retired certificate for KM 2
|
||||
PIV_OBJ_RETIRED_X509_3, // Retired certificate for KM 3
|
||||
PIV_OBJ_RETIRED_X509_4, // Retired certificate for KM 4
|
||||
PIV_OBJ_RETIRED_X509_5, // Retired certificate for KM 5
|
||||
PIV_OBJ_RETIRED_X509_6, // Retired certificate for KM 6
|
||||
PIV_OBJ_RETIRED_X509_7, // Retired certificate for KM 7
|
||||
PIV_OBJ_RETIRED_X509_8, // Retired certificate for KM 8
|
||||
PIV_OBJ_RETIRED_X509_9, // Retired certificate for KM 9
|
||||
PIV_OBJ_RETIRED_X509_10, // Retired certificate for KM 10
|
||||
PIV_OBJ_RETIRED_X509_11, // Retired certificate for KM 11
|
||||
PIV_OBJ_RETIRED_X509_12, // Retired certificate for KM 12
|
||||
PIV_OBJ_RETIRED_X509_13, // Retired certificate for KM 13
|
||||
PIV_OBJ_RETIRED_X509_14, // Retired certificate for KM 14
|
||||
PIV_OBJ_RETIRED_X509_15, // Retired certificate for KM 15
|
||||
PIV_OBJ_RETIRED_X509_16, // Retired certificate for KM 16
|
||||
PIV_OBJ_RETIRED_X509_17, // Retired certificate for KM 17
|
||||
PIV_OBJ_RETIRED_X509_18, // Retired certificate for KM 18
|
||||
PIV_OBJ_RETIRED_X509_19, // Retired certificate for KM 19
|
||||
PIV_OBJ_RETIRED_X509_20, // Retired certificate for KM 20*/
|
||||
//PIV_OBJ_IRIS_IMAGE, // Cardholder iris images
|
||||
//PIV_OBJ_BITGT, // Biometric information templates group template
|
||||
//PIV_OBJ_SM_SIGNER, // Secure messaging signer
|
||||
//PIV_OBJ_PC_REF_DATA, // Pairing code reference data
|
||||
};
|
||||
static const CK_ULONG token_objects_num = sizeof(token_objects) / sizeof(piv_obj_id_t);
|
||||
|
||||
@@ -220,6 +255,7 @@ CK_RV YUBICO_get_token_mechanism_info(CK_MECHANISM_TYPE mec, CK_MECHANISM_INFO_P
|
||||
CK_RV YUBICO_get_token_objects_num(CK_ULONG_PTR num) {
|
||||
|
||||
*num = token_objects_num;
|
||||
//fprintf("TIENI %lu\n", token_objects_num);
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user