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:
args.usage |= pkcs15_check_bool_cka(attr, SC_PKCS15_PRKEY_USAGE_NONREPUDIATION);
break;
case CKA_ALWAYS_AUTHENTICATE:
args.user_consent = (int) (pkcs15_check_bool_cka(attr, 1));
break;
default:
/* ignore unknown attrs, or flag error? */
continue;
@ -2318,7 +2321,10 @@ pkcs15_create_secret_key(struct sc_pkcs11_slot *slot, struct sc_profile *profile
break;
case CKA_EXTRACTABLE:
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;
default:
/* 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];
int rc;
CK_RV rv = CKR_OK;
CK_BBOOL always_auth = CK_FALSE;
sc_log(context, "Keypair generation, mech = 0x%0lx",
pMechanism->mechanism);
@ -3046,6 +3053,12 @@ pkcs15_gen_keypair(struct sc_pkcs11_slot *slot, CK_MECHANISM_PTR pMechanism,
goto kpgen_done;
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 */
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_ALWAYSSENSITIVE) == 0) ? CK_TRUE : CK_FALSE;
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:
check_attribute_buffer(attr, sizeof(CK_ULONG));
*(CK_ULONG*)attr->pValue = skey->info->data.len;

View File

@ -228,6 +228,7 @@ struct sc_pkcs15init_prkeyargs {
unsigned long x509_usage;
unsigned int flags;
unsigned int access_flags;
int user_consent;
union {
struct sc_pkcs15init_keyarg_gost_params gost;
@ -269,13 +270,14 @@ struct sc_pkcs15init_skeyargs {
struct sc_pkcs15_id id;
struct sc_pkcs15_id auth_id;
const char * label;
unsigned long usage;
unsigned long usage;
unsigned int flags;
unsigned int access_flags;
unsigned long algorithm; /* User requested algorithm */
unsigned long value_len; /* User requested length */
int session_object; /* If nonzero. this is a session object, which will
be cleared from card when the session is closed.*/
int user_consent;
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->modulus_length = keybits;
key_info->access_flags = keyargs->access_flags;
object->user_consent = keyargs->user_consent;
/* Path is selected below */
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)
object->session_object = 1;
object->user_consent = keyargs->user_consent;
/* Select a Key ID if the user didn't specify one,
* otherwise make sure it's compatible with our intended use */
r = select_id(p15card, SC_PKCS15_TYPE_SKEY, &keyargs->id);

View File

@ -152,6 +152,7 @@ enum {
OPT_SALT,
OPT_VERIFY,
OPT_SIGNATURE_FILE,
OPT_ALWAYS_AUTH
};
static const struct option options[] = {
@ -221,6 +222,7 @@ static const struct option options[] = {
{ "test-fork", 0, NULL, OPT_TEST_FORK },
#endif
{ "generate-random", 1, NULL, OPT_GENERATE_RANDOM },
{ "always-auth", 0, NULL, OPT_ALWAYS_AUTH },
{ NULL, 0, NULL, 0 }
};
@ -292,6 +294,7 @@ static const char *option_help[] = {
"Test forking and calling C_Initialize() in the child",
#endif
"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 */
@ -340,6 +343,7 @@ static CK_MECHANISM_TYPE opt_hash_alg = 0;
static unsigned long opt_mgf = 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_always_auth = 0;
static void *module = NULL;
static CK_FUNCTION_LIST_PTR p11 = NULL;
@ -886,7 +890,9 @@ int main(int argc, char * argv[])
do_generate_random = 1;
action_count++;
break;
case OPT_ALWAYS_AUTH:
opt_always_auth = 1;
break;
default:
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++;
}
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,
publicKeyTemplate, n_pubkey_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));
n_attr++;
if (opt_always_auth != 0) {
FILL_ATTR(keyTemplate[n_attr], CKA_ALWAYS_AUTHENTICATE,
&_true, sizeof(_true));
n_attr++;
}
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));
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
if (cert.subject_len != 0) {

View File

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