diff options
author | NIIBE Yutaka <[email protected]> | 2023-03-16 05:59:14 +0000 |
---|---|---|
committer | NIIBE Yutaka <[email protected]> | 2023-03-16 05:59:14 +0000 |
commit | a53441c8dd2e234dfcbaf4f0f073885b1a94940c (patch) | |
tree | 7492f3311265fb8ea6e1c29abda43e0fad2583aa | |
parent | tkd: Check CKF_TOKEN_PRESENT, too. (diff) | |
download | gnupg-a53441c8dd2e234dfcbaf4f0f073885b1a94940c.tar.gz gnupg-a53441c8dd2e234dfcbaf4f0f073885b1a94940c.zip |
tkd: Fix for rescanning the slot list.
Signed-off-by: NIIBE Yutaka <[email protected]>
-rw-r--r-- | tkd/command.c | 2 | ||||
-rw-r--r-- | tkd/pkcs11.c | 243 | ||||
-rw-r--r-- | tkd/tkdaemon.h | 2 |
3 files changed, 169 insertions, 78 deletions
diff --git a/tkd/command.c b/tkd/command.c index b640eb7f7..451e0a2fb 100644 --- a/tkd/command.c +++ b/tkd/command.c @@ -248,7 +248,7 @@ cmd_slotlist (assuan_context_t ctx, char *line) line = skip_options (line); (void)line; - err = token_init (ctrl, ctx); + err = token_init (ctrl, ctx, 1); return err; } diff --git a/tkd/pkcs11.c b/tkd/pkcs11.c index 42a90b7e9..f08e02f57 100644 --- a/tkd/pkcs11.c +++ b/tkd/pkcs11.c @@ -98,43 +98,29 @@ static struct cryptoki ck_instance[1]; static long -get_function_list (struct cryptoki *ck, const char *libname) +get_function_list (struct cryptoki *ck) { - unsigned long err = 0; + unsigned long r = 0; unsigned long (*p_func) (struct ck_function_list **); - if (ck->handle == NULL) - { - void *handle; - - handle = dlopen (libname, RTLD_NOW); - if (handle == NULL) - { - return -1; - } - - ck->handle = handle; - } - p_func = (CK_C_GetFunctionList)dlsym (ck->handle, "C_GetFunctionList"); if (p_func == NULL) { return -1; } - err = p_func (&ck->f); + r = p_func (&ck->f); - if (err || ck->f == NULL) + if (r || ck->f == NULL) { return -1; } - err = ck->f->C_Initialize (NULL); - if (err) + r = ck->f->C_Initialize (NULL); + if (r) { return -1; } - /* For now, we never call dlclose to unload the LIBNAME */ return 0; } @@ -239,6 +225,9 @@ close_session (struct token *token) return -1; } + token->session = 0; + token->num_keys = 0; + return 0; } @@ -983,95 +972,169 @@ do_pksign (struct key *key, int hash_algo, return err; } +gpg_error_t +token_new (assuan_context_t ctx, struct cryptoki *ck, struct token *token, + ck_slot_id_t slot_id) +{ + gpg_error_t err = 0; + struct ck_token_info tk_info; + long r; + + token->ck = ck; + token->valid = 0; + token->slot_id = slot_id; + + if (get_token_info (token, &tk_info)) + return gpg_error (GPG_ERR_INV_RESPONSE); + + if ((tk_info.flags & CKF_TOKEN_INITIALIZED) == 0 + || (tk_info.flags & CKF_TOKEN_PRESENT) == 0 + || (tk_info.flags & CKF_USER_PIN_LOCKED) != 0) + return gpg_error (GPG_ERR_CARD_NOT_PRESENT); + + token->login_required = (tk_info.flags & CKF_LOGIN_REQUIRED); + + r = open_session (token); + if (r) + { + log_error ("Error at open_session: %ld\n", r); + return gpg_error (GPG_ERR_INV_RESPONSE); + } + + if (token->login_required) + { + char *command; + int rc; + unsigned char *value; + size_t valuelen; + + log_debug ("asking for PIN '%ld'\n", token->slot_id); + + rc = gpgrt_asprintf (&command, "NEEDPIN %ld", token->slot_id); + if (rc < 0) + return gpg_error (gpg_err_code_from_errno (errno)); + + assuan_begin_confidential (ctx); + err = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN); + assuan_end_confidential (ctx); + xfree (command); + if (err) + { + close_session (token); + return err; + } + + login (token, value, valuelen); + xfree (value); + } + + r = learn_keys (token); + return 0; +} + gpg_error_t -token_init (ctrl_t ctrl, assuan_context_t ctx) +token_init (ctrl_t ctrl, assuan_context_t ctx, int rescan) { gpg_error_t err = 0; long r; struct cryptoki *ck = ck_instance; unsigned long num_slots = MAX_SLOTS; - ck_slot_id_t slot_list[MAX_SLOTS]; + ck_slot_id_t slot_list[MAX_SLOTS]; int i; - int num_tokens = 0; const char *module_name; - (void)ctrl; - (void)ctx; module_name = opt.pkcs11_driver; if (!module_name) return gpg_error (GPG_ERR_NO_NAME); - r = get_function_list (ck, module_name); - if (r) + if (ck->handle == NULL) { - return gpg_error (GPG_ERR_INV_RESPONSE); + void *handle; + int num_tokens = 0; + + handle = dlopen (module_name, RTLD_NOW); + if (handle == NULL) + { + return -1; + } + + ck->handle = handle; + + r = get_function_list (ck); + if (r) + { + dlclose (ck->handle); + ck->handle = NULL; + return gpg_error (GPG_ERR_INV_RESPONSE); + } + + r = get_slot_list (ck, &num_slots, slot_list); + if (r) + { + dlclose (ck->handle); + ck->handle = NULL; + return gpg_error (GPG_ERR_INV_RESPONSE); + } + + for (i = 0; i < num_slots; i++) + { + struct token *token = &ck->token_list[num_tokens]; /* Allocate one token in CK */ + + err = token_new (ctx, ck, token, slot_list[i]); + if (!err) + num_tokens++; + } + + ck->num_slots = num_tokens; + return 0; } + else if (rescan == 0) + return 0; + + /* Rescan the slots to see the changes. */ r = get_slot_list (ck, &num_slots, slot_list); if (r) { + token_fini (ctrl, ctx); return gpg_error (GPG_ERR_INV_RESPONSE); } for (i = 0; i < num_slots; i++) { - struct ck_token_info tk_info; - struct token *token = &ck->token_list[num_tokens]; /* Allocate one token in CK */ + ck_slot_id_t slot_id = slot_list[i]; + int j; + int found = 0; - token->ck = ck; - token->valid = 0; - token->slot_id = slot_list[i]; - - if (get_token_info (token, &tk_info) == 0) + for (j = 0; j < ck->num_slots; j++) { - if ((tk_info.flags & CKF_TOKEN_INITIALIZED) == 0 - || (tk_info.flags & CKF_TOKEN_PRESENT) == 0 - || (tk_info.flags & CKF_USER_PIN_LOCKED) != 0) - continue; + struct token *token = &ck->token_list[j]; - token->login_required = (tk_info.flags & CKF_LOGIN_REQUIRED); - - r = open_session (token); - if (r) + if (slot_id == token->slot_id) { - log_error ("Error at open_session: %ld\n", r); - continue; - } - - if (token->login_required) - { - char *command; - int rc; - unsigned char *value; - size_t valuelen; - - log_debug ("asking for PIN '%ld'\n", token->slot_id); - - rc = gpgrt_asprintf (&command, "NEEDPIN %ld", token->slot_id); - if (rc < 0) - return gpg_error (gpg_err_code_from_errno (errno)); - - assuan_begin_confidential (ctx); - err = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN); - assuan_end_confidential (ctx); - xfree (command); - if (err) - return err; - - login (token, value, valuelen); - xfree (value); + found = 1; + break; } + } - num_tokens++; - r = learn_keys (token); + if (found) + { + /*XXX: rescan the keys??? */ + } + else + /* new token */ + { + /* Allocate one token in CK */ + struct token *token = &ck->token_list[ck->num_slots]; + err = token_new (ctx, ck, token, slot_id); + if (!err) + ck->num_slots++; } } - ck->num_slots = num_tokens; - return err; } @@ -1081,6 +1144,7 @@ token_fini (ctrl_t ctrl, assuan_context_t ctx) long r; struct cryptoki *ck = ck_instance; int i; + int j; (void)ctrl; (void)ctx; @@ -1090,16 +1154,41 @@ token_fini (ctrl_t ctrl, assuan_context_t ctx) struct token *token = &ck->token_list[i]; if (!token->valid) - continue; + { + token->ck = NULL; + token->slot_id = 0; + token->login_required = 0; + continue; + } if (token->login_required) logout (token); r = close_session (token); if (r) + log_error ("Error at close_session: %ld\n", r); + + token->ck = NULL; + token->slot_id = 0; + token->login_required = 0; + + for (j = 0; j < token->num_keys; j++) { - log_error ("Error at close_session: %ld\n", r); - continue; + struct key *k = &token->key_list[i]; + + if ((k->flags & KEY_FLAG_VALID)) + { + gcry_sexp_release (k->pubkey); + k->pubkey = NULL; + } + + k->token = NULL; + k->flags = 0; + k->key_type = 0; + k->label_len = 0; + k->id_len = 0; + k->p11_keyid = 0; + k->mechanism = 0; } token->valid = 0; @@ -1113,6 +1202,8 @@ token_fini (ctrl_t ctrl, assuan_context_t ctx) return -1; } + ck->f = NULL; + dlclose (ck->handle); ck->handle = NULL; diff --git a/tkd/tkdaemon.h b/tkd/tkdaemon.h index dd1b243f1..e00755bf0 100644 --- a/tkd/tkdaemon.h +++ b/tkd/tkdaemon.h @@ -110,7 +110,7 @@ void send_keyinfo (ctrl_t ctrl, int data, const char *keygrip_str, const char *usage); /*-- pkcs11.c --*/ -gpg_error_t token_init (ctrl_t ctrl, assuan_context_t ctx); +gpg_error_t token_init (ctrl_t ctrl, assuan_context_t ctx, int rescan); gpg_error_t token_fini (ctrl_t ctrl, assuan_context_t ctx); gpg_error_t token_sign (ctrl_t ctrl, assuan_context_t ctx, |