~jb55/chibipub

431f3822009b5a961e7e62953d5da4baa2fcaad1 — William Casarin a month ago c1382e6
initial sigcache logic
5 files changed, 165 insertions(+), 21 deletions(-)

M Makefile
M src/hash.h
M src/io.c
M src/io.h
M src/sigcheck.c
M Makefile => Makefile +2 -1
@@ 19,7 19,8 @@ BLAKE3_OBJS = deps/blake3/blake3.o \
	      deps/blake3/blake3_portable.o \
	      deps/blake3/blake3_sse2_x86-64_unix.o \
	      deps/blake3/blake3_sse41_x86-64_unix.o \
	      deps/blake3/blake3_avx2_x86-64_unix.o
	      deps/blake3/blake3_avx2_x86-64_unix.o \
	      deps/blake3/blake3_avx512_x86-64_unix.o \

HEADERS = $(wildcard src/*.h) deps/sha256/sha256.h


M src/hash.h => src/hash.h +2 -2
@@ 18,14 18,14 @@ static inline uint32_t fnv1a(unsigned char *bytes, int len)
	while (len--)
		hash = fnv1a_byte(*p++, hash);

	return hash
	return hash;
}

static inline int blake3_hash(unsigned char *data, int data_len,
		unsigned char *dest)
{
	blake3_hasher hasher;
	blake3_hadher_init(&hasher);
	blake3_hasher_init(&hasher);
	blake3_hasher_update(&hasher, data, data_len);
	blake3_hasher_finalize(&hasher, dest, BLAKE3_OUT_LEN);
	return BLAKE3_OUT_LEN;

M src/io.c => src/io.c +27 -0
@@ 22,3 22,30 @@ int map_file(const char *filename, unsigned char **p, size_t *flen)
	return *p != MAP_FAILED;
}

int read_fd(FILE *fd, unsigned char *buf, int buflen, int *written)
{
	unsigned char *p = buf;
	int len = 0;
	*written = 0;

	do {
		len = fread(p, 1, 4096, fd);
		*written += len;
		p += len;
		if (p > buf + buflen)
			return 0;
	} while (len == 4096);

	return 1;
}

int read_file(const char *filename, unsigned char *out, int out_len, int *written)
{
	FILE *file = NULL;

	file = fopen(filename, "rb");
	if (file == NULL)
		return 0;

	return read_fd(file, out, out_len, written);
}

M src/io.h => src/io.h +4 -0
@@ 3,7 3,11 @@
#define CHIBIPUB_IO

#include <stddef.h>
#include <stdio.h>

int map_file(const char *filename, unsigned char **p, size_t *flen);

int read_fd(FILE *fd, unsigned char *buf, int buflen, int *written);
int read_file(const char *filename, unsigned char *out, int out_len, int *written);

#endif /* CHIBIPUB_IO */

M src/sigcheck.c => src/sigcheck.c +130 -18
@@ 2,11 2,15 @@
#define SCRATCH_SIZE 1048576

#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>

#include "json.h"
#include "ubjson.h"
#include "hash.h"
#include "io.h"
#include "sigcheck.h"
#include "util.h"


@@ 32,32 36,55 @@ static int verify_signature(struct cursor cur, struct cursor *arena)
	return 1;
}

struct keyid {
	unsigned char *pubkey;
	int pubkey_size;
};

static inline int push_keyid(struct cursor *c, const char *keyid, int keyid_len)
{
	struct keyid offset = {0};
	return push_int(c, keyid_len)
		&& push_data(c, (unsigned char *)keyid, keyid_len);
		&& push_data(c, (unsigned char *)keyid, keyid_len)
		&& push_data(c, (unsigned char *)&offset, sizeof(offset)); // reserved for pubkey data index
}

static int pull_keyid(struct cursor *c, unsigned char **keyid_str,
		int *keyid_len, struct keyid **keyid)
{
	if (!pull_int(c, keyid_len)) {
		return 0;
	}

	*keyid_str = c->p;
	c->p += *keyid_len;
	*keyid = (struct keyid*)c->p;
	c->p += sizeof(struct keyid);

	return 1;
}

