diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index 44d352b5..d096a380 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -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; diff --git a/src/pkcs15init/pkcs15-init.h b/src/pkcs15init/pkcs15-init.h index 08beaac1..e01ec996 100644 --- a/src/pkcs15init/pkcs15-init.h +++ b/src/pkcs15init/pkcs15-init.h @@ -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; }; diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c index 0ee162a3..f47bb4c3 100644 --- a/src/pkcs15init/pkcs15-lib.c +++ b/src/pkcs15init/pkcs15-lib.c @@ -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); diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index ff1c00ac..3e8b3c2d 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -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) { diff --git a/src/tools/pkcs15-init.c b/src/tools/pkcs15-init.c index b527f684..296e8cfe 100644 --- a/src/tools/pkcs15-init.c +++ b/src/tools/pkcs15-init.c @@ -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); }