commit 65157e646a6fd2a156aa09eee7d008686a6ea4b7
parent 526fce1ea18343535048def444d86cc2cf22da98
Author: Jan Pobrislo <ccx@te2000.cz>
Date: Mon, 7 Oct 2024 13:06:52 +0000
Rudimentary miniroon parsing and signature check
Diffstat:
2 files changed, 181 insertions(+), 49 deletions(-)
diff --git a/src/gen-miniroon.py b/src/gen-miniroon.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python3
+import sys
+import hmac
+
+def to_ns(b):
+ assert isinstance(b, bytes)
+ return b'%d:%s,' % (len(b), b)
+
+
+def rec_ns(data):
+ if isinstance(data, bytes):
+ return to_ns(data)
+ if isinstance(data, str):
+ return to_ns(data.encode('ascii'))
+ return to_ns(b''.join(rec_ns(i) for i in data))
+
+
+def miniroon_hmac(key, msg):
+ print('miniroon_hmac%r' % ((key, msg),), file=sys.stderr)
+ #return hmac.digest(key, msg, 'blake2s')
+ return hmac.digest(key, msg, 'sha256')
+
+
+def make_miniroon(name, action='invoke-once', secret=b'\0'*32, caveats=(), version='capv0'):
+ hdr = rec_ns((version, name, action))
+ sig = miniroon_hmac(secret, hdr)
+ for c in caveats:
+ sig = miniroon_hmac(sig, c)
+ return rec_ns([
+ hdr,
+ caveats,
+ sig,
+ ])
+
+
+if __name__ == '__main__':
+ import os
+ os.write(1, make_miniroon(name='ccx'))
diff --git a/src/miniroon.c b/src/miniroon.c
@@ -11,9 +11,10 @@
#include <skalibs/netstring.h>
#include <skalibs/uint64.h>
#include <skalibs/blake2s.h>
+#include <skalibs/sha256.h>
-#define USAGE "macrun directory"
-#define PROG "macrun"
+#define USAGE "miniroon directory"
+#define PROG "miniroon"
#define input_fd 0
#define payload_size_max 1024*1024
@@ -43,16 +44,59 @@ typedef struct miniroon_header_s {
} miniroon_header;
/* declarations */
+void dbg_print_bb(const bytebuffer *bb);
+void dbg_print_bb1(const char *text, const bytebuffer *bb);
void parse_payload(bytebuffer *payload);
void parse_header(miniroon_header *header, bytebuffer *source);
void parse_caveat(bytebuffer *source); // TODO
void read_secret(bytebuffer *secret); // TODO
void hmac_b2s_256(const bytebuffer *key, const bytebuffer *msg, bytebuffer *output);
+void hmac_sha2_256(const bytebuffer *key, const bytebuffer *msg, bytebuffer *output);
#define MINIROON_HMAC_SIZE 32
-#define MINIROON_HMAC_FUNC(key, msg, out) hmac_b2s_256(key, msg, out)
+//#define MINIROON_HMAC_FUNC(key, msg, out) hmac_b2s_256(key, msg, out)
+#define MINIROON_HMAC_FUNC(key, msg, out) hmac_sha2_256(key, msg, out)
/* definitions */
+void dbg_print_bb(const bytebuffer *bb) {
+ static const char digit[] = "0123456789abcdef";
+ char ascii[16];
+ char hex[32];
+ size_t i, j, a_off=0, h_off=0;
+ for (i = 0; i < bb->len; ++i) {
+ if (i % 16 == 0) {
+ if(i) {
+ write(2, "|", 1);
+ write(2, hex, h_off);
+ write(2, "| [", 3);
+ write(2, ascii, a_off);
+ write(2, "]\n", 2);
+ }
+ a_off=0;
+ h_off=0;
+ }
+ unsigned char c = bb->data[i];
+ ascii[a_off++] = (c >= ' ' && c <= '~') ? c : '.';
+ hex[h_off++] = digit[0xf & (c >> 4)];
+ hex[h_off++] = digit[0xf & c];
+ }
+ while(h_off < 32) {
+ hex[h_off++] = ' ';
+ }
+ write(2, "|", 1);
+ write(2, hex, h_off);
+ write(2, "| [", 3);
+ write(2, ascii, a_off);
+ write(2, "]\n", 2);
+}
+
+void dbg_print_bb1(const char *text, const bytebuffer *bb) {
+ write(2, "\n", 1);
+ write(2, text, strlen(text));
+ write(2, ":\n", 2);
+ dbg_print_bb(bb);
+}
+
void netstring_chunk_init (netstring_chunk *chunk, const bytebuffer source) {
memset(chunk, 0, sizeof(netstring_chunk));
chunk->source = source;
@@ -70,66 +114,30 @@ bool netstring_chunk_next (netstring_chunk *c) {
if (c->outer.len + c->inner.len >= c->source.len) {
strerr_dief1x(111, "Malformed netstring (truncated)");
}
- if (c->source.data[c->outer.len + c->inner.len] != ',') {
+ if (c->source.data[c->outer.len + c->inner.len + 1] != ',') {
strerr_dief1x(111, "Malformed netstring (expected ',')");
}
c->inner.data = &c->source.data[c->outer.len + 1];
c->outer.len += c->inner.len + 2;
c->source.data += c->outer.len;
c->source.len -= c->outer.len;
+ return true;
}
-int netstring_get_chunk (const bytebuffer *input, bytebuffer *chunk, bytebuffer *rest)
-{
- uint64_t nlen; /* size of payload */
- size_t pos; /* size of numerical prefix */
- if (!input->len) {
- return 0;
- }
- pos = uint64_scan(input->data, &nlen) ;
- if (pos >= input->len) {
- return 0;
- }
- if (input->data[pos] != ':') {
- return 0;
- }
- char *s = input->data + pos + 1; /* start of payload */
- if (input->len <= nlen + pos + 1) {
- return 0;
- }
- if (s[nlen] != ',') {
- return 0;
- }
- if (chunk != NULL) {
- chunk->data = s;
- chunk->len = nlen;
- }
- if (rest != NULL) {
- chunk->data = s + 1;
- chunk->len = input->len - nlen - pos - 2;
- }
- return 1;
-}
void fd_block(int fd) {
int flags = fcntl(fd, F_GETFL);
if(flags == -1) {
strerr_dief1sys(111, "fcntl() getfd");
}
- if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
+ if(fcntl(fd, F_SETFL, flags | ~O_NONBLOCK) < 0) {
strerr_dief1sys(111, "fcntl() setfd");
}
}
-void parse_header(miniroon_header *header, bytebuffer *outer) {
- bytebuffer input=*outer, chunk, next;
- if(!input.len) {
- strerr_dief1x(111, "Empty header");
- }
- if(!netstring_get_chunk(&input, &chunk, &next)) {
- strerr_dief1x(111, "Malformed netstring");
- }
-
+void parse_header(miniroon_header *header, bytebuffer *source) {
+ // TODO
+ dbg_print_bb1("Got header", source);
}
void handle_payload(size_t payload_size) {
@@ -143,7 +151,7 @@ void handle_payload(size_t payload_size) {
}
if(read_size == -1) {
if(errno != EINTR) {
- strerr_dief1sys(111, "read()");
+ strerr_dief1sys(111, "read() payload");
}
continue;
}
@@ -154,6 +162,7 @@ void handle_payload(size_t payload_size) {
}
bytebuffer payload_bb = {payload, payload_size};
+ dbg_print_bb1("Got payload", &payload_bb);
parse_payload(&payload_bb);
}
@@ -180,7 +189,9 @@ void parse_payload(bytebuffer *payload) {
uint8_t hmac_data[MINIROON_HMAC_SIZE];
bytebuffer hmac_bb = {hmac_data, MINIROON_HMAC_SIZE};
read_secret(&hmac_bb);
+ // dbg_print_bb1("Secret", &hmac_bb);
MINIROON_HMAC_FUNC(&hmac_bb, &c.inner, &hmac_bb);
+ // dbg_print_bb1("Signature update", &hmac_bb);
if(!netstring_chunk_next(&c)) {
strerr_dief1x(111, "Mising miniroon body");
@@ -189,19 +200,22 @@ void parse_payload(bytebuffer *payload) {
netstring_chunk_init(&body, c.inner);
while(netstring_chunk_next(&body)) {
+ dbg_print_bb1("Got caveat", &body.inner);
parse_caveat(&body.inner);
MINIROON_HMAC_FUNC(&hmac_bb, &body.inner, &hmac_bb);
+ // dbg_print_bb1("Signature update", &hmac_bb);
}
if(!netstring_chunk_next(&c)) {
strerr_dief1x(111, "Mising miniroon signature");
}
+ dbg_print_bb1("Got signature", &c.inner);
if(c.inner.len != MINIROON_HMAC_SIZE) {
- strerr_dief1x(111, "Mising miniroon signature length");
+ strerr_dief1x(111, "Invalid miniroon signature length");
}
/* constant time hash compare */
uint8_t bitdiff = 0;
- for(size_t i=0; i<=MINIROON_HMAC_SIZE; i++) {
+ for(size_t i=0; i<MINIROON_HMAC_SIZE; i++) {
bitdiff |= hmac_data[i] ^ c.inner.data[i];
}
if(netstring_chunk_next(&c)) {
@@ -218,6 +232,8 @@ void hmac_b2s_256(const bytebuffer *key, const bytebuffer *msg, bytebuffer *outp
assert(output->len == block_size);
assert(msg);
+ dbg_print_bb1("HMAC key", key);
+ dbg_print_bb1("HMAC message", msg);
blake2s_ctx hash_ctx;
uint8_t pad[block_size], ihash[block_size];
@@ -240,6 +256,84 @@ void hmac_b2s_256(const bytebuffer *key, const bytebuffer *msg, bytebuffer *outp
blake2s_update(&hash_ctx, pad, block_size);
blake2s_update(&hash_ctx, ihash, block_size);
blake2s_final(&hash_ctx, output->data);
+ dbg_print_bb1("HMAC output", output);
+}
+
+/* function doing the HMAC-SHA-256 calculation */
+void hmac_sha256(const uint8_t* key, const uint32_t keysize, const uint8_t* msg, const uint32_t msgsize, uint8_t* output)
+{
+ static const size_t block_size = 64, digest_size = 32;
+ SHA256Schedule outer, inner;
+ uint8_t tmp;
+
+ if (keysize > block_size) // if len(key) > blocksize(sha256) => key = sha256(key)
+ {
+ uint8_t new_key[digest_size];
+ sha256_init(&outer);
+ sha256_update(&outer, key, keysize);
+ sha256_final(&outer, new_key);
+ return hmac_sha256(new_key, digest_size, msg, msgsize, output);
+ }
+ sha256_init(&outer);
+ sha256_init(&inner);
+
+ uint32_t i;
+ for (i = 0; i < keysize; ++i)
+ {
+ tmp = key[i] ^ 0x5C;
+ sha256_update(&outer, &tmp, 1);
+ tmp = key[i] ^ 0x36;
+ sha256_update(&inner, &tmp, 1);
+ }
+ for (; i < block_size; ++i)
+ {
+ tmp = 0x5C;
+ sha256_update(&outer, &tmp, 1);
+ tmp = 0x36;
+ sha256_update(&inner, &tmp, 1);
+ }
+
+ sha256_update(&inner, msg, msgsize);
+ sha256_final(&inner, output);
+
+ sha256_update(&outer, output, digest_size);
+ sha256_final(&outer, output);
+}
+
+void hmac_sha2_256(const bytebuffer *key, const bytebuffer *msg, bytebuffer *output) {
+ static const size_t block_size = 32;
+ assert(key->len == block_size);
+ assert(output->len == block_size);
+ assert(msg);
+
+ dbg_print_bb1("HMAC key", key);
+ dbg_print_bb1("HMAC message", msg);
+ hmac_sha256(key->data, key->len, msg->data, msg->len, output->data);
+ /*
+ SHA256Schedule hash_ctx;
+ uint8_t pad[block_size], ihash[block_size];
+
+ sha256_init(&hash_ctx);
+ // i_key_pad := block_sized_key xor [0x36 blockSize] // Inner padded key
+ for(size_t i=0; i<block_size; i++) {
+ pad[i] = key->data[i] ^ 0x36;
+ }
+ // ihash = hash(i_key_pad || message)
+ sha256_update(&hash_ctx, pad, block_size);
+ sha256_update(&hash_ctx, msg->data, msg->len);
+ sha256_final(&hash_ctx, ihash);
+
+ sha256_init(&hash_ctx);
+ // o_key_pad := block_sized_key xor [0x5c blockSize] // Outer padded key
+ for(size_t i=0; i<block_size; i++) {
+ pad[i] = key->data[i] ^ 0x5c;
+ }
+ // ohash = hash(o_key_pad || ihash)
+ sha256_update(&hash_ctx, pad, block_size);
+ sha256_update(&hash_ctx, ihash, block_size);
+ sha256_final(&hash_ctx, output->data);
+ */
+ dbg_print_bb1("HMAC output", output);
}
/*
@@ -294,7 +388,7 @@ int main (int argc, char const *const *argv)
break;
case -1:
if(errno != EINTR) {
- strerr_dief1sys(111, "read()");
+ strerr_dief1sys(111, "read() length");
}
break;
default: