From e944cead95bd5832cb7bfbb2145165754b8b8cbe Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 6 Mar 2023 11:53:07 +0900 Subject: [PATCH] Use two-phase sign to match PKCS#11 API. Tested Scute for RSA and ECDSA. Signed-off-by: NIIBE Yutaka --- tkd/pkcs11.c | 110 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 73 insertions(+), 37 deletions(-) diff --git a/tkd/pkcs11.c b/tkd/pkcs11.c index 4a47faf7d..290de214d 100644 --- a/tkd/pkcs11.c +++ b/tkd/pkcs11.c @@ -841,10 +841,8 @@ iter_find_key (struct iter_key *iter, struct key **r_key) } static gpg_error_t -do_pksign (struct key *key, int hash_algo, - const unsigned char *u_data, unsigned long u_data_len, - unsigned char **r_signature, - unsigned long *r_signature_len) +setup_pksign (struct key *key, int hash_algo, + unsigned char **r_signature, unsigned long *r_signature_len) { gpg_error_t err = 0; unsigned long r = 0; @@ -852,8 +850,6 @@ do_pksign (struct key *key, int hash_algo, struct cryptoki *ck = token->ck; ck_mechanism_type_t mechanism; struct ck_mechanism mechanism_struct; - unsigned char data[1024]; - unsigned long data_len; unsigned int nbits; unsigned long siglen; unsigned char *sig; @@ -863,14 +859,66 @@ do_pksign (struct key *key, int hash_algo, mechanism = key->mechanism; if (key->key_type == KEY_RSA) { - size_t asnlen = sizeof (data); - /* It's CKM_RSA_PKCS, it requires that hash algo OID included in the data to be signed. */ if (!hash_algo) return gpg_error (GPG_ERR_DIGEST_ALGO); siglen = (nbits+7)/8; + } + else if (key->key_type == KEY_EC) + { + siglen = ((nbits+7)/8) * 2; + } + else if (key->key_type == KEY_EDDSA) + { + mechanism = CKM_EDDSA; + siglen = ((nbits+7)/8)*2; + } + else + return gpg_error (GPG_ERR_BAD_SECKEY); + + mechanism_struct.mechanism = mechanism; + mechanism_struct.parameter = NULL; + mechanism_struct.parameter_len = 0; + + r = ck->f->C_SignInit (token->session, &mechanism_struct, + key->p11_keyid); + if (r) + { + log_error ("C_SignInit error: %ld", r); + return gpg_error (GPG_ERR_INV_RESPONSE); + } + + sig = xtrymalloc (siglen); + if (!sig) + return gpg_error_from_syserror (); + + *r_signature = sig; + *r_signature_len = siglen; + + return err; +} + +static gpg_error_t +do_pksign (struct key *key, int hash_algo, + const unsigned char *u_data, unsigned long u_data_len, + unsigned char *signature, + unsigned long *r_signature_len) +{ + gpg_error_t err = 0; + unsigned long r = 0; + struct token *token = key->token; + struct cryptoki *ck = token->ck; + ck_mechanism_type_t mechanism; + unsigned char data[1024]; + unsigned long data_len; + + mechanism = key->mechanism; + if (key->key_type == KEY_RSA) + { + size_t asnlen = sizeof (data); + gcry_md_get_asnoid (hash_algo, data, &asnlen); gcry_md_hash_buffer (hash_algo, data+asnlen, u_data, u_data_len); @@ -878,7 +926,6 @@ do_pksign (struct key *key, int hash_algo, } else if (key->key_type == KEY_EC) { - siglen = ((nbits+7)/8) * 2; if (mechanism == CKM_ECDSA) { /* SoftHSMv2 */ @@ -908,44 +955,20 @@ do_pksign (struct key *key, int hash_algo, else if (key->key_type == KEY_EDDSA) { mechanism = CKM_EDDSA; - siglen = ((nbits+7)/8)*2; memcpy (data, u_data, u_data_len); data_len = u_data_len; } else return gpg_error (GPG_ERR_BAD_SECKEY); - mechanism_struct.mechanism = mechanism; - mechanism_struct.parameter = NULL; - mechanism_struct.parameter_len = 0; - - r = ck->f->C_SignInit (token->session, &mechanism_struct, - key->p11_keyid); - if (r) - { - log_error ("C_SignInit error: %ld", r); - return gpg_error (GPG_ERR_INV_RESPONSE); - } - - sig = xtrymalloc (siglen); - if (!sig) - { - return gpg_error_from_syserror (); - } - - *r_signature_len = siglen; - r = ck->f->C_Sign (token->session, data, data_len, - sig, r_signature_len); + signature, r_signature_len); if (r) { - xfree (sig); return gpg_error (GPG_ERR_INV_RESPONSE); } - *r_signature = sig; - return err; } @@ -1038,6 +1061,7 @@ 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 */ + *r_outdata = NULL; r = find_key (ck, keygrip, &k); if (r) return gpg_error (GPG_ERR_NO_SECKEY); @@ -1046,17 +1070,29 @@ token_sign (ctrl_t ctrl, assuan_context_t ctx, const char *cmd; unsigned char *value; size_t valuelen; + unsigned char *sig = NULL; + + err = setup_pksign (k, hash_algo, &sig, r_outdatalen); + if (err) + return err; cmd = "VALUE"; err = assuan_inquire (ctx, cmd, &value, &valuelen, MAXLEN_VALUE); if (err) - return err; + { + xfree (sig); + return err; + } - err = do_pksign (k, hash_algo, value, valuelen, r_outdata, r_outdatalen); + err = do_pksign (k, hash_algo, value, valuelen, sig, r_outdatalen); wipememory (value, valuelen); xfree (value); if (err) - return err; + { + xfree (sig); + return err; + } + *r_outdata = sig; } return err;