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

2
.gitignore vendored
View file

@ -37,3 +37,5 @@ test_lzp
test_base64 test_base64
*.trs *.trs
stpdfs-fuse stpdfs-fuse
test_hchacha
test_xchacha

View file

@ -3,6 +3,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stddef.h> #include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
@ -16,6 +17,18 @@
# include <libgen.h> # include <libgen.h>
#endif /* HAVE_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 const char *prg_name;
static int fd = -1; 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)); stpdfs_read(fd, 1, &sb, sizeof(struct stpdfs_sb));
printf("StupidFS last opened: %s\n", asctime(localtime(&sb.time)));
return (NULL); return (NULL);
} }
@ -76,6 +89,26 @@ static int
fuse_stpdfs_getattr(const char *path, struct stat *stbuf, fuse_stpdfs_getattr(const char *path, struct stat *stbuf,
struct fuse_file_info *fi) 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); return (0);
} }
@ -145,7 +178,14 @@ main(int argc, char *argv[])
if (options.show_version) show_version(); if (options.show_version) show_version();
if (options.show_help) show_help(); 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); ret = fuse_main(args.argc, args.argv, &stpdfs_oper, NULL);
fuse_opt_free_args(&args); fuse_opt_free_args(&args);

View file

@ -1,2 +1,7 @@
noinst_LIBRARIES = libstpdfs.a 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 #ifndef STPDFS_CRYPTO_CHACHA_H
# define STPDFS_CRYPTO_CHACHA_H 1 # define STPDFS_CRYPTO_CHACHA_H 1
# include <stdint.h>
# define CHACHA_CONST1 "expa" # define CHACHA_CONST1 "expa"
# define CHACHA_CONST2 "nd 3" # define CHACHA_CONST2 "nd 3"
# define CHACHA_CONST3 "2-by" # define CHACHA_CONST3 "2-by"
@ -14,11 +16,21 @@
c += d; b ^= c; b = CHACHA_ROT_L(b, 7); \ c += d; b ^= c; b = CHACHA_ROT_L(b, 7); \
} while (0) } while (0)
# define HCHACHA_KEY_BYTES 32
# define HCHACHA_NONCE_BYTES 16
# define HCHACHA_OUT_BYTES 32 # 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) # 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 */ #endif /* STPDFS_CRYPTO_CHACHA_H */

View file

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

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

View file

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

View file

@ -10,17 +10,17 @@
void void
hchacha(uint8_t out[HCHACHA_OUT_BYTES], hchacha(uint8_t out[HCHACHA_OUT_BYTES],
const uint8_t key[HCHACHA_KEY_BYTES], const uint8_t key[CHACHA_KEY_BYTES],
const uint8_t nonce[HCHACHA_NONCE_BYTES], const uint8_t nonce[CHACHA_NONCE_BYTES],
int round); 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, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f 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 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> #include <crypto/chacha.h>
void void xchacha(uint8_t *out, uint8_t key[CHACHA_KEY_BYTES], uint8_t nonce[24],
hchacha(uint8_t out[HCHACHA_OUT_BYTES], uint8_t *in, size_t inlen, int round);
const uint8_t key[HCHACHA_KEY_BYTES], void chacha_init(struct chacha_ctx *ctx, const uint8_t key[CHACHA_KEY_BYTES],
const uint8_t nonce[HCHACHA_NONCE_BYTES], const uint32_t ctr, const uint8_t nonce[CHACHA_NONCE_BYTES]);
int round); 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, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f 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 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 static void
test_xchacha20(void **state) test_xchacha20(void **state)
{ {
uint8_t out[HCHACHA_OUT_BYTES]; uint8_t expected[] = {
uint8_t expected[HCHACHA_OUT_BYTES] = { 0xa2, 0x12, 0x09, 0x09, 0x65, 0x94, 0xde, 0x8c,
0x82, 0x41, 0x3b, 0x42, 0x27, 0xb2, 0x7b, 0xfe, 0xd3, 0x0e, 0x42, 0x50, 0x8a, 0x87, 0x7d, 0x73, 0x56, 0x67, 0xb1, 0xd1, 0x3a, 0xd9, 0x3f, 0x74,
0xa0, 0xf9, 0xe4, 0xd5, 0x8a, 0x74, 0xa8, 0x53, 0xc1, 0x2e, 0xc4, 0x13, 0x26, 0xd3, 0xec, 0xdc 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); xchacha(out, key2, nonce2, in, 91, 20);
assert_memory_equal(expected, out, HCHACHA_OUT_BYTES);
assert_memory_equal(expected, out, 91);
} }
int int
main(void) main(void)
{ {
const struct CMUnitTest tests[] = { const struct CMUnitTest tests[] = {
cmocka_unit_test(test_chacha_key_init),
cmocka_unit_test(test_chacha20_block),
cmocka_unit_test(test_xchacha20), cmocka_unit_test(test_xchacha20),
}; };

View file

@ -158,6 +158,7 @@ mkfs()
rootdirent[1].inode = 1; rootdirent[1].inode = 1;
strcpy(rootdirent[1].filename, ".."); strcpy(rootdirent[1].filename, "..");
rootdirent[1].inode = 1; 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, 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); stpdfs_write(fd, 2, &inds, sizeof(struct stpdfs_inode) * STPDFS_INODES_PER_BLOCK);