aboutsummaryrefslogtreecommitdiffstats
path: root/src/libcryptobox/cryptobox.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcryptobox/cryptobox.c')
-rw-r--r--src/libcryptobox/cryptobox.c132
1 files changed, 130 insertions, 2 deletions
diff --git a/src/libcryptobox/cryptobox.c b/src/libcryptobox/cryptobox.c
index 63ade4d1c..9ab8f93c2 100644
--- a/src/libcryptobox/cryptobox.c
+++ b/src/libcryptobox/cryptobox.c
@@ -21,6 +21,12 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/* Workaround for memset_s */
+#ifdef __APPLE__
+#define __STDC_WANT_LIB_EXT1__ 1
+#include <string.h>
+#endif
+
#include "cryptobox.h"
#include "platform_config.h"
#include "chacha20/chacha.h"
@@ -33,6 +39,15 @@
#include <cpuid.h>
#endif
+
+#ifndef ALIGNED
+#if defined(_MSC_VER)
+# define ALIGNED(x) __declspec(align(x))
+#else
+# define ALIGNED(x) __attribute__((aligned(x)))
+#endif
+#endif
+
unsigned long cpu_config = 0;
static const guchar n0[16] = {0};
@@ -164,7 +179,7 @@ void rspamd_cryptobox_encrypt_nm_inplace (guchar *data, gsize len,
const rspamd_nm_t nm, rspamd_sig_t sig)
{
poly1305_state mac_ctx;
- guchar subkey[CHACHA_BLOCKBYTES];
+ guchar ALIGNED(32) subkey[CHACHA_BLOCKBYTES];
chacha_state s;
gsize r;
@@ -183,12 +198,112 @@ void rspamd_cryptobox_encrypt_nm_inplace (guchar *data, gsize len,
rspamd_explicit_memzero (subkey, sizeof (subkey));
}
+static void
+rspamd_cryptobox_flush_outbuf (struct rspamd_cryptobox_segment *st,
+ const guchar *buf, gsize len, gsize offset)
+{
+ gsize cpy_len;
+
+ while (len > 0) {
+ cpy_len = MIN (len, st->len - offset);
+ memcpy (st->data + offset, buf, cpy_len);
+ st ++;
+ buf += cpy_len;
+ len -= cpy_len;
+ offset = 0;
+ }
+}
+
+void rspamd_cryptobox_encryptv_nm_inplace (struct rspamd_cryptobox_segment *segments,
+ gsize cnt,
+ const rspamd_nonce_t nonce,
+ const rspamd_nm_t nm, rspamd_sig_t sig)
+{
+ struct rspamd_cryptobox_segment *cur = segments, *start_seg = segments;
+ guchar ALIGNED(32) subkey[CHACHA_BLOCKBYTES],
+ outbuf[CHACHA_BLOCKBYTES * 16];
+ poly1305_state mac_ctx;
+ guchar *out, *in;
+ chacha_state s;
+ gsize r, remain, inremain, seg_offset;
+
+ xchacha_init (&s, (const chacha_key *)nm, (const chacha_iv24 *)nonce, 20);
+ memset (subkey, 0, sizeof (subkey));
+ chacha_update (&s, subkey, subkey, sizeof (subkey));
+ poly1305_init (&mac_ctx, (const poly1305_key *)subkey);
+
+ remain = sizeof (outbuf);
+ out = outbuf;
+ inremain = cur->len;
+ seg_offset = 0;
+
+ for (;;) {
+ if (cur->len <= remain) {
+ memcpy (out, cur->data, cur->len);
+ remain -= cur->len;
+ out += cur->len;
+ cur ++;
+
+ if (remain == 0) {
+ rspamd_cryptobox_flush_outbuf (start_seg, outbuf,
+ sizeof (outbuf), seg_offset);
+ start_seg = cur;
+ seg_offset = 0;
+ remain = sizeof (outbuf);
+ out = outbuf;
+ }
+ }
+ else {
+ memcpy (out, cur->data, remain);
+ chacha_update (&s, outbuf, outbuf, sizeof (outbuf));
+ poly1305_update (&mac_ctx, outbuf, sizeof (outbuf));
+ rspamd_cryptobox_flush_outbuf (start_seg, outbuf, sizeof (outbuf),
+ seg_offset);
+ seg_offset = 0;
+
+ inremain = cur->len - remain;
+ in = cur->data + remain;
+ out = outbuf;
+ remain = 0;
+ start_seg = cur;
+
+ while (inremain > 0) {
+ if (sizeof (outbuf) <= inremain) {
+ memcpy (outbuf, in, sizeof (outbuf));
+ chacha_update (&s, outbuf, outbuf, sizeof (outbuf));
+ poly1305_update (&mac_ctx, outbuf, sizeof (outbuf));
+ memcpy (in, outbuf, sizeof (outbuf));
+ in += sizeof (outbuf);
+ inremain -= sizeof (outbuf);
+ }
+ else {
+ memcpy (outbuf, in, inremain);
+ remain = sizeof (outbuf) - inremain;
+ cur ++;
+ seg_offset = inremain;
+ inremain = 0;
+ }
+ }
+ }
+ }
+
+ r = chacha_final (&s, out);
+ remain -= r;
+ poly1305_update (&mac_ctx, outbuf, sizeof (outbuf) - remain);
+ poly1305_finish (&mac_ctx, sig);
+
+ rspamd_cryptobox_flush_outbuf (start_seg, outbuf, sizeof (outbuf) - remain,
+ seg_offset);
+ rspamd_explicit_memzero (&mac_ctx, sizeof (mac_ctx));
+ rspamd_explicit_memzero (subkey, sizeof (subkey));
+}
+
gboolean
rspamd_cryptobox_decrypt_nm_inplace (guchar *data, gsize len,
const rspamd_nonce_t nonce, const rspamd_nm_t nm, const rspamd_sig_t sig)
{
poly1305_state mac_ctx;
- guchar subkey[CHACHA_BLOCKBYTES];
+ guchar ALIGNED(32) subkey[CHACHA_BLOCKBYTES];
rspamd_sig_t mac;
chacha_state s;
gsize r;
@@ -245,6 +360,19 @@ rspamd_cryptobox_encrypt_inplace (guchar *data, gsize len,
rspamd_explicit_memzero (nm, sizeof (nm));
}
+void
+rspamd_cryptobox_encryptv_inplace (struct rspamd_cryptobox_segment *segments,
+ gsize cnt,
+ const rspamd_nonce_t nonce,
+ const rspamd_pk_t pk, const rspamd_sk_t sk, rspamd_sig_t sig)
+{
+ guchar nm[rspamd_cryptobox_NMBYTES];
+
+ rspamd_cryptobox_nm (nm, pk, sk);
+ rspamd_cryptobox_encryptv_nm_inplace (segments, cnt, nonce, nm, sig);
+ rspamd_explicit_memzero (nm, sizeof (nm));
+}
+
void
rspamd_cryptobox_siphash (unsigned char *out, const unsigned char *in,