aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNIIBE Yutaka <[email protected]>2023-03-17 02:37:11 +0000
committerNIIBE Yutaka <[email protected]>2023-03-17 02:37:11 +0000
commit22be07a08c55f9d25434bb9c503eec39ede995e5 (patch)
tree5ea6c5ef09e84fb01afc2913f557350aca98decd
parenttkd: Fix for rescanning the slot list. (diff)
downloadgnupg-22be07a08c55f9d25434bb9c503eec39ede995e5.tar.gz
gnupg-22be07a08c55f9d25434bb9c503eec39ede995e5.zip
tkd: sorted out entities and initialize PKCS#11 on demand.
tkd: host side process which manages KEYs on TOKENs It's a KEYGRIP which identifies a KEY. it's TKD which administrates: where is a KEY on which TOKEN. cryptoki (ck): access object of PKCS#11 API. CRYPTOKI has slots. token: abstraction of a device. Each slots has slot_id. Slot_id corresponds a TOKEN. 1:1 map between slot_id and TOKEN. KEY: TOKEN may have multiple KEYs. Signed-off-by: NIIBE Yutaka <[email protected]>
-rw-r--r--tkd/command.c10
-rw-r--r--tkd/pkcs11.c192
-rw-r--r--tkd/tkdaemon.h22
3 files changed, 135 insertions, 89 deletions
diff --git a/tkd/command.c b/tkd/command.c
index 451e0a2fb..1f38d18d8 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, 1);
+ err = tkd_init (ctrl, ctx, 1);
return err;
}
@@ -268,7 +268,7 @@ cmd_readkey (assuan_context_t ctx, char *line)
if (strlen (keygrip) != 40)
err = gpg_error (GPG_ERR_INV_ID);
- err = token_readkey (ctrl, ctx, keygrip);
+ err = tkd_readkey (ctrl, ctx, keygrip);
return err;
}
@@ -305,10 +305,10 @@ cmd_pksign (assuan_context_t ctx, char *line)
if (strlen (keygrip) != 40)
err = gpg_error (GPG_ERR_INV_ID);
- err = token_sign (ctrl, ctx, keygrip, hash_algo, &outdata, &outdatalen);
+ err = tkd_sign (ctrl, ctx, keygrip, hash_algo, &outdata, &outdatalen);
if (err)
{
- log_error ("token_sign failed: %s\n", gpg_strerror (err));
+ log_error ("tkd_sign failed: %s\n", gpg_strerror (err));
}
else
{
@@ -385,7 +385,7 @@ cmd_keyinfo (assuan_context_t ctx, char *line)
else
keygrip = skip_options (line);
- err = token_keyinfo (ctrl, keygrip, opt_data, cap);
+ err = tkd_keyinfo (ctrl, ctx, keygrip, opt_data, cap);
return err;
}
diff --git a/tkd/pkcs11.c b/tkd/pkcs11.c
index f08e02f57..da147ae5a 100644
--- a/tkd/pkcs11.c
+++ b/tkd/pkcs11.c
@@ -146,8 +146,7 @@ get_slot_list (struct cryptoki *ck,
}
static long
-get_token_info (struct token *token,
- struct ck_token_info *tk_info)
+get_token_info (struct token *token, struct ck_token_info *tk_info)
{
unsigned long err = 0;
struct cryptoki *ck = token->ck;
@@ -225,9 +224,6 @@ close_session (struct token *token)
return -1;
}
- token->session = 0;
- token->num_keys = 0;
-
return 0;
}
@@ -972,9 +968,9 @@ 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)
+static gpg_error_t
+token_open (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;
@@ -1021,6 +1017,7 @@ token_new (assuan_context_t ctx, struct cryptoki *ck, struct token *token,
if (err)
{
close_session (token);
+ token->session = 0;
return err;
}
@@ -1032,9 +1029,79 @@ token_new (assuan_context_t ctx, struct cryptoki *ck, struct token *token,
return 0;
}
+static gpg_error_t
+token_close (struct token *token)
+{
+ int j;
+ long r;
+ int num_keys = token->num_keys;
+
+ if (!token->valid)
+ return 0;
+
+ 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;
+ token->session = 0;
+ token->num_keys = 0;
+
+ for (j = 0; j < num_keys; j++)
+ {
+ struct key *k = &token->key_list[j];
+
+ 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;
+ return 0;
+}
+
+
+static gpg_error_t
+token_check (struct token *token)
+{
+ struct ck_token_info tk_info;
+
+ if (get_token_info (token, &tk_info))
+ {
+ /* Possibly, invalidate the token and close session.
+ * Now, ingore the error. */
+ 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)
+ {
+ token_close (token);
+ return gpg_error (GPG_ERR_CARD_NOT_PRESENT);
+ }
+
+ return 0;
+}
+
gpg_error_t
-token_init (ctrl_t ctrl, assuan_context_t ctx, int rescan)
+tkd_init (ctrl_t ctrl, assuan_context_t ctx, int rescan)
{
gpg_error_t err = 0;
@@ -1083,7 +1150,7 @@ token_init (ctrl_t ctrl, assuan_context_t ctx, int rescan)
{
struct token *token = &ck->token_list[num_tokens]; /* Allocate one token in CK */
- err = token_new (ctx, ck, token, slot_list[i]);
+ err = token_open (ctx, ck, token, slot_list[i]);
if (!err)
num_tokens++;
}
@@ -1099,37 +1166,33 @@ token_init (ctrl_t ctrl, assuan_context_t ctx, int rescan)
r = get_slot_list (ck, &num_slots, slot_list);
if (r)
{
- token_fini (ctrl, ctx);
+ tkd_fini (ctrl, ctx);
return gpg_error (GPG_ERR_INV_RESPONSE);
}
for (i = 0; i < num_slots; i++)
{
- ck_slot_id_t slot_id = slot_list[i];
int j;
- int found = 0;
+ ck_slot_id_t slot_id = slot_list[i];
+ struct token *token = NULL;
for (j = 0; j < ck->num_slots; j++)
- {
- struct token *token = &ck->token_list[j];
-
- if (slot_id == token->slot_id)
- {
- found = 1;
- break;
- }
- }
+ if (slot_id == ck->token_list[j].slot_id)
+ {
+ token = &ck->token_list[j];
+ break;
+ }
- if (found)
+ if (token)
{
- /*XXX: rescan the keys??? */
+ err = token_check (token);
}
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);
+ token = &ck->token_list[ck->num_slots];
+ err = token_open (ctx, ck, token, slot_id);
if (!err)
ck->num_slots++;
}
@@ -1139,12 +1202,11 @@ token_init (ctrl_t ctrl, assuan_context_t ctx, int rescan)
}
gpg_error_t
-token_fini (ctrl_t ctrl, assuan_context_t ctx)
+tkd_fini (ctrl_t ctrl, assuan_context_t ctx)
{
long r;
struct cryptoki *ck = ck_instance;
int i;
- int j;
(void)ctrl;
(void)ctx;
@@ -1153,45 +1215,7 @@ token_fini (ctrl_t ctrl, assuan_context_t ctx)
{
struct token *token = &ck->token_list[i];
- if (!token->valid)
- {
- 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++)
- {
- 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;
+ token_close (token);
}
ck->num_slots = 0;
@@ -1212,10 +1236,9 @@ token_fini (ctrl_t ctrl, assuan_context_t ctx)
gpg_error_t
-token_sign (ctrl_t ctrl, assuan_context_t ctx,
- const char *keygrip, int hash_algo,
- unsigned char **r_outdata,
- size_t *r_outdatalen)
+tkd_sign (ctrl_t ctrl, assuan_context_t ctx,
+ const char *keygrip, int hash_algo,
+ unsigned char **r_outdata, size_t *r_outdatalen)
{
gpg_error_t err;
struct key *k;
@@ -1226,6 +1249,13 @@ token_sign (ctrl_t ctrl, assuan_context_t ctx,
/* mismatch: size_t for GnuPG, unsigned long for PKCS#11 */
/* mismatch: application prepare buffer for PKCS#11 */
+ if (!ck->handle)
+ {
+ err = tkd_init (ctrl, ctx, 0);
+ if (err)
+ return err;
+ }
+
*r_outdata = NULL;
r = find_key (ck, keygrip, &k);
if (r)
@@ -1287,7 +1317,7 @@ get_usage_string (struct key *k)
}
gpg_error_t
-token_readkey (ctrl_t ctrl, assuan_context_t ctx, const char *keygrip)
+tkd_readkey (ctrl_t ctrl, assuan_context_t ctx, const char *keygrip)
{
gpg_error_t err = 0;
struct key *k;
@@ -1296,6 +1326,14 @@ token_readkey (ctrl_t ctrl, assuan_context_t ctx, const char *keygrip)
(void)ctrl;
(void)ctx;
+
+ if (!ck->handle)
+ {
+ err = tkd_init (ctrl, ctx, 0);
+ if (err)
+ return err;
+ }
+
r = find_key (ck, keygrip, &k);
if (r)
return gpg_error (GPG_ERR_NO_SECKEY);
@@ -1304,13 +1342,21 @@ token_readkey (ctrl_t ctrl, assuan_context_t ctx, const char *keygrip)
}
gpg_error_t
-token_keyinfo (ctrl_t ctrl, const char *keygrip, int opt_data, int cap)
+tkd_keyinfo (ctrl_t ctrl, assuan_context_t ctx, const char *keygrip,
+ int opt_data, int cap)
{
gpg_error_t err = 0;
struct cryptoki *ck = ck_instance;
struct key *k;
const char *usage;
+ if (!ck->handle)
+ {
+ err = tkd_init (ctrl, ctx, 0);
+ if (err)
+ return err;
+ }
+
if (keygrip)
{
unsigned long r;
diff --git a/tkd/tkdaemon.h b/tkd/tkdaemon.h
index e00755bf0..5d2a15fea 100644
--- a/tkd/tkdaemon.h
+++ b/tkd/tkdaemon.h
@@ -110,17 +110,17 @@ 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, 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,
- const char *keygrip, int hash_algo,
- unsigned char **r_outdata,
- size_t *r_outdatalen);
-gpg_error_t token_readkey (ctrl_t ctrl, assuan_context_t ctx,
- const char *keygrip);
-gpg_error_t token_keyinfo (ctrl_t ctrl,
- const char *keygrip, int opt_data, int cap);
+gpg_error_t tkd_init (ctrl_t ctrl, assuan_context_t ctx, int rescan);
+gpg_error_t tkd_fini (ctrl_t ctrl, assuan_context_t ctx);
+
+gpg_error_t tkd_sign (ctrl_t ctrl, assuan_context_t ctx,
+ const char *keygrip, int hash_algo,
+ unsigned char **r_outdata,
+ size_t *r_outdatalen);
+gpg_error_t tkd_readkey (ctrl_t ctrl, assuan_context_t ctx,
+ const char *keygrip);
+gpg_error_t tkd_keyinfo (ctrl_t ctrl, assuan_context_t ctx,
+ const char *keygrip, int opt_data, int cap);
#endif /*TKDAEMON_H*/