summaryrefslogtreecommitdiffstats
path: root/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/chacha20poly1305.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/chacha20poly1305.c148
1 files changed, 148 insertions, 0 deletions
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/chacha20poly1305.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/chacha20poly1305.c
new file mode 100644
index 00000000..0aef7254
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/chacha20poly1305.c
@@ -0,0 +1,148 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "chacha20poly1305.h"
+#include "salsa20.h"
+#include "poly1305.h"
+#include "bitops.h"
+#include "handy.h"
+
+#define ENCRYPT 1
+#define DECRYPT 0
+
+#define SUCCESS 0
+#define FAILURE 1
+
+static int process(const uint8_t key[32],
+ const uint8_t nonce[12],
+ const uint8_t *header, size_t nheader,
+ const uint8_t *input, size_t nbytes,
+ uint8_t *output,
+ int mode,
+ uint8_t tag[16])
+{
+ /* First, generate the Poly1305 key by running ChaCha20 with the
+ * given key and a zero counter. The first half of the
+ * 64-byte output is the key. */
+ uint8_t fullnonce[16] = { 0 };
+ memcpy(fullnonce + 4, nonce, 12);
+
+ uint8_t polykey[32] = { 0 };
+ cf_chacha20_ctx chacha;
+ cf_chacha20_init_custom(&chacha, key, 32, fullnonce, 4);
+ cf_chacha20_cipher(&chacha, polykey, polykey, sizeof polykey);
+
+ /* Now initialise Poly1305. */
+ cf_poly1305 poly;
+ cf_poly1305_init(&poly, polykey, polykey + 16);
+ mem_clean(polykey, sizeof polykey);
+
+ /* Discard next 32 bytes of chacha20 key stream. */
+ cf_chacha20_cipher(&chacha, polykey, polykey, sizeof polykey);
+ mem_clean(polykey, sizeof polykey);
+
+ /* The input to Poly1305 is:
+ * AAD || pad(AAD) || cipher || pad(cipher) || len_64(aad) || len_64(cipher) */
+ uint8_t padbuf[16] = { 0 };
+
+#define PADLEN(x) (16 - ((x) & 0xf))
+
+ /* AAD || pad(AAD) */
+ cf_poly1305_update(&poly, header, nheader);
+ cf_poly1305_update(&poly, padbuf, PADLEN(nheader));
+
+ /* || cipher */
+ if (mode == ENCRYPT)
+ {
+ /* If we're encrypting, we compute the ciphertext
+ * before inputting it into the MAC. */
+ cf_chacha20_cipher(&chacha, input, output, nbytes);
+ cf_poly1305_update(&poly, output, nbytes);
+ } else {
+ /* Otherwise: decryption -- input the ciphertext.
+ * Delay actual decryption until we checked the MAC. */
+ cf_poly1305_update(&poly, input, nbytes);
+ }
+
+ /* || pad(cipher) */
+ cf_poly1305_update(&poly, padbuf, PADLEN(nbytes));
+
+ /* || len_64(aad) || len_64(cipher) */
+ write64_le(nheader, padbuf);
+ write64_le(nbytes, padbuf + 8);
+ cf_poly1305_update(&poly, padbuf, sizeof padbuf);
+
+ /* MAC computation is now complete. */
+
+ if (mode == ENCRYPT)
+ {
+ cf_poly1305_finish(&poly, tag);
+ mem_clean(&chacha, sizeof chacha);
+ return SUCCESS;
+ }
+
+ /* Decrypt mode: calculate tag, and check it.
+ * If it's correct, proceed with decryption. */
+ uint8_t checktag[16];
+ cf_poly1305_finish(&poly, checktag);
+
+ if (mem_eq(checktag, tag, sizeof checktag))
+ {
+ cf_chacha20_cipher(&chacha, input, output, nbytes);
+ mem_clean(&chacha, sizeof chacha);
+ mem_clean(checktag, sizeof checktag);
+ return SUCCESS;
+ } else {
+ mem_clean(output, nbytes);
+ mem_clean(&chacha, sizeof chacha);
+ mem_clean(checktag, sizeof checktag);
+ return FAILURE;
+ }
+}
+
+void cf_chacha20poly1305_encrypt(const uint8_t key[32],
+ const uint8_t nonce[12],
+ const uint8_t *header, size_t nheader,
+ const uint8_t *plaintext, size_t nbytes,
+ uint8_t *ciphertext,
+ uint8_t tag[16])
+{
+ process(key,
+ nonce,
+ header, nheader,
+ plaintext, nbytes,
+ ciphertext,
+ ENCRYPT,
+ tag);
+}
+
+int cf_chacha20poly1305_decrypt(const uint8_t key[32],
+ const uint8_t nonce[12],
+ const uint8_t *header, size_t nheader,
+ const uint8_t *ciphertext, size_t nbytes,
+ const uint8_t tag[16],
+ uint8_t *plaintext)
+{
+ uint8_t ourtag[16];
+ memcpy(ourtag, tag, sizeof ourtag);
+
+ return process(key,
+ nonce,
+ header, nheader,
+ ciphertext, nbytes,
+ plaintext,
+ DECRYPT,
+ ourtag);
+}
+