aead: replace init args with implementation-specific params struct

This unbreaks {,X}ChaCha20-Poly1305. Thanks to the use of params, the
{,X}ChaCha20-Poly1305 doesn't need to reach into the guts of ChaCha20
state. Move {en,de}cryption and key setup into its own functions.

This breaks the tests, which will be fixed in the following commit.
This commit is contained in:
Lucas Gabriel Vuotto 2024-06-07 23:29:29 +00:00
parent 79ce4400dd
commit a6208487e4
4 changed files with 306 additions and 241 deletions

14
aead.c
View File

@ -20,18 +20,16 @@
int int
lc_aead_seal(const struct lc_aead_impl *impl, uint8_t *out, size_t *outlen, lc_aead_seal(const struct lc_aead_impl *impl, uint8_t *out, size_t *outlen,
const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, const void *argparams, const uint8_t *aad, size_t aadlen,
const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen) const uint8_t *in, size_t inlen)
{ {
return impl->seal(out, outlen, key, keylen, iv, ivlen, aad, aadlen, in, return impl->seal(out, outlen, argparams, aad, aadlen, in, inlen);
inlen);
} }
int int
lc_aead_open(const struct lc_aead_impl *impl, uint8_t *out, size_t *outlen, lc_aead_open(const struct lc_aead_impl *impl, uint8_t *out, size_t *outlen,
const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, const void *argparams, const uint8_t *aad, size_t aadlen,
const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen) const uint8_t *in, size_t inlen)
{ {
return impl->open(out, outlen, key, keylen, iv, ivlen, aad, aadlen, in, return impl->open(out, outlen, argparams, aad, aadlen, in, inlen);
inlen);
} }

10
aead.h
View File

@ -19,10 +19,8 @@
struct lc_aead_impl { struct lc_aead_impl {
int (*seal)(uint8_t *, size_t *, const uint8_t *, size_t, int (*seal)(uint8_t *, size_t *, const void *, const uint8_t *,
const uint8_t *, size_t, const uint8_t *, size_t, size_t, const uint8_t *, size_t);
const uint8_t *, size_t); int (*open)(uint8_t *, size_t *, const void *, const uint8_t *,
int (*open)(uint8_t *, size_t *, const uint8_t *, size_t, size_t, const uint8_t *, size_t);
const uint8_t *, size_t, const uint8_t *, size_t,
const uint8_t *, size_t);
}; };

View File

