chibipub

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit c1382e6b640f4805c9b4f8cf0cacd5b2c89cf050
parent c542737153224f9b6dde9d0e2281d67a8d79e02d
Author: William Casarin <jb55@jb55.com>
Date:   Sun, 17 Jan 2021 12:33:45 -0800

gather keyids

Diffstat:
Msrc/ap_json.c | 5+++--
Msrc/cursor.h | 5+++++
Asrc/hash.h | 34++++++++++++++++++++++++++++++++++
Msrc/sigcheck.c | 126++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Msrc/util.h | 2++
5 files changed, 166 insertions(+), 6 deletions(-)

diff --git a/src/ap_json.c b/src/ap_json.c @@ -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 { diff --git a/src/cursor.h b/src/cursor.h @@ -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; diff --git a/src/hash.h b/src/hash.h @@ -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 */ diff --git a/src/sigcheck.c b/src/sigcheck.c @@ -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); diff --git a/src/util.h b/src/util.h @@ -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;