chibipub

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

commit 431f3822009b5a961e7e62953d5da4baa2fcaad1
parent c1382e6b640f4805c9b4f8cf0cacd5b2c89cf050
Author: William Casarin <jb55@jb55.com>
Date:   Sun, 17 Jan 2021 22:24:41 -0800

initial sigcache logic

Diffstat:
MMakefile | 3++-
Msrc/hash.h | 4++--
Msrc/io.c | 27+++++++++++++++++++++++++++
Msrc/io.h | 4++++
Msrc/sigcheck.c | 148+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
5 files changed, 165 insertions(+), 21 deletions(-)

diff --git a/Makefile b/Makefile @@ -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 diff --git a/src/hash.h b/src/hash.h @@ -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; diff --git a/src/io.c b/src/io.c @@ -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); +} diff --git a/src/io.h b/src/io.h @@ -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 */ diff --git a/src/sigcheck.c b/src/sigcheck.c @@ -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);