@ -16,10 +16,7 @@
#include "lilcrypto.h" #include "lilcrypto.h"
#include "aead.h" #include "aead.h"
#include "auth_poly1305.h"
#include "cipher_chacha20.h"
#include "impl_chacha20.h" #include "impl_chacha20.h"
#include "impl_poly1305.h"
#include "util.h" #include "util.h"
@ -31,99 +28,230 @@
static const uint8_t zeropad[16]; static const uint8_t zeropad[16];
static int
aead_poly1305_keysetup(struct lc_cipher_ctx *cctx,
uint8_t akey[LC_POLY1305_KEYLEN], const void *initparams)
{
size_t i, olen, akeylen;
for (i = 0; i < LC_POLY1305_KEYLEN; i++)
akey[i] = 0;
if (!lc_cipher_encrypt_init(cctx, initparams) ||
!lc_cipher_encrypt_update(cctx, akey, &olen, akey,
LC_POLY1305_KEYLEN))
return 0;
akeylen = olen;
if (!lc_cipher_encrypt_final(cctx, akey + olen, &olen))
return 0;
akeylen += olen;
return akeylen == LC_POLY1305_KEYLEN;
}
static int static int
chacha20_poly1305_seal(uint8_t *out, size_t *outlen, const uint8_t *key, aead_poly1305_anycrypt(struct lc_cipher_ctx *cctx, uint8_t *out,
size_t keylen, const uint8_t *iv, size_t ivlen, const uint8_t *aad, size_t *outlen, const void *initparams, const uint8_t *in, size_t inlen)
size_t aadlen, const uint8_t *in, size_t inlen)
{ {
struct chacha20_ctx cctx; size_t olen;
struct poly1305_ctx pctx;
uint8_t poly1305_key[LC_POLY1305_KEYLEN];
uint8_t buf[sizeof(uint64_t) * 2];
size_t i, olen;
if (inlen > UINT64_MAX || aadlen > UINT64_MAX || if (!lc_cipher_encrypt_init(cctx, initparams) ||
inlen > SIZE_MAX - LC_POLY1305_TAGLEN || !lc_cipher_encrypt_update(cctx, out, &olen, in, inlen))
inlen > SIZE_MAX - CHACHA20_CHUNK + 1 || return 0;
(inlen + CHACHA20_CHUNK - 1) / CHACHA20_CHUNK > *outlen = olen;
CHACHA20_CTRMAX - 1) { if (!lc_cipher_encrypt_final(cctx, out + olen, &olen))
if (out == NULL) return 0;
*outlen = 0; *outlen += olen;
return *outlen == inlen;
}
static int
chacha20_poly1305_seal(uint8_t *out, size_t *outlen, const void *initparams,
const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen)
{
const struct lc_chacha20_poly1305_params *params = initparams;
struct lc_cipher_ctx *cctx = NULL;
struct lc_auth_ctx *actx = NULL;
struct lc_chacha20_params cparams;
struct lc_poly1305_params aparams;
uint8_t buf[sizeof(uint64_t) * 2];
size_t i, olen;
int ret = 0;
*outlen = 0;
/* inlen and aadlen are capped by design; enough space of tag. */
if (inlen > UINT64_MAX || aadlen > UINT64_MAX ||
inlen > SIZE_MAX - LC_POLY1305_TAGLEN)
return 0;
/* Counter 0 is used for deriving Poly1305 key. */
if (inlen > SIZE_MAX - (CHACHA20_CHUNK - 1) ||
(inlen + CHACHA20_CHUNK - 1) / CHACHA20_CHUNK >
CHACHA20_CTRMAX - 1)
return 0; return 0;
}
if (out == NULL) { if (out == NULL) {
*outlen = inlen + LC_POLY1305_TAGLEN; *outlen = inlen + LC_POLY1305_TAGLEN;
return 1; return 1;
} }
*outlen = 0; cctx = lc_cipher_ctx_new(lc_cipher_impl_chacha20());
if (cctx == NULL)
goto cleanup;
actx = lc_auth_ctx_new(lc_auth_impl_poly1305());
if (actx == NULL)
goto cleanup;
for (i = 0; i < LC_POLY1305_KEYLEN; i++) for (i = 0; i < sizeof(params->key); i++)
poly1305_key[i] = 0; cparams.key[i] = params->key[i];
if (!chacha20_common_init(&cctx, key, keylen, iv, ivlen) || for (i = 0; i < sizeof(params->nonce); i++)
!chacha20_common_update(&cctx, poly1305_key, &olen, poly1305_key, cparams.nonce[i] = params->nonce[i];
LC_POLY1305_KEYLEN))
return 0;
if (!chacha20_common_final(&cctx, poly1305_key + olen, &olen))
return 0;
if (!poly1305_init(&pctx, poly1305_key, LC_POLY1305_KEYLEN) || cparams.counter = 0;
!poly1305_update(&pctx, aad, aadlen)) if (!aead_poly1305_keysetup(cctx, aparams.key, &cparams))
return 0; goto cleanup;
if (!lc_auth_init(actx, &aparams) ||
!lc_auth_update(actx, aad, aadlen))
goto cleanup;
if (aadlen % 16 != 0) if (aadlen % 16 != 0)
if (!poly1305_update(&pctx, zeropad, 16 - (aadlen % 16))) if (!lc_auth_update(actx, zeropad, 16 - (aadlen % 16)))
return 0; goto cleanup;
if (!chacha20_common_init_from(&cctx, key, keylen, iv, ivlen, 1)) cparams.counter = 1;
return 0; if (!aead_poly1305_anycrypt(cctx, out, outlen, &cparams, in, inlen))
if (!chacha20_common_update(&cctx, out, &olen, in, inlen)) goto cleanup;
return 0;
*outlen = olen; if (!lc_auth_update(actx, out, inlen))
if (!chacha20_common_final(&cctx, out + olen, &olen)) goto cleanup;
return 0;
if (!poly1305_update(&pctx, out, inlen))
return 0;
if (inlen % 16 != 0) if (inlen % 16 != 0)
if (!poly1305_update(&pctx, zeropad, 16 - (inlen % 16))) if (!lc_auth_update(actx, zeropad, 16 - (inlen % 16)))
return 0; goto cleanup;
store64le(&buf[0], aadlen); store64le(&buf[0], aadlen);
store64le(&buf[sizeof(uint64_t)], inlen); store64le(&buf[sizeof(uint64_t)], inlen);
if (!poly1305_update(&pctx, buf, sizeof(buf)) || if (!lc_auth_update(actx, buf, sizeof(buf)) ||
!poly1305_final(&pctx, out + inlen, &olen)) !lc_auth_final(actx, out + inlen, &olen))
return 0; goto cleanup;
*outlen += olen;
if (*outlen != inlen + LC_POLY1305_TAGLEN)
goto cleanup;
ret = 1;
cleanup:
lc_scrub(buf, sizeof(buf)); lc_scrub(buf, sizeof(buf));
lc_scrub(poly1305_key, sizeof(poly1305_key)); lc_scrub(&aparams, sizeof(aparams));
lc_scrub(&cparams, sizeof(cparams));
lc_auth_ctx_free(actx);
lc_cipher_ctx_free(cctx);
*outlen = inlen + LC_POLY1305_TAGLEN; return ret;
return 1;
} }
static int static int
chacha20_poly1305_open(uint8_t *out, size_t *outlen, const uint8_t *key, xchacha20_poly1305_seal(uint8_t *out, size_t *outlen, const void *initparams,
size_t keylen, const uint8_t *iv, size_t ivlen, const uint8_t *aad, const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen)
size_t aadlen, const uint8_t *in, size_t inlen)
{ {
const uint8_t *tagp; const struct lc_xchacha20_poly1305_params *params = initparams;
struct chacha20_ctx cctx; struct lc_cipher_ctx *cctx = NULL;
struct poly1305_ctx pctx; struct lc_auth_ctx *actx = NULL;
uint8_t poly1305_key[LC_POLY1305_KEYLEN]; struct lc_xchacha20_params cparams;
uint8_t tag[LC_POLY1305_TAGLEN]; struct lc_poly1305_params aparams;
uint8_t buf[sizeof(uint64_t) * 2]; uint8_t buf[sizeof(uint64_t) * 2];
size_t i, olen, ctlen; size_t i, olen;
int ret = 0;
*outlen = 0;
/* inlen and aadlen are capped by design; enough space of tag. */
if (inlen > UINT64_MAX || aadlen > UINT64_MAX ||
inlen > SIZE_MAX - LC_POLY1305_TAGLEN)
return 0;
/* Counter 0 is used for deriving Poly1305 key. */
if (inlen > SIZE_MAX - (CHACHA20_CHUNK - 1) ||
(inlen + CHACHA20_CHUNK - 1) / CHACHA20_CHUNK >
CHACHA20_CTRMAX - 1)
return 0;
if (out == NULL) {
*outlen = inlen + LC_POLY1305_TAGLEN;
return 1;
}
cctx = lc_cipher_ctx_new(lc_cipher_impl_xchacha20());
if (cctx == NULL)
goto cleanup;
actx = lc_auth_ctx_new(lc_auth_impl_poly1305());
if (actx == NULL)
goto cleanup;
for (i = 0; i < sizeof(params->key); i++)
cparams.key[i] = params->key[i];
for (i = 0; i < sizeof(params->nonce); i++)
cparams.nonce[i] = params->nonce[i];
cparams.counter = 0;
if (!aead_poly1305_keysetup(cctx, aparams.key, &cparams))
goto cleanup;
if (!lc_auth_init(actx, &aparams) ||
!lc_auth_update(actx, aad, aadlen))
goto cleanup;
if (aadlen % 16 != 0)
if (!lc_auth_update(actx, zeropad, 16 - (aadlen % 16)))
goto cleanup;
cparams.counter = 1;
if (!aead_poly1305_anycrypt(cctx, out, outlen, &cparams, in, inlen))
goto cleanup;
if (!lc_auth_update(actx, out, inlen))
goto cleanup;
if (inlen % 16 != 0)
if (!lc_auth_update(actx, zeropad, 16 - (inlen % 16)))
goto cleanup;
store64le(&buf[0], aadlen);
store64le(&buf[sizeof(uint64_t)], inlen);
if (!lc_auth_update(actx, buf, sizeof(buf)) ||
!lc_auth_final(actx, out + inlen, &olen))
goto cleanup;
*outlen += olen;
if (*outlen != inlen + LC_POLY1305_TAGLEN)
goto cleanup;
ret = 1;
cleanup:
lc_scrub(buf, sizeof(buf));
lc_scrub(&aparams, sizeof(aparams));
lc_scrub(&cparams, sizeof(cparams));
lc_auth_ctx_free(actx);
lc_cipher_ctx_free(cctx);
return ret;
}
static int
chacha20_poly1305_open(uint8_t *out, size_t *outlen, const void *initparams,
const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen)
{
const struct lc_chacha20_poly1305_params *params = initparams;
struct lc_cipher_ctx *cctx = NULL;
struct lc_auth_ctx *actx = NULL;
struct lc_chacha20_params cparams;
struct lc_poly1305_params aparams;
uint8_t tag[LC_POLY1305_TAGLEN];
uint8_t buf[sizeof(uint64_t) * 2];
size_t i, olen, ctlen;
int ret = 0;
*outlen = 0;
/* inlen includes the tag; inlen and aadlen are capped by design. */
if (inlen < LC_POLY1305_TAGLEN || if (inlen < LC_POLY1305_TAGLEN ||
inlen > UINT64_MAX || aadlen > UINT64_MAX || inlen > UINT64_MAX || aadlen > UINT64_MAX)
inlen > SIZE_MAX - LC_POLY1305_TAGLEN || return 0;
inlen > SIZE_MAX - CHACHA20_CHUNK + 1 || /* Counter 0 is used for deriving Poly1305 key. */
if (inlen > SIZE_MAX - (CHACHA20_CHUNK - 1) ||
(inlen + CHACHA20_CHUNK - 1) / CHACHA20_CHUNK > (inlen + CHACHA20_CHUNK - 1) / CHACHA20_CHUNK >
CHACHA20_CTRMAX - 1) { CHACHA20_CTRMAX - 1) {
if (out == NULL)
*outlen = 0;
return 0; return 0;
} }
@ -132,148 +260,85 @@ chacha20_poly1305_open(uint8_t *out, size_t *outlen, const uint8_t *key,
return 1; return 1;
} }
*outlen = 0; cctx = lc_cipher_ctx_new(lc_cipher_impl_chacha20());
ctlen = inlen - LC_POLY1305_TAGLEN; if (cctx == NULL)
tagp = in + ctlen; goto cleanup;
actx = lc_auth_ctx_new(lc_auth_impl_poly1305());
if (actx == NULL)
goto cleanup;
for (i = 0; i < LC_POLY1305_KEYLEN; i++) for (i = 0; i < sizeof(params->key); i++)
poly1305_key[i] = 0; cparams.key[i] = params->key[i];
if (!chacha20_common_init(&cctx, key, keylen, iv, ivlen) || for (i = 0; i < sizeof(params->nonce); i++)
!chacha20_common_update(&cctx, poly1305_key, &olen, poly1305_key, cparams.nonce[i] = params->nonce[i];
LC_POLY1305_KEYLEN))
return 0;
if (!chacha20_common_final(&cctx, poly1305_key + olen, &olen))
return 0;
if (!poly1305_init(&pctx, poly1305_key, LC_POLY1305_KEYLEN) || cparams.counter = 0;
!poly1305_update(&pctx, aad, aadlen)) if (!aead_poly1305_keysetup(cctx, aparams.key, &cparams))
return 0; goto cleanup;
if (!lc_auth_init(actx, &aparams) ||
!lc_auth_update(actx, aad, aadlen))
goto cleanup;
if (aadlen % 16 != 0) if (aadlen % 16 != 0)
if (!poly1305_update(&pctx, zeropad, 16 - (aadlen % 16))) if (!lc_auth_update(actx, zeropad, 16 - (aadlen % 16)))
return 0; goto cleanup;
if (!poly1305_update(&pctx, in, ctlen)) ctlen = inlen - LC_POLY1305_TAGLEN;
return 0; if (!lc_auth_update(actx, in, ctlen))
goto cleanup;
if (ctlen % 16 != 0) if (ctlen % 16 != 0)
if (!poly1305_update(&pctx, zeropad, 16 - (ctlen % 16))) if (!lc_auth_update(actx, zeropad, 16 - (ctlen % 16)))
return 0; goto cleanup;
store64le(&buf[0], aadlen); store64le(&buf[0], aadlen);
store64le(&buf[sizeof(uint64_t)], ctlen); store64le(&buf[sizeof(uint64_t)], ctlen);
if (!poly1305_update(&pctx, buf, sizeof(buf)) || if (!lc_auth_update(actx, buf, sizeof(buf)) ||
!poly1305_final(&pctx, tag, &olen)) !lc_auth_final(actx, tag, &olen))
return 0; goto cleanup;
if (olen != LC_POLY1305_TAGLEN)
goto cleanup;
if (!lc_ct_cmp(tag, in + ctlen, LC_POLY1305_TAGLEN))
goto cleanup;
if (!lc_ct_cmp(tag, tagp, LC_POLY1305_TAGLEN)) cparams.counter = 1;
return 0; if (!aead_poly1305_anycrypt(cctx, out, outlen, &cparams, in, ctlen))
goto cleanup;
ret = 1;
cleanup:
lc_scrub(buf, sizeof(buf)); lc_scrub(buf, sizeof(buf));
lc_scrub(poly1305_key, sizeof(poly1305_key)); lc_scrub(&aparams, sizeof(aparams));
lc_scrub(&cparams, sizeof(cparams));
lc_scrub(tag, sizeof(tag));
lc_auth_ctx_free(actx);
lc_cipher_ctx_free(cctx);
if (!chacha20_common_init_from(&cctx, key, keylen, iv, ivlen, 1)) return ret;
return 0;
if (!chacha20_common_update(&cctx, out, &olen, in, ctlen))
return 0;
*outlen = olen;
if (!chacha20_common_final(&cctx, out + olen, &olen))
return 0;
*outlen += olen;
return 1;
} }
static int static int
xchacha20_poly1305_seal(uint8_t *out, size_t *outlen, const uint8_t *key, xchacha20_poly1305_open(uint8_t *out, size_t *outlen, const void *initparams,
size_t keylen, const uint8_t *iv, size_t ivlen, const uint8_t *aad, const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen)
size_t aadlen, const uint8_t *in, size_t inlen)
{ {
struct chacha20_ctx cctx; const struct lc_xchacha20_poly1305_params *params = initparams;
struct poly1305_ctx pctx; struct lc_cipher_ctx *cctx = NULL;
uint8_t poly1305_key[LC_POLY1305_KEYLEN]; struct lc_auth_ctx *actx = NULL;
uint8_t buf[sizeof(uint64_t) * 2]; struct lc_xchacha20_params cparams;
size_t i, olen; struct lc_poly1305_params aparams;
uint8_t tag[LC_POLY1305_TAGLEN];
if (inlen > UINT64_MAX || aadlen > UINT64_MAX || uint8_t buf[sizeof(uint64_t) * 2];
inlen > SIZE_MAX - LC_POLY1305_TAGLEN || size_t i, olen, ctlen;
inlen > SIZE_MAX - CHACHA20_CHUNK + 1 || int ret = 0;
(inlen + CHACHA20_CHUNK - 1) / CHACHA20_CHUNK >
CHACHA20_CTRMAX - 1) {
if (out == NULL)
*outlen = 0;
return 0;
}
if (out == NULL) {
*outlen = inlen + LC_POLY1305_TAGLEN;
return 1;
}
*outlen = 0; *outlen = 0;
/* inlen includes the tag; inlen and aadlen are capped by design. */
for (i = 0; i < LC_POLY1305_KEYLEN; i++)
poly1305_key[i] = 0;
if (!xchacha20_common_init(&cctx, key, keylen, iv, ivlen) ||
!chacha20_common_update(&cctx, poly1305_key, &olen, poly1305_key,
LC_POLY1305_KEYLEN))
return 0;
if (!chacha20_common_final(&cctx, poly1305_key + olen, &olen))
return 0;
if (!poly1305_init(&pctx, poly1305_key, LC_POLY1305_KEYLEN) ||
!poly1305_update(&pctx, aad, aadlen))
return 0;
if (aadlen % 16 != 0)
if (!poly1305_update(&pctx, zeropad, 16 - (aadlen % 16)))
return 0;
if (!xchacha20_common_init_from(&cctx, key, keylen, iv, ivlen, 1))
return 0;
if (!chacha20_common_update(&cctx, out, &olen, in, inlen))
return 0;
*outlen = olen;
if (!chacha20_common_final(&cctx, out + olen, &olen))
return 0;
if (!poly1305_update(&pctx, out, inlen))
return 0;
if (inlen % 16 != 0)
if (!poly1305_update(&pctx, zeropad, 16 - (inlen % 16)))
return 0;
store64le(&buf[0], aadlen);
store64le(&buf[sizeof(uint64_t)], inlen);
if (!poly1305_update(&pctx, buf, sizeof(buf)) ||
!poly1305_final(&pctx, out + inlen, &olen))
return 0;
lc_scrub(buf, sizeof(buf));
lc_scrub(poly1305_key, sizeof(poly1305_key));
*outlen = inlen + LC_POLY1305_TAGLEN;
return 1;
}
static int
xchacha20_poly1305_open(uint8_t *out, size_t *outlen, const uint8_t *key,
size_t keylen, const uint8_t *iv, size_t ivlen, const uint8_t *aad,
size_t aadlen, const uint8_t *in, size_t inlen)
{
const uint8_t *tagp;
struct chacha20_ctx cctx;
struct poly1305_ctx pctx;
uint8_t poly1305_key[LC_POLY1305_KEYLEN];
uint8_t tag[LC_POLY1305_TAGLEN];
uint8_t buf[sizeof(uint64_t) * 2];
size_t i, olen, ctlen;
if (inlen < LC_POLY1305_TAGLEN || if (inlen < LC_POLY1305_TAGLEN ||
inlen > UINT64_MAX || aadlen > UINT64_MAX || inlen > UINT64_MAX || aadlen > UINT64_MAX)
inlen > SIZE_MAX - LC_POLY1305_TAGLEN || return 0;
inlen > SIZE_MAX - CHACHA20_CHUNK + 1 || /* Counter 0 is used for deriving Poly1305 key. */
if (inlen > SIZE_MAX - (CHACHA20_CHUNK - 1) ||
(inlen + CHACHA20_CHUNK - 1) / CHACHA20_CHUNK > (inlen + CHACHA20_CHUNK - 1) / CHACHA20_CHUNK >
CHACHA20_CTRMAX - 1) { CHACHA20_CTRMAX - 1) {
if (out == NULL)
*outlen = 0;
return 0; return 0;
} }
@ -282,54 +347,60 @@ xchacha20_poly1305_open(uint8_t *out, size_t *outlen, const uint8_t *key,
return 1; return 1;
} }
*outlen = 0; cctx = lc_cipher_ctx_new(lc_cipher_impl_xchacha20());
ctlen = inlen - LC_POLY1305_TAGLEN; if (cctx == NULL)
tagp = in + ctlen; goto cleanup;
actx = lc_auth_ctx_new(lc_auth_impl_poly1305());
if (actx == NULL)
goto cleanup;
for (i = 0; i < LC_POLY1305_KEYLEN; i++) for (i = 0; i < sizeof(params->key); i++)
poly1305_key[i] = 0; cparams.key[i] = params->key[i];
if (!xchacha20_common_init(&cctx, key, keylen, iv, ivlen) || for (i = 0; i < sizeof(params->nonce); i++)
!chacha20_common_update(&cctx, poly1305_key, &olen, poly1305_key, cparams.nonce[i] = params->nonce[i];
LC_POLY1305_KEYLEN))
return 0;
if (!chacha20_common_final(&cctx, poly1305_key + olen, &olen))
return 0;
if (!poly1305_init(&pctx, poly1305_key, LC_POLY1305_KEYLEN) || cparams.counter = 0;
!poly1305_update(&pctx, aad, aadlen)) if (!aead_poly1305_keysetup(cctx, aparams.key, &cparams))
return 0; goto cleanup;
if (!lc_auth_init(actx, &aparams) ||
!lc_auth_update(actx, aad, aadlen))
goto cleanup;
if (aadlen % 16 != 0) if (aadlen % 16 != 0)
if (!poly1305_update(&pctx, zeropad, 16 - (aadlen % 16))) if (!lc_auth_update(actx, zeropad, 16 - (aadlen % 16)))
return 0; goto cleanup;
if (!poly1305_update(&pctx, in, ctlen)) ctlen = inlen - LC_POLY1305_TAGLEN;
return 0; if (!lc_auth_update(actx, in, ctlen))
goto cleanup;
if (ctlen % 16 != 0) if (ctlen % 16 != 0)
if (!poly1305_update(&pctx, zeropad, 16 - (ctlen % 16))) if (!lc_auth_update(actx, zeropad, 16 - (ctlen % 16)))
return 0; goto cleanup;
store64le(&buf[0], aadlen); store64le(&buf[0], aadlen);
store64le(&buf[sizeof(uint64_t)], ctlen); store64le(&buf[sizeof(uint64_t)], ctlen);
if (!poly1305_update(&pctx, buf, sizeof(buf)) || if (!lc_auth_update(actx, buf, sizeof(buf)) ||
!poly1305_final(&pctx, tag, &olen)) !lc_auth_final(actx, tag, &olen))
return 0; goto cleanup;
if (olen != LC_POLY1305_TAGLEN)
goto cleanup;
if (!lc_ct_cmp(tag, in + ctlen, LC_POLY1305_TAGLEN))
goto cleanup;
if (!lc_ct_cmp(tag, tagp, LC_POLY1305_TAGLEN)) cparams.counter = 1;
return 0; if (!aead_poly1305_anycrypt(cctx, out, outlen, &cparams, in, ctlen))
goto cleanup;
ret = 1;
cleanup:
lc_scrub(buf, sizeof(buf)); lc_scrub(buf, sizeof(buf));
lc_scrub(poly1305_key, sizeof(poly1305_key)); lc_scrub(&aparams, sizeof(aparams));
lc_scrub(&cparams, sizeof(cparams));
lc_scrub(tag, sizeof(tag));
lc_auth_ctx_free(actx);
lc_cipher_ctx_free(cctx);
if (!xchacha20_common_init_from(&cctx, key, keylen, iv, ivlen, 1)) return ret;
return 0;
if (!chacha20_common_update(&cctx, out, &olen, in, ctlen))
return 0;
*outlen = olen;
if (!chacha20_common_final(&cctx, out + olen, &olen))
return 0;
*outlen += olen;
return 1;
} }

View File

@ -175,11 +175,9 @@ struct lc_aead_impl;
int lc_aead_seal(const struct lc_aead_impl *, uint8_t *, size_t *, int lc_aead_seal(const struct lc_aead_impl *, uint8_t *, size_t *,
const uint8_t *, size_t, const uint8_t *, size_t, const uint8_t *, const void *, const uint8_t *, size_t, const uint8_t *, size_t);
size_t, const uint8_t *, size_t);
int lc_aead_open(const struct lc_aead_impl *, uint8_t *, size_t *, int lc_aead_open(const struct lc_aead_impl *, uint8_t *, size_t *,
const uint8_t *, size_t, const uint8_t *, size_t, const uint8_t *, const void *, const uint8_t *, size_t, const uint8_t *, size_t);
size_t, const uint8_t *, size_t);
const struct lc_aead_impl *lc_aead_impl_chacha20_poly1305(void); const struct lc_aead_impl *lc_aead_impl_chacha20_poly1305(void);
const struct lc_aead_impl *lc_aead_impl_xchacha20_poly1305(void); const struct lc_aead_impl *lc_aead_impl_xchacha20_poly1305(void);