Merge branch 'development' of gitlab.yubico.com:Yubico/yubico-piv-tool into development

This commit is contained in:
Klas Lindfors
2015-10-28 16:08:12 +01:00
11 changed files with 162 additions and 56 deletions
+7 -2
View File
@@ -163,6 +163,7 @@ CK_RV apply_sign_mechanism_init(op_info_t *op_info) {
case CKM_RSA_X_509:
case CKM_ECDSA:
// No hash required for this mechanism
op_info->op.sign.md_ctx = NULL;
return CKR_OK;
case CKM_SHA1_RSA_PKCS:
@@ -419,7 +420,7 @@ CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG
default:
DBG(("Invalid attribute %lx in public key template", templ[i].type));
return CKR_ATTRIBUTE_VALUE_INVALID;
return CKR_ATTRIBUTE_TYPE_INVALID;
}
}
@@ -432,6 +433,7 @@ CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG
CK_ULONG i;
op_info->op.gen.rsa = is_RSA_mechanism(op_info->mechanism.mechanism);
op_info->op.gen.vendor_defined = 0;
for (i = 0; i < n; i++) {
switch (templ[i].type) {
@@ -472,6 +474,9 @@ CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG
op_info->op.gen.key_id = PIV_PVTK_OBJ_PIV_AUTH + *((CK_BYTE_PTR)templ[i].pValue);
break;
case CKA_VENDOR_DEFINED:
op_info->op.gen.vendor_defined = (*((CK_ULONG_PTR)templ[i].pValue));
case CKA_SENSITIVE:
case CKA_DECRYPT:
case CKA_UNWRAP:
@@ -484,7 +489,7 @@ CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG
default:
DBG(("Invalid attribute %lx in private key template", templ[i].type));
return CKR_ATTRIBUTE_VALUE_INVALID;
return CKR_ATTRIBUTE_TYPE_INVALID;
}
}
+46 -25
View File
@@ -233,6 +233,10 @@ static CK_RV get_curve_parameters(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR
return do_get_curve_parameters(key, data, len);
}
static CK_RV get_raw_cert(X509 *cert, CK_BYTE_PTR data, CK_ULONG_PTR len) {
return do_get_raw_cert(cert, data, len);
}
/* Get data object attribute */
CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
CK_BYTE_PTR data;
@@ -319,31 +323,32 @@ CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
/* Get certificate object attribute */
CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
CK_BYTE_PTR data;
CK_BYTE tmp[64];
CK_BYTE b_tmp[1024];
CK_ULONG ul_tmp;
CK_ULONG len = 0;
DBG(("For certificate object %lu, get ", obj));
switch (template->type) { // TODO: is this needed here? or is it enough ot have one a "level" above?
switch (template->type) {
case CKA_CLASS:
DBG(("CLASS"));
len = 1;
tmp[0] = CKO_CERTIFICATE;
data = tmp;
len = sizeof(CK_ULONG);
ul_tmp = CKO_CERTIFICATE;
data = (CK_BYTE_PTR) &ul_tmp;
break;
case CKA_TOKEN:
// Technically all these objects are token objects
DBG(("TOKEN"));
len = 1;
tmp[0] = piv_objects[obj].token;
data = tmp;
len = sizeof(CK_BBOOL);
b_tmp[0] = piv_objects[obj].token;
data = b_tmp;
break;
case CKA_PRIVATE:
DBG(("PRIVATE"));
len = 1;
tmp[0] = piv_objects[obj].private;
data = tmp;
len = sizeof(CK_BBOOL);
b_tmp[0] = piv_objects[obj].private;
data = b_tmp;
break;
case CKA_LABEL:
@@ -353,14 +358,18 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
break;
case CKA_VALUE:
DBG(("VALUE TODO"));
return CKR_FUNCTION_FAILED;
DBG(("VALUE"));
len = sizeof(b_tmp);
if (get_raw_cert(cert_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK)
return CKR_FUNCTION_FAILED;
data = b_tmp;
break;
case CKA_CERTIFICATE_TYPE:
DBG(("CERTIFICATE TYPE"));
len = 1;
tmp[0] = CKC_X_509; // Support only X.509 certs
data = tmp;
len = sizeof(CK_ULONG);
ul_tmp = CKC_X_509; // Support only X.509 certs
data = (CK_BYTE_PTR) ul_tmp;
break;
case CKA_ISSUER:
@@ -377,9 +386,9 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
case CKA_ID:
DBG(("ID"));
len = 1;
tmp[0] = piv_objects[obj].sub_id;
data = tmp;
len = sizeof(CK_BYTE);
b_tmp[0] = piv_objects[obj].sub_id;
data = b_tmp;
break;
case CKA_START_DATE:
@@ -392,9 +401,9 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
case CKA_MODIFIABLE:
DBG(("MODIFIABLE"));
len = 1;
tmp[0] = piv_objects[obj].modifiable;
data = tmp;
len = sizeof(CK_BBOOL);
b_tmp[0] = piv_objects[obj].modifiable;
data = b_tmp;
break;
default: // TODO: there are other attributes for a (x509) certificate
@@ -666,7 +675,7 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
CK_BYTE_PTR data;
CK_BYTE b_tmp[1024];
CK_ULONG ul_tmp; // TODO: fix elsewhere too
CK_ULONG ul_tmp;
CK_ULONG len = 0;
DBG(("For public key object %lu, get ", obj));
@@ -1054,7 +1063,7 @@ CK_RV check_create_cert(CK_ATTRIBUTE_PTR templ, CK_ULONG n,
}
CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id,
CK_BYTE_PTR *value, CK_ULONG_PTR value_len) {
CK_BYTE_PTR *value, CK_ULONG_PTR value_len, CK_ULONG_PTR vendor_defined) {
CK_ULONG i;
CK_BBOOL has_id = CK_FALSE;
@@ -1064,6 +1073,8 @@ CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id,
CK_BYTE_PTR ec_params;
CK_ULONG ec_params_len;
*vendor_defined = 0;
for (i = 0; i < n; i++) {
switch (templ[i].type) {
case CKA_CLASS:
@@ -1099,6 +1110,10 @@ CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id,
break;
case CKA_VENDOR_DEFINED:
*vendor_defined = *((CK_ULONG_PTR)templ[i].pValue);
break;
case CKA_TOKEN:
case CKA_LABEL:
case CKA_SUBJECT:
@@ -1129,7 +1144,7 @@ CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id,
CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id,
CK_BYTE_PTR *p, CK_BYTE_PTR *q, CK_BYTE_PTR *dp,
CK_BYTE_PTR *dq, CK_BYTE_PTR *qinv, CK_ULONG_PTR value_len) {
CK_BYTE_PTR *dq, CK_BYTE_PTR *qinv, CK_ULONG_PTR value_len, CK_ULONG_PTR vendor_defined) {
CK_ULONG i;
CK_BBOOL has_id = CK_FALSE;
@@ -1145,6 +1160,8 @@ CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id,
CK_ULONG dq_len;
CK_ULONG qinv_len;
*vendor_defined = 0;
for (i = 0; i < n; i++) {
switch (templ[i].type) {
case CKA_CLASS:
@@ -1208,6 +1225,10 @@ CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id,
break;
case CKA_VENDOR_DEFINED:
*vendor_defined = *((CK_ULONG_PTR)templ[i].pValue);
break;
case CKA_TOKEN:
case CKA_LABEL:
case CKA_SUBJECT:
+2 -2
View File
@@ -15,10 +15,10 @@ CK_RV store_cert(piv_obj_id_t cert_id, CK_BYTE_PTR data, CK_ULONG len);
CK_RV check_create_cert(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id,
CK_BYTE_PTR *value, CK_ULONG_PTR cert_len);
CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id,
CK_BYTE_PTR *value, CK_ULONG_PTR value_len);
CK_BYTE_PTR *value, CK_ULONG_PTR value_len, CK_ULONG_PTR vendor_defined);
CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id,
CK_BYTE_PTR *p, CK_BYTE_PTR *q, CK_BYTE_PTR *dp,
CK_BYTE_PTR *dq, CK_BYTE_PTR *qinv, CK_ULONG_PTR value_len);
CK_BYTE_PTR *dq, CK_BYTE_PTR *qinv, CK_ULONG_PTR value_len, CK_ULONG_PTR vendor_defined);
#endif
+20
View File
@@ -236,6 +236,26 @@ CK_RV do_check_cert(CK_BYTE_PTR in, CK_ULONG_PTR cert_len) {
return CKR_OK;
}
CK_RV do_get_raw_cert(X509 *cert, CK_BYTE_PTR out, CK_ULONG_PTR out_len) {
CK_BYTE_PTR p;
int len;
len = i2d_X509(cert, NULL);
if (len < 0)
return CKR_FUNCTION_FAILED;
if ((CK_ULONG)len > *out_len)
return CKR_BUFFER_TOO_SMALL;
p = out;
if ((*out_len = i2d_X509(cert, &p)) == 0)
return CKR_FUNCTION_FAILED;
return CKR_OK;
}
CK_RV free_cert(X509 *cert) {
X509_free((X509 *) cert);
+1
View File
@@ -13,6 +13,7 @@ CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert);
CK_RV do_create_empty_cert(CK_BYTE_PTR in, CK_ULONG in_len, CK_BBOOL is_rsa,
CK_BYTE_PTR out, CK_ULONG_PTR out_len);
CK_RV do_check_cert(CK_BYTE_PTR in, CK_ULONG_PTR cert_len);
CK_RV do_get_raw_cert(X509 *cert, CK_BYTE_PTR out, CK_ULONG_PTR out_len);
CK_RV free_cert(X509 *cert);
CK_RV do_store_pubk(X509 *cert, EVP_PKEY **key);
+7
View File
@@ -1183,4 +1183,11 @@ typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR;
/* undo packing */
//#include "pkcs11u.h" // TODO: msc specific?
// YUBICO specific attributes
#define CKA_TOUCH_PIN_DEFAULT 0x00000000U
#define CKA_TOUCH_ALWAYS 0x00000001U
#define CKA_PIN_ONCE 0x00000002U
#define CKA_PIN_ALWAYS 0x00000004U
#endif
+62 -15
View File
@@ -4,6 +4,9 @@
#include <string.h>
#include "debug.h"
#include <stdbool.h>
#include "../tool/util.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?
@@ -31,9 +34,11 @@ static CK_RV COMMON_token_login(ykpiv_state *state, CK_USER_TYPE user, CK_UTF8CH
return CKR_OK;
}
static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE key, CK_ULONG key_len) {
static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa,
CK_BYTE key, CK_ULONG key_len, CK_ULONG vendor_defined) {
// TODO: make a function in ykpiv for this
unsigned char in_data[5];
unsigned char in_data[11];
unsigned char *in_ptr = in_data;
unsigned char data[1024];
unsigned char templ[] = {0, YKPIV_INS_GENERATE_ASYMMERTRIC, 0, 0};
unsigned char *certptr;
@@ -45,10 +50,10 @@ static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE
templ[3] = key;
in_data[0] = 0xac;
in_data[1] = 3;
in_data[2] = 0x80;
in_data[3] = 1;
*in_ptr++ = 0xac;
*in_ptr++ = 3;
*in_ptr++ = 0x80;
*in_ptr++ = 1;
switch(key_len) {
case 2048:
@@ -61,7 +66,7 @@ static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE
case 1024:
if (rsa == CK_TRUE)
in_data[4] = YKPIV_ALGO_RSA1024;
*in_ptr++ = YKPIV_ALGO_RSA1024;
else
return CKR_FUNCTION_FAILED;
@@ -69,7 +74,7 @@ static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE
case 256:
if (rsa == CK_FALSE)
in_data[4] = YKPIV_ALGO_ECCP256;
*in_ptr++ = YKPIV_ALGO_ECCP256;
else
return CKR_FUNCTION_FAILED;
@@ -78,8 +83,30 @@ static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE
default:
return CKR_FUNCTION_FAILED;
}
//DBG(("Generating key %x with algorithm %u and length %lu", templ[3], in_data[4], key_len));
if(ykpiv_transfer_data(state, templ, in_data, sizeof(in_data), data, &recv_len, &sw) != YKPIV_OK ||
// PIN policy and touch
if (vendor_defined != 0) {
if (vendor_defined & CKA_PIN_ONCE) {
in_data[1] += 3;
*in_ptr++ = YKPIV_PINPOLICY_TAG;
*in_ptr++ = 0x01;
*in_ptr++ = YKPIV_PINPOLICY_ONCE;
}
else if (vendor_defined & CKA_PIN_ALWAYS) {
in_data[1] += 3;
*in_ptr++ = YKPIV_PINPOLICY_TAG;
*in_ptr++ = 0x01;
*in_ptr++ = YKPIV_PINPOLICY_ALWAYS;
}
if (vendor_defined & CKA_TOUCH_ALWAYS) {
in_data[1] += 3;
*in_ptr++ = YKPIV_TOUCHPOLICY_TAG;
*in_ptr++ = 0x01;
*in_ptr++ = YKPIV_TOUCHPOLICY_ALWAYS;
}
}
if(ykpiv_transfer_data(state, templ, in_data, in_ptr - in_data, data, &recv_len, &sw) != YKPIV_OK ||
sw != 0x9000)
return CKR_DEVICE_ERROR;
@@ -151,7 +178,7 @@ static CK_RV COMMON_token_import_cert(ykpiv_state *state, CK_ULONG cert_id, CK_B
CK_RV COMMON_token_import_private_key(ykpiv_state *state, CK_BYTE key_id, CK_BYTE_PTR p, CK_BYTE_PTR q,
CK_BYTE_PTR dp, CK_BYTE_PTR dq, CK_BYTE_PTR qinv,
CK_BYTE_PTR ec_data, CK_ULONG elem_len) {
CK_BYTE_PTR ec_data, CK_ULONG elem_len, CK_ULONG vendor_defined) {
unsigned char key_data[1024];
unsigned char *in_ptr = key_data;
@@ -193,17 +220,37 @@ CK_RV COMMON_token_import_private_key(ykpiv_state *state, CK_BYTE key_id, CK_BYT
memcpy(in_ptr, qinv, (size_t)(elem_len));
in_ptr += elem_len;
}
else if(templ[2] == YKPIV_ALGO_ECCP256) {
else if (templ[2] == YKPIV_ALGO_ECCP256) {
*in_ptr++ = 0x06;
in_ptr += set_length(in_ptr, elem_len);
memcpy(in_ptr, ec_data, (size_t)(elem_len));
in_ptr += elem_len;
}
if(ykpiv_transfer_data(state, templ, key_data, in_ptr - key_data, data, &recv_len, &sw) != YKPIV_OK)
// PIN policy and touch
if (vendor_defined != 0) {
if (vendor_defined & CKA_PIN_ONCE) {
*in_ptr++ = YKPIV_PINPOLICY_TAG;
*in_ptr++ = 0x01;
*in_ptr++ = YKPIV_PINPOLICY_ONCE;
}
else if (vendor_defined & CKA_PIN_ALWAYS) {
*in_ptr++ = YKPIV_PINPOLICY_TAG;
*in_ptr++ = 0x01;
*in_ptr++ = YKPIV_PINPOLICY_ALWAYS;
}
if (vendor_defined & CKA_TOUCH_ALWAYS) {
*in_ptr++ = YKPIV_TOUCHPOLICY_TAG;
*in_ptr++ = 0x01;
*in_ptr++ = YKPIV_TOUCHPOLICY_ALWAYS;
}
}
if (ykpiv_transfer_data(state, templ, key_data, in_ptr - key_data, data, &recv_len, &sw) != YKPIV_OK)
return CKR_FUNCTION_FAILED;
if(sw != 0x9000)
if (sw != 0x9000)
return CKR_DEVICE_ERROR;
return CKR_OK;
@@ -211,7 +258,7 @@ CK_RV COMMON_token_import_private_key(ykpiv_state *state, CK_BYTE key_id, CK_BYT
}
token_vendor_t get_token_vendor(vendor_id_t vid) {
token_vendor_t v;
token_vendor_t v;
switch (vid) {
case YUBICO:
+2 -2
View File
@@ -21,10 +21,10 @@ typedef CK_RV (*get_t_raw_certificate_f)(ykpiv_state *, piv_obj_id_t, CK_BYTE_PT
// 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_generate_key_f)(ykpiv_state *, CK_BBOOL, CK_BYTE, CK_ULONG, 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,
CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_ULONG);
CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_ULONG, CK_ULONG);
// TODO: replace all the common calls with functions defined in .c that use libykpiv
+9 -5
View File
@@ -10,6 +10,9 @@
#include "openssl_types.h"
#include "debug.h"
#include <stdbool.h>
#include "../tool/util.h"
#define YKCS11_MANUFACTURER "Yubico (www.yubico.com)"
#define YKCS11_LIBDESC "PKCS#11 PIV Library (SP-800-73)"
@@ -854,6 +857,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)(
CK_BYTE_PTR dp;
CK_BYTE_PTR dq;
CK_BYTE_PTR qinv;
CK_ULONG vendor_defined;
token_vendor_t token;
CK_BBOOL is_new;
CK_BBOOL is_rsa;
@@ -974,11 +978,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)(
// Try to parse the key as EC
is_rsa = CK_FALSE;
rv = check_create_ec_key(pTemplate, ulCount, &id, &value, &value_len);
rv = check_create_ec_key(pTemplate, ulCount, &id, &value, &value_len, &vendor_defined);
if (rv != CKR_OK) {
// Try to parse the key as RSA
is_rsa = CK_TRUE;
rv = check_create_rsa_key(pTemplate, ulCount, &id, &p, &q, &dp, &dq, &qinv, &value_len);
rv = check_create_rsa_key(pTemplate, ulCount, &id, &p, &q, &dp, &dq, &qinv, &value_len, &vendor_defined);
if (rv != CKR_OK) {
DBG(("Private key template not valid"));
return rv;
@@ -993,7 +997,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)(
DBG(("Key is RSA"));
rv = token.token_import_private_key(piv_state, piv_2_ykpiv(object), p, q, dp, dq, qinv,
NULL,
value_len);
value_len, vendor_defined);
if (rv != CKR_OK) {
DBG(("Unable to import RSA private key"));
return rv;
@@ -1003,7 +1007,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)(
DBG(("Key is ECDSA"));
rv = token.token_import_private_key(piv_state, piv_2_ykpiv(object), NULL, NULL, NULL, NULL, NULL,
value,
value_len);
value_len, vendor_defined);
if (rv != CKR_OK) {
DBG(("Unable to import ECDSA private key"));
return rv;
@@ -2052,7 +2056,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)(
token = get_token_vendor(session.slot->token->vid);
if ((rv = token.token_generate_key(piv_state, op_info.op.gen.rsa, piv_2_ykpiv(op_info.op.gen.key_id), op_info.op.gen.key_len)) != CKR_OK) {
if ((rv = token.token_generate_key(piv_state, op_info.op.gen.rsa, piv_2_ykpiv(op_info.op.gen.key_id), op_info.op.gen.key_len, op_info.op.gen.vendor_defined)) != CKR_OK) {
DBG(("Unable to generate key pair"));
return rv;
}
+5 -5
View File
@@ -6,7 +6,7 @@
#include "openssl_types.h"
#include "vendors.h"
#define YKCS11_OP_BUFSIZE 4096
#define YKCS11_OP_BUFSIZE 4096
typedef struct {
vendor_id_t vid;
@@ -28,7 +28,6 @@ typedef struct {
ykcs11_slot_t *slot;
} ykcs11_session_t;
typedef enum {
YKCS11_NOOP,
YKCS11_GEN,
@@ -38,9 +37,10 @@ typedef enum {
} ykcs11_op_type_t;
typedef struct {
CK_BBOOL rsa; // RSA or EC key
CK_BYTE key_id; // Key id
CK_ULONG key_len; // Length in bits
CK_BBOOL rsa; // RSA or EC key
CK_BYTE key_id; // Key id
CK_ULONG key_len; // Length in bits
CK_ULONG vendor_defined; // Additional parameters (touch and PIN policy)
} gen_info_t;
typedef struct {
+1
View File
@@ -2,6 +2,7 @@
#include "pkcs11.h"
#include <string.h>
#include "debug.h"
#include "objects.h"
#define YUBICO_MECHANISMS_NUM 5