[PATCH setup 2/4] Add support for RSA key signatures
Jon Turney
jon.turney@dronecode.org.uk
Mon Feb 24 22:02:00 GMT 2020
---
crypto.cc | 162 ++++++++++++++++++++++++++++++++++--------------------
crypto.h | 5 +-
2 files changed, 103 insertions(+), 64 deletions(-)
diff --git a/crypto.cc b/crypto.cc
index e2ed7b2..118d4d7 100644
--- a/crypto.cc
+++ b/crypto.cc
@@ -52,7 +52,7 @@ static BoolOption UntrustedKeysOption (false, 'u', "untrusted-keys",
static BoolOption KeepUntrustedKeysOption (false, 'U', "keep-untrusted-keys",
"Use untrusted keys and retain all");
-/* Embedded public half of Cygwin DSA signing key. */
+/* Embedded public half of Cygwin signing key. */
static const char *cygwin_pubkey_sexpr =
#include "cyg-pubkey.h"
;
@@ -63,14 +63,21 @@ static const char *dsa_pubkey_templ = "(public-key (dsa (p %m) (q %m) (g %m) (y
/* S-expr template for DSA signature. */
static const char *dsa_sig_templ = "(sig-val (dsa (r %m) (s %m)))";
+/* S-expr template for RSA signature. */
+static const char *rsa_sig_templ = "(sig-val (rsa (s %m)))";
+
/* S-expr template for data block to be signed. */
-static const char *data_hash_templ = "(data (flags raw) (value %m))";
+static const char *dsa_data_hash_templ = "(data (flags raw) (value %m))";
+
+/* S-expr template for RSA data block to be signed. */
+static const char *rsa_data_hash_templ = "(data (flags pkcs1) (hash %s %b))";
/* User context data for sig packet walk. */
struct sig_data
{
/* MPI values of sig components. */
gcry_mpi_t dsa_mpi_r, dsa_mpi_s;
+ gcry_mpi_t rsa_mpi_s;
/* Hash context. */
gcry_md_hd_t md;
@@ -315,8 +322,9 @@ pkt_cb_resp sig_file_walker (struct packet_walker *wlk, unsigned char tag,
ERRKIND (wlk->owner, IDS_CRYPTO_ERROR, sigdat->sig_type, "unsupported sig type.");
return pktHALT;
}
- // And we only speak DSA.
- if (sigdat->pk_alg != RFC4880_PK_DSA)
+
+ // We only handle RSA and DSA keys
+ if ((sigdat->pk_alg != RFC4880_PK_DSA) && (sigdat->pk_alg != RFC4880_PK_RSA))
{
ERRKIND (wlk->owner, IDS_CRYPTO_ERROR, sigdat->pk_alg, "unsupported pk alg.");
return pktHALT;
@@ -366,20 +374,35 @@ pkt_cb_resp sig_file_walker (struct packet_walker *wlk, unsigned char tag,
MESSAGE ("sig type %d, pk_alg %d, hash_alg %d - first $%04x\n", sigdat->sig_type,
sigdat->pk_alg, sigdat->hash_alg, hash_first);
- /* Algorithm-Specific Fields for DSA signatures:
+ /* Algorithm-Specific Fields for signatures:
- - MPI of DSA value r.
+ for DSA:
+ - MPI of DSA value r
+ - MPI of DSA value s
- - MPI of DSA value s.
+ DSA signatures MUST use hashes that are equal in size to the number of
+ bits of q, the group generated by the DSA key's generator value.
- DSA signatures MUST use hashes that are equal in size to the number
- of bits of q, the group generated by the DSA key's generator value. */
+ for RSA:
+ - MPI of RSA value m^d mod n (aka s)
+ */
- if ((pkt_get_mpi (&sigdat->dsa_mpi_r, wlk->pfile) < 0)
- || (pkt_get_mpi (&sigdat->dsa_mpi_s, wlk->pfile) < 0))
+ if (sigdat->pk_alg == RFC4880_PK_DSA)
{
- ERRKIND (wlk->owner, IDS_CRYPTO_ERROR, "unpacking mpi.");
- return pktHALT;
+ if ((pkt_get_mpi (&sigdat->dsa_mpi_r, wlk->pfile) < 0)
+ || (pkt_get_mpi (&sigdat->dsa_mpi_s, wlk->pfile) < 0))
+ {
+ ERRKIND (wlk->owner, IDS_CRYPTO_ERROR, "unpacking mpi.");
+ return pktHALT;
+ }
+ }
+ else if (sigdat->pk_alg == RFC4880_PK_RSA)
+ {
+ if (pkt_get_mpi (&sigdat->rsa_mpi_s, wlk->pfile) < 0)
+ {
+ ERRKIND (wlk->owner, IDS_CRYPTO_ERROR, "unpacking mpi.");
+ return pktHALT;
+ }
}
MESSAGE ("Read sig packets succesfully!\n");
@@ -598,55 +621,81 @@ verify_ini_file_sig (io_stream *ini_file, io_stream *ini_sig_file, HWND owner)
sigdat.complete = false;
sigdat.sign_data = ini_file;
sigdat.dsa_mpi_r = sigdat.dsa_mpi_s = 0;
+ sigdat.rsa_mpi_s = 0;
sigdat.md = 0;
pkt_walk_packets (ini_sig_file, sig_file_walker, owner, 0,
ini_sig_file->get_size (), &sigdat);
if (sigdat.complete)
{
- /* DSA sig coefficients in s-expr format. */
- gcry_sexp_t dsa_sig;
+ /* sig coefficients in s-expr format. */
+ gcry_sexp_t sig;
- /* DSA signature hash data in s-expr format. */
- gcry_sexp_t dsa_hash;
+ /* signature hash data in s-expr format. */
+ gcry_sexp_t hash;
/* So, we have hashed all the data, and found the sig coefficients.
- Next stages are to finalise the hash, build everything into
+ Next stages are to finalise the hash, build everything into
s-exprs, and call the libgcrypt verification routine. */
- rv = gcry_sexp_build (&dsa_sig, &n, dsa_sig_templ, sigdat.dsa_mpi_r,
- sigdat.dsa_mpi_s);
- if (rv != GPG_ERR_NO_ERROR)
- {
- ERRKIND (owner, IDS_CRYPTO_ERROR, rv, "while creating sig s-expr.");
- return false;
- }
-
gcry_md_final (sigdat.md);
+ MESSAGE("digest length is %d\n",gcry_md_get_algo_dlen (sigdat.algo));
- // Make a temp mpi from the hash output, then an s-expr from that.
- gcry_mpi_t dsa_mpi_hash = 0;
- unsigned char *tmpbuf = gcry_md_read (sigdat.md, 0);
- size_t dlen = gcry_md_get_algo_dlen (sigdat.algo);
- rv = gcry_mpi_scan (&dsa_mpi_hash, GCRYMPI_FMT_USG, tmpbuf, dlen, 0UL);
- if (rv != GPG_ERR_NO_ERROR)
- {
- ERRKIND (owner, IDS_CRYPTO_ERROR, rv, "while creating hash MPI.");
- return false;
- }
+ if (sigdat.pk_alg == RFC4880_PK_DSA)
+ {
+ rv = gcry_sexp_build (&sig, &n, dsa_sig_templ, sigdat.dsa_mpi_r,
+ sigdat.dsa_mpi_s);
+ if (rv != GPG_ERR_NO_ERROR)
+ {
+ ERRKIND (owner, IDS_CRYPTO_ERROR, rv, "while creating sig s-expr.");
+ return false;
+ }
+
+ // Make a temp mpi from the hash output, then an s-expr from that.
+ gcry_mpi_t mpi_hash = 0;
+ unsigned char *tmpbuf = gcry_md_read (sigdat.md, 0);
+ size_t dlen = gcry_md_get_algo_dlen (sigdat.algo);
+ rv = gcry_mpi_scan (&mpi_hash, GCRYMPI_FMT_USG, tmpbuf, dlen, 0UL);
+ if (rv != GPG_ERR_NO_ERROR)
+ {
+ ERRKIND (owner, IDS_CRYPTO_ERROR, rv, "while creating hash MPI.");
+ return false;
+ }
- rv = gcry_sexp_build (&dsa_hash, &n, data_hash_templ, dsa_mpi_hash);
- if (rv != GPG_ERR_NO_ERROR)
- {
- ERRKIND (owner, IDS_CRYPTO_ERROR, rv, "while creating hash s-expr.");
- return false;
- }
+ rv = gcry_sexp_build (&hash, &n, dsa_data_hash_templ, mpi_hash);
+ if (rv != GPG_ERR_NO_ERROR)
+ {
+ ERRKIND (owner, IDS_CRYPTO_ERROR, rv, "while creating hash s-expr.");
+ return false;
+ }
+
+ gcry_mpi_release (mpi_hash);
+ }
+ else if (sigdat.pk_alg == RFC4880_PK_RSA)
+ {
+ rv = gcry_sexp_build (&sig, &n, rsa_sig_templ, sigdat.rsa_mpi_s);
+ if (rv != GPG_ERR_NO_ERROR)
+ {
+ ERRKIND (owner, IDS_CRYPTO_ERROR, rv, "while creating sig s-expr.");
+ return false;
+ }
+
+ rv = gcry_sexp_build (&hash, &n, rsa_data_hash_templ,
+ gcry_md_algo_name(sigdat.algo),
+ gcry_md_get_algo_dlen (sigdat.algo),
+ gcry_md_read (sigdat.md, 0));
+ if (rv != GPG_ERR_NO_ERROR)
+ {
+ ERRKIND (owner, IDS_CRYPTO_ERROR, rv, "while creating hash s-expr.");
+ return false;
+ }
+ }
#if CRYPTODEBUGGING
- n = gcry_sexp_sprint (dsa_sig, GCRYSEXP_FMT_ADVANCED, sexprbuf,
- GPG_KEY_SEXPR_BUF_SIZE);
+ n = gcry_sexp_sprint (sig, GCRYSEXP_FMT_ADVANCED, sexprbuf,
+ GPG_KEY_SEXPR_BUF_SIZE);
LogBabblePrintf ("sig:%d\n'%s'", n, sexprbuf);
- n = gcry_sexp_sprint (dsa_hash, GCRYSEXP_FMT_ADVANCED, sexprbuf,
- GPG_KEY_SEXPR_BUF_SIZE);
+ n = gcry_sexp_sprint (hash, GCRYSEXP_FMT_ADVANCED, sexprbuf,
+ GPG_KEY_SEXPR_BUF_SIZE);
LogBabblePrintf ("hash:%d\n'%s'", n, sexprbuf);
#endif /* CRYPTODEBUGGING */
@@ -656,29 +705,22 @@ verify_ini_file_sig (io_stream *ini_file, io_stream *ini_sig_file, HWND owner)
std::vector<key_info>::iterator it;
for (it = keys_to_try.begin (); it < keys_to_try.end (); ++it)
{
- MESSAGE ("Trying key %s\n", it->name.c_str());
- rv = gcry_pk_verify (dsa_sig, dsa_hash, it->key);
+ rv = gcry_pk_verify (sig, hash, it->key);
+
+ LogBabblePrintf("signature: tried key %s, returned 0x%08x %s\n",
+ it->name.c_str(), rv, gcry_strerror(rv));
+
if (rv != GPG_ERR_NO_ERROR)
continue;
// Found it! This key gets kept!
- LogBabblePrintf("Valid signature by key %s", it->name.c_str());
if (!it->builtin)
add_key_from_sexpr (it->key);
break;
}
sig_ok = (rv == GPG_ERR_NO_ERROR);
-#if CRYPTODEBUGGING
- gcry_err_code_t code;
- gcry_err_source_t src;
- code = gcry_err_code (rv);
- src = gcry_err_source (rv);
- LogBabblePrintf ("Well, pk verify returned $%08x - code %d src %d\n", rv, code, src);
-#endif /* CRYPTODEBUGGING */
-
- gcry_mpi_release (dsa_mpi_hash);
- gcry_sexp_release (dsa_sig);
- gcry_sexp_release (dsa_hash);
+ gcry_sexp_release (sig);
+ gcry_sexp_release (hash);
}
// Discard the temp data then.
diff --git a/crypto.h b/crypto.h
index 860df6c..661d86d 100644
--- a/crypto.h
+++ b/crypto.h
@@ -308,12 +308,9 @@ extern bool verify_ini_file_sig (io_stream *ini_file, io_stream *ini_sig_file, H
*/
-// Big enough to dump the coefficients of a DSA
+// Big enough to dump the coefficients of a
// signing key of any reasonable size in ASCII
// s-expr representation.
#define GPG_KEY_SEXPR_BUF_SIZE (8192)
-// As long as you respect this maximum coefficient size.
-#define GPG_KEY_MAX_COEFF_SIZE (8192)
-
#endif /* SETUP_CRYPTO_H */
--
2.21.0
More information about the Cygwin-apps
mailing list