static int has_keyid(struct cursor *keyids, const char *keyid, int keyid_len)
{
	struct cursor scan;
	int size;
	unsigned char *keyid_str;
	struct keyid *offset;

	scan.start = keyids->start;
	scan.p = keyids->start;
	scan.end = keyids->p;

	while (scan.p < scan.end) {
		if (!pull_int(&scan, &size))
		if (!pull_keyid(&scan, &keyid_str, &size, &offset)) {
			return 0;
		}
		if (size != keyid_len) {
			scan.p += size;
			continue;
		}
		if (!memcmp(keyid, scan.p, keyid_len)) {
		if (!memcmp(keyid, keyid_str, keyid_len)) {
			return 1;
		}
		scan.p += size;
	}

	return 0;


@@ 67,6 94,8 @@ static int print_keyids(struct cursor *keyids)
{
	struct cursor scan;
	int size;
	unsigned char *keyid_str;
	struct keyid *keyid;

	scan.start = keyids->start;
	scan.p = keyids->start;


@@ 74,36 103,32 @@ static int print_keyids(struct cursor *keyids)

	printf("keyids\n");
	while (scan.p < scan.end) {
		if (!pull_int(&scan, &size))
		if (!pull_keyid(&scan, &keyid_str, &size, &keyid))
			return 0;
		printf("%.*s\n", size, scan.p);
		scan.p += size;
		printf("%.*s\n", size, keyid_str);
	}

	return 1;
}

static int gather_keyids(unsigned char *json, int json_len,
		struct cursor *arena, unsigned char **keyids)
		struct cursor *arena, struct cursor *keyids_cur)
{
	static const char *path[] = {"@wskeyid"};
	const int ubjson_mem_size = 1024 * 256;

	struct ubjson ubjson;
	struct json val;
	struct cursor keyids_cur;
	struct json_parser parser;
	struct json_handlers handlers;
	unsigned char *ubjson_mem;

	ubjson_mem = cursor_alloc(arena, ubjson_mem_size);
	make_cursor(arena->p, arena->end, &keyids_cur);
	make_cursor(arena->p, arena->end, keyids_cur);
	init_ubjson(&ubjson, ubjson_mem, ubjson_mem_size);
	make_ubjson_handlers(&handlers, &ubjson.cur);
	init_json_parser(&parser, json, json_len, &handlers);

	*keyids = keyids_cur.start;

	while (parse_json(&parser)) {
		init_ubjson(&ubjson, ubjson_mem, ubjson_mem_size);
		ubjson.data_end = ubjson.cur.p;


@@ 113,29 138,116 @@ static int gather_keyids(unsigned char *json, int json_len,
			return 0;
		}

		if (has_keyid(&keyids_cur, val.string, val.len)) {
		if (has_keyid(keyids_cur, val.string, val.len)) {
			continue;
		}

		if (!push_keyid(&keyids_cur, val.string, val.len)) {
		if (!push_keyid(keyids_cur, val.string, val.len)) {
			note_error(&parser.errs, "push_keyid");
			return 0;
		}
	}

	print_keyids(&keyids_cur);
	print_keyids(keyids_cur);

	return 1;
}

static int hex_bytes(unsigned char *bytes, int n_bytes, unsigned char *buf,
		int buf_size)
{
	static const char *hex = "0123456789abcdef";
	int b;

	if (n_bytes * 2 < buf_size)
		return 0;

	for (int i = 0; i < buf_size; i++) {
		b = bytes[i/2];
		b = i % 2 ? b & 0x0F : (b & 0xF0) >> 4;
		buf[i] = hex[b];
	}

	return 1;
}

static int get_cached_pubkey(unsigned char *keyid, int size,
		unsigned char *buf, int buflen, int *pubkey_size)
{
	unsigned char hash[32];
	unsigned char hash_str[64];
	char path[128] = {0};
	mode_t mode = 0777;

	// if we sucessfully created a directory, then we definitely
	// don't have any cached pubkeys
	if (0 == mkdir(".chibipub", mode)) {
		return 0;
	}
	
	if (0 == mkdir(".chibipub/objects", mode)) {
		return 0;
	}

	blake3_hash(keyid, size, hash);
	if (!hex_bytes(hash, 32, hash_str, 64)) {
		assert(0);
	}

	sprintf(path, ".chibipub/objects/%c%c/%.*s",
			hash_str[0], hash_str[1], 64, hash_str);

	fprintf(stderr, "sig cache exists? '%s' ", path);
	if (access(path, F_OK)) {
		fprintf(stderr, "no.\n");
		return 0;
	}
	fprintf(stderr, "yes!\n");

	return read_file(path, buf, buflen, pubkey_size);
}

static int fetch_signature(unsigned char *keyid, int keyid_len)
{
	printf("fetch signature %.*s\n", keyid_len, keyid);
	return 1;
}

static int fetch_signatures(unsigned char *json, int json_len,
		struct cursor *arena)
{
	unsigned char *keyids;
	struct cursor keyids;
	struct cursor scan;
	int size;
	unsigned char *keyid_str;
	struct keyid *keyid;

	if (!gather_keyids(json, json_len, arena, &keyids)) {
		return 0;
	}

	scan.start = keyids.start;
	scan.p = scan.start;
	scan.end = keyids.p;
	while (scan.p < scan.end) {
		if (!pull_keyid(&scan, &keyid_str, &size, &keyid)) {
			return 0;
		}

		if (get_cached_pubkey(scan.p, size, arena->p,
				      arena->end - arena->p,
				      &keyid->pubkey_size)) {
			keyid->pubkey = arena->p;
			arena->p += keyid->pubkey_size;
			printf("got cached pubkey of size %d... do something\n",
					keyid->pubkey_size);

			continue;
		}

		fetch_signature(keyid_str, size);
	}

	return 1;
}



@@ 165,7 277,7 @@ int sigcheck(struct sigcheck *check)
	start = out_cur.p;
	while (parse_json(&jsonp)) {
		count++;
		printf("[%d] parse success, \n", count);
		printf("[%d] parse success\n", count);

		if (!verify_signature(out_cur, &out_cur)) {
			printf("bad signature #%d\n", count);