test: add test_xchacha.c

This commit is contained in:
d0p1 🏳️‍⚧️ 2024-06-16 13:56:59 +00:00
parent 2e5886303d
commit 21d335ed95
11 changed files with 284 additions and 35 deletions

4
.gitignore vendored
View file

@ -36,4 +36,6 @@ mkfs.stpd
test_lzp
test_base64
*.trs
stpdfs-fuse
stpdfs-fuse
test_hchacha
test_xchacha

View file

@ -3,6 +3,7 @@
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
@ -16,6 +17,18 @@
# include <libgen.h>
#endif /* HAVE_LIBGEN_H */
static struct path {
char *name;
uint32_t inode;
size_t child_count;
struct path *child;
} root_path = {
"/", 1, 0, NULL
};
static const char *prg_name;
static int fd = -1;
@ -54,7 +67,7 @@ fuse_stpdfs_init(struct fuse_conn_info *conn,
}
stpdfs_read(fd, 1, &sb, sizeof(struct stpdfs_sb));
printf("StupidFS last opened: %s\n", asctime(localtime(&sb.time)));
return (NULL);
}
@ -76,6 +89,26 @@ static int
fuse_stpdfs_getattr(const char *path, struct stat *stbuf,
struct fuse_file_info *fi)
{
struct stpdfs_inode inodes[STPDFS_INODES_PER_BLOCK];
struct stpdfs_inode inode;
size_t idx;
uint32_t ino;
char *p = strtok(path, "/");
stpdfs_read(fd, 2, &inodes, sizeof(struct stpdfs_inode) * STPDFS_INODES_PER_BLOCK);
inode = inodes[1];
if (p != NULL)
{
// todo
}
stbuf->st_atim.tv_sec = inode.actime;
stbuf->st_mtim.tv_sec = inode.modtime;
stbuf->st_size = inode.size;
stbuf->st_mode = inode.mode;
stbuf->st_gid = inode.gid;
stbuf->st_uid = inode.uid;
return (0);
}
@ -145,7 +178,14 @@ main(int argc, char *argv[])
if (options.show_version) show_version();
if (options.show_help) show_help();
if (options.filename == NULL) show_help();
if (options.filename)
{
options.filename = realpath(options.filename, NULL);
}
else
{
show_help();
}
ret = fuse_main(args.argc, args.argv, &stpdfs_oper, NULL);
fuse_opt_free_args(&args);

View file

@ -1,2 +1,7 @@
noinst_LIBRARIES = libstpdfs.a
libstpdfs_a_SOURCES = block.c superblock.c codec/base64.c compression/lzp.c crypto/hchacha.c
libstpdfs_a_SOURCES = block.c \
superblock.c \
codec/base64.c \
compression/lzp.c \
crypto/hchacha.c \
crypto/xchacha.c

View file

@ -1,6 +1,8 @@
#ifndef STPDFS_CRYPTO_CHACHA_H
# define STPDFS_CRYPTO_CHACHA_H 1
# include <stdint.h>
# define CHACHA_CONST1 "expa"
# define CHACHA_CONST2 "nd 3"
# define CHACHA_CONST3 "2-by"
@ -14,11 +16,21 @@
c += d; b ^= c; b = CHACHA_ROT_L(b, 7); \
} while (0)
# define HCHACHA_KEY_BYTES 32
# define HCHACHA_NONCE_BYTES 16
# define HCHACHA_OUT_BYTES 32
# define HCHACHA_CONST_BYTES 16
# define CHACHA_KEY_BYTES 32
# define CHACHA_NONCE_BYTES 16
# define CHACHA_BLOCK_BYTES 64
# define TO_LE_32(x) ((x)[0]) | ((x)[1] << 8) | ((x)[2] << 16) | ((x)[3] << 24)
struct chacha_ctx {
uint32_t state[4][4];
uint32_t ctr;
};
void
hchacha(uint8_t out[HCHACHA_OUT_BYTES],
const uint8_t key[CHACHA_KEY_BYTES],
const uint8_t nonce[CHACHA_NONCE_BYTES], int round);
#endif /* STPDFS_CRYPTO_CHACHA_H */

View file

