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:
parent
79ce4400dd
commit
a6208487e4
14
aead.c
14
aead.c
@ -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
10
aead.h
@ -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);
|
|
||||||
};
|
};
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user