--- 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