extract chachapoly logic in cifra so that it can be reused
diff --git a/lib/chacha20poly1305.h b/lib/chacha20poly1305.h
new file mode 100644
index 0000000..1b78dd2
--- /dev/null
+++ b/lib/chacha20poly1305.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2016-2023 DeNA Co., Ltd., Kazuho Oku, Lars Eggert, Christian
+ Huitema, Fastly
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include <stddef.h>
+#include "picotls.h"
+
+struct chacha20poly1305_context_t {
+ ptls_aead_context_t super;
+ ptls_cipher_context_t *chacha;
+ uint8_t static_iv[PTLS_CHACHA20POLY1305_IV_SIZE];
+ size_t aadlen;
+ size_t textlen;
+ void (*poly1305_init)(struct chacha20poly1305_context_t *, const void *);
+ void (*poly1305_update)(struct chacha20poly1305_context_t *, const void *, size_t);
+ void (*poly1305_finish)(struct chacha20poly1305_context_t *, void *);
+};
+
+static void chacha20poly1305_write_u64(uint8_t *buf, uint64_t v)
+{
+ *buf++ = v & 0xff;
+ *buf++ = (v >> 8) & 0xff;
+ *buf++ = (v >> 16) & 0xff;
+ *buf++ = (v >> 24) & 0xff;
+ *buf++ = (v >> 32) & 0xff;
+ *buf++ = (v >> 40) & 0xff;
+ *buf++ = (v >> 48) & 0xff;
+ *buf = (v >> 56) & 0xff;
+}
+
+static void chacha20poly1305_encrypt_pad(struct chacha20poly1305_context_t *ctx, size_t n)
+{
+ static const uint8_t zeros[16] = {0};
+ if (n % 16 != 0)
+ ctx->poly1305_update(ctx, zeros, 16 - (n % 16));
+}
+
+static void chacha20poly1305_finalize(struct chacha20poly1305_context_t *ctx, uint8_t *tag)
+{
+ uint8_t lenbuf[16];
+
+ chacha20poly1305_encrypt_pad(ctx, ctx->textlen);
+
+ chacha20poly1305_write_u64(lenbuf, ctx->aadlen);
+ chacha20poly1305_write_u64(lenbuf + 8, ctx->textlen);
+ ctx->poly1305_update(ctx, lenbuf, sizeof(lenbuf));
+
+ ctx->poly1305_finish(ctx, tag);
+}
+
+static void chacha20poly1305_dispose_crypto(ptls_aead_context_t *_ctx)
+{
+ struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
+ ptls_cipher_free(ctx->chacha);
+}
+
+static void chacha20poly1305_init(ptls_aead_context_t *_ctx, uint64_t seq, const void *aad, size_t aadlen)
+{
+ struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
+ uint8_t tmpbuf[64];
+
+ /* init chacha */
+ memset(tmpbuf, 0, 16 - PTLS_CHACHA20POLY1305_IV_SIZE);
+ ptls_aead__build_iv(ctx->super.algo, tmpbuf + 16 - PTLS_CHACHA20POLY1305_IV_SIZE, ctx->static_iv, seq);
+ ptls_cipher_init(ctx->chacha, tmpbuf);
+
+ /* init poly1305 */
+ memset(tmpbuf, 0, sizeof(tmpbuf));
+ ptls_cipher_encrypt(ctx->chacha, tmpbuf, tmpbuf, 64);
+ ctx->poly1305_init(ctx, tmpbuf);
+
+ ptls_clear_memory(tmpbuf, sizeof(tmpbuf));
+
+ /* aad */
+ if (aadlen != 0) {
+ ctx->poly1305_update(ctx, aad, aadlen);
+ chacha20poly1305_encrypt_pad(ctx, aadlen);
+ }
+
+ ctx->aadlen = aadlen;
+ ctx->textlen = 0;
+}
+
+static size_t chacha20poly1305_encrypt_update(ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen)
+{
+ struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
+
+ ptls_cipher_encrypt(ctx->chacha, output, input, inlen);
+ ctx->poly1305_update(ctx, output, inlen);
+ ctx->textlen += inlen;
+
+ return inlen;
+}
+
+static size_t chacha20poly1305_encrypt_final(ptls_aead_context_t *_ctx, void *output)
+{
+ struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
+
+ chacha20poly1305_finalize(ctx, output);
+
+ return PTLS_CHACHA20POLY1305_TAG_SIZE;
+}
+
+static size_t chacha20poly1305_decrypt(ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen, uint64_t seq,
+ const void *aad, size_t aadlen)
+{
+ struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
+ uint8_t tag[PTLS_CHACHA20POLY1305_TAG_SIZE];
+ size_t ret;
+
+ if (inlen < sizeof(tag))
+ return SIZE_MAX;
+
+ chacha20poly1305_init(&ctx->super, seq, aad, aadlen);
+
+ ctx->poly1305_update(ctx, input, inlen - sizeof(tag));
+ ctx->textlen = inlen - sizeof(tag);
+
+ chacha20poly1305_finalize(ctx, tag);
+ if (ptls_mem_equal(tag, (const uint8_t *)input + inlen - sizeof(tag), sizeof(tag))) {
+ ptls_cipher_encrypt(ctx->chacha, output, input, inlen - sizeof(tag));
+ ret = inlen - sizeof(tag);
+ } else {
+ ret = SIZE_MAX;
+ }
+
+ ptls_clear_memory(tag, sizeof(tag));
+
+ return ret;
+}
+
+static void chacha20poly1305_xor_iv(ptls_aead_context_t *_ctx, const void *_bytes, size_t len)
+{
+ struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
+ const uint8_t *bytes = _bytes;
+
+ for (size_t i = 0; i < len; ++i)
+ ctx->static_iv[i] ^= bytes[i];
+}
+
+static int chacha20poly1305_setup_crypto(ptls_aead_context_t *_ctx, int is_enc, const void *key, const void *iv,
+ ptls_cipher_algorithm_t *chacha,
+ void (*poly1305_init)(struct chacha20poly1305_context_t *, const void *),
+ void (*poly1305_update)(struct chacha20poly1305_context_t *, const void *, size_t),
+ void (*poly1305_finish)(struct chacha20poly1305_context_t *, void *))
+{
+ struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
+
+ ctx->super.dispose_crypto = chacha20poly1305_dispose_crypto;
+ ctx->super.do_xor_iv = chacha20poly1305_xor_iv;
+ if (is_enc) {
+ ctx->super.do_encrypt_init = chacha20poly1305_init;
+ ctx->super.do_encrypt_update = chacha20poly1305_encrypt_update;
+ ctx->super.do_encrypt_final = chacha20poly1305_encrypt_final;
+ ctx->super.do_encrypt = ptls_aead__do_encrypt;
+ ctx->super.do_encrypt_v = ptls_aead__do_encrypt_v;
+ ctx->super.do_decrypt = NULL;
+ } else {
+ ctx->super.do_encrypt_init = NULL;
+ ctx->super.do_encrypt_update = NULL;
+ ctx->super.do_encrypt_final = NULL;
+ ctx->super.do_encrypt = NULL;
+ ctx->super.do_encrypt_v = NULL;
+ ctx->super.do_decrypt = chacha20poly1305_decrypt;
+ }
+
+ if ((ctx->chacha = ptls_cipher_new(chacha, is_enc, key)) == NULL)
+ return PTLS_ERROR_LIBRARY;
+
+ memcpy(ctx->static_iv, iv, sizeof(ctx->static_iv));
+ ctx->poly1305_init = poly1305_init;
+ ctx->poly1305_update = poly1305_update;
+ ctx->poly1305_finish = poly1305_finish;
+
+ return 0;
+}
diff --git a/lib/cifra/chacha20.c b/lib/cifra/chacha20.c
index 3332877..d56a8ca 100644
--- a/lib/cifra/chacha20.c
+++ b/lib/cifra/chacha20.c
@@ -27,6 +27,7 @@
#include "sha2.h"
#include "picotls.h"
#include "picotls/minicrypto.h"
+#include "../chacha20poly1305.h"
struct chacha20_context_t {
ptls_cipher_context_t super;
@@ -64,155 +65,33 @@
return 0;
}
-struct chacha20poly1305_context_t {
- ptls_aead_context_t super;
- uint8_t key[PTLS_CHACHA20_KEY_SIZE];
- uint8_t static_iv[PTLS_CHACHA20POLY1305_IV_SIZE];
- cf_chacha20_ctx chacha;
+struct cifra_chacha20poly1305_context_t {
+ struct chacha20poly1305_context_t super;
cf_poly1305 poly;
- size_t aadlen;
- size_t textlen;
};
-static void chacha20poly1305_dispose_crypto(ptls_aead_context_t *_ctx)
+static void cifra_poly1305_init(struct chacha20poly1305_context_t *_ctx, const void *rs)
{
- struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
-
- /* clear all memory except super */
- ptls_clear_memory(&ctx->key, sizeof(*ctx) - offsetof(struct chacha20poly1305_context_t, key));
+ struct cifra_chacha20poly1305_context_t *ctx = (struct cifra_chacha20poly1305_context_t *)_ctx;
+ cf_poly1305_init(&ctx->poly, rs, (const uint8_t *)rs + 16);
}
-static const uint8_t zeros64[64] = {0};
-
-static void chacha20poly1305_encrypt_pad(cf_poly1305 *poly, size_t n)
+static void cifra_poly1305_update(struct chacha20poly1305_context_t *_ctx, const void *input, size_t len)
{
- if (n % 16 != 0)
- cf_poly1305_update(poly, zeros64, 16 - (n % 16));
+ struct cifra_chacha20poly1305_context_t *ctx = (struct cifra_chacha20poly1305_context_t *)_ctx;
+ cf_poly1305_update(&ctx->poly, input, len);
}
-static void chacha20poly1305_finalize(struct chacha20poly1305_context_t *ctx, uint8_t *tag)
+static void cifra_poly1305_finish(struct chacha20poly1305_context_t *_ctx, void *tag)
{
- uint8_t lenbuf[16];
-
- chacha20poly1305_encrypt_pad(&ctx->poly, ctx->textlen);
-
- write64_le(ctx->aadlen, lenbuf);
- write64_le(ctx->textlen, lenbuf + 8);
- cf_poly1305_update(&ctx->poly, lenbuf, sizeof(lenbuf));
-
+ struct cifra_chacha20poly1305_context_t *ctx = (struct cifra_chacha20poly1305_context_t *)_ctx;
cf_poly1305_finish(&ctx->poly, tag);
}
-static void chacha20poly1305_init(ptls_aead_context_t *_ctx, uint64_t seq, const void *aad, size_t aadlen)
+static int cifra_chacha20poly1305_setup_crypto(ptls_aead_context_t *ctx, int is_enc, const void *key, const void *iv)
{
- struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
- uint8_t tmpbuf[64];
-
- /* init chacha */
- memset(tmpbuf, 0, 16 - PTLS_CHACHA20POLY1305_IV_SIZE);
- ptls_aead__build_iv(ctx->super.algo, tmpbuf + 16 - PTLS_CHACHA20POLY1305_IV_SIZE, ctx->static_iv, seq);
- cf_chacha20_init_custom(&ctx->chacha, ctx->key, sizeof(ctx->key), tmpbuf, 4);
-
- /* init poly1305 (by using first 16 bytes of the key stream of the first block) */
- cf_chacha20_cipher(&ctx->chacha, zeros64, tmpbuf, 64);
- cf_poly1305_init(&ctx->poly, tmpbuf, tmpbuf + 16);
-
- ptls_clear_memory(tmpbuf, sizeof(tmpbuf));
-
- /* aad */
- if (aadlen != 0) {
- cf_poly1305_update(&ctx->poly, aad, aadlen);
- chacha20poly1305_encrypt_pad(&ctx->poly, aadlen);
- }
-
- ctx->aadlen = aadlen;
- ctx->textlen = 0;
-}
-
-static size_t chacha20poly1305_encrypt_update(ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen)
-{
- struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
-
- cf_chacha20_cipher(&ctx->chacha, input, output, inlen);
- cf_poly1305_update(&ctx->poly, output, inlen);
- ctx->textlen += inlen;
-
- return inlen;
-}
-
-static size_t chacha20poly1305_encrypt_final(ptls_aead_context_t *_ctx, void *output)
-{
- struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
-
- chacha20poly1305_finalize(ctx, output);
-
- ptls_clear_memory(&ctx->chacha, sizeof(ctx->chacha));
- return PTLS_CHACHA20POLY1305_TAG_SIZE;
-}
-
-static size_t chacha20poly1305_decrypt(ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen, uint64_t seq,
- const void *aad, size_t aadlen)
-{
- struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
- uint8_t tag[PTLS_CHACHA20POLY1305_TAG_SIZE];
- size_t ret;
-
- if (inlen < sizeof(tag))
- return SIZE_MAX;
-
- chacha20poly1305_init(&ctx->super, seq, aad, aadlen);
-
- cf_poly1305_update(&ctx->poly, input, inlen - sizeof(tag));
- ctx->textlen = inlen - sizeof(tag);
-
- chacha20poly1305_finalize(ctx, tag);
- if (mem_eq(tag, (const uint8_t *)input + inlen - sizeof(tag), sizeof(tag))) {
- cf_chacha20_cipher(&ctx->chacha, input, output, inlen - sizeof(tag));
- ret = inlen - sizeof(tag);
- } else {
- ret = SIZE_MAX;
- }
-
- ptls_clear_memory(tag, sizeof(tag));
- ptls_clear_memory(&ctx->poly, sizeof(ctx->poly));
-
- return ret;
-}
-
-static void chacha20poly1305_xor_iv(ptls_aead_context_t *_ctx, const void *_bytes, size_t len)
-{
- struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
- const uint8_t *bytes = _bytes;
-
- for (size_t i = 0; i < len; ++i)
- ctx->static_iv[i] ^= bytes[i];
-}
-
-static int aead_chacha20poly1305_setup_crypto(ptls_aead_context_t *_ctx, int is_enc, const void *key, const void *iv)
-{
- struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
-
- ctx->super.dispose_crypto = chacha20poly1305_dispose_crypto;
- ctx->super.do_xor_iv = chacha20poly1305_xor_iv;
- if (is_enc) {
- ctx->super.do_encrypt_init = chacha20poly1305_init;
- ctx->super.do_encrypt_update = chacha20poly1305_encrypt_update;
- ctx->super.do_encrypt_final = chacha20poly1305_encrypt_final;
- ctx->super.do_encrypt = ptls_aead__do_encrypt;
- ctx->super.do_encrypt_v = ptls_aead__do_encrypt_v;
- ctx->super.do_decrypt = NULL;
- } else {
- ctx->super.do_encrypt_init = NULL;
- ctx->super.do_encrypt_update = NULL;
- ctx->super.do_encrypt_final = NULL;
- ctx->super.do_encrypt = NULL;
- ctx->super.do_encrypt_v = NULL;
- ctx->super.do_decrypt = chacha20poly1305_decrypt;
- }
-
- memcpy(ctx->key, key, sizeof(ctx->key));
- memcpy(ctx->static_iv, iv, sizeof(ctx->static_iv));
- return 0;
+ return chacha20poly1305_setup_crypto(ctx, is_enc, key, iv, &ptls_minicrypto_chacha20, cifra_poly1305_init,
+ cifra_poly1305_update, cifra_poly1305_finish);
}
ptls_cipher_algorithm_t ptls_minicrypto_chacha20 = {
@@ -230,8 +109,8 @@
{PTLS_TLS12_CHACHAPOLY_FIXED_IV_SIZE, PTLS_TLS12_CHACHAPOLY_RECORD_IV_SIZE},
0,
0,
- sizeof(struct chacha20poly1305_context_t),
- aead_chacha20poly1305_setup_crypto};
+ sizeof(struct cifra_chacha20poly1305_context_t),
+ cifra_chacha20poly1305_setup_crypto};
ptls_cipher_suite_t ptls_minicrypto_chacha20poly1305sha256 = {.id = PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256,
.name = PTLS_CIPHER_SUITE_NAME_CHACHA20_POLY1305_SHA256,
.aead = &ptls_minicrypto_chacha20poly1305,
diff --git a/picotls.xcodeproj/project.pbxproj b/picotls.xcodeproj/project.pbxproj
index 9a917b3..17b2483 100644
--- a/picotls.xcodeproj/project.pbxproj
+++ b/picotls.xcodeproj/project.pbxproj
@@ -8,6 +8,8 @@
/* Begin PBXBuildFile section */
081F00CA2918823200534A86 /* hpke.c in Sources */ = {isa = PBXBuildFile; fileRef = 081F00C92918823200534A86 /* hpke.c */; };
+ 08A835E22995E04100D872CE /* chacha20poly1305.h in Headers */ = {isa = PBXBuildFile; fileRef = 08A835E12995E04100D872CE /* chacha20poly1305.h */; };
+ 08A835E32995E04100D872CE /* chacha20poly1305.h in Headers */ = {isa = PBXBuildFile; fileRef = 08A835E12995E04100D872CE /* chacha20poly1305.h */; };
08F0FDF62910F67A00EE657D /* hpke.c in Sources */ = {isa = PBXBuildFile; fileRef = 08F0FDF52910F67A00EE657D /* hpke.c */; };
105900431DC8D57000FB4085 /* picotls.c in Sources */ = {isa = PBXBuildFile; fileRef = 106530E91D9B7C13005B2C60 /* picotls.c */; };
105900441DC8D57000FB4085 /* picotest.c in Sources */ = {isa = PBXBuildFile; fileRef = 106530E31D9B4021005B2C60 /* picotest.c */; };
@@ -203,6 +205,7 @@
081F00CC291A358800534A86 /* asn1.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = asn1.h; sourceTree = "<group>"; };
081F00CD291A358800534A86 /* pembase64.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = pembase64.h; sourceTree = "<group>"; };
081F00CE291A358800534A86 /* ptlsbcrypt.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ptlsbcrypt.h; sourceTree = "<group>"; };
+ 08A835E12995E04100D872CE /* chacha20poly1305.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = chacha20poly1305.h; sourceTree = "<group>"; };
08B3298229419DFC009D6766 /* ech-live.t */ = {isa = PBXFileReference; lastKnownFileType = text; path = "ech-live.t"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.perl; };
08F0FDF52910F67A00EE657D /* hpke.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = hpke.c; sourceTree = "<group>"; };
105900241DC8D37500FB4085 /* aes.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = aes.c; path = src/aes.c; sourceTree = "<group>"; };
@@ -434,6 +437,7 @@
E99B75DE1F5CDDB500CF503E /* asn1.c */,
E9E4B12A2180530400514B47 /* certificate_compression.c */,
E9F20BDF22E34B210018D260 /* cifra */,
+ 08A835E12995E04100D872CE /* chacha20poly1305.h */,
1059003F1DC8D53200FB4085 /* cifra.c */,
E97577022212405D00D1EF74 /* ffx.c */,
E9B43DBF24619D1700824E51 /* fusion.c */,
@@ -560,6 +564,7 @@
buildActionMask = 2147483647;
files = (
105900A21DC8E20D00FB4085 /* openssl.h in Headers */,
+ 08A835E32995E04100D872CE /* chacha20poly1305.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -608,6 +613,7 @@
10EACB0E1DCEAF0F00CA0341 /* chash.h in Headers */,
10EACB0F1DCEAF0F00CA0341 /* sha2.h in Headers */,
E9BC76DE1EF3CCD100EB7A09 /* poly1305.h in Headers */,
+ 08A835E22995E04100D872CE /* chacha20poly1305.h in Headers */,
10EACB101DCEAF0F00CA0341 /* aes.h in Headers */,
10EACB111DCEAF0F00CA0341 /* minicrypto.h in Headers */,
10EACB121DCEAF0F00CA0341 /* gf128.h in Headers */,