@ -1,13 +1,11 @@
#include <string.h>
#include <endian.h>
#include <stdint.h>
#include <string.h>
#include "chacha.h"
void
hchacha(uint8_t out[HCHACHA_OUT_BYTES],
const uint8_t key[HCHACHA_KEY_BYTES],
const uint8_t nonce[HCHACHA_NONCE_BYTES],
const uint8_t key[CHACHA_KEY_BYTES],
const uint8_t nonce[CHACHA_NONCE_BYTES],
int round)
{
int idx;
@ -60,8 +58,8 @@ hchacha(uint8_t out[HCHACHA_OUT_BYTES],
void
hchacha12(uint8_t out[HCHACHA_OUT_BYTES],
const uint8_t key[HCHACHA_KEY_BYTES],
const uint8_t nonce[HCHACHA_NONCE_BYTES])
const uint8_t key[CHACHA_KEY_BYTES],
const uint8_t nonce[CHACHA_NONCE_BYTES])
{
return (hchacha(out, key, nonce, 12));
}

View file

@ -0,0 +1,129 @@
#include <endian.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "chacha.h"
void
chacha_init(struct chacha_ctx *ctx, const uint8_t key[CHACHA_KEY_BYTES],
const uint32_t ctr, const uint8_t nonce[CHACHA_NONCE_BYTES])
{
ctx->ctr = ctr;
ctx->state[0][0] = TO_LE_32(CHACHA_CONST1);
ctx->state[0][1] = TO_LE_32(CHACHA_CONST2);
ctx->state[0][2] = TO_LE_32(CHACHA_CONST3);
ctx->state[0][3] = TO_LE_32(CHACHA_CONST4);
ctx->state[1][0] = TO_LE_32(key);
ctx->state[1][1] = TO_LE_32(key + 4);
ctx->state[1][2] = TO_LE_32(key + 4 * 2);
ctx->state[1][3] = TO_LE_32(key + 4 * 3);
ctx->state[2][0] = TO_LE_32(key + 16);
ctx->state[2][1] = TO_LE_32(key + 16 + 4);
ctx->state[2][2] = TO_LE_32(key + 16 + 4 * 2);
ctx->state[2][3] = TO_LE_32(key + 16 + 4 * 3);
ctx->state[3][0] = htole32(ctx->ctr);
ctx->state[3][1] = TO_LE_32(nonce);
ctx->state[3][2] = TO_LE_32(nonce + 4);
ctx->state[3][3] = TO_LE_32(nonce + 4 * 2);
}
void
chacha_block(struct chacha_ctx *ctx, uint8_t *out, int round)
{
int idx;
uint32_t tmp[4][4];
for (idx = 0; idx < 4; idx++)
{
tmp[idx][0] = ctx->state[idx][0];
tmp[idx][1] = ctx->state[idx][1];
tmp[idx][2] = ctx->state[idx][2];
tmp[idx][3] = ctx->state[idx][3];
}
for (idx = 0; idx < round/2; idx++)
{
CHACHA_QUARTERROUND(tmp[0][0], tmp[1][0], tmp[2][0], tmp[3][0]);
CHACHA_QUARTERROUND(tmp[0][1], tmp[1][1], tmp[2][1], tmp[3][1]);
CHACHA_QUARTERROUND(tmp[0][2], tmp[1][2], tmp[2][2], tmp[3][2]);
CHACHA_QUARTERROUND(tmp[0][3], tmp[1][3], tmp[2][3], tmp[3][3]);
CHACHA_QUARTERROUND(tmp[0][0], tmp[1][1], tmp[2][2], tmp[3][3]);
CHACHA_QUARTERROUND(tmp[0][1], tmp[1][2], tmp[2][3], tmp[3][0]);
CHACHA_QUARTERROUND(tmp[0][2], tmp[1][3], tmp[2][0], tmp[3][1]);
CHACHA_QUARTERROUND(tmp[0][3], tmp[1][0], tmp[2][1], tmp[3][2]);
}
*(uint32_t *)(out + 0) = htole32(tmp[0][0] + ctx->state[0][0]);
*(uint32_t *)(out + 4) = htole32(tmp[0][1] + ctx->state[0][1]);
*(uint32_t *)(out + 8) = htole32(tmp[0][2] + ctx->state[0][2]);
*(uint32_t *)(out + 12) = htole32(tmp[0][3] + ctx->state[0][3]);
*(uint32_t *)(out + 16) = htole32(tmp[1][0] + ctx->state[1][0]);
*(uint32_t *)(out + 20) = htole32(tmp[1][1] + ctx->state[1][1]);
*(uint32_t *)(out + 24) = htole32(tmp[1][2] + ctx->state[1][2]);
*(uint32_t *)(out + 28) = htole32(tmp[1][3] + ctx->state[1][3]);
*(uint32_t *)(out + 32) = htole32(tmp[2][0] + ctx->state[2][0]);
*(uint32_t *)(out + 36) = htole32(tmp[2][1] + ctx->state[2][1]);
*(uint32_t *)(out + 40) = htole32(tmp[2][2] + ctx->state[2][2]);
*(uint32_t *)(out + 44) = htole32(tmp[2][3] + ctx->state[2][3]);
*(uint32_t *)(out + 48) = htole32(tmp[3][0] + ctx->state[3][0]);
*(uint32_t *)(out + 52) = htole32(tmp[3][1] + ctx->state[3][1]);
*(uint32_t *)(out + 56) = htole32(tmp[3][2] + ctx->state[3][2]);
*(uint32_t *)(out + 60) = htole32(tmp[3][3] + ctx->state[3][3]);
ctx->ctr++;
ctx->state[3][0] = htole32(ctx->ctr);
}
void
chacha_encrypt(struct chacha_ctx *ctx, uint8_t *out, uint8_t *in, size_t inlen, int round)
{
size_t i;
size_t j;
uint8_t block[CHACHA_BLOCK_BYTES];
chacha_block(ctx, block, round);
for (i = 0, j = 0; i < inlen; i++, j++)
{
if (j >= CHACHA_BLOCK_BYTES)
{
j = 0;
chacha_block(ctx, block, round);
}
out[i] = in[i] ^ block[j];
}
}
void
xchacha(uint8_t *out, uint8_t key[CHACHA_KEY_BYTES], uint8_t nonce[24],
uint8_t *in, size_t inlen, int round)
{
uint8_t subkey[CHACHA_KEY_BYTES];
uint8_t tmp[12];
struct chacha_ctx ctx;
hchacha(subkey, key, nonce, round);
memset(tmp, 0, 12);
memcpy(tmp + 4, nonce + 16, 8);
chacha_init(&ctx, subkey, 1, tmp);
chacha_encrypt(&ctx, out, in, inlen, round);
}
void
xchacha12(uint8_t *out, uint8_t key[CHACHA_KEY_BYTES], uint8_t nonce[24],
uint8_t *in, size_t inlen)
{
xchacha(out, key, nonce, in, inlen, 12);
}

View file

@ -19,9 +19,10 @@
# define STPDFS_ROOT_INO 1
# define STPDFS_INO_FLAG_ALOC (1 << 15)
# define STPDFS_INO_FLAG_LZP (1 << 0)
# define STPDFS_INO_FLAG_ENC (1 << 1)
# define STPDFS_INO_FLAG_ALOC (1 << 15)
# define STPDFS_INO_FLAG_LARGE (1 << 0)
# define STPDFS_INO_FLAG_LZP (1 << 1)
# define STPDFS_INO_FLAG_ENC (1 << 2)
# define STPDFS_S_IFMT 0xF000
# define STPDFS_S_IFSOCK 0xA000

View file

@ -1,7 +1,7 @@
AM_CPPFLAGS = -I$(top_srcdir)/lib
TESTS = test_lzp test_base64 test_hchacha
check_PROGRAMS = test_lzp test_base64 test_hchacha
TESTS = test_lzp test_base64 test_hchacha test_xchacha
check_PROGRAMS = test_lzp test_base64 test_hchacha test_xchacha
LDADD = -lcmocka ../lib/libstpdfs.a
@ -10,3 +10,5 @@ test_lzp_SOURCES = test_lzp.c
test_base64_SOURCES = test_base64.c
test_hchacha_SOURCES = test_hchacha.c
test_xchacha_SOURCES = test_xchacha.c

View file

@ -10,17 +10,17 @@
void
hchacha(uint8_t out[HCHACHA_OUT_BYTES],
const uint8_t key[HCHACHA_KEY_BYTES],
const uint8_t nonce[HCHACHA_NONCE_BYTES],
const uint8_t key[CHACHA_KEY_BYTES],
const uint8_t nonce[CHACHA_NONCE_BYTES],
int round);
uint8_t key[HCHACHA_KEY_BYTES] = {
uint8_t key[CHACHA_KEY_BYTES] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
};
uint8_t nonce[HCHACHA_NONCE_BYTES] = {
uint8_t nonce[CHACHA_NONCE_BYTES] = {
0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x31, 0x41, 0x59, 0x27
};

View file

@ -6,39 +6,98 @@
#include <crypto/chacha.h>
void
hchacha(uint8_t out[HCHACHA_OUT_BYTES],
const uint8_t key[HCHACHA_KEY_BYTES],
const uint8_t nonce[HCHACHA_NONCE_BYTES],
int round);
void xchacha(uint8_t *out, uint8_t key[CHACHA_KEY_BYTES], uint8_t nonce[24],
uint8_t *in, size_t inlen, int round);
void chacha_init(struct chacha_ctx *ctx, const uint8_t key[CHACHA_KEY_BYTES],
const uint32_t ctr, const uint8_t nonce[CHACHA_NONCE_BYTES]);
void chacha_block(struct chacha_ctx *ctx, uint8_t *out, int round);
uint8_t key[HCHACHA_KEY_BYTES] = {
uint8_t key[CHACHA_KEY_BYTES] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
};
uint8_t nonce[HCHACHA_NONCE_BYTES] = {
uint8_t nonce[CHACHA_NONCE_BYTES] = {
0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x31, 0x41, 0x59, 0x27
};
uint8_t nonce2[24] = {
0xc0, 0x47, 0x54, 0x82, 0x66, 0xb7, 0xc3, 0x70,
0xd3, 0x35, 0x66, 0xa2, 0x42, 0x5c, 0xbf, 0x30,
0xd8, 0x2d, 0x1e, 0xaf, 0x52, 0x94, 0x10, 0x9e
};
uint8_t key2[CHACHA_KEY_BYTES] = {
0xc0, 0x47, 0x54, 0x82, 0x66, 0xb7, 0xc3, 0x70,
0xd3, 0x35, 0x66, 0xa2, 0x42, 0x5c, 0xbf, 0x30,
0xd8, 0x2d, 0x1e, 0xaf, 0x52, 0x94, 0x10, 0x9e
};
static void
test_chacha_key_init(void **state)
{
struct chacha_ctx ctx;
uint32_t expected[] = {
0x61707865, 0x3320646e, 0x79622d32, 0x6b206574,
0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c,
0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c,
0x00000001, 0x09000000, 0x4a000000, 0x00000000
};
chacha_init(&ctx, key, 1, nonce);
assert_memory_equal(expected, ctx.state, 64);
}
static void
test_chacha20_block(void **state)
{
struct chacha_ctx ctx;
uint8_t block[CHACHA_BLOCK_BYTES];
uint32_t expected[] = {
0xe4e7f110, 0x15593bd1, 0x1fdd0f50, 0xc47120a3,
0xc7f4d1c7, 0x0368c033, 0x9aaa2204, 0x4e6cd4c3,
0x466482d2, 0x09aa9f07, 0x05d7c214, 0xa2028bd9,
0xd19c12b5, 0xb94e16de, 0xe883d0cb, 0x4e3c50a2
};
chacha_init(&ctx, key, 1, nonce);
chacha_block(&ctx, block, 20);
assert_memory_equal(expected, block, CHACHA_BLOCK_BYTES);
}
static void
test_xchacha20(void **state)
{
uint8_t out[HCHACHA_OUT_BYTES];
uint8_t expected[HCHACHA_OUT_BYTES] = {
0x82, 0x41, 0x3b, 0x42, 0x27, 0xb2, 0x7b, 0xfe, 0xd3, 0x0e, 0x42, 0x50, 0x8a, 0x87, 0x7d, 0x73,
0xa0, 0xf9, 0xe4, 0xd5, 0x8a, 0x74, 0xa8, 0x53, 0xc1, 0x2e, 0xc4, 0x13, 0x26, 0xd3, 0xec, 0xdc
uint8_t expected[] = {
0xa2, 0x12, 0x09, 0x09, 0x65, 0x94, 0xde, 0x8c,
0x56, 0x67, 0xb1, 0xd1, 0x3a, 0xd9, 0x3f, 0x74,
0x41, 0x06, 0xd0, 0x54, 0xdf, 0x21, 0x0e, 0x47,
0x82, 0xcd, 0x39, 0x6f, 0xec, 0x69, 0x2d, 0x35,
0x15, 0xa2, 0x0b, 0xf3, 0x51, 0xee, 0xc0, 0x11,
0xa9, 0x2c, 0x36, 0x78, 0x88, 0xbc, 0x46, 0x4c,
0x32, 0xf0, 0x80, 0x7a, 0xcd, 0x6c, 0x20, 0x3a,
0x24, 0x7e, 0x0d, 0xb8, 0x54, 0x14, 0x84, 0x68,
0xe9, 0xf9, 0x6b, 0xee, 0x4c, 0xf7, 0x18, 0xd6,
0x8d, 0x5f, 0x63, 0x7c, 0xbd, 0x5a, 0x37, 0x64,
0x57, 0x78, 0x8e, 0x6f, 0xae, 0x90, 0xfc, 0x31, 0x09, 0x7c, 0xfc
};
uint8_t out[91];
uint8_t in[91] = { 0 };
hchacha(out, key, nonce, 20);
assert_memory_equal(expected, out, HCHACHA_OUT_BYTES);
xchacha(out, key2, nonce2, in, 91, 20);
assert_memory_equal(expected, out, 91);
}
int
main(void)
{
const struct CMUnitTest tests[] = {
cmocka_unit_test(test_chacha_key_init),
cmocka_unit_test(test_chacha20_block),
cmocka_unit_test(test_xchacha20),
};

View file

@ -158,6 +158,7 @@ mkfs()
rootdirent[1].inode = 1;
strcpy(rootdirent[1].filename, "..");
rootdirent[1].inode = 1;
inds[STPDFS_INO_ROOTDIR].nlink += 2;
stpdfs_write(fd, inds[STPDFS_INO_ROOTDIR].zones[0], rootdirent, sizeof(struct stpdfs_dirent) * 2);
stpdfs_write(fd, 2, &inds, sizeof(struct stpdfs_inode) * STPDFS_INODES_PER_BLOCK);