From bb096905b9ee1f5175efee1ab6c98045a26a2678 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 10 Aug 2020 10:01:03 +0200 Subject: [PATCH] agent: Add option --pss to pksign to be used by smartcards. * agent/command.c (cmd_sethash): Add option --pss and allow for --hash=null. * agent/agent.h (struct server_control_s): Add digest.is_pss and zero where needed. * agent/pksign.c (agent_pksign_do): Allow for PSS with cards. * scd/command.c (cmd_pksign): Add for --hash=none. -- This is not a full implementaion of PSS but allows scdaemon card drivers to detect already PSS formatted data. Signed-off-by: Werner Koch --- agent/agent.h | 8 +++++--- agent/command-ssh.c | 1 + agent/command.c | 12 +++++++++--- agent/pksign.c | 14 +++++++++++++- scd/command.c | 4 +++- 5 files changed, 31 insertions(+), 8 deletions(-) diff --git a/agent/agent.h b/agent/agent.h index 7ef0ffca7..7f18eb601 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -254,12 +254,14 @@ struct server_control_s /* Information on the currently used digest (for signing commands). */ struct { char *data; /* NULL or malloced data of length VALUELEN. If - this is set The other fields are ignored. Used - for PureEdDSA. */ + this is set the other fields are ignored. Used + for PureEdDSA and RSA with PSS (in which case + data_is_pss is also set). */ int valuelen; int algo; unsigned char value[MAX_DIGEST_LEN]; - int raw_value: 1; + unsigned int raw_value: 1; + unsigned int is_pss: 1; /* DATA holds PSS formated data. */ } digest; unsigned char keygrip[20]; int have_keygrip; diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 5e3ce4c39..664bd0d30 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -2790,6 +2790,7 @@ ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response) ctrl->digest.algo = hash_algo; xfree (ctrl->digest.data); ctrl->digest.data = NULL; + ctrl->digest.is_pss = 0; if ((spec.flags & SPEC_FLAG_USE_PKCS1V2)) ctrl->digest.raw_value = 0; else diff --git a/agent/command.c b/agent/command.c index 2980ae2da..6efde5e28 100644 --- a/agent/command.c +++ b/agent/command.c @@ -707,11 +707,12 @@ cmd_setkeydesc (assuan_context_t ctx, char *line) static const char hlp_sethash[] = "SETHASH (--hash=)|() ]\n" - "SETHASH --inquire\n" + "SETHASH [--pss] --inquire\n" "\n" "The client can use this command to tell the server about the data\n" "(which usually is a hash) to be signed. The option --inquire is\n" - "used to ask back for to-be-signed data in case of PureEdDSA"; + "used to ask back for to-be-signed data in case of PureEdDSA or\n" + "with --pss for pre-formatted rsaPSS."; static gpg_error_t cmd_sethash (assuan_context_t ctx, char *line) { @@ -722,7 +723,7 @@ cmd_sethash (assuan_context_t ctx, char *line) unsigned char *buf; char *endp; int algo; - int opt_inquire; + int opt_inquire, opt_pss; /* Parse the alternative hash options which may be used instead of the algo number. */ @@ -744,6 +745,8 @@ cmd_sethash (assuan_context_t ctx, char *line) algo = GCRY_MD_MD5; else if (has_option (line, "--hash=tls-md5sha1")) algo = MD_USER_TLS_MD5SHA1; + else if (has_option (line, "--hash=none")) + algo = 0; else { err = set_error (GPG_ERR_ASS_PARAMETER, "invalid hash algorithm"); @@ -753,6 +756,7 @@ cmd_sethash (assuan_context_t ctx, char *line) else algo = 0; + opt_pss = has_option (line, "--pss"); opt_inquire = has_option (line, "--inquire"); line = skip_options (line); @@ -772,6 +776,7 @@ cmd_sethash (assuan_context_t ctx, char *line) ctrl->digest.data = NULL; ctrl->digest.algo = algo; ctrl->digest.raw_value = 0; + ctrl->digest.is_pss = opt_pss; if (opt_inquire) { @@ -3807,6 +3812,7 @@ start_command_handler (ctrl_t ctrl, gnupg_fd_t listen_fd, gnupg_fd_t fd) ctrl->digest.data = NULL; ctrl->digest.raw_value = 0; + ctrl->digest.is_pss = 0; assuan_set_io_monitor (ctx, io_monitor, NULL); agent_set_progress_cb (progress_cb, ctrl); diff --git a/agent/pksign.c b/agent/pksign.c index 0640b04ef..6d13278ff 100644 --- a/agent/pksign.c +++ b/agent/pksign.c @@ -497,6 +497,12 @@ agent_pksign_do (ctrl_t ctrl, const char *cache_nonce, err = do_encode_dsa (data, datalen, algo, s_skey, &s_hash); + else if (ctrl->digest.is_pss) + { + log_info ("signing with rsaPSS is currently only supported" + " for (some) smartcards\n"); + err = gpg_error (GPG_ERR_NOT_SUPPORTED); + } else err = do_encode_md (data, datalen, ctrl->digest.algo, @@ -540,7 +546,13 @@ agent_pksign_do (ctrl_t ctrl, const char *cache_nonce, if (s_hash == NULL) { - if (ctrl->digest.algo == MD_USER_TLS_MD5SHA1) + if (ctrl->digest.is_pss) + { + err = gcry_sexp_build (&s_hash, NULL, + "(data (flags raw) (value %b))", + (int)datalen, data); + } + else if (ctrl->digest.algo == MD_USER_TLS_MD5SHA1) err = do_encode_raw_pkcs1 (data, datalen, gcry_pk_get_nbits (sexp_key), &s_hash); else diff --git a/scd/command.c b/scd/command.c index 800156ca5..02cf8907f 100644 --- a/scd/command.c +++ b/scd/command.c @@ -891,7 +891,7 @@ pin_cb (void *opaque, const char *info, char **retstr) static const char hlp_pksign[] = - "PKSIGN [--hash=[rmd160|sha{1,224,256,384,512}|md5]] \n" + "PKSIGN [--hash=[rmd160|sha{1,224,256,384,512}|md5|none]] \n" "\n" "The --hash option is optional; the default is SHA1."; static gpg_error_t @@ -920,6 +920,8 @@ cmd_pksign (assuan_context_t ctx, char *line) hash_algo = GCRY_MD_SHA512; else if (has_option (line, "--hash=md5")) hash_algo = GCRY_MD_MD5; + else if (has_option (line, "--hash=none")) /* For raw RSA. */ + hash_algo = 0; else if (!strstr (line, "--")) hash_algo = GCRY_MD_SHA1; else