From 3fc31cc8724885d8d0f2d7ff8028f3b4f6b49c8e Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Sat, 19 May 2018 14:50:43 +0100 Subject: [PATCH] [Minor] Add method to decrypt data using keypair --- src/libcryptobox/keypair.c | 69 ++++++++++++++++++++++++++++++++++++++ src/libcryptobox/keypair.h | 17 ++++++++++ 2 files changed, 86 insertions(+) diff --git a/src/libcryptobox/keypair.c b/src/libcryptobox/keypair.c index 98401e10f..1f8acc6d1 100644 --- a/src/libcryptobox/keypair.c +++ b/src/libcryptobox/keypair.c @@ -20,6 +20,8 @@ #include "libutil/str_util.h" #include "libutil/printf.h" +const guchar encrypted_magic[7] = {'r', 'u', 'c', 'l', 'e', 'v', '1'}; + static GQuark rspamd_keypair_quark (void) { @@ -908,3 +910,70 @@ rspamd_pubkey_equal (const struct rspamd_cryptobox_pubkey *k1, return FALSE; } + +gboolean +rspamd_keypair_decrypt (struct rspamd_cryptobox_keypair *kp, + const guchar *in, gsize inlen, + guchar **out, gsize *outlen, + GError **err) +{ + const guchar *nonce, *mac, *data, *pubkey; + + g_assert (kp != NULL); + g_assert (in != NULL); + + if (kp->type != RSPAMD_KEYPAIR_KEX) { + g_set_error (err, rspamd_keypair_quark (), EINVAL, + "invalid keypair type"); + + return FALSE; + } + + if (inlen < sizeof (encrypted_magic) + rspamd_cryptobox_pk_bytes (kp->alg) + + rspamd_cryptobox_mac_bytes (kp->alg) + + rspamd_cryptobox_nonce_bytes (kp->alg)) { + g_set_error (err, rspamd_keypair_quark (), E2BIG, "invalid size: too small"); + + return FALSE; + } + + if (memcmp (in, encrypted_magic, sizeof (encrypted_magic)) != 0) { + g_set_error (err, rspamd_keypair_quark (), EINVAL, + "invalid magic"); + + return FALSE; + } + + /* Set pointers */ + pubkey = in + sizeof (encrypted_magic); + mac = pubkey + rspamd_cryptobox_pk_bytes (kp->alg); + nonce = mac + rspamd_cryptobox_mac_bytes (kp->alg); + data = nonce + rspamd_cryptobox_nonce_bytes (kp->alg); + + if (data - in >= inlen) { + g_set_error (err, rspamd_keypair_quark (), E2BIG, "invalid size: too small"); + + return FALSE; + } + + inlen -= data - in; + + /* Allocate memory for output */ + *out = g_malloc (inlen); + memcpy (*out, data, inlen); + + if (!rspamd_cryptobox_decrypt_inplace (*out, inlen, nonce, pubkey, + rspamd_keypair_component (kp, RSPAMD_KEYPAIR_COMPONENT_SK, NULL), + mac, kp->alg)) { + g_set_error (err, rspamd_keypair_quark (), EPERM, "verification failed"); + g_free (*out); + + return FALSE; + } + + if (outlen) { + *outlen = inlen; + } + + return TRUE; +} diff --git a/src/libcryptobox/keypair.h b/src/libcryptobox/keypair.h index b24ecc9aa..fc17412e2 100644 --- a/src/libcryptobox/keypair.h +++ b/src/libcryptobox/keypair.h @@ -28,6 +28,8 @@ enum rspamd_cryptobox_keypair_type { RSPAMD_KEYPAIR_SIGN }; +extern const guchar encrypted_magic[7]; + /** * Opaque structure for the full (public + private) keypair */ @@ -270,5 +272,20 @@ gboolean rspamd_keypair_verify (struct rspamd_cryptobox_pubkey *pk, gboolean rspamd_pubkey_equal (const struct rspamd_cryptobox_pubkey *k1, const struct rspamd_cryptobox_pubkey *k2); +/** + * Decrypts data using keypair and a pubkey stored in in, in must start from + * `encrypted_magic` constant + * @param kp keypair + * @param in raw input + * @param inlen input length + * @param out output (allocated internally using g_malloc) + * @param outlen output size + * @return TRUE if decryption is completed, out must be freed in this case + */ +gboolean rspamd_keypair_decrypt (struct rspamd_cryptobox_keypair *kp, + const guchar *in, gsize inlen, + guchar **out, gsize *outlen, + GError **err); + #endif /* SRC_LIBCRYPTOBOX_KEYPAIR_H_ */ -- 2.39.5