Implemented handling of CKA_ALWAYS_AUTHENTICATE attribute when importing and generating keys, mapping it to pkcs#15 userConsent field. Added command line options to pkcs11-tool and pkcs15-init tool to use the feature.

This commit is contained in:
Hannu Honkanen 2018-11-26 17:02:59 +02:00 committed by Frank Morgner
parent b01ca2dcc9
commit ee8c80af4f
5 changed files with 58 additions and 3 deletions

View File

@ -2153,6 +2153,9 @@ pkcs15_create_private_key(struct sc_pkcs11_slot *slot, struct sc_profile *profil
case CKA_OPENSC_NON_REPUDIATION: case CKA_OPENSC_NON_REPUDIATION:
args.usage |= pkcs15_check_bool_cka(attr, SC_PKCS15_PRKEY_USAGE_NONREPUDIATION); args.usage |= pkcs15_check_bool_cka(attr, SC_PKCS15_PRKEY_USAGE_NONREPUDIATION);
break; break;
case CKA_ALWAYS_AUTHENTICATE:
args.user_consent = (int) (pkcs15_check_bool_cka(attr, 1));
break;
default: default:
/* ignore unknown attrs, or flag error? */ /* ignore unknown attrs, or flag error? */
continue; continue;
@ -2318,7 +2321,10 @@ pkcs15_create_secret_key(struct sc_pkcs11_slot *slot, struct sc_profile *profile
break; break;
case CKA_EXTRACTABLE: case CKA_EXTRACTABLE:
if (pkcs15_check_bool_cka(attr, 1)) if (pkcs15_check_bool_cka(attr, 1))
args.access_flags |= SC_PKCS15_PRKEY_ACCESS_EXTRACTABLE; args.access_flags |= SC_PKCS15_PRKEY_ACCESS_EXTRACTABLE;
break;
case CKA_ALWAYS_AUTHENTICATE:
args.user_consent = (int) (pkcs15_check_bool_cka(attr, 1));
break; break;
default: default:
/* ignore unknown attrs, or flag error? */ /* ignore unknown attrs, or flag error? */
@ -2931,6 +2937,7 @@ pkcs15_gen_keypair(struct sc_pkcs11_slot *slot, CK_MECHANISM_PTR pMechanism,
char priv_label[SC_PKCS15_MAX_LABEL_SIZE]; char priv_label[SC_PKCS15_MAX_LABEL_SIZE];
int rc; int rc;
CK_RV rv = CKR_OK; CK_RV rv = CKR_OK;
CK_BBOOL always_auth = CK_FALSE;
sc_log(context, "Keypair generation, mech = 0x%0lx", sc_log(context, "Keypair generation, mech = 0x%0lx",
pMechanism->mechanism); pMechanism->mechanism);
@ -3046,6 +3053,12 @@ pkcs15_gen_keypair(struct sc_pkcs11_slot *slot, CK_MECHANISM_PTR pMechanism,
goto kpgen_done; goto kpgen_done;
pub_args.x509_usage = keygen_args.prkey_args.x509_usage; pub_args.x509_usage = keygen_args.prkey_args.x509_usage;
len = sizeof(always_auth);
rv = attr_find(pPrivTpl, ulPrivCnt, CKA_ALWAYS_AUTHENTICATE, &always_auth, &len);
if (rv == CKR_OK && always_auth == CK_TRUE) {
keygen_args.prkey_args.user_consent = 1;
}
/* 3.a Try on-card key pair generation */ /* 3.a Try on-card key pair generation */
sc_pkcs15init_set_p15card(profile, fw_data->p15_card); sc_pkcs15init_set_p15card(profile, fw_data->p15_card);
@ -4832,6 +4845,10 @@ pkcs15_skey_get_attribute(struct sc_pkcs11_session *session,
&& (skey->base.p15_object->flags & SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE) == 0 && (skey->base.p15_object->flags & SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE) == 0
&& (skey->base.p15_object->flags & SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE) == 0) ? CK_TRUE : CK_FALSE; && (skey->base.p15_object->flags & SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE) == 0) ? CK_TRUE : CK_FALSE;
break; break;
case CKA_ALWAYS_AUTHENTICATE:
check_attribute_buffer(attr, sizeof(CK_BBOOL));
*(CK_BBOOL*)attr->pValue = skey->base.p15_object->user_consent;
break;
case CKA_VALUE_LEN: case CKA_VALUE_LEN:
check_attribute_buffer(attr, sizeof(CK_ULONG)); check_attribute_buffer(attr, sizeof(CK_ULONG));
*(CK_ULONG*)attr->pValue = skey->info->data.len; *(CK_ULONG*)attr->pValue = skey->info->data.len;

View File

@ -228,6 +228,7 @@ struct sc_pkcs15init_prkeyargs {
unsigned long x509_usage; unsigned long x509_usage;
unsigned int flags; unsigned int flags;
unsigned int access_flags; unsigned int access_flags;
int user_consent;
union { union {
struct sc_pkcs15init_keyarg_gost_params gost; struct sc_pkcs15init_keyarg_gost_params gost;
@ -269,13 +270,14 @@ struct sc_pkcs15init_skeyargs {
struct sc_pkcs15_id id; struct sc_pkcs15_id id;
struct sc_pkcs15_id auth_id; struct sc_pkcs15_id auth_id;
const char * label; const char * label;
unsigned long usage; unsigned long usage;
unsigned int flags; unsigned int flags;
unsigned int access_flags; unsigned int access_flags;
unsigned long algorithm; /* User requested algorithm */ unsigned long algorithm; /* User requested algorithm */
unsigned long value_len; /* User requested length */ unsigned long value_len; /* User requested length */
int session_object; /* If nonzero. this is a session object, which will int session_object; /* If nonzero. this is a session object, which will
be cleared from card when the session is closed.*/ be cleared from card when the session is closed.*/
int user_consent;
struct sc_pkcs15_skey key; struct sc_pkcs15_skey key;
}; };

View File

@ -1211,6 +1211,7 @@ sc_pkcs15init_init_prkdf(struct sc_pkcs15_card *p15card, struct sc_profile *prof
key_info->key_reference = 0; key_info->key_reference = 0;
key_info->modulus_length = keybits; key_info->modulus_length = keybits;
key_info->access_flags = keyargs->access_flags; key_info->access_flags = keyargs->access_flags;
object->user_consent = keyargs->user_consent;
/* Path is selected below */ /* Path is selected below */
if (keyargs->access_flags & SC_PKCS15_PRKEY_ACCESS_EXTRACTABLE) { if (keyargs->access_flags & SC_PKCS15_PRKEY_ACCESS_EXTRACTABLE) {
@ -1352,6 +1353,8 @@ sc_pkcs15init_init_skdf(struct sc_pkcs15_card *p15card, struct sc_profile *profi
if (keyargs->session_object > 0) if (keyargs->session_object > 0)
object->session_object = 1; object->session_object = 1;
object->user_consent = keyargs->user_consent;
/* Select a Key ID if the user didn't specify one, /* Select a Key ID if the user didn't specify one,
* otherwise make sure it's compatible with our intended use */ * otherwise make sure it's compatible with our intended use */
r = select_id(p15card, SC_PKCS15_TYPE_SKEY, &keyargs->id); r = select_id(p15card, SC_PKCS15_TYPE_SKEY, &keyargs->id);

View File

@ -152,6 +152,7 @@ enum {
OPT_SALT, OPT_SALT,
OPT_VERIFY, OPT_VERIFY,
OPT_SIGNATURE_FILE, OPT_SIGNATURE_FILE,
OPT_ALWAYS_AUTH
}; };
static const struct option options[] = { static const struct option options[] = {
@ -221,6 +222,7 @@ static const struct option options[] = {
{ "test-fork", 0, NULL, OPT_TEST_FORK }, { "test-fork", 0, NULL, OPT_TEST_FORK },
#endif #endif
{ "generate-random", 1, NULL, OPT_GENERATE_RANDOM }, { "generate-random", 1, NULL, OPT_GENERATE_RANDOM },
{ "always-auth", 0, NULL, OPT_ALWAYS_AUTH },
{ NULL, 0, NULL, 0 } { NULL, 0, NULL, 0 }
}; };
@ -292,6 +294,7 @@ static const char *option_help[] = {
"Test forking and calling C_Initialize() in the child", "Test forking and calling C_Initialize() in the child",
#endif #endif
"Generate given amount of random data", "Generate given amount of random data",
"Set the CKA_ALWAYS_AUTHENTICATE attribute to a key object (require PIN verification for each use)",
}; };
static const char * app_name = "pkcs11-tool"; /* for utils.c */ static const char * app_name = "pkcs11-tool"; /* for utils.c */
@ -340,6 +343,7 @@ static CK_MECHANISM_TYPE opt_hash_alg = 0;
static unsigned long opt_mgf = 0; static unsigned long opt_mgf = 0;
static long opt_salt_len = 0; static long opt_salt_len = 0;
static int opt_salt_len_given = 0; /* 0 - not given, 1 - given with input parameters */ static int opt_salt_len_given = 0; /* 0 - not given, 1 - given with input parameters */
static int opt_always_auth = 0;
static void *module = NULL; static void *module = NULL;
static CK_FUNCTION_LIST_PTR p11 = NULL; static CK_FUNCTION_LIST_PTR p11 = NULL;
@ -886,7 +890,9 @@ int main(int argc, char * argv[])
do_generate_random = 1; do_generate_random = 1;
action_count++; action_count++;
break; break;
case OPT_ALWAYS_AUTH:
opt_always_auth = 1;
break;
default: default:
util_print_usage_and_die(app_name, options, option_help, NULL); util_print_usage_and_die(app_name, options, option_help, NULL);
} }
@ -2380,6 +2386,12 @@ static int gen_keypair(CK_SLOT_ID slot, CK_SESSION_HANDLE session,
n_pubkey_attr++; n_pubkey_attr++;
} }
if (opt_always_auth != 0) {
FILL_ATTR(privateKeyTemplate[n_privkey_attr], CKA_ALWAYS_AUTHENTICATE,
&_true, sizeof(_true));
n_privkey_attr++;
}
rv = p11->C_GenerateKeyPair(session, &mechanism, rv = p11->C_GenerateKeyPair(session, &mechanism,
publicKeyTemplate, n_pubkey_attr, publicKeyTemplate, n_pubkey_attr,
privateKeyTemplate, n_privkey_attr, privateKeyTemplate, n_privkey_attr,
@ -2499,6 +2511,12 @@ gen_key(CK_SLOT_ID slot, CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *hSecretKey
FILL_ATTR(keyTemplate[n_attr], CKA_VALUE_LEN, &key_length, sizeof(key_length)); FILL_ATTR(keyTemplate[n_attr], CKA_VALUE_LEN, &key_length, sizeof(key_length));
n_attr++; n_attr++;
if (opt_always_auth != 0) {
FILL_ATTR(keyTemplate[n_attr], CKA_ALWAYS_AUTHENTICATE,
&_true, sizeof(_true));
n_attr++;
}
mechanism.mechanism = opt_mechanism; mechanism.mechanism = opt_mechanism;
} }
@ -2969,6 +2987,11 @@ static int write_object(CK_SESSION_HANDLE session)
FILL_ATTR(privkey_templ[n_privkey_attr], CKA_DERIVE, &_true, sizeof(_true)); FILL_ATTR(privkey_templ[n_privkey_attr], CKA_DERIVE, &_true, sizeof(_true));
n_privkey_attr++; n_privkey_attr++;
} }
if (opt_always_auth != 0) {
FILL_ATTR(privkey_templ[n_privkey_attr], CKA_ALWAYS_AUTHENTICATE,
&_true, sizeof(_true));
n_privkey_attr++;
}
#ifdef ENABLE_OPENSSL #ifdef ENABLE_OPENSSL
if (cert.subject_len != 0) { if (cert.subject_len != 0) {

View File

@ -147,6 +147,7 @@ enum {
OPT_UPDATE_EXISTING, OPT_UPDATE_EXISTING,
OPT_MD_CONTAINER_GUID, OPT_MD_CONTAINER_GUID,
OPT_VERSION, OPT_VERSION,
OPT_USER_CONSENT,
OPT_PIN1 = 0x10000, /* don't touch these values */ OPT_PIN1 = 0x10000, /* don't touch these values */
OPT_PUK1 = 0x10001, OPT_PUK1 = 0x10001,
@ -218,6 +219,7 @@ const struct option options[] = {
{ "wait", no_argument, NULL, 'w' }, { "wait", no_argument, NULL, 'w' },
{ "help", no_argument, NULL, 'h' }, { "help", no_argument, NULL, 'h' },
{ "verbose", no_argument, NULL, 'v' }, { "verbose", no_argument, NULL, 'v' },
{ "user-consent", required_argument, NULL, OPT_USER_CONSENT},
/* Hidden options for testing */ /* Hidden options for testing */
{ "assert-pristine", no_argument, NULL, OPT_ASSERT_PRISTINE }, { "assert-pristine", no_argument, NULL, OPT_ASSERT_PRISTINE },
@ -283,6 +285,7 @@ static const char * option_help[] = {
"Wait for card insertion", "Wait for card insertion",
"Display this message", "Display this message",
"Verbose operation. Use several times to enable debug output.", "Verbose operation. Use several times to enable debug output.",
"Set userConsent. Default = 0",
NULL, NULL,
NULL, NULL,
@ -394,6 +397,7 @@ static unsigned int opt_secret_count;
static int opt_ignore_ca_certs = 0; static int opt_ignore_ca_certs = 0;
static int opt_update_existing = 0; static int opt_update_existing = 0;
static int verbose = 0; static int verbose = 0;
static int opt_user_consent = 0;
static struct sc_pkcs15init_callbacks callbacks = { static struct sc_pkcs15init_callbacks callbacks = {
get_pin_callback, /* get_pin() */ get_pin_callback, /* get_pin() */
@ -1814,6 +1818,7 @@ static int init_prkeyargs(struct sc_pkcs15init_prkeyargs *args)
args->guid = (unsigned char *)opt_md_container_guid; args->guid = (unsigned char *)opt_md_container_guid;
args->guid_len = strlen(opt_md_container_guid); args->guid_len = strlen(opt_md_container_guid);
} }
args->user_consent = opt_user_consent;
return 0; return 0;
} }
@ -1842,6 +1847,7 @@ static int init_skeyargs(struct sc_pkcs15init_skeyargs *args)
if ((opt_x509_usage & SC_PKCS15INIT_X509_KEY_ENCIPHERMENT) == SC_PKCS15INIT_X509_KEY_ENCIPHERMENT) { if ((opt_x509_usage & SC_PKCS15INIT_X509_KEY_ENCIPHERMENT) == SC_PKCS15INIT_X509_KEY_ENCIPHERMENT) {
args->usage |= SC_PKCS15_PRKEY_USAGE_WRAP | SC_PKCS15_PRKEY_USAGE_UNWRAP; args->usage |= SC_PKCS15_PRKEY_USAGE_WRAP | SC_PKCS15_PRKEY_USAGE_UNWRAP;
} }
args->user_consent = opt_user_consent;
return 0; return 0;
} }
@ -2848,6 +2854,10 @@ handle_option(const struct option *opt)
case OPT_VERSION: case OPT_VERSION:
this_action = ACTION_PRINT_VERSION; this_action = ACTION_PRINT_VERSION;
break; break;
case OPT_USER_CONSENT:
if (optarg != NULL)
opt_user_consent = atoi(optarg);
break;
default: default:
util_print_usage_and_die(app_name, options, option_help, NULL); util_print_usage_and_die(app_name, options, option_help, NULL);
} }