From 459d1a80c88d3be8b41c52ba0dcf1de511717750 Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Fri, 16 Aug 2019 12:49:33 +0100 Subject: [PATCH] symm/latinpoly-def.h: Implement Bernstein's `crypto_secretbox'. --- symm/.gitignore | 6 +++ symm/Makefile.am | 9 ++++ symm/chacha-poly1305.c | 12 ++++++ symm/latinpoly-def.h | 107 +++++++++++++++++++++++++++++++++++++++++++++++- symm/latinpoly.c | 3 ++ symm/latinpoly.h | 10 ++++- symm/salsa20-poly1305.c | 12 ++++++ symm/t/salsa20.local | 12 ++++++ 8 files changed, 169 insertions(+), 2 deletions(-) diff --git a/symm/.gitignore b/symm/.gitignore index adc9d880..5c18b126 100644 --- a/symm/.gitignore +++ b/symm/.gitignore @@ -46,6 +46,9 @@ /xchacha20.h /xchacha12.h /xchacha8.h +/chacha20-naclbox.h +/chacha12-naclbox.h +/chacha8-naclbox.h /chacha20-poly1305.h /chacha12-poly1305.h /chacha8-poly1305.h @@ -58,6 +61,9 @@ /xsalsa20.h /xsalsa2012.h /xsalsa208.h +/salsa20-naclbox.h +/salsa2012-naclbox.h +/salsa208-naclbox.h /salsa20-poly1305.h /salsa2012-poly1305.h /salsa208-poly1305.h diff --git a/symm/Makefile.am b/symm/Makefile.am index a4f45e9d..2a43f077 100644 --- a/symm/Makefile.am +++ b/symm/Makefile.am @@ -604,12 +604,21 @@ libsymmtest_la_SOURCES += latinpoly-test.c latinpoly-test.h ALL_AEADS += chacha20-poly1305 salsa20-poly1305 ALL_AEADS += chacha12-poly1305 salsa2012-poly1305 ALL_AEADS += chacha8-poly1305 salsa208-poly1305 +ALL_AEADS += chacha20-naclbox salsa20-naclbox +ALL_AEADS += chacha12-naclbox salsa2012-naclbox +ALL_AEADS += chacha8-naclbox salsa208-naclbox STUBS_HDR += ChaCha20-Poly1305,chacha20-poly1305,latinpoly STUBS_HDR += ChaCha12-Poly1305,chacha12-poly1305,latinpoly STUBS_HDR += ChaCha8-Poly1305,chacha8-poly1305,latinpoly STUBS_HDR += Salsa20-Poly1305,salsa20-poly1305,latinpoly STUBS_HDR += Salsa20/12-Poly1305,salsa2012-poly1305,latinpoly STUBS_HDR += Salsa20/8-Poly1305,salsa208-poly1305,latinpoly +STUBS_HDR += ChaCha20-NaClBox,chacha20-naclbox,latinpoly +STUBS_HDR += ChaCha12-NaClBox,chacha12-naclbox,latinpoly +STUBS_HDR += ChaCha8-NaClBox,chacha8-naclbox,latinpoly +STUBS_HDR += Salsa20-NaClBox,salsa20-naclbox,latinpoly +STUBS_HDR += Salsa20/12-NaClBox,salsa2012-naclbox,latinpoly +STUBS_HDR += Salsa20/8-NaClBox,salsa208-naclbox,latinpoly TESTS += chacha-poly1305.t$(EXEEXT) TESTS += salsa20-poly1305.t$(EXEEXT) diff --git a/symm/chacha-poly1305.c b/symm/chacha-poly1305.c index f307e6b2..657987ee 100644 --- a/symm/chacha-poly1305.c +++ b/symm/chacha-poly1305.c @@ -50,6 +50,12 @@ static int check_chacha12_poly1305(dstr *v) { return latinpoly_test(&chacha12_poly1305, v); } static int check_chacha8_poly1305(dstr *v) { return latinpoly_test(&chacha8_poly1305, v); } +static int check_chacha20_naclbox(dstr *v) + { return latinpoly_test(&chacha20_naclbox, v); } +static int check_chacha12_naclbox(dstr *v) + { return latinpoly_test(&chacha12_naclbox, v); } +static int check_chacha8_naclbox(dstr *v) + { return latinpoly_test(&chacha8_naclbox, v); } static const test_chunk tests[] = { { "chacha20-poly1305", check_chacha20_poly1305, @@ -58,6 +64,12 @@ static const test_chunk tests[] = { { &type_hex, &type_hex, &type_hex, &type_hex, &type_hex, &type_hex } }, { "chacha8-poly1305", check_chacha8_poly1305, { &type_hex, &type_hex, &type_hex, &type_hex, &type_hex, &type_hex } }, + { "chacha20-naclbox", check_chacha20_naclbox, + { &type_hex, &type_hex, &type_hex, &type_hex, &type_hex, &type_hex } }, + { "chacha12-naclbox", check_chacha12_naclbox, + { &type_hex, &type_hex, &type_hex, &type_hex, &type_hex, &type_hex } }, + { "chacha8-naclbox", check_chacha8_naclbox, + { &type_hex, &type_hex, &type_hex, &type_hex, &type_hex, &type_hex } }, { 0, 0, { 0 } } #undef TEST }; diff --git a/symm/latinpoly-def.h b/symm/latinpoly-def.h index 404098f9..af917fad 100644 --- a/symm/latinpoly-def.h +++ b/symm/latinpoly-def.h @@ -91,10 +91,12 @@ extern const octet latinpoly_noncesz[], latinpoly_tagsz[]; /* AAD methods. */ extern void latinpoly_aadhash_poly1305(gaead_aad */*a*/, const void */*h*/, size_t /*hsz*/); +extern void latinpoly_aadhash_naclbox(gaead_aad */*a*/, + const void */*h*/, size_t /*hsz*/); extern void latinpoly_aaddestroy(gaead_aad */*a*/); /* Variants. */ -enum { LPVAR_POLY1305 }; +enum { LPVAR_NACLBOX, LPVAR_POLY1305 }; /* --- @latinpoly_tag@ --- * * @@ -146,6 +148,9 @@ static int reinit_##latin(x##latin##_ctx *ctx, int var, \ poly1305_keyinit(&pk, b, POLY1305_KEYSZ); \ poly1305_macinit(ctpoly, &pk, b + POLY1305_KEYSZ); \ switch (var) { \ + case LPVAR_NACLBOX: \ + aadpoly->count = 0; aadpoly->nbuf = 0; \ + break; \ case LPVAR_POLY1305: \ poly1305_macinit(aadpoly, &pk, b + POLY1305_KEYSZ); \ latin##_encrypt(&ctx->s, 0, 0, SALSA20_OUTSZ - sizeof(b)); \ @@ -161,6 +166,8 @@ static int reinit_##latin(x##latin##_ctx *ctx, int var, \ static const gaead_aadops gaops_##latin##_poly1305 = \ { &latin##_poly1305, 0, latinpoly_aadhash_poly1305, latinpoly_aaddestroy }; \ \ +static const gaead_aadops gaops_##latin##_naclbox = \ + { &latin##_naclbox, 0, latinpoly_aadhash_naclbox, latinpoly_aaddestroy }; \ \ /* Encryption operations. */ \ \ @@ -183,6 +190,15 @@ static int gereinit_##latin##_poly1305(gaead_enc *e, \ &enc->aad.poly, &enc->poly, n, nsz)); \ } \ \ +static int gereinit_##latin##_naclbox(gaead_enc *e, \ + const void *n, size_t nsz, \ + size_t hsz, size_t msz, size_t tsz) \ +{ \ + gectx_##latin *enc = (gectx_##latin *)e; \ + return (reinit_##latin(&enc->ctx, LPVAR_NACLBOX, \ + &enc->aad.poly, &enc->poly, n, nsz)); \ +} \ + \ static int geenc_##latin(gaead_enc *e, \ const void *m, size_t msz, buf *b) \ { \ @@ -218,6 +234,17 @@ static int gedone_##latin##_poly1305(gaead_enc *e, const gaead_aad *a, \ return (0); \ } \ \ +static int gedone_##latin##_naclbox(gaead_enc *e, const gaead_aad *a, \ + buf *b, void *t, size_t tsz) \ +{ \ + gectx_##latin *enc = (gectx_##latin *)e; \ + const latinpoly_aad *aad = (const latinpoly_aad *)a; \ + \ + if (gedone_##latin##_common(enc, aad, b, tsz)) return (-1); \ + poly1305_done(&enc->poly, t); \ + return (0); \ +} \ + \ static void gedestroy_##latin(gaead_enc *e) \ { gectx_##latin *enc = (gectx_##latin *)e; BURN(*enc); S_DESTROY(enc); } \ \ @@ -225,6 +252,10 @@ static gaead_encops geops_##latin##_poly1305 = \ { &latin##_poly1305, geaad_##latin, gereinit_##latin##_poly1305, \ geenc_##latin, gedone_##latin##_poly1305, gedestroy_##latin }; \ \ +static gaead_encops geops_##latin##_naclbox = \ + { &latin##_naclbox, geaad_##latin, gereinit_##latin##_naclbox, \ + geenc_##latin, gedone_##latin##_naclbox, gedestroy_##latin }; \ + \ /* Decryption operations. */ \ \ typedef struct gdctx_##latin { \ @@ -246,6 +277,15 @@ static int gdreinit_##latin##_poly1305(gaead_dec *d, \ &dec->aad.poly, &dec->poly, n, nsz)); \ } \ \ +static int gdreinit_##latin##_naclbox(gaead_dec *d, \ + const void *n, size_t nsz, \ + size_t hsz, size_t msz, size_t tsz) \ +{ \ + gdctx_##latin *dec = (gdctx_##latin *)d; \ + return (reinit_##latin(&dec->ctx, LPVAR_NACLBOX, \ + &dec->aad.poly, &dec->poly, n, nsz)); \ +} \ + \ static int gddec_##latin(gaead_dec *d, \ const void *c, size_t csz, buf *b) \ { \ @@ -283,6 +323,19 @@ static int gddone_##latin##_poly1305(gaead_dec *d, const gaead_aad *a, \ else return (0); \ } \ \ +static int gddone_##latin##_naclbox(gaead_dec *d, const gaead_aad *a, \ + buf *b, const void *t, size_t tsz) \ +{ \ + gdctx_##latin *dec = (gdctx_##latin *)d; \ + const latinpoly_aad *aad = (const latinpoly_aad *)a; \ + octet u[POLY1305_TAGSZ]; \ + \ + if (gddone_##latin##_common(dec, aad, b, tsz)) return (-1); \ + poly1305_done(&dec->poly, u); \ + if (ct_memeq(t, u, POLY1305_TAGSZ)) return (+1); \ + else return (0); \ +} \ + \ static void gddestroy_##latin(gaead_dec *d) \ { gdctx_##latin *dec = (gdctx_##latin *)d; BURN(*dec); S_DESTROY(dec); } \ \ @@ -290,6 +343,10 @@ static gaead_decops gdops_##latin##_poly1305 = \ { &latin##_poly1305, gdaad_##latin, gdreinit_##latin##_poly1305, \ gddec_##latin, gddone_##latin##_poly1305, gddestroy_##latin }; \ \ +static gaead_decops gdops_##latin##_naclbox = \ + { &latin##_poly1305, gdaad_##latin, gdreinit_##latin##_naclbox, \ + gddec_##latin, gddone_##latin##_naclbox, gddestroy_##latin }; \ + \ /* Key operations. */ \ \ static gaead_enc *gkenc_##latin##_poly1305(const gaead_key *k, \ @@ -309,6 +366,23 @@ static gaead_enc *gkenc_##latin##_poly1305(const gaead_key *k, \ return (&enc->e); \ } \ \ +static gaead_enc *gkenc_##latin##_naclbox(const gaead_key *k, \ + const void *n, size_t nsz, \ + size_t hsz, size_t msz, \ + size_t tsz) \ +{ \ + latinpoly_key *key = (latinpoly_key *)k; \ + gectx_##latin *enc = S_CREATE(gectx_##latin); \ + \ + enc->e.ops = &geops_##latin##_naclbox; \ + enc->aad.a.ops = &gaops_##latin##_naclbox; \ + x##latin##_init(&enc->ctx, key->key, key->ksz, 0); \ + if (reinit_##latin(&enc->ctx, LPVAR_NACLBOX, \ + &enc->aad.poly, &enc->poly, n, nsz)) \ + { gedestroy_##latin(&enc->e); return (0); } \ + return (&enc->e); \ +} \ + \ static gaead_dec *gkdec_##latin##_poly1305(const gaead_key *k, \ const void *n, size_t nsz, \ size_t hsz, size_t msz, \ @@ -326,6 +400,23 @@ static gaead_dec *gkdec_##latin##_poly1305(const gaead_key *k, \ return (&dec->d); \ } \ \ +static gaead_dec *gkdec_##latin##_naclbox(const gaead_key *k, \ + const void *n, size_t nsz, \ + size_t hsz, size_t msz, \ + size_t tsz) \ +{ \ + latinpoly_key *key = (latinpoly_key *)k; \ + gdctx_##latin *dec = S_CREATE(gdctx_##latin); \ + \ + dec->d.ops = &gdops_##latin##_naclbox; \ + dec->aad.a.ops = &gaops_##latin##_naclbox; \ + x##latin##_init(&dec->ctx, key->key, key->ksz, 0); \ + if (reinit_##latin(&dec->ctx, LPVAR_NACLBOX, \ + &dec->aad.poly, &dec->poly, n, nsz)) \ + { gddestroy_##latin(&dec->d); return (0); } \ + return (&dec->d); \ +} \ + \ static void gkdestroy_##latin(gaead_key *k) \ { latinpoly_key *key = (latinpoly_key *)k; BURN(*key); S_DESTROY(key); } \ \ @@ -334,6 +425,11 @@ static const gaead_keyops gkops_##latin##_poly1305 = \ gkenc_##latin##_poly1305, gkdec_##latin##_poly1305, \ gkdestroy_##latin }; \ \ +static const gaead_keyops gkops_##latin##_naclbox = \ + { &latin##_naclbox, 0, \ + gkenc_##latin##_naclbox, gkdec_##latin##_naclbox, \ + gkdestroy_##latin }; \ + \ /* Class definition. */ \ \ static gaead_key *gkey_##latin##_common(const gaead_keyops *ops, \ @@ -349,10 +445,19 @@ static gaead_key *gkey_##latin##_common(const gaead_keyops *ops, \ static gaead_key *gkey_##latin##_poly1305(const void *k, size_t ksz) \ { return (gkey_##latin##_common(&gkops_##latin##_poly1305, k, ksz)); } \ \ +static gaead_key *gkey_##latin##_naclbox(const void *k, size_t ksz) \ + { return (gkey_##latin##_common(&gkops_##latin##_naclbox, k, ksz)); } \ + \ const gcaead latin##_poly1305 = { \ name "-poly1305", latin##_keysz, latinpoly_noncesz, latinpoly_tagsz, \ 64, 0, 0, AEADF_AADNDEP, \ gkey_##latin##_poly1305 \ +}; \ + \ +const gcaead latin##_naclbox = { \ + name "-naclbox", latin##_keysz, latinpoly_noncesz, latinpoly_tagsz, \ + 64, 0, 0, AEADF_AADNDEP | AEADF_NOAAD, \ + gkey_##latin##_naclbox \ }; /*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/latinpoly.c b/symm/latinpoly.c index a4aad363..29ba71ab 100644 --- a/symm/latinpoly.c +++ b/symm/latinpoly.c @@ -54,6 +54,9 @@ void latinpoly_aadhash_poly1305(gaead_aad *a, const void *h, size_t hsz) poly1305_hash(&aad->poly, h, hsz); } +void latinpoly_aadhash_naclbox(gaead_aad *a, const void *h, size_t hsz) + { assert(!hsz); } + void latinpoly_aaddestroy(gaead_aad *a) { ; } /* --- @latinpoly_tag@ --- * diff --git a/symm/latinpoly.h b/symm/latinpoly.h index 2efcd002..a9bb25ee 100644 --- a/symm/latinpoly.h +++ b/symm/latinpoly.h @@ -44,6 +44,12 @@ * except that an application should not mix nonce sizes with the same key. * (It is possible to do this safely, but it requires detailed understanding * of how everything fits together and isn't worth the effort.) + * + * The @salsa20_naclbox@ with a 192-bit nonce is exactly the scheme + * implemented in Bernstein's `NaCl' library as @crypto_secretbox@, except + * that it's flexible regarding tag placement rather than insisting on + * prefixing it to the ciphertext. Unlike NaCl, we provide a restartable + * interface, and allow the use of other ciphers and nonce lengths. */ #ifndef CATACOMB_LATINPOLY_H @@ -63,7 +69,9 @@ extern const gcaead chacha20_poly1305, chacha12_poly1305, chacha8_poly1305, - salsa20_poly1305, salsa2012_poly1305, salsa208_poly1305; + chacha20_naclbox, chacha12_naclbox, chacha8_naclbox, + salsa20_poly1305, salsa2012_poly1305, salsa208_poly1305, + salsa20_naclbox, salsa2012_naclbox, salsa208_naclbox; /*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/salsa20-poly1305.c b/symm/salsa20-poly1305.c index 55ba69a9..201a0832 100644 --- a/symm/salsa20-poly1305.c +++ b/symm/salsa20-poly1305.c @@ -50,6 +50,12 @@ static int check_salsa2012_poly1305(dstr *v) { return latinpoly_test(&salsa2012_poly1305, v); } static int check_salsa208_poly1305(dstr *v) { return latinpoly_test(&salsa208_poly1305, v); } +static int check_salsa20_naclbox(dstr *v) + { return latinpoly_test(&salsa20_naclbox, v); } +static int check_salsa2012_naclbox(dstr *v) + { return latinpoly_test(&salsa2012_naclbox, v); } +static int check_salsa208_naclbox(dstr *v) + { return latinpoly_test(&salsa208_naclbox, v); } static const test_chunk tests[] = { { "salsa20-poly1305", check_salsa20_poly1305, @@ -58,6 +64,12 @@ static const test_chunk tests[] = { { &type_hex, &type_hex, &type_hex, &type_hex, &type_hex, &type_hex } }, { "salsa20/8-poly1305", check_salsa208_poly1305, { &type_hex, &type_hex, &type_hex, &type_hex, &type_hex, &type_hex } }, + { "salsa20-naclbox", check_salsa20_naclbox, + { &type_hex, &type_hex, &type_hex, &type_hex, &type_hex, &type_hex } }, + { "salsa20/12-naclbox", check_salsa2012_naclbox, + { &type_hex, &type_hex, &type_hex, &type_hex, &type_hex, &type_hex } }, + { "salsa20/8-nacblox", check_salsa208_naclbox, + { &type_hex, &type_hex, &type_hex, &type_hex, &type_hex, &type_hex } }, { 0, 0, { 0 } } #undef TEST }; diff --git a/symm/t/salsa20.local b/symm/t/salsa20.local index 91887492..b03d2c3a 100644 --- a/symm/t/salsa20.local +++ b/symm/t/salsa20.local @@ -87,3 +87,15 @@ xsalsa20 { be075fc53c81f2d5cf141316ebeb0c7b5228c52a4c62cbd44b66849b64244ffce5ecbaaf33bd751a1ac728d45e6c61296cdc3c01233561f41db66cce314adb310e3be8250c46f06dceea3a7fa1348057e2f6556ad6b1318a024a838f21af1fde048977eb48f59ffd4924ca1c60902e52f0a089bc76897040e082f937763848645e0705 8e993b9f48681273c29650ba32fc76ce48332ea7164d96a4476fb8c531a1186ac0dfc17c98dce87b4da7f011ec48c97271d2c20f9b928fe2270d6fb863d51738b48eeee314a7cc8ab932164548e526ae90224368517acfeabd6bb3732bc0e9da99832b61ca01b6de56244a9e88d5f9b37973f622a43d14a6599b1f654cb45a74e355a5; } + +salsa20-naclbox { + ## Taken from Daniel J. Bernstein, `Cryptography in NaCl', + ## https://cr.yp.to/highspeed/naclcrypto-20090310.pdf + + 1b27556473e985d462cd51197a9a46c76009549eac6474f206c4ee0844f68389 + 69696ee955b62b73cd62bda875fc73d68219e0036b7a0b37 + "" + be075fc53c81f2d5cf141316ebeb0c7b5228c52a4c62cbd44b66849b64244ffce5ecbaaf33bd751a1ac728d45e6c61296cdc3c01233561f41db66cce314adb310e3be8250c46f06dceea3a7fa1348057e2f6556ad6b1318a024a838f21af1fde048977eb48f59ffd4924ca1c60902e52f0a089bc76897040e082f937763848645e0705 + 8e993b9f48681273c29650ba32fc76ce48332ea7164d96a4476fb8c531a1186ac0dfc17c98dce87b4da7f011ec48c97271d2c20f9b928fe2270d6fb863d51738b48eeee314a7cc8ab932164548e526ae90224368517acfeabd6bb3732bc0e9da99832b61ca01b6de56244a9e88d5f9b37973f622a43d14a6599b1f654cb45a74e355a5 + f3ffc7703f9400e52a7dfb4b3d3305d9; +} -- 2.11.0