get rid of the unportable bs bigint.h bs; slowcrypt cli wip
This commit is contained in:
179
poly1305.h
Normal file
179
poly1305.h
Normal file
@@ -0,0 +1,179 @@
|
||||
#ifndef SLOWCRYPT_POLY1305_H
|
||||
#define SLOWCRYPT_POLY1305_H
|
||||
|
||||
#ifndef SLOWCRYPT_POLY1305_FUNC
|
||||
#define SLOWCRYPT_POLY1305_FUNC /**/
|
||||
#endif
|
||||
|
||||
#ifndef SLOWCRYPT_POLY1305_DONT_USE_BITINT
|
||||
#include <limits.h>
|
||||
#ifdef BITINT_MAXWIDTH
|
||||
#if BITINT_MAXWIDTH >= 264
|
||||
#define SLOWCRYPT_POLY1305_USE_BITINT
|
||||
#endif
|
||||
#elif defined(__BITINT_MAXWIDTH__)
|
||||
#if __BITINT_MAXWIDTH__ >= 264
|
||||
#define SLOWCRYPT_POLY1305_USE_BITINT
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef SLOWCRYPT_POLY1305_USE_BITINT
|
||||
#else
|
||||
ERROR NOT YET IMPLEMENTED;
|
||||
#ifdef SLOWCRYPT_POLY1305_IMPL
|
||||
#define BIGINT_IMPLEMENTATION
|
||||
#endif
|
||||
#define BIGINT_FUNC SLOWCRYPT_POLY1305_FUNC
|
||||
#define BIGINT_NAMESPACE(x) slowcrypt_poly1305_bigint_##x
|
||||
#define BIGINT_UNDEF
|
||||
#define BIGINT_NO_MALLOC
|
||||
#define BIGINT_DEFAULT_LIMIT 33
|
||||
#define BIGINT_WORD_WIDTH 1
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
#ifdef SLOWCRYPT_POLY1305_USE_BITINT
|
||||
unsigned _BitInt(128) r, s;
|
||||
unsigned _BitInt(136) acc;
|
||||
unsigned _BitInt(264) prod;
|
||||
#else
|
||||
slowcrypt_poly1305_bigint_bigint r, s, acc, p, temp1, temp2;
|
||||
#endif
|
||||
} slowcrypt_poly1305;
|
||||
|
||||
/* the key buffer will be destroyed: used as scratch buffer */
|
||||
SLOWCRYPT_POLY1305_FUNC void slowcrypt_poly1305_init(slowcrypt_poly1305* p,
|
||||
uint8_t key[32]);
|
||||
|
||||
/* only the last block is allowed to be shorter than 16 bytes!
|
||||
*
|
||||
* length has to be maximum 16
|
||||
*/
|
||||
SLOWCRYPT_POLY1305_FUNC void slowcrypt_poly1305_next_block(
|
||||
slowcrypt_poly1305* p,
|
||||
uint8_t const* data,
|
||||
unsigned int length);
|
||||
|
||||
/* also zeroizes memory */
|
||||
SLOWCRYPT_POLY1305_FUNC void slowcrypt_poly1305_finish(slowcrypt_poly1305* p,
|
||||
uint8_t out[16]);
|
||||
|
||||
#ifdef SLOWCRYPT_POLY1305_IMPL
|
||||
|
||||
#ifdef SLOWCRYPT_POLY1305_USE_BITINT
|
||||
|
||||
static unsigned _BitInt(136) slowcrypt_poly1305_from_le(uint8_t const* buf,
|
||||
unsigned int buf_len,
|
||||
uint8_t top)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned _BitInt(136) out = (unsigned _BitInt(136))top << (buf_len * 8);
|
||||
for (i = 0; i < buf_len; i++)
|
||||
out |= (unsigned _BitInt(136))buf[i] << (i * 8);
|
||||
return out;
|
||||
}
|
||||
|
||||
SLOWCRYPT_POLY1305_FUNC void slowcrypt_poly1305_init(slowcrypt_poly1305* p,
|
||||
uint8_t key[32])
|
||||
{
|
||||
key[3] &= 15;
|
||||
key[7] &= 15;
|
||||
key[11] &= 15;
|
||||
key[15] &= 15;
|
||||
key[4] &= 252;
|
||||
key[8] &= 252;
|
||||
key[12] &= 252;
|
||||
p->r = (unsigned _BitInt(128))slowcrypt_poly1305_from_le(key, 16, 0);
|
||||
p->s = (unsigned _BitInt(128))slowcrypt_poly1305_from_le(&key[16], 16, 0);
|
||||
p->acc = 0;
|
||||
}
|
||||
|
||||
SLOWCRYPT_POLY1305_FUNC void slowcrypt_poly1305_next_block(
|
||||
slowcrypt_poly1305* p,
|
||||
uint8_t const* data,
|
||||
unsigned int length)
|
||||
{
|
||||
if (length == 0)
|
||||
return;
|
||||
p->prod = p->acc + slowcrypt_poly1305_from_le(data, length, 0x01);
|
||||
p->prod *= p->r;
|
||||
p->prod %= ((unsigned _BitInt(136))1 << 130) - (unsigned _BitInt(136))5;
|
||||
p->acc = p->prod;
|
||||
}
|
||||
|
||||
SLOWCRYPT_POLY1305_FUNC void slowcrypt_poly1305_finish(slowcrypt_poly1305* p,
|
||||
uint8_t out[16])
|
||||
{
|
||||
unsigned int i;
|
||||
p->acc += p->s;
|
||||
for (i = 0; i < 16; i++)
|
||||
out[i] = (uint8_t)((p->acc >> (i * 8)));
|
||||
|
||||
for (i = 0; i < sizeof(slowcrypt_poly1305); i++)
|
||||
((char*)p)[i] = 0;
|
||||
}
|
||||
|
||||
#else
|
||||
static void slowcrypt_poly1305_from_le(slowcrypt_poly1305_bigint_bigint* out,
|
||||
slowcrypt_poly1305_bigint_bigint* temp,
|
||||
uint8_t const* buf,
|
||||
unsigned int buf_len,
|
||||
uint8_t top)
|
||||
{
|
||||
slowcrypt_poly1305_bigint_from_u8(temp, top);
|
||||
for (; buf_len-- > 0; buf++) {
|
||||
slowcrypt_poly1305_bigint_from_u8(temp, *buf);
|
||||
slowcrypt_poly1305_bigint_lshift_overwrite(out, 8);
|
||||
slowcrypt_poly1305_bigint_inc(out, temp);
|
||||
}
|
||||
}
|
||||
|
||||
SLOWCRYPT_POLY1305_FUNC void slowcrypt_poly1305_init(slowcrypt_poly1305* p,
|
||||
uint8_t key[32])
|
||||
{
|
||||
(void)slowcrypt_poly1305_bigint_from_cstring(
|
||||
&p->p, "3fffffffffffffffffffffffffffffffb", 16);
|
||||
key[3] &= 15;
|
||||
key[7] &= 15;
|
||||
key[11] &= 15;
|
||||
key[15] &= 15;
|
||||
key[4] &= 252;
|
||||
key[8] &= 252;
|
||||
key[12] &= 252;
|
||||
slowcrypt_poly1305_from_le(&p->r, &p->temp1, key, 16, 0);
|
||||
slowcrypt_poly1305_from_le(&p->s, &p->temp1, &key[16], 16, 0);
|
||||
}
|
||||
|
||||
/* only the last block is allowed to be shorter than 16 bytes! */
|
||||
SLOWCRYPT_POLY1305_FUNC void slowcrypt_poly1305_next_block(
|
||||
slowcrypt_poly1305* p,
|
||||
uint8_t const* data,
|
||||
unsigned int length)
|
||||
{
|
||||
if (length == 0)
|
||||
return;
|
||||
slowcrypt_poly1305_from_le(&p->temp1, &p->temp2, data, length, 0x01);
|
||||
slowcrypt_poly1305_bigint_inc(&p->acc, &p->temp1);
|
||||
slowcrypt_poly1305_bigint_mul(&p->acc, &p->acc, &p->r);
|
||||
slowcrypt_poly1305_bigint_div_mod(&p->temp1, &p->acc, &p->acc, &p->p);
|
||||
}
|
||||
|
||||
SLOWCRYPT_POLY1305_FUNC void slowcrypt_poly1305_finish(slowcrypt_poly1305* p,
|
||||
uint8_t out[16])
|
||||
{
|
||||
unsigned int i;
|
||||
slowcrypt_poly1305_bigint_inc(&p->acc, &p->s);
|
||||
for (i = 0; i < 16; i++)
|
||||
out[i] = p->acc.words[i];
|
||||
for (i = 0; i < sizeof(slowcrypt_poly1305); i++)
|
||||
((char*)p)[i] = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
198
slowcrypt/slowcrypt.c
Normal file
198
slowcrypt/slowcrypt.c
Normal file
@@ -0,0 +1,198 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define SLOWCRYPT_CHACHA20_IMPL
|
||||
#include "../chacha20.h"
|
||||
|
||||
#define SLOWCRYPT_POLY1305_IMPL
|
||||
#include "../poly1305.h"
|
||||
|
||||
struct algo
|
||||
{
|
||||
char const* name;
|
||||
void (*run)(char**);
|
||||
};
|
||||
|
||||
static FILE* file_open(char const* path)
|
||||
{
|
||||
FILE* fp;
|
||||
|
||||
if (!strcmp(path, "-"))
|
||||
return stdin;
|
||||
|
||||
fp = fopen(path, "rb");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "Could not open %s\n", path);
|
||||
exit(1);
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
static void file_close(FILE* p)
|
||||
{
|
||||
if (!p)
|
||||
return;
|
||||
if (p == stdout || p == stdin || p == stderr)
|
||||
return;
|
||||
fclose(p);
|
||||
}
|
||||
|
||||
static int anyeq__impl(char const* str, char const** opts)
|
||||
{
|
||||
for (; *opts; opts++)
|
||||
if (!strcmp(str, *opts))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
#define anyeq(str, ...) anyeq__impl(str, (char const*[]){__VA_ARGS__, 0})
|
||||
|
||||
static char const* parse_hex_prefix(char const* msg)
|
||||
{
|
||||
if (*msg == 'h')
|
||||
msg++;
|
||||
else if (msg[0] == '0' && msg[1] == 'x')
|
||||
msg++;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
static uint8_t parse_hex_nibble(char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9')
|
||||
return c - '0';
|
||||
if (c >= 'a' && c <= 'f')
|
||||
return c - 'a' + 0xA;
|
||||
if (c >= 'A' && c <= 'F')
|
||||
return c - 'A' + 0xA;
|
||||
fprintf(stderr, "Not a hexadecimal number!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static uint8_t parse_hex(char const** msg)
|
||||
{
|
||||
uint8_t res = parse_hex_nibble(*(*msg)++);
|
||||
if (**msg) {
|
||||
res <<= 4;
|
||||
res |= parse_hex_nibble(*(*msg)++);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static void parse_hex2buf(uint8_t* buf,
|
||||
unsigned int buflen,
|
||||
char const* label,
|
||||
char const* hex)
|
||||
{
|
||||
unsigned int num = 0;
|
||||
hex = parse_hex_prefix(hex);
|
||||
for (; num < buflen && *hex; num++)
|
||||
buf[num] = parse_hex(&hex);
|
||||
if (num != buflen || *hex) {
|
||||
fprintf(stderr, "Expected %s to be %u (hexadecimal) bytes!\n", label,
|
||||
buflen);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned long file_read_chunk(FILE* file,
|
||||
uint8_t* buf,
|
||||
unsigned long buflen)
|
||||
{
|
||||
unsigned long n;
|
||||
if (feof(file))
|
||||
return 0;
|
||||
n = fread(buf, 1, buflen, file);
|
||||
if (ferror(file)) {
|
||||
fprintf(stderr, "File read error!");
|
||||
exit(1);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static void run_poly1305(char** args)
|
||||
{
|
||||
static char const help[] =
|
||||
"poly1305 [--key] <hex-key> [file]\n"
|
||||
"\n"
|
||||
"Run the Poly1305 one-time authenticator on the data from the given file "
|
||||
"or stdin\n";
|
||||
char const* key = 0;
|
||||
char const* fpath = "-";
|
||||
FILE* fp;
|
||||
unsigned int npos = 0;
|
||||
uint8_t keybuf[32];
|
||||
uint8_t chunk[16];
|
||||
slowcrypt_poly1305 poly1305;
|
||||
unsigned int nb;
|
||||
|
||||
if (!*args) {
|
||||
printf("%s", help);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
for (; *args; args++) {
|
||||
if (!key && anyeq(*args, "-k", "-key", "--key") && args[1]) {
|
||||
args++;
|
||||
key = *args;
|
||||
} else if (anyeq(*args, "-h", "-help", "--help")) {
|
||||
printf("%s", help);
|
||||
exit(0);
|
||||
} else if (npos == 1 && ++npos) {
|
||||
fpath = *args;
|
||||
} else if (npos == 0 && ++npos && !key) {
|
||||
key = *args;
|
||||
} else {
|
||||
fprintf(stderr, "Unexpected argument: %s\n", *args);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!key) {
|
||||
fprintf(stderr, "Missing argument: [--key] <hex-key>");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fp = file_open(fpath);
|
||||
|
||||
parse_hex2buf(keybuf, 32, "key", key);
|
||||
slowcrypt_poly1305_init(&poly1305, keybuf);
|
||||
|
||||
while ((nb = file_read_chunk(fp, chunk, 16))) {
|
||||
slowcrypt_poly1305_next_block(&poly1305, chunk, nb);
|
||||
}
|
||||
slowcrypt_poly1305_finish(&poly1305, chunk);
|
||||
|
||||
for (nb = 0; nb < 16; nb++)
|
||||
printf("%02x", chunk[nb]);
|
||||
printf("\n");
|
||||
|
||||
file_close(fp);
|
||||
}
|
||||
|
||||
static struct algo bytes2sum[] = {{"poly1305", run_poly1305}, {0, 0}};
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
argv++;
|
||||
struct algo* a;
|
||||
|
||||
if (!*argv || anyeq(*argv, "-h", "-help", "--help")) {
|
||||
printf("bytes -> hash\n");
|
||||
for (a = bytes2sum; a->name; a++) {
|
||||
printf(" %s\n", a->name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (a = bytes2sum; a->name; a++) {
|
||||
if (!strcmp(a->name, *argv)) {
|
||||
a->run(argv + 1);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "Unknown algorithm %s\n", *argv);
|
||||
return 1;
|
||||
}
|
Reference in New Issue
Block a user