~jb55/chibipub

c1382e6b640f4805c9b4f8cf0cacd5b2c89cf050 — William Casarin a month ago c542737
gather keyids
5 files changed, 166 insertions(+), 6 deletions(-)

M src/ap_json.c
M src/cursor.h
A src/hash.h
M src/sigcheck.c
M src/util.h
M src/ap_json.c => src/ap_json.c +3 -2
@@ 208,7 208,7 @@ static int handle_wssigbuf(struct ap_json *a)

	for (i = 0; i < n_headers; i++) {
		str = &strs[i];
		if (!push_data(c, str->text, str->size)) {
		if (!push_escaped(c, str->text, str->size)) {
			return 0;
		}
		if (!push_str(c, ": ")) {


@@ 221,7 221,8 @@ static int handle_wssigbuf(struct ap_json *a)
				return 0;
			}
		} else if ((header = find_header(a->req->headers, str->text, str->size))) {
			if (!push_str(c, header->value)) {
			if (!push_escaped(c, (unsigned char*)header->value,
						strlen(header->value))) {
				return 0;
			}
		} else {

M src/cursor.h => src/cursor.h +5 -0
@@ 33,6 33,11 @@ static inline void *cursor_alloc(struct cursor *mem, unsigned long size)
	return ret;
}

static inline void reset_cursor(struct cursor *cur)
{
	cur->p = cur->start;
}

static inline void copy_cursor(struct cursor *src, struct cursor *dest)
{
	dest->start = src->start;

A src/hash.h => src/hash.h +34 -0
@@ 0,0 1,34 @@


#ifndef CHIBIPUB_HASH
#define CHIBIPUB_HASH

#include "blake3/blake3.h"

static inline uint32_t fnv1a_byte(unsigned char b, uint32_t hash)
{
	return (b ^ hash) * 0x01000193;
}


static inline uint32_t fnv1a(unsigned char *bytes, int len)
{
	uint32_t hash = 0x811C9DC5;
	unsigned char *p = bytes;
	while (len--)
		hash = fnv1a_byte(*p++, 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_update(&hasher, data, data_len);
	blake3_hasher_finalize(&hasher, dest, BLAKE3_OUT_LEN);
	return BLAKE3_OUT_LEN;
}

#endif /* CHIBIPUB_HASH */

M src/sigcheck.c => src/sigcheck.c +122 -4
@@ 24,7 24,7 @@ static int verify_signature(struct cursor cur, struct cursor *arena)
	ubjson.data_end = cur.p;

	static const char *path[] = {"@wssigbuf"};
	if (!ubjson_lookup(&ubjson, path, 2, &val)) {
	if (!ubjson_lookup(&ubjson, path, ARRAY_SIZE(path), &val)) {
		note_error(&ubjson.errs, "Signature header not found");
		return 0;
	}


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

static inline int push_keyid(struct cursor *c, const char *keyid, int keyid_len)
{
	return push_int(c, keyid_len)
		&& push_data(c, (unsigned char *)keyid, keyid_len);
}

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

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

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

	return 0;
}

static int print_keyids(struct cursor *keyids)
{
	struct cursor scan;
	int size;

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

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

	return 1;
}

static int gather_keyids(unsigned char *json, int json_len,
		struct cursor *arena, unsigned char **keyids)
{
	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);
	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;

		if (!ubjson_lookup(&ubjson, path, ARRAY_SIZE(path), &val)) {
			note_error(&parser.errs, "@wskeyid not found");
			return 0;
		}

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

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

	print_keyids(&keyids_cur);

	return 1;
}

static int fetch_signatures(unsigned char *json, int json_len,
		struct cursor *arena)
{
	unsigned char *keyids;
	if (!gather_keyids(json, json_len, arena, &keyids)) {
		return 0;
	}

	return 1;
}

int sigcheck(struct sigcheck *check)
{
	int count = 0;
	unsigned char *p, *scratch;
	unsigned char *p, *start, *scratch;
	size_t flen;
	struct json_parser jsonp;
	struct json_handlers handlers;


@@ 50,11 157,22 @@ int sigcheck(struct sigcheck *check)
	make_ubjson_handlers(&handlers, &out_cur);
	init_json_parser(&jsonp, p, flen, &handlers);

	if (!fetch_signatures(p, flen, &out_cur)) {
		note_error(&jsonp.errs, "fatal error fetching signature");
		return 0;
	}

	start = out_cur.p;
	while (parse_json(&jsonp)) {
		printf("success #%d\n", ++count);
		count++;
		printf("[%d] parse success, \n", count);

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

		// overwrite last ubjson
		out_cur.p = start;
	}

	munmap(p, flen);

M src/util.h => src/util.h +2 -0
@@ 7,6 7,8 @@

#include "cursor.h"

#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))

static inline int stricmp(const char *a, const char *b) {
	int len, i;