diff options
Diffstat (limited to 'wsutil/wsgcrypt.c')
-rw-r--r-- | wsutil/wsgcrypt.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/wsutil/wsgcrypt.c b/wsutil/wsgcrypt.c index 869111a214..a6d527f4bd 100644 --- a/wsutil/wsgcrypt.c +++ b/wsutil/wsgcrypt.c @@ -71,6 +71,92 @@ void crypt_des_ecb(guint8 *output, const guint8 *buffer, const guint8 *key56) gcry_cipher_close(handle); } +size_t rsa_decrypt_inplace(const guint len, guchar* data, gcry_sexp_t pk, gboolean pkcs1_padding, char **err) +{ + gint rc = 0; + size_t decr_len = 0, i = 0; + gcry_sexp_t s_data = NULL, s_plain = NULL; + gcry_mpi_t encr_mpi = NULL, text = NULL; + + *err = NULL; + + /* create mpi representation of encrypted data */ + rc = gcry_mpi_scan(&encr_mpi, GCRYMPI_FMT_USG, data, len, NULL); + if (rc != 0 ) { + *err = g_strdup_printf("can't convert data to mpi (size %d):%s", len, gcry_strerror(rc)); + return 0; + } + + /* put the data into a simple list */ + rc = gcry_sexp_build(&s_data, NULL, "(enc-val(rsa(a%m)))", encr_mpi); + if (rc != 0) { + *err = g_strdup_printf("can't build encr_sexp:%s", gcry_strerror(rc)); + decr_len = 0; + goto out; + } + + /* pass it to libgcrypt */ + rc = gcry_pk_decrypt(&s_plain, s_data, pk); + if (rc != 0) + { + *err = g_strdup_printf("can't decrypt key:%s", gcry_strerror(rc)); + decr_len = 0; + goto out; + } + + /* convert plain text sexp to mpi format */ + text = gcry_sexp_nth_mpi(s_plain, 0, 0); + if (! text) { + *err = g_strdup("can't convert sexp to mpi"); + decr_len = 0; + goto out; + } + + /* compute size requested for plaintext buffer */ + rc = gcry_mpi_print(GCRYMPI_FMT_USG, NULL, 0, &decr_len, text); + if (rc != 0) { + *err = g_strdup_printf("can't compute decr size:%s", gcry_strerror(rc)); + decr_len = 0; + goto out; + } + + /* sanity check on out buffer */ + if (decr_len > len) { + *err = g_strdup_printf("decrypted data is too long ?!? (%" G_GSIZE_MODIFIER "u max %d)", decr_len, len); + decr_len = 0; + goto out; + } + + /* write plain text to newly allocated buffer */ + rc = gcry_mpi_print(GCRYMPI_FMT_USG, data, len, &decr_len, text); + if (rc != 0) { + *err = g_strdup_printf("can't print decr data to mpi (size %" G_GSIZE_MODIFIER "u):%s", decr_len, gcry_strerror(rc)); + decr_len = 0; + goto out; + } + + if (pkcs1_padding) { + /* strip the padding*/ + rc = 0; + for (i = 1; i < decr_len; i++) { + if (data[i] == 0) { + rc = (gint) i+1; + break; + } + } + + decr_len -= rc; + memmove(data, data+rc, decr_len); + } + +out: + gcry_sexp_release(s_data); + gcry_sexp_release(s_plain); + gcry_mpi_release(encr_mpi); + gcry_mpi_release(text); + return decr_len; +} + /* * Editor modelines - http://www.wireshark.org/tools/modelines.html * |