initial import
This commit is contained in:
commit
7bc527c769
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
obj/
|
17
Makefile.inc
Normal file
17
Makefile.inc
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
LC_SRCS+= auth.c auth_poly1305.c
|
||||||
|
LC_SRCS+= cipher.c cipher_chacha20.c
|
||||||
|
LC_SRCS+= aead.c aead_chacha20_poly1305.c
|
||||||
|
LC_SRCS+= impl_chacha20.c impl_poly1305.c
|
||||||
|
LC_SRCS+= ct.c util.c
|
||||||
|
|
||||||
|
CFLAGS+= -Wall
|
||||||
|
CFLAGS+= -Wextra
|
||||||
|
CFLAGS+= -Wmissing-declarations
|
||||||
|
CFLAGS+= -Wmissing-prototypes
|
||||||
|
CFLAGS+= -Wpointer-arith
|
||||||
|
CFLAGS+= -Wshadow
|
||||||
|
CFLAGS+= -Wstrict-prototypes
|
||||||
|
CFLAGS+= -Wunused
|
||||||
|
CFLAGS+= -Wno-unused-parameter
|
||||||
|
|
||||||
|
.include <bsd.own.mk>
|
79
README
Normal file
79
README
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
lilcrypto
|
||||||
|
=========
|
||||||
|
|
||||||
|
> They see me rollin', they hatin'.
|
||||||
|
|
||||||
|
Experiment on rolling my own crypto. Kinda. I'm not creating any new
|
||||||
|
protocol, but implementing known algorithms and constructions. The main
|
||||||
|
focus is to understand how to implement the math behind the algorithms,
|
||||||
|
and to get to know the constructions better.
|
||||||
|
|
||||||
|
Algorithms
|
||||||
|
==========
|
||||||
|
|
||||||
|
Utilities
|
||||||
|
---------
|
||||||
|
|
||||||
|
- Constant-time operations
|
||||||
|
- [/] compare: returns `0` if match, non-`0` otherwise. The non-`0`
|
||||||
|
case might leak information. Would be better to return `0xffffffff`
|
||||||
|
if match, `0` otherwise.
|
||||||
|
|
||||||
|
Authentication
|
||||||
|
--------------
|
||||||
|
|
||||||
|
- [x] Poly1305
|
||||||
|
- [ ] SHA-512 (needed for Ed25519)
|
||||||
|
|
||||||
|
Ciphers
|
||||||
|
-------
|
||||||
|
|
||||||
|
- [x] ChaCha20
|
||||||
|
- [ ] XChaCha20
|
||||||
|
|
||||||
|
AEAD
|
||||||
|
----
|
||||||
|
|
||||||
|
- [/] ChaCha20-Poly1305 (missing aead_open)
|
||||||
|
- [ ] XChaCha20-Poly1305
|
||||||
|
|
||||||
|
ECC
|
||||||
|
---
|
||||||
|
|
||||||
|
- Curve25519
|
||||||
|
- [ ] Ed25519 (EdDSA)
|
||||||
|
- [ ] X25519 (ECDH)
|
||||||
|
|
||||||
|
Nice-to-haves
|
||||||
|
=============
|
||||||
|
|
||||||
|
Utilities
|
||||||
|
---------
|
||||||
|
|
||||||
|
- [ ] Portable Makefile
|
||||||
|
- [ ] NaCl interface
|
||||||
|
- [ ] signify interface
|
||||||
|
|
||||||
|
Authentication
|
||||||
|
--------------
|
||||||
|
|
||||||
|
- [ ] GMAC
|
||||||
|
|
||||||
|
Ciphers
|
||||||
|
-------
|
||||||
|
|
||||||
|
- [ ] AES
|
||||||
|
- [ ] Camellia
|
||||||
|
- [ ] Salsa20 (no Wycheproof test vector suite)
|
||||||
|
- [ ] XSalsa20 (no Wycheproof test vector suite)
|
||||||
|
|
||||||
|
AEAD
|
||||||
|
----
|
||||||
|
|
||||||
|
- [ ] AES-GCM
|
||||||
|
- [ ] Camellia-GCM
|
||||||
|
- [ ] Salsa20-Poly1305 (no Wycherproof test vector suite)
|
||||||
|
- [ ] XSalsa20-Poly1305 (no Wycherproof test vector suite)
|
||||||
|
|
||||||
|
KDF?
|
||||||
|
----
|
39
aead.c
Normal file
39
aead.c
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Lucas Gabriel Vuotto <lucas@lgv5.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lilcrypto.h"
|
||||||
|
#include "aead.h"
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
lc_aead_seal(const struct lc_aead_impl *impl, const uint8_t *key,
|
||||||
|
size_t keylen, const uint8_t *iv, size_t ivlen, uint8_t *out,
|
||||||
|
size_t *outlen, const uint8_t *aad, size_t aadlen, const uint8_t *in,
|
||||||
|
size_t inlen)
|
||||||
|
{
|
||||||
|
return impl->seal(key, keylen, iv, ivlen, out, outlen, aad, aadlen, in,
|
||||||
|
inlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
lc_aead_open(const struct lc_aead_impl *impl, const uint8_t *key,
|
||||||
|
size_t keylen, const uint8_t *iv, size_t ivlen, uint8_t *out,
|
||||||
|
size_t *outlen, const uint8_t *aad, size_t aadlen, const uint8_t *in,
|
||||||
|
size_t inlen)
|
||||||
|
{
|
||||||
|
return impl->open(key, keylen, iv, ivlen, out, outlen, aad, aadlen, in,
|
||||||
|
inlen);
|
||||||
|
}
|
28
aead.h
Normal file
28
aead.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Lucas Gabriel Vuotto <lucas@lgv5.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct lc_aead_impl {
|
||||||
|
int (*seal)(const uint8_t *, size_t, const uint8_t *, size_t,
|
||||||
|
uint8_t *, size_t *, const uint8_t *, size_t,
|
||||||
|
const uint8_t *, size_t);
|
||||||
|
int (*open)(const uint8_t *, size_t, const uint8_t *, size_t,
|
||||||
|
uint8_t *, size_t *, const uint8_t *, size_t,
|
||||||
|
const uint8_t *, size_t);
|
||||||
|
};
|
114
aead_chacha20_poly1305.c
Normal file
114
aead_chacha20_poly1305.c
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Lucas Gabriel Vuotto <lucas@lgv5.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lilcrypto.h"
|
||||||
|
#include "aead.h"
|
||||||
|
#include "auth_poly1305.h"
|
||||||
|
#include "cipher_chacha20.h"
|
||||||
|
#include "impl_chacha20.h"
|
||||||
|
#include "impl_poly1305.h"
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Implements ChaCha20-Poly1305 according to RFC 8439.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static uint8_t zeropad[16];
|
||||||
|
|
||||||
|
static int
|
||||||
|
chacha20_poly1305_seal(const uint8_t *key, size_t keylen, const uint8_t *iv,
|
||||||
|
size_t ivlen, uint8_t *out, size_t *outlen, const uint8_t *aad,
|
||||||
|
size_t aadlen, const uint8_t *in, size_t inlen)
|
||||||
|
{
|
||||||
|
struct chacha20_ctx cctx;
|
||||||
|
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 ||
|
||||||
|
inlen > SIZE_MAX - LC_POLY1305_TAGLEN ||
|
||||||
|
inlen > SIZE_MAX - CHACHA20_CHUNK + 1 ||
|
||||||
|
(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;
|
||||||
|
|
||||||
|
for (i = 0; i < LC_POLY1305_KEYLEN; i++)
|
||||||
|
poly1305_key[i] = 0;
|
||||||
|
if (!chacha20_x_init(&cctx, key, keylen, iv, ivlen) ||
|
||||||
|
!chacha20_x_update(&cctx, poly1305_key, &olen, poly1305_key,
|
||||||
|
LC_POLY1305_KEYLEN))
|
||||||
|
return 0;
|
||||||
|
for (i = 0; i < LC_POLY1305_KEYLEN / sizeof(uint32_t); i++)
|
||||||
|
store32le(&poly1305_key[i * 4], cctx.s[i]);
|
||||||
|
|
||||||
|
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 (!chacha20_x_init_from(&cctx, key, keylen, iv, ivlen, 1))
|
||||||
|
return 0;
|
||||||
|
if (!chacha20_x_update(&cctx, out, &olen, in, inlen))
|
||||||
|
return 0;
|
||||||
|
*outlen = olen;
|
||||||
|
if (!chacha20_x_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 struct lc_aead_impl chacha20_poly1305_impl = {
|
||||||
|
.seal = &chacha20_poly1305_seal,
|
||||||
|
.open = NULL, //&chacha20_poly1305_open,
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct lc_aead_impl *
|
||||||
|
lc_aead_impl_chacha20_poly1305(void)
|
||||||
|
{
|
||||||
|
return &chacha20_poly1305_impl;
|
||||||
|
}
|
78
auth.c
Normal file
78
auth.c
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Lucas Gabriel Vuotto <lucas@lgv5.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "lilcrypto.h"
|
||||||
|
#include "auth.h"
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
lc_auth_init(struct lc_auth_ctx *ctx, const uint8_t *key, size_t keylen)
|
||||||
|
{
|
||||||
|
return ctx->impl->init(ctx->arg, key, keylen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
lc_auth_update(struct lc_auth_ctx *ctx, const uint8_t *in, size_t inlen)
|
||||||
|
{
|
||||||
|
return ctx->impl->update(ctx->arg, in, inlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
lc_auth_final(struct lc_auth_ctx *ctx, uint8_t *out, size_t *outlen)
|
||||||
|
{
|
||||||
|
return ctx->impl->final(ctx->arg, out, outlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
lc_auth(const struct lc_auth_impl *impl, const uint8_t *key, size_t keylen,
|
||||||
|
uint8_t *out, size_t *outlen, const uint8_t *in, size_t inlen)
|
||||||
|
{
|
||||||
|
return impl->auth(key, keylen, out, outlen, in, inlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct lc_auth_ctx *
|
||||||
|
lc_auth_ctx_new(const struct lc_auth_impl *impl)
|
||||||
|
{
|
||||||
|
struct lc_auth_ctx *ctx;
|
||||||
|
void *arg;
|
||||||
|
|
||||||
|
ctx = malloc(sizeof(*ctx));
|
||||||
|
if (ctx == NULL)
|
||||||
|
return NULL;
|
||||||
|
if (impl->argsz > 0) {
|
||||||
|
arg = malloc(impl->argsz);
|
||||||
|
if (arg == NULL) {
|
||||||
|
free(ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ctx->arg = arg;
|
||||||
|
} else
|
||||||
|
ctx->arg = NULL;
|
||||||
|
ctx->impl = impl;
|
||||||
|
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
lc_auth_ctx_free(struct lc_auth_ctx *ctx)
|
||||||
|
{
|
||||||
|
if (ctx != NULL)
|
||||||
|
free(ctx->arg);
|
||||||
|
free(ctx);
|
||||||
|
}
|
34
auth.h
Normal file
34
auth.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Lucas Gabriel Vuotto <lucas@lgv5.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct lc_auth_impl {
|
||||||
|
int (*init)(void *, const uint8_t *, size_t);
|
||||||
|
int (*update)(void *, const uint8_t *, size_t);
|
||||||
|
int (*final)(void *, uint8_t *, size_t *);
|
||||||
|
int (*auth)(const uint8_t *, size_t, uint8_t *, size_t *,
|
||||||
|
const uint8_t *, size_t);
|
||||||
|
|
||||||
|
size_t argsz;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct lc_auth_ctx {
|
||||||
|
const struct lc_auth_impl *impl;
|
||||||
|
void *arg;
|
||||||
|
};
|
168
auth_poly1305.c
Normal file
168
auth_poly1305.c
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Lucas Gabriel Vuotto <lucas@lgv5.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lilcrypto.h"
|
||||||
|
#include "auth.h"
|
||||||
|
#include "auth_poly1305.h"
|
||||||
|
#include "impl_poly1305.h"
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
poly1305_init(void *arg, const uint8_t *key, size_t keylen)
|
||||||
|
{
|
||||||
|
struct poly1305_ctx *ctx = arg;
|
||||||
|
size_t i;
|
||||||
|
uint32_t t0, t1, t2, t3;
|
||||||
|
|
||||||
|
if (keylen != LC_POLY1305_KEYLEN)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ctx->h0 = 0;
|
||||||
|
ctx->h1 = 0;
|
||||||
|
ctx->h2 = 0;
|
||||||
|
ctx->h3 = 0;
|
||||||
|
ctx->h4 = 0;
|
||||||
|
|
||||||
|
t0 = load32le(&key[0]);
|
||||||
|
t1 = load32le(&key[4]);
|
||||||
|
t2 = load32le(&key[8]);
|
||||||
|
t3 = load32le(&key[12]);
|
||||||
|
|
||||||
|
ctx->r0 = t0 & 0x3ffffff;
|
||||||
|
ctx->r1 = ((t1 << 6) | (t0 >> 26)) & 0x3ffff03;
|
||||||
|
ctx->r2 = ((t2 << 12) | (t1 >> 20)) & 0x3ffc0ff;
|
||||||
|
ctx->r3 = ((t3 << 18) | (t2 >> 14)) & 0x3f03fff;
|
||||||
|
ctx->r4 = (t3 >> 8) & 0xfffff;
|
||||||
|
|
||||||
|
ctx->x1 = 5 * ctx->r1;
|
||||||
|
ctx->x2 = 5 * ctx->r2;
|
||||||
|
ctx->x3 = 5 * ctx->r3;
|
||||||
|
ctx->x4 = 5 * ctx->r4;
|
||||||
|
|
||||||
|
ctx->s0 = load32le(&key[16]);
|
||||||
|
ctx->s1 = load32le(&key[20]);
|
||||||
|
ctx->s2 = load32le(&key[24]);
|
||||||
|
ctx->s3 = load32le(&key[28]);
|
||||||
|
|
||||||
|
ctx->mlen = 0;
|
||||||
|
for (i = 0; i < POLY1305_CHUNK; i++)
|
||||||
|
ctx->m[i] = 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
poly1305_update(void *arg, const uint8_t *in, size_t inlen)
|
||||||
|
{
|
||||||
|
struct poly1305_ctx *ctx = arg;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i + ctx->mlen < POLY1305_CHUNK && i < inlen; i++)
|
||||||
|
ctx->m[i + ctx->mlen] = in[i];
|
||||||
|
ctx->mlen += i;
|
||||||
|
in += i;
|
||||||
|
inlen -= i;
|
||||||
|
|
||||||
|
if (ctx->mlen == POLY1305_CHUNK) {
|
||||||
|
poly1305_block(ctx, 1);
|
||||||
|
ctx->mlen = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inlen == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
while (inlen >= POLY1305_CHUNK) {
|
||||||
|
for (i = 0; i < POLY1305_CHUNK; i++)
|
||||||
|
ctx->m[i] = in[i];
|
||||||
|
poly1305_block(ctx, 1);
|
||||||
|
|
||||||
|
in += POLY1305_CHUNK;
|
||||||
|
inlen -= POLY1305_CHUNK;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < inlen; i++)
|
||||||
|
ctx->m[i] = in[i];
|
||||||
|
ctx->mlen = inlen;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
poly1305_final(void *arg, uint8_t *out, size_t *outlen)
|
||||||
|
{
|
||||||
|
struct poly1305_ctx *ctx = arg;
|
||||||
|
uint32_t tag[POLY1305_TAGLEN_WORDS];
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
*outlen = LC_POLY1305_TAGLEN;
|
||||||
|
if (out == NULL)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
i = ctx->mlen;
|
||||||
|
if (i > 0) {
|
||||||
|
if (i < POLY1305_CHUNK) {
|
||||||
|
ctx->m[i++] = 1;
|
||||||
|
for (; i < POLY1305_CHUNK; i++)
|
||||||
|
ctx->m[i] = 0;
|
||||||
|
poly1305_block(ctx, 0);
|
||||||
|
} else
|
||||||
|
poly1305_block(ctx, 1);
|
||||||
|
}
|
||||||
|
poly1305_reduce(ctx, tag);
|
||||||
|
|
||||||
|
store32le(&out[0], tag[0]);
|
||||||
|
store32le(&out[4], tag[1]);
|
||||||
|
store32le(&out[8], tag[2]);
|
||||||
|
store32le(&out[12], tag[3]);
|
||||||
|
|
||||||
|
lc_scrub(ctx, sizeof(*ctx));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
poly1305_auth(const uint8_t *key, size_t keylen, uint8_t *out, size_t *outlen,
|
||||||
|
const uint8_t *in, size_t inlen)
|
||||||
|
{
|
||||||
|
struct poly1305_ctx ctx;
|
||||||
|
|
||||||
|
if (out == NULL) {
|
||||||
|
*outlen = LC_POLY1305_TAGLEN;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return poly1305_init(&ctx, key, keylen) &&
|
||||||
|
poly1305_update(&ctx, in, inlen) &&
|
||||||
|
poly1305_final(&ctx, out, outlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct lc_auth_impl poly1305_impl = {
|
||||||
|
.init = &poly1305_init,
|
||||||
|
.update = &poly1305_update,
|
||||||
|
.final = &poly1305_final,
|
||||||
|
.auth = &poly1305_auth,
|
||||||
|
|
||||||
|
.argsz = sizeof(struct poly1305_ctx),
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct lc_auth_impl *
|
||||||
|
lc_auth_impl_poly1305(void)
|
||||||
|
{
|
||||||
|
return &poly1305_impl;
|
||||||
|
}
|
23
auth_poly1305.h
Normal file
23
auth_poly1305.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Lucas Gabriel Vuotto <lucas@lgv5.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
int poly1305_init(void *, const uint8_t *, size_t);
|
||||||
|
int poly1305_update(void *, const uint8_t *, size_t);
|
||||||
|
int poly1305_final(void *, uint8_t *, size_t *);
|
110
cipher.c
Normal file
110
cipher.c
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Lucas Gabriel Vuotto <lucas@lgv5.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "lilcrypto.h"
|
||||||
|
#include "cipher.h"
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
lc_cipher_encrypt_init(struct lc_cipher_ctx *ctx, const uint8_t *key,
|
||||||
|
size_t keylen, const uint8_t *iv, size_t ivlen)
|
||||||
|
{
|
||||||
|
return ctx->impl->encrypt_init(ctx->arg, key, keylen, iv, ivlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
lc_cipher_encrypt_update(struct lc_cipher_ctx *ctx, uint8_t *out,
|
||||||
|
size_t *outlen, const uint8_t *in, size_t inlen)
|
||||||
|
{
|
||||||
|
return ctx->impl->encrypt_update(ctx->arg, out, outlen, in, inlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
lc_cipher_encrypt_final(struct lc_cipher_ctx *ctx, uint8_t *out,
|
||||||
|
size_t *outlen)
|
||||||
|
{
|
||||||
|
return ctx->impl->encrypt_final(ctx->arg, out, outlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
lc_cipher_encrypt(const struct lc_cipher_impl *impl, const uint8_t *key,
|
||||||
|
size_t keylen, const uint8_t *iv, size_t ivlen, uint8_t *out,
|
||||||
|
size_t *outlen, const uint8_t *in, size_t inlen)
|
||||||
|
{
|
||||||
|
return impl->encrypt(key, keylen, iv, ivlen, out, outlen, in, inlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
lc_cipher_decrypt_init(struct lc_cipher_ctx *ctx, const uint8_t *key,
|
||||||
|
size_t keylen, const uint8_t *iv, size_t ivlen)
|
||||||
|
{
|
||||||
|
return ctx->impl->decrypt_init(ctx->arg, key, keylen, iv, ivlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
lc_cipher_decrypt_update(struct lc_cipher_ctx *ctx, uint8_t *out,
|
||||||
|
size_t *outlen, const uint8_t *in, size_t inlen)
|
||||||
|
{
|
||||||
|
return ctx->impl->decrypt_update(ctx->arg, out, outlen, in, inlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
lc_cipher_decrypt_final(struct lc_cipher_ctx *ctx, uint8_t *out,
|
||||||
|
size_t *outlen)
|
||||||
|
{
|
||||||
|
return ctx->impl->decrypt_final(ctx->arg, out, outlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
lc_cipher_decrypt(const struct lc_cipher_impl *impl, const uint8_t *key,
|
||||||
|
size_t keylen, const uint8_t *iv, size_t ivlen, uint8_t *out,
|
||||||
|
size_t *outlen, const uint8_t *in, size_t inlen)
|
||||||
|
{
|
||||||
|
return impl->decrypt(key, keylen, iv, ivlen, out, outlen, in, inlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct lc_cipher_ctx *
|
||||||
|
lc_cipher_ctx_new(const struct lc_cipher_impl *impl)
|
||||||
|
{
|
||||||
|
struct lc_cipher_ctx *ctx;
|
||||||
|
void *arg;
|
||||||
|
|
||||||
|
ctx = malloc(sizeof(*ctx));
|
||||||
|
if (ctx == NULL)
|
||||||
|
return NULL;
|
||||||
|
if (impl->argsz > 0) {
|
||||||
|
arg = malloc(impl->argsz);
|
||||||
|
if (arg == NULL) {
|
||||||
|
free(ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ctx->arg = arg;
|
||||||
|
} else
|
||||||
|
ctx->arg = NULL;
|
||||||
|
ctx->impl = impl;
|
||||||
|
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
lc_cipher_ctx_free(struct lc_cipher_ctx *ctx)
|
||||||
|
{
|
||||||
|
if (ctx != NULL)
|
||||||
|
free(ctx->arg);
|
||||||
|
free(ctx);
|
||||||
|
}
|
44
cipher.h
Normal file
44
cipher.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Lucas Gabriel Vuotto <lucas@lgv5.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct lc_cipher_impl {
|
||||||
|
int (*encrypt_init)(void *, const uint8_t *, size_t,
|
||||||
|
const uint8_t *, size_t);
|
||||||
|
int (*encrypt_update)(void *, uint8_t *, size_t *, const uint8_t *,
|
||||||
|
size_t);
|
||||||
|
int (*encrypt_final)(void *, uint8_t *, size_t *);
|
||||||
|
int (*encrypt)(const uint8_t *, size_t, const uint8_t *, size_t,
|
||||||
|
uint8_t *, size_t *, const uint8_t *, size_t);
|
||||||
|
|
||||||
|
int (*decrypt_init)(void *, const uint8_t *, size_t,
|
||||||
|
const uint8_t *, size_t);
|
||||||
|
int (*decrypt_update)(void *, uint8_t *, size_t *, const uint8_t *,
|
||||||
|
size_t);
|
||||||
|
int (*decrypt_final)(void *, uint8_t *, size_t *);
|
||||||
|
int (*decrypt)(const uint8_t *, size_t, const uint8_t *, size_t,
|
||||||
|
uint8_t *, size_t *, const uint8_t *, size_t);
|
||||||
|
|
||||||
|
size_t argsz;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct lc_cipher_ctx {
|
||||||
|
const struct lc_cipher_impl *impl;
|
||||||
|
void *arg;
|
||||||
|
};
|
199
cipher_chacha20.c
Normal file
199
cipher_chacha20.c
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Lucas Gabriel Vuotto <lucas@lgv5.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include "lilcrypto.h"
|
||||||
|
#include "cipher.h"
|
||||||
|
#include "cipher_chacha20.h"
|
||||||
|
#include "impl_chacha20.h"
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
chacha20_x_init_from(void *arg, const uint8_t *key, size_t keylen,
|
||||||
|
const uint8_t *iv, size_t ivlen, uint32_t counter)
|
||||||
|
{
|
||||||
|
struct chacha20_ctx *ctx = arg;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (keylen != LC_CHACHA20_KEYLEN || ivlen != LC_CHACHA20_IVLEN)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (i = 0; i < CHACHA20_CHUNK_WORDS; i++)
|
||||||
|
ctx->s[i] = 0;
|
||||||
|
for (i = 0; i < CHACHA20_KEY_WORDS; i++)
|
||||||
|
ctx->k[i] = load32le(&key[i * 4]);
|
||||||
|
ctx->c = counter;
|
||||||
|
for (i = 0; i < CHACHA20_NONCE_WORDS; i++)
|
||||||
|
ctx->n[i] = load32le(&iv[i * 4]);
|
||||||
|
ctx->blen = 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
chacha20_x_init(void *arg, const uint8_t *key, size_t keylen,
|
||||||
|
const uint8_t *iv, size_t ivlen)
|
||||||
|
{
|
||||||
|
return chacha20_x_init_from(arg, key, keylen, iv, ivlen, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
chacha20_x_update(void *arg, uint8_t *out, size_t *outlen, const uint8_t *in,
|
||||||
|
size_t inlen)
|
||||||
|
{
|
||||||
|
struct chacha20_ctx *ctx = arg;
|
||||||
|
uint32_t h;
|
||||||
|
uint8_t s[4];
|
||||||
|
size_t i, blocks, off, pad;
|
||||||
|
|
||||||
|
*outlen = 0;
|
||||||
|
if (inlen > SIZE_MAX - (CHACHA20_CHUNK - 1) - ctx->blen)
|
||||||
|
return 0;
|
||||||
|
blocks = inlen + ctx->blen + CHACHA20_CHUNK - 1;
|
||||||
|
if (blocks / CHACHA20_CHUNK + ctx->c > CHACHA20_CTRMAX)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (out == NULL) {
|
||||||
|
*outlen = inlen;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*outlen = inlen;
|
||||||
|
|
||||||
|
if (ctx->blen == 0)
|
||||||
|
goto fullblock;
|
||||||
|
|
||||||
|
off = ctx->blen % 4;
|
||||||
|
if (off != 0) {
|
||||||
|
store32le(s, ctx->s[ctx->blen / 4]);
|
||||||
|
for (i = 0; i + off < 4 && i < inlen; i++)
|
||||||
|
out[i] = in[i] ^ s[i + off];
|
||||||
|
ctx->blen += i;
|
||||||
|
out += i;
|
||||||
|
in += i;
|
||||||
|
inlen -= i;
|
||||||
|
}
|
||||||
|
|
||||||
|
pad = inlen % 4;
|
||||||
|
for (i = 0; i + ctx->blen < CHACHA20_CHUNK && i < inlen - pad; i += 4) {
|
||||||
|
h = load32le(&in[i * 4]);
|
||||||
|
h ^= ctx->s[(i + ctx->blen) / 4];
|
||||||
|
store32le(&out[i * 4], h);
|
||||||
|
}
|
||||||
|
ctx->blen += i * 4;
|
||||||
|
out += i * 4;
|
||||||
|
in += i * 4;
|
||||||
|
inlen -= i * 4;
|
||||||
|
|
||||||
|
fullblock:
|
||||||
|
while (inlen >= CHACHA20_CHUNK) {
|
||||||
|
chacha20_block(ctx);
|
||||||
|
ctx->c++;
|
||||||
|
|
||||||
|
for (i = 0; i < CHACHA20_CHUNK_WORDS; i++) {
|
||||||
|
h = load32le(&in[i * 4]);
|
||||||
|
h ^= ctx->s[i];
|
||||||
|
store32le(&out[i * 4], h);
|
||||||
|
}
|
||||||
|
out += CHACHA20_CHUNK;
|
||||||
|
in += CHACHA20_CHUNK;
|
||||||
|
inlen -= CHACHA20_CHUNK;
|
||||||
|
}
|
||||||
|
|
||||||
|
chacha20_block(ctx);
|
||||||
|
ctx->c++;
|
||||||
|
ctx->blen = inlen;
|
||||||
|
|
||||||
|
pad = inlen % 4;
|
||||||
|
for (i = 0; i < (inlen - pad) / 4; i++) {
|
||||||
|
h = load32le(&in[i * 4]);
|
||||||
|
h ^= ctx->s[i];
|
||||||
|
store32le(&out[i * 4], h);
|
||||||
|
}
|
||||||
|
out += i * 4;
|
||||||
|
in += i * 4;
|
||||||
|
inlen -= i * 4;
|
||||||
|
|
||||||
|
store32le(s, ctx->s[i]);
|
||||||
|
for (i = 0; i < pad; i++)
|
||||||
|
out[i] = in[i] ^ s[i];
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
chacha20_x_final(void *arg, uint8_t *out, size_t *outlen)
|
||||||
|
{
|
||||||
|
struct chacha20_ctx *ctx = arg;
|
||||||
|
|
||||||
|
*outlen = 0;
|
||||||
|
lc_scrub(ctx, sizeof(*ctx));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
chacha20_x(const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen,
|
||||||
|
uint8_t *out, size_t *outlen, const uint8_t *in, size_t inlen)
|
||||||
|
{
|
||||||
|
struct chacha20_ctx ctx;
|
||||||
|
size_t l0, l1;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
*outlen = 0;
|
||||||
|
|
||||||
|
if (inlen > SIZE_MAX - (CHACHA20_CHUNK - 1) ||
|
||||||
|
(inlen + CHACHA20_CHUNK - 1) / CHACHA20_CHUNK > CHACHA20_CTRMAX)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (out == NULL) {
|
||||||
|
*outlen = inlen;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = chacha20_x_init(&ctx, key, keylen, iv, ivlen) &&
|
||||||
|
chacha20_x_update(&ctx, out, &l0, in, inlen) &
|
||||||
|
chacha20_x_final(&ctx, out + l0, &l1);
|
||||||
|
|
||||||
|
if (rc)
|
||||||
|
*outlen = l0 + l1;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct lc_cipher_impl chacha20_impl = {
|
||||||
|
.encrypt_init = &chacha20_x_init,
|
||||||
|
.encrypt_update = &chacha20_x_update,
|
||||||
|
.encrypt_final = &chacha20_x_final,
|
||||||
|
.encrypt = &chacha20_x,
|
||||||
|
|
||||||
|
.decrypt_init = &chacha20_x_init,
|
||||||
|
.decrypt_update = &chacha20_x_update,
|
||||||
|
.decrypt_final = &chacha20_x_final,
|
||||||
|
.decrypt = &chacha20_x,
|
||||||
|
|
||||||
|
.argsz = sizeof(struct chacha20_ctx),
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct lc_cipher_impl *
|
||||||
|
lc_cipher_impl_chacha20(void)
|
||||||
|
{
|
||||||
|
return &chacha20_impl;
|
||||||
|
}
|
29
cipher_chacha20.h
Normal file
29
cipher_chacha20.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Lucas Gabriel Vuotto <lucas@lgv5.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
int chacha20_x_init_from(void *, const uint8_t *, size_t, const uint8_t *,
|
||||||
|
size_t, uint32_t);
|
||||||
|
int chacha20_x_init(void *, const uint8_t *, size_t, const uint8_t *,
|
||||||
|
size_t);
|
||||||
|
int chacha20_x_update(void *, uint8_t *, size_t *, const uint8_t *,
|
||||||
|
size_t);
|
||||||
|
int chacha20_x_final(void *, uint8_t *, size_t *);
|
||||||
|
int chacha20_x(const uint8_t *, size_t, const uint8_t *, size_t, uint8_t *,
|
||||||
|
size_t *, const uint8_t *, size_t);
|
29
ct.c
Normal file
29
ct.c
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Lucas Gabriel Vuotto <lucas@lgv5.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lilcrypto.h"
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
lc_ct_cmp(const uint8_t *x, const uint8_t *y, size_t l)
|
||||||
|
{
|
||||||
|
uint32_t r = 0;
|
||||||
|
|
||||||
|
for (; l > 0; l--)
|
||||||
|
r |= *x++ ^ *y++;
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
85
impl_chacha20.c
Normal file
85
impl_chacha20.c
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Lucas Gabriel Vuotto <lucas@lgv5.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "impl_chacha20.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ChaCha20 implementation.
|
||||||
|
*
|
||||||
|
* ChaCha originally designed by Daniel J. Bernstein, "ChaCha, a variant of
|
||||||
|
* Salsa20", https://cr.yp.to/chacha/chacha-20080128.pdf .
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* "expand 32-byte k" */
|
||||||
|
#define SIGMA0 UINT32_C(0x61707865)
|
||||||
|
#define SIGMA1 UINT32_C(0x3320646e)
|
||||||
|
#define SIGMA2 UINT32_C(0x79622d32)
|
||||||
|
#define SIGMA3 UINT32_C(0x6b206574)
|
||||||
|
|
||||||
|
#define QUARTERROUND(a, b, c, d) do { \
|
||||||
|
a += b; d ^= a; d = rotl32(d, 16); \
|
||||||
|
c += d; b ^= c; b = rotl32(b, 12); \
|
||||||
|
a += b; d ^= a; d = rotl32(d, 8); \
|
||||||
|
c += d; b ^= c; b = rotl32(b, 7); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
chacha20_block(struct chacha20_ctx *ctx)
|
||||||
|
{
|
||||||
|
uint32_t x[CHACHA20_CHUNK_WORDS];
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
x[0] = SIGMA0;
|
||||||
|
x[1] = SIGMA1;
|
||||||
|
x[2] = SIGMA2;
|
||||||
|
x[3] = SIGMA3;
|
||||||
|
x[4] = ctx->k[0];
|
||||||
|
x[5] = ctx->k[1];
|
||||||
|
x[6] = ctx->k[2];
|
||||||
|
x[7] = ctx->k[3];
|
||||||
|
x[8] = ctx->k[4];
|
||||||
|
x[9] = ctx->k[5];
|
||||||
|
x[10] = ctx->k[6];
|
||||||
|
x[11] = ctx->k[7];
|
||||||
|
x[12] = ctx->c;
|
||||||
|
x[13] = ctx->n[0];
|
||||||
|
x[14] = ctx->n[1];
|
||||||
|
x[15] = ctx->n[2];
|
||||||
|
|
||||||
|
for (i = 0; i < CHACHA20_CHUNK_WORDS; i++)
|
||||||
|
ctx->s[i] = x[i];
|
||||||
|
|
||||||
|
for (i = 0; i < CHACHA20_ROUNDS; i++) {
|
||||||
|
QUARTERROUND(x[0], x[4], x[8], x[12]);
|
||||||
|
QUARTERROUND(x[1], x[5], x[9], x[13]);
|
||||||
|
QUARTERROUND(x[2], x[6], x[10], x[14]);
|
||||||
|
QUARTERROUND(x[3], x[7], x[11], x[15]);
|
||||||
|
|
||||||
|
QUARTERROUND(x[0], x[5], x[10], x[15]);
|
||||||
|
QUARTERROUND(x[1], x[6], x[11], x[12]);
|
||||||
|
QUARTERROUND(x[2], x[7], x[8], x[13]);
|
||||||
|
QUARTERROUND(x[3], x[4], x[9], x[14]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < CHACHA20_CHUNK_WORDS; i++)
|
||||||
|
ctx->s[i] += x[i];
|
||||||
|
}
|
40
impl_chacha20.h
Normal file
40
impl_chacha20.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Lucas Gabriel Vuotto <lucas@lgv5.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "lilcrypto.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define CHACHA20_CHUNK 64
|
||||||
|
#define CHACHA20_CHUNK_WORDS (CHACHA20_CHUNK / sizeof(uint32_t))
|
||||||
|
#define CHACHA20_CTRMAX 4294967295 /* 2^32 - 1 */
|
||||||
|
#define CHACHA20_KEY_WORDS (LC_CHACHA20_KEYLEN / sizeof(uint32_t))
|
||||||
|
#define CHACHA20_NONCE_WORDS (LC_CHACHA20_IVLEN / sizeof(uint32_t))
|
||||||
|
#define CHACHA20_ROUNDS 10
|
||||||
|
|
||||||
|
|
||||||
|
struct chacha20_ctx {
|
||||||
|
uint32_t s[CHACHA20_CHUNK_WORDS];
|
||||||
|
uint32_t k[CHACHA20_KEY_WORDS];
|
||||||
|
uint32_t c;
|
||||||
|
uint32_t n[CHACHA20_NONCE_WORDS];
|
||||||
|
size_t blen;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void chacha20_block(struct chacha20_ctx *);
|
243
impl_poly1305.c
Normal file
243
impl_poly1305.c
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Lucas Gabriel Vuotto <lucas@lgv5.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "impl_poly1305.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Poly1305 implementation.
|
||||||
|
*
|
||||||
|
* Poly1305 originally designed by Daniel J. Bernstein, "The Poly1305-AES
|
||||||
|
* message-authentication code", https://cr.yp.to/mac/poly1305-20050329.pdf .
|
||||||
|
*
|
||||||
|
* This implementation is written from scratch, but consulting poly1305-donna
|
||||||
|
* by Andrew Moon, https://github.com/floodyberry/poly1305-donna, released
|
||||||
|
* under MIT license. Similarities are to be expected.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2011-2016 Andrew Moon <liquidsun@gmail.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To ease reduction modulo p = 2^130 - 5, work in base 2^130, as 2^130 = 5 mod
|
||||||
|
* p, allowing for easier operations. 2^130 splits evenly into 5 limbs of 26
|
||||||
|
* bits.
|
||||||
|
*
|
||||||
|
* Addition is performed limb-wise:
|
||||||
|
*
|
||||||
|
* h = h4 h3 h2 h1 h0
|
||||||
|
* c = c4 c3 c2 c1 c0
|
||||||
|
* -----------------------------------
|
||||||
|
* h+c = h4+c4 h3+c3 h2+c2 h1+c1 h0+c0
|
||||||
|
*
|
||||||
|
* Carry won't be propagated at this step.
|
||||||
|
*
|
||||||
|
* Considering h = h + c, multiplication is performed as school multiplication
|
||||||
|
* / long multiplication:
|
||||||
|
*
|
||||||
|
* h = h4 h3 h2 h1 h0
|
||||||
|
* r = r4 r3 r2 r1 r0
|
||||||
|
* -----------------------------------------------------------
|
||||||
|
* h4*r0 h3*r0 h2*r0 h1*r0 h0*r0
|
||||||
|
* h4*r1 h3*r1 h2*r1 h1*r1 h0*r1
|
||||||
|
* h4*r2 h3*r2 h2*r2 h1*r2 h0*r2
|
||||||
|
* h4*r3 h3*r3 h2*r3 h1*r3 h0*r3
|
||||||
|
* h4*r4 h3*r4 h2*r4 h1*r4 h0*r4
|
||||||
|
*
|
||||||
|
* Each hn*rn fits in 53 bits. Carry won't be propagated at this step. Partial
|
||||||
|
* reduction modulo p starts here:
|
||||||
|
*
|
||||||
|
* 2^130
|
||||||
|
* h = | h4 h3 h2 h1 h0
|
||||||
|
* r = | r4 r3 r2 r1 r0
|
||||||
|
* ------------------------------|------------------------------
|
||||||
|
* | h4*r0 h3*r0 h2*r0 h1*r0 h0*r0
|
||||||
|
* h4*r1 | h3*r1 h2*r1 h1*r1 h0*r1
|
||||||
|
* h4*r2 h3*r2 | h2*r2 h1*r2 h0*r2
|
||||||
|
* h4*r3 h3*r3 h2*r3 | h1*r3 h0*r3
|
||||||
|
* h4*r4 h3*r4 h2*r4 h1*r4 | h0*r4
|
||||||
|
*
|
||||||
|
* 2^130
|
||||||
|
* h = | h4 h3 h2 h1 h0
|
||||||
|
* r = | r4 r3 r2 r1 r0
|
||||||
|
* --------|--------------------------------------
|
||||||
|
* | h4*r0 h3*r0 h2*r0 h1*r0 h0*r0
|
||||||
|
* | h3*r1 h2*r1 h1*r1 h0*r1 5*h4*r1
|
||||||
|
* | h2*r2 h1*r2 h0*r2 5*h4*r2 5*h3*r2
|
||||||
|
* | h1*r3 h0*r3 5*h4*r3 5*h3*r3 5*h2*r3
|
||||||
|
* | h0*r4 5*h4*r4 5*h3*r4 5*h2*r4 5*h1*r4
|
||||||
|
* --------|--------------------------------------
|
||||||
|
* h*r = | t4 t3 t2 t1 t0
|
||||||
|
*
|
||||||
|
* All the carry propagations are performed after this step. h0 is set t0 low
|
||||||
|
* 26 bits of t0; h1 thru h4 are set to tn + (tn-1 >> 26) to propagate the
|
||||||
|
* carry. t4 might overflow so it needs to be backpropagated to h0 and h1. h1
|
||||||
|
* won't carry into h2: given the highest possible h, c, and r,
|
||||||
|
*
|
||||||
|
* h = 0xffffffffffffffffffffffffffffffff
|
||||||
|
* c = 0x1ffffffffffffffffffffffffffffffff
|
||||||
|
* r = 0x0ffffffc0ffffffc0ffffffc0fffffff
|
||||||
|
*
|
||||||
|
* the limbs and t4 before h0 and h1 second propagation are
|
||||||
|
*
|
||||||
|
* h4 = 0x257ffff
|
||||||
|
* h3 = 0x3a95fff
|
||||||
|
* h2 = 0x3fea57f
|
||||||
|
* h1 = 0x3fffa70
|
||||||
|
* h0 = 0x2000002
|
||||||
|
* t4 = 0x77fffffa57ffff
|
||||||
|
*
|
||||||
|
* which becomes
|
||||||
|
*
|
||||||
|
* h4 = 0x257ffff
|
||||||
|
* h3 = 0x3a95fff
|
||||||
|
* h2 = 0x3fea57f
|
||||||
|
* h1 = 0x3fffa95
|
||||||
|
* h0 = 0x3fffff8
|
||||||
|
*
|
||||||
|
* To perform the final reduction modulo p, observe that each hn is bound by
|
||||||
|
* 2^26, which means that h is bound by 2^130. Define minusp = 2^136 - p.
|
||||||
|
* - If h < p, minusp + h < 2^136.
|
||||||
|
* - If h >= p, then h = p + k with k in {0,1,2,3,4}, and minusp + h =
|
||||||
|
* 2^136 - p + p + k = 2^136 + k >= 2^136, and both minusp + h = k mod 2^136
|
||||||
|
* and h = k mod p for all possible values of k.
|
||||||
|
*
|
||||||
|
* To avoid information leaking via side channels, define g = minusp + h, and
|
||||||
|
* select g if bit 136 is set, h otherwise. In particular, define a 32-bit
|
||||||
|
* mask = ~(g >> 136) + 1.
|
||||||
|
* - If bit 136 of g is 1, mask = ~1 + 1 = 0xffffffff.
|
||||||
|
* - If bit 136 of g is 0, mask = ~0 + 1 = 0.
|
||||||
|
* Then perform (h & ~mask) | (g & mask).
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
poly1305_block(struct poly1305_ctx *ctx, uint32_t hibit)
|
||||||
|
{
|
||||||
|
uint64_t h0, h1, h2, h3, h4, t0, t1, t2, t3, t4;
|
||||||
|
uint32_t r0, r1, r2, r3, r4, x1, x2, x3, x4;
|
||||||
|
|
||||||
|
h0 = ctx->h0;
|
||||||
|
h1 = ctx->h1;
|
||||||
|
h2 = ctx->h2;
|
||||||
|
h3 = ctx->h3;
|
||||||
|
h4 = ctx->h4;
|
||||||
|
r0 = ctx->r0;
|
||||||
|
r1 = ctx->r1;
|
||||||
|
r2 = ctx->r2;
|
||||||
|
r3 = ctx->r3;
|
||||||
|
r4 = ctx->r4;
|
||||||
|
x1 = ctx->x1;
|
||||||
|
x2 = ctx->x2;
|
||||||
|
x3 = ctx->x3;
|
||||||
|
x4 = ctx->x4;
|
||||||
|
|
||||||
|
t0 = load32le(&ctx->m[0]);
|
||||||
|
t1 = load32le(&ctx->m[4]);
|
||||||
|
t2 = load32le(&ctx->m[8]);
|
||||||
|
t3 = load32le(&ctx->m[12]);
|
||||||
|
t4 = hibit;
|
||||||
|
|
||||||
|
h0 += t0 & 0x3ffffff;
|
||||||
|
h1 += ((t1 << 6) | (t0 >> 26)) & 0x3ffffff;
|
||||||
|
h2 += ((t2 << 12) | (t1 >> 20)) & 0x3ffffff;
|
||||||
|
h3 += ((t3 << 18) | (t2 >> 14)) & 0x3ffffff;
|
||||||
|
h4 += (t4 << 24) | (t3 >> 8);
|
||||||
|
|
||||||
|
t0 = h0 * r0 + h4 * x1 + h3 * x2 + h2 * x3 + h1 * x4;
|
||||||
|
t1 = h1 * r0 + h0 * r1 + h4 * x2 + h3 * x3 + h2 * x4;
|
||||||
|
t2 = h2 * r0 + h1 * r1 + h0 * r2 + h4 * x3 + h3 * x4;
|
||||||
|
t3 = h3 * r0 + h2 * r1 + h1 * r2 + h0 * r3 + h4 * x4;
|
||||||
|
t4 = h4 * r0 + h3 * r1 + h2 * r2 + h1 * r3 + h0 * r4;
|
||||||
|
|
||||||
|
h0 = t0 & 0x3ffffff;
|
||||||
|
t1 += t0 >> 26;
|
||||||
|
h1 = t1 & 0x3ffffff;
|
||||||
|
t2 += t1 >> 26;
|
||||||
|
h2 = t2 & 0x3ffffff;
|
||||||
|
t3 += t2 >> 26;
|
||||||
|
h3 = t3 & 0x3ffffff;
|
||||||
|
t4 += t3 >> 26;
|
||||||
|
h4 = t4 & 0x3ffffff;
|
||||||
|
|
||||||
|
h0 += 5 * (t4 >> 26);
|
||||||
|
h1 += h0 >> 26;
|
||||||
|
h0 &= 0x3ffffff;
|
||||||
|
|
||||||
|
ctx->h0 = h0;
|
||||||
|
ctx->h1 = h1;
|
||||||
|
ctx->h2 = h2;
|
||||||
|
ctx->h3 = h3;
|
||||||
|
ctx->h4 = h4;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
poly1305_reduce(struct poly1305_ctx *ctx, uint32_t a[POLY1305_TAGLEN_WORDS])
|
||||||
|
{
|
||||||
|
uint64_t t0, t1, t2, t3, t4, g0, g1, g2, g3, g4;
|
||||||
|
uint32_t mask;
|
||||||
|
|
||||||
|
t0 = (ctx->h0 | (ctx->h1 << 26)) & 0xffffffff;
|
||||||
|
t1 = ((ctx->h1 >> 6) | (ctx->h2 << 20)) & 0xffffffff;
|
||||||
|
t2 = ((ctx->h2 >> 12) | (ctx->h3 << 14)) & 0xffffffff;
|
||||||
|
t3 = ((ctx->h3 >> 18) | (ctx->h4 << 8)) & 0xffffffff;
|
||||||
|
t4 = ctx->h4 >> 24;
|
||||||
|
|
||||||
|
g0 = t0 + 5;
|
||||||
|
g1 = t1 + (g0 >> 32);
|
||||||
|
g2 = t2 + (g1 >> 32);
|
||||||
|
g3 = t3 + (g2 >> 32);
|
||||||
|
g4 = t4 + (g3 >> 32) + 252;
|
||||||
|
|
||||||
|
mask = ~(g4 >> 8) + 1;
|
||||||
|
|
||||||
|
t0 = (t0 & ~mask) | (g0 & mask);
|
||||||
|
t1 = (t1 & ~mask) | (g1 & mask);
|
||||||
|
t2 = (t2 & ~mask) | (g2 & mask);
|
||||||
|
t3 = (t3 & ~mask) | (g3 & mask);
|
||||||
|
|
||||||
|
t0 += ctx->s0;
|
||||||
|
t1 += ctx->s1 + (t0 >> 32);
|
||||||
|
t2 += ctx->s2 + (t1 >> 32);
|
||||||
|
t3 += ctx->s3 + (t2 >> 32);
|
||||||
|
|
||||||
|
a[0] = t0 & 0xffffffff;
|
||||||
|
a[1] = t1 & 0xffffffff;
|
||||||
|
a[2] = t2 & 0xffffffff;
|
||||||
|
a[3] = t3 & 0xffffffff;
|
||||||
|
}
|
39
impl_poly1305.h
Normal file
39
impl_poly1305.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Lucas Gabriel Vuotto <lucas@lgv5.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "lilcrypto.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define POLY1305_CHUNK 16
|
||||||
|
#define POLY1305_TAGLEN_WORDS (LC_POLY1305_TAGLEN / sizeof(uint32_t))
|
||||||
|
|
||||||
|
|
||||||
|
struct poly1305_ctx {
|
||||||
|
uint32_t h0, h1, h2, h3, h4;
|
||||||
|
uint32_t r0, r1, r2, r3, r4;
|
||||||
|
uint32_t x1, x2, x3, x4;
|
||||||
|
uint32_t s0, s1, s2, s3;
|
||||||
|
size_t mlen;
|
||||||
|
uint8_t m[POLY1305_CHUNK];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void poly1305_block(struct poly1305_ctx *, uint32_t);
|
||||||
|
void poly1305_reduce(struct poly1305_ctx *,
|
||||||
|
uint32_t [POLY1305_TAGLEN_WORDS]);
|
7
lib/Makefile
Normal file
7
lib/Makefile
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
.PATH: ${.CURDIR}/..
|
||||||
|
|
||||||
|
LIB= lilcrypto
|
||||||
|
NOMAN= noman
|
||||||
|
SRCS= ${LC_SRCS}
|
||||||
|
|
||||||
|
.include <bsd.lib.mk>
|
1
lib/shlib_version
Normal file
1
lib/shlib_version
Normal file
@ -0,0 +1 @@
|
|||||||
|
LIBlilcrypto_VERSION=0.0
|
106
lilcrypto.h
Normal file
106
lilcrypto.h
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Lucas Gabriel Vuotto <lucas@lgv5.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Constants.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Authentitcation. */
|
||||||
|
#define LC_POLY1305_KEYLEN 32
|
||||||
|
#define LC_POLY1305_TAGLEN 16
|
||||||
|
|
||||||
|
/* Ciphers. */
|
||||||
|
#define LC_CHACHA20_KEYLEN 32
|
||||||
|
#define LC_CHACHA20_IVLEN 12
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Constant-time operations.
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint32_t lc_ct_cmp(const uint8_t *, const uint8_t *, size_t);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Message authentication code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct lc_auth_ctx;
|
||||||
|
struct lc_auth_impl;
|
||||||
|
|
||||||
|
|
||||||
|
int lc_auth_init(struct lc_auth_ctx *, const uint8_t *, size_t);
|
||||||
|
int lc_auth_update(struct lc_auth_ctx *, const uint8_t *, size_t);
|
||||||
|
int lc_auth_final(struct lc_auth_ctx *, uint8_t *, size_t *);
|
||||||
|
int lc_auth(const struct lc_auth_impl *, const uint8_t *, size_t,
|
||||||
|
uint8_t *, size_t *, const uint8_t *, size_t);
|
||||||
|
|
||||||
|
struct lc_auth_ctx *lc_auth_ctx_new(const struct lc_auth_impl *);
|
||||||
|
void lc_auth_ctx_free(struct lc_auth_ctx *);
|
||||||
|
|
||||||
|
const struct lc_auth_impl *lc_auth_impl_poly1305(void);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ciphers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct lc_cipher_ctx;
|
||||||
|
struct lc_cipher_impl;
|
||||||
|
|
||||||
|
|
||||||
|
int lc_cipher_encrypt_init(struct lc_cipher_ctx *, const uint8_t *, size_t,
|
||||||
|
const uint8_t *, size_t);
|
||||||
|
int lc_cipher_encrypt_update(struct lc_cipher_ctx *, uint8_t *, size_t *,
|
||||||
|
const uint8_t *, size_t);
|
||||||
|
int lc_cipher_encrypt_final(struct lc_cipher_ctx *, uint8_t *, size_t *);
|
||||||
|
int lc_cipher_encrypt(const struct lc_cipher_impl *, const uint8_t *,
|
||||||
|
size_t, const uint8_t *, size_t, uint8_t *, size_t *,
|
||||||
|
const uint8_t *, size_t);
|
||||||
|
int lc_cipher_decrypt_init(struct lc_cipher_ctx *, const uint8_t *, size_t,
|
||||||
|
const uint8_t *, size_t);
|
||||||
|
int lc_cipher_decrypt_update(struct lc_cipher_ctx *, uint8_t *, size_t *,
|
||||||
|
const uint8_t *, size_t);
|
||||||
|
int lc_cipher_decrypt_final(struct lc_cipher_ctx *, uint8_t *, size_t *);
|
||||||
|
int lc_cipher_decrypt(const struct lc_cipher_impl *, const uint8_t *,
|
||||||
|
size_t, const uint8_t *, size_t, uint8_t *, size_t *,
|
||||||
|
const uint8_t *, size_t);
|
||||||
|
|
||||||
|
struct lc_cipher_ctx *lc_cipher_ctx_new(const struct lc_cipher_impl *);
|
||||||
|
void lc_cipher_ctx_free(struct lc_cipher_ctx *);
|
||||||
|
|
||||||
|
const struct lc_cipher_impl *lc_cipher_impl_chacha20(void);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Authenticated encryption with additional data.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct lc_aead_impl;
|
||||||
|
|
||||||
|
|
||||||
|
int lc_aead_seal(const struct lc_aead_impl *, const uint8_t *, size_t,
|
||||||
|
const uint8_t *, size_t, uint8_t *, size_t *, const uint8_t *, size_t,
|
||||||
|
const uint8_t *, size_t);
|
||||||
|
int lc_aead_open(const struct lc_aead_impl *, const uint8_t *, size_t,
|
||||||
|
const uint8_t *, size_t, uint8_t *, size_t *, const uint8_t *, size_t,
|
||||||
|
const uint8_t *, size_t);
|
||||||
|
|
||||||
|
const struct lc_aead_impl *lc_aead_impl_chacha20_poly1305(void);
|
26
util.c
Normal file
26
util.c
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Lucas Gabriel Vuotto <lucas@lgv5.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
lc_scrub(void *b, size_t len)
|
||||||
|
{
|
||||||
|
explicit_bzero(b, len);
|
||||||
|
}
|
109
util.h
Normal file
109
util.h
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Lucas Gabriel Vuotto <lucas@lgv5.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define nelems(_a) (sizeof((_a)) / sizeof((_a)[0]))
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* External definitions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void lc_scrub(void *, size_t);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Endianness.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline uint16_t
|
||||||
|
load16le(const uint8_t *x)
|
||||||
|
{
|
||||||
|
return x[0] | (x[1] << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t
|
||||||
|
load32le(const uint8_t *x)
|
||||||
|
{
|
||||||
|
return x[0] | (x[1] << 8) | (x[2] << 16) | (x[3] << 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint64_t
|
||||||
|
load64le(const uint8_t *x)
|
||||||
|
{
|
||||||
|
return load32le(x) | (((uint64_t)load32le(x + 4)) << 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
store16le(uint8_t *x, uint64_t v)
|
||||||
|
{
|
||||||
|
x[0] = v & 0xff;
|
||||||
|
x[1] = v >> 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
store32le(uint8_t *x, uint32_t v)
|
||||||
|
{
|
||||||
|
x[0] = v & 0xff;
|
||||||
|
x[1] = (v >> 8) & 0xff;
|
||||||
|
x[2] = (v >> 16) & 0xff;
|
||||||
|
x[3] = v >> 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
store64le(uint8_t *x, uint64_t v)
|
||||||
|
{
|
||||||
|
x[0] = v & 0xff;
|
||||||
|
x[1] = (v >> 8) & 0xff;
|
||||||
|
x[2] = (v >> 16) & 0xff;
|
||||||
|
x[3] = (v >> 24) & 0xff;
|
||||||
|
x[4] = (v >> 32) & 0xff;
|
||||||
|
x[5] = (v >> 40) & 0xff;
|
||||||
|
x[6] = (v >> 48) & 0xff;
|
||||||
|
x[7] = v >> 56;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rotr and rotl.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline uint32_t
|
||||||
|
rotl32(uint32_t x, uint32_t r)
|
||||||
|
{
|
||||||
|
return (x << r) | (x >> (32 - r));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint64_t
|
||||||
|
rotl64(uint64_t x, uint64_t r)
|
||||||
|
{
|
||||||
|
return (x << r) | (x >> (64 - r));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t
|
||||||
|
rotr32(uint32_t x, uint32_t r)
|
||||||
|
{
|
||||||
|
return rotl32(x, 32 - r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint64_t
|
||||||
|
rotr64(uint64_t x, uint64_t r)
|
||||||
|
{
|
||||||
|
return rotl64(x, 64 - r);
|
||||||
|
}
|
25
wycheproof/Makefile
Normal file
25
wycheproof/Makefile
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
.PATH: ${.CURDIR}/..
|
||||||
|
|
||||||
|
AEAD= wycheproof_aead
|
||||||
|
|
||||||
|
PROGS= ${AEAD}
|
||||||
|
NOMAN= noman
|
||||||
|
|
||||||
|
SRCS_wycheproof_aead= wycheproof_aead.c
|
||||||
|
|
||||||
|
LDADD+= ${.CURDIR}/../lib/obj/liblilcrypto.a
|
||||||
|
|
||||||
|
|
||||||
|
tests: all tests-aead
|
||||||
|
|
||||||
|
tests-aead:
|
||||||
|
.ifndef WYCHEPROOF_DIR
|
||||||
|
@echo Undefined WYCHEPROOF_DIR; false
|
||||||
|
.endif
|
||||||
|
.for p in ${AEAD}
|
||||||
|
perl ${.CURDIR}/aead.pl -x ./${p} \
|
||||||
|
${WYCHEPROOF_DIR}/testvectors/chacha20_poly1305_test.json \
|
||||||
|
${WYCHEPROOF_DIR}/testvectors_v1/chacha20_poly1305_test.json
|
||||||
|
.endfor
|
||||||
|
|
||||||
|
.include <bsd.prog.mk>
|
69
wycheproof/aead.pl
Normal file
69
wycheproof/aead.pl
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#!/usr/bin/env perl
|
||||||
|
use v5.38;;
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use Getopt::Std;
|
||||||
|
use JSON::PP;
|
||||||
|
|
||||||
|
my $progname = $0 =~ s@.*/@@r;
|
||||||
|
|
||||||
|
sub slurp ($fh) { local $/; <$fh> }
|
||||||
|
|
||||||
|
sub usage ()
|
||||||
|
{
|
||||||
|
say STDERR "Usage: $progname -x runner json_file [json_files ...]";
|
||||||
|
exit 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub main ()
|
||||||
|
{
|
||||||
|
my %opts;
|
||||||
|
my $rc = 0;
|
||||||
|
|
||||||
|
getopts("x:", \%opts) && @ARGV > 0 or usage;
|
||||||
|
usage unless defined $opts{"x"};
|
||||||
|
|
||||||
|
for my $f (@ARGV) {
|
||||||
|
open(my $fh, "<", $f) or die "open failed: $!";
|
||||||
|
|
||||||
|
my $json = decode_json(slurp($fh));
|
||||||
|
for my $testgroup ($json->{testGroups}->@*) {
|
||||||
|
for my $test ($testgroup->{tests}->@*) {
|
||||||
|
my @args;
|
||||||
|
|
||||||
|
push(@args, $json->{algorithm});
|
||||||
|
push(@args, "-a", $test->{aad});
|
||||||
|
push(@args, "-c", $test->{ct});
|
||||||
|
push(@args, "-I", $testgroup->{ivSize});
|
||||||
|
push(@args, "-i", $test->{iv});
|
||||||
|
push(@args, "-K", $testgroup->{keySize});
|
||||||
|
push(@args, "-k", $test->{key});
|
||||||
|
push(@args, "-m", $test->{msg});
|
||||||
|
push(@args, "-T", $testgroup->{tagSize});
|
||||||
|
push(@args, "-t", $test->{tag});
|
||||||
|
|
||||||
|
open(my $th, "-|", $opts{"x"}, @args) or die;
|
||||||
|
my $result = slurp($th);
|
||||||
|
close($th);
|
||||||
|
|
||||||
|
chomp($result);
|
||||||
|
if ($result ne $test->{result}) {
|
||||||
|
$rc = 1;
|
||||||
|
say STDERR "case $test->{tcId}: ",
|
||||||
|
"expected $test->{result}: ",
|
||||||
|
"$test->{comment} [",
|
||||||
|
join(",", $test->{flags}->@*),
|
||||||
|
"]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close($fh);
|
||||||
|
}
|
||||||
|
|
||||||
|
say "ALL TESTS PASSED!" if $rc == 0;
|
||||||
|
return $rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit main;
|
326
wycheproof_aead.c
Normal file
326
wycheproof_aead.c
Normal file
@ -0,0 +1,326 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Lucas Gabriel Vuotto <lucas@lgv5.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <err.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "lilcrypto.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define nelems(_a) (sizeof((_a)) / sizeof((_a)[0]))
|
||||||
|
|
||||||
|
|
||||||
|
static inline uint8_t
|
||||||
|
hex2num(char s)
|
||||||
|
{
|
||||||
|
return s >= 'A' ? 10 + (s >= 'a' ? s - 'a' : s - 'A') : s - '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
hexparse(const char *s, uint8_t *out, size_t *outlen)
|
||||||
|
{
|
||||||
|
size_t l;
|
||||||
|
|
||||||
|
l = strlen(s);
|
||||||
|
if (l % 2 != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (out == NULL) {
|
||||||
|
*outlen = l / 2;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*outlen = 0;
|
||||||
|
while (*s != '\0') {
|
||||||
|
if (!isxdigit(s[0]) || !isxdigit(s[1]))
|
||||||
|
return 0;
|
||||||
|
*out++ = (hex2num(s[0]) << 4) | hex2num(s[1]);
|
||||||
|
(*outlen)++;
|
||||||
|
s += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
hexdump(FILE *fp, const uint8_t *blob, size_t len)
|
||||||
|
{
|
||||||
|
size_t i, off;
|
||||||
|
int pad;
|
||||||
|
|
||||||
|
for (i = 0; len > (1 << (8 * i)); i++)
|
||||||
|
;
|
||||||
|
pad = (i + 1) * 2;
|
||||||
|
|
||||||
|
off = 0;
|
||||||
|
while (len >= 16) {
|
||||||
|
fprintf(fp, "%0*zx\t", pad, off);
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
fprintf(fp, "%02x ", blob[i]);
|
||||||
|
for (; i < 16; i++)
|
||||||
|
fprintf(fp, " %02x", blob[i]);
|
||||||
|
|
||||||
|
fprintf(fp, "\t|");
|
||||||
|
for (i = 0; i < 16; i++)
|
||||||
|
fprintf(fp, "%c", isprint(blob[i]) ? blob[i] : '.');
|
||||||
|
fprintf(fp, "|\n");
|
||||||
|
|
||||||
|
blob += 16;
|
||||||
|
off += 16;
|
||||||
|
len -= 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len == 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
fprintf(fp, "%0*zx\t", pad, off);
|
||||||
|
for (i = 0; i < len && i < 8; i++)
|
||||||
|
fprintf(fp, "%02x ", blob[i]);
|
||||||
|
for (; i < 8; i++)
|
||||||
|
fprintf(fp, " ");
|
||||||
|
for (; i < len && i < 16; i++)
|
||||||
|
fprintf(fp, " %02x", blob[i]);
|
||||||
|
for (; i < 16; i++)
|
||||||
|
fprintf(fp, " ");
|
||||||
|
|
||||||
|
fprintf(fp, "\t|");
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
fprintf(fp, "%c", isprint(blob[i]) ? blob[i] : '.');
|
||||||
|
fprintf(fp, "|\n");
|
||||||
|
|
||||||
|
out:
|
||||||
|
fprintf(fp, "%0*zx\n", pad, off + len);
|
||||||
|
fflush(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct kwimpl {
|
||||||
|
const char *kw;
|
||||||
|
const struct lc_aead_impl *(*impl)(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
kwimpl_cmp(const void *k0, const void *h0)
|
||||||
|
{
|
||||||
|
const struct kwimpl *h = h0;
|
||||||
|
const char *k = k0;
|
||||||
|
|
||||||
|
return strcmp(k, h->kw);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct lc_aead_impl *
|
||||||
|
kw2impl(const char *s)
|
||||||
|
{
|
||||||
|
static const struct kwimpl tbl[] = {
|
||||||
|
{ "CHACHA20-POLY1305", &lc_aead_impl_chacha20_poly1305 },
|
||||||
|
};
|
||||||
|
struct kwimpl *match;
|
||||||
|
|
||||||
|
match = bsearch(s, tbl, nelems(tbl), sizeof(struct kwimpl),
|
||||||
|
&kwimpl_cmp);
|
||||||
|
|
||||||
|
return match != NULL ? match->impl() : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: %s [options]\n", getprogname());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
const struct lc_aead_impl *impl;
|
||||||
|
uint8_t *aad, *ct, *iv, *key, *msg, *tag, *out;
|
||||||
|
const char *errstr;
|
||||||
|
size_t aadlen, ctlen, ivlen, keylen, msglen, taglen;
|
||||||
|
size_t ivlenarg, keylenarg, taglenarg;
|
||||||
|
size_t l, outlen;
|
||||||
|
int aflag, cflag, Iflag, iflag, Kflag, kflag, mflag,
|
||||||
|
Tflag, tflag;
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
if (argc < 2)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
impl = kw2impl(argv[1]);
|
||||||
|
if (impl == NULL)
|
||||||
|
errx(1, "unsupported algorithm: %s", argv[1]);
|
||||||
|
|
||||||
|
optind = 2;
|
||||||
|
aflag = cflag = Iflag = iflag = Kflag = kflag = mflag = Tflag = tflag =
|
||||||
|
0;
|
||||||
|
while ((ch = getopt(argc, argv, "a:c:I:i:K:k:m:T:t:")) != -1) {
|
||||||
|
switch (ch) {
|
||||||
|
case 'a':
|
||||||
|
aflag = 1;
|
||||||
|
(void)hexparse(optarg, NULL, &aadlen);
|
||||||
|
if (aadlen != 0) {
|
||||||
|
aad = malloc(aadlen);
|
||||||
|
if (aad == NULL)
|
||||||
|
err(1, "out of memory");
|
||||||
|
} else
|
||||||
|
aad = NULL;
|
||||||
|
if (!hexparse(optarg, aad, &l) || l != aadlen)
|
||||||
|
errx(1, "invalid hex string: %s", optarg);
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
cflag = 1;
|
||||||
|
(void)hexparse(optarg, NULL, &ctlen);
|
||||||
|
if (ctlen != 0) {
|
||||||
|
ct = malloc(ctlen);
|
||||||
|
if (ct == NULL)
|
||||||
|
err(1, "out of memory");
|
||||||
|
} else
|
||||||
|
ct = NULL;
|
||||||
|
if (!hexparse(optarg, ct, &l) || l != ctlen)
|
||||||
|
errx(1, "invalid hex string: %s", optarg);
|
||||||
|
break;
|
||||||
|
case 'I':
|
||||||
|
Iflag = 1;
|
||||||
|
ivlenarg = strtonum(optarg, 0, LLONG_MAX, &errstr);
|
||||||
|
if (errstr != NULL)
|
||||||
|
errx(1, "ivlen is %s: %s", errstr, optarg);
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
iflag = 1;
|
||||||
|
(void)hexparse(optarg, NULL, &ivlen);
|
||||||
|
if (ivlen != 0) {
|
||||||
|
iv = malloc(ivlen);
|
||||||
|
if (iv == NULL)
|
||||||
|
err(1, "out of memory");
|
||||||
|
} else
|
||||||
|
iv = NULL;
|
||||||
|
if (!hexparse(optarg, iv, &l) || l != ivlen)
|
||||||
|
errx(1, "invalid hex string: %s", optarg);
|
||||||
|
break;
|
||||||
|
case 'K':
|
||||||
|
Kflag = 1;
|
||||||
|
keylenarg = strtonum(optarg, 0, LLONG_MAX, &errstr);
|
||||||
|
if (errstr != NULL)
|
||||||
|
errx(1, "keylen is %s: %s", errstr, optarg);
|
||||||
|
if (keylenarg % 8 != 0)
|
||||||
|
errx(1, "unsupport K value: %zu", keylenarg);
|
||||||
|
break;
|
||||||
|
case 'k':
|
||||||
|
kflag = 1;
|
||||||
|
(void)hexparse(optarg, NULL, &keylen);
|
||||||
|
if (keylen != 0) {
|
||||||
|
key = malloc(keylen);
|
||||||
|
if (key == NULL)
|
||||||
|
err(1, "out of memory");
|
||||||
|
} else
|
||||||
|
key = NULL;
|
||||||
|
if (!hexparse(optarg, key, &l) || l != keylen)
|
||||||
|
errx(1, "invalid hex string: %s", optarg);
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
mflag = 1;
|
||||||
|
(void)hexparse(optarg, NULL, &msglen);
|
||||||
|
if (msglen != 0) {
|
||||||
|
msg = malloc(msglen);
|
||||||
|
if (msg == NULL)
|
||||||
|
err(1, "out of memory");
|
||||||
|
} else
|
||||||
|
msg = NULL;
|
||||||
|
if (!hexparse(optarg, msg, &l) || l != msglen)
|
||||||
|
errx(1, "invalid hex string: %s", optarg);
|
||||||
|
break;
|
||||||
|
case 'T':
|
||||||
|
Tflag = 1;
|
||||||
|
taglenarg = strtonum(optarg, 0, LLONG_MAX, &errstr);
|
||||||
|
if (errstr != NULL)
|
||||||
|
errx(1, "taglen is %s: %s", errstr, optarg);
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
tflag = 1;
|
||||||
|
(void)hexparse(optarg, NULL, &taglen);
|
||||||
|
if (taglen != 0) {
|
||||||
|
tag = malloc(taglen);
|
||||||
|
if (tag == NULL)
|
||||||
|
err(1, "out of memory");
|
||||||
|
} else
|
||||||
|
tag = NULL;
|
||||||
|
if (!hexparse(optarg, tag, &l) || l != taglen)
|
||||||
|
errx(1, "invalid hex string: %s", optarg);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
argc -= optind;
|
||||||
|
argv += optind;
|
||||||
|
|
||||||
|
if (!(aflag && cflag && Iflag && iflag && Kflag && kflag && mflag &&
|
||||||
|
Tflag && tflag))
|
||||||
|
errx(1, "missing required arguments");
|
||||||
|
|
||||||
|
if (!lc_aead_seal(impl, key, keylenarg, iv, ivlenarg, NULL, &outlen,
|
||||||
|
aad, aadlen, msg, msglen)) {
|
||||||
|
puts("invalid");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ivlenarg /= 8;
|
||||||
|
keylenarg /= 8;
|
||||||
|
taglenarg /= 8;
|
||||||
|
|
||||||
|
out = malloc(outlen);
|
||||||
|
if (out == NULL)
|
||||||
|
err(1, "out of memory");
|
||||||
|
|
||||||
|
if (!lc_aead_seal(impl, key, keylenarg, iv, ivlenarg, out, &outlen,
|
||||||
|
aad, aadlen, msg, msglen)) {
|
||||||
|
puts("invalid");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctlen != outlen - LC_POLY1305_TAGLEN ||
|
||||||
|
lc_ct_cmp(out, ct, ctlen) != 0) {
|
||||||
|
fprintf(stderr, "ct (%zu, %zu)\n", ctlen,
|
||||||
|
outlen - LC_POLY1305_TAGLEN);
|
||||||
|
hexdump(stderr, msg, msglen);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
hexdump(stderr, ct, ctlen);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
hexdump(stderr, out, outlen - LC_POLY1305_TAGLEN);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
puts("invalid");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (taglenarg != LC_POLY1305_TAGLEN ||
|
||||||
|
lc_ct_cmp(out + ctlen, tag, LC_POLY1305_TAGLEN) != 0) {
|
||||||
|
fprintf(stderr, "tag (%zu, %zu)\n", taglenarg,
|
||||||
|
(size_t)LC_POLY1305_TAGLEN);
|
||||||
|
hexdump(stderr, tag, taglen);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
hexdump(stderr, out + ctlen, LC_POLY1305_TAGLEN);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
puts("invalid");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
puts("valid");
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user