diff options
author | Laurent Bercot <ska-skaware@skarnet.org> | 2021-05-20 10:55:18 +0000 |
---|---|---|
committer | Laurent Bercot <ska-skaware@skarnet.org> | 2021-05-20 10:55:18 +0000 |
commit | 4aae040b1a8aecddcd0e1e959c77bb262fe6b850 (patch) | |
tree | 37c985cc6ff250ec486c3eaa09428eb5bf08cdb2 /src/sbearssl | |
parent | 6780eee3e0dbe37640f72ed1e37a95c506e23f8c (diff) | |
download | s6-networking-4aae040b1a8aecddcd0e1e959c77bb262fe6b850.tar.xz |
Add an x509 engine wrapping minimal. NOT FUNCTIONAL, FOR TESTING.
Diffstat (limited to 'src/sbearssl')
-rw-r--r-- | src/sbearssl/deps-lib/sbearssl | 3 | ||||
-rw-r--r-- | src/sbearssl/sbearssl_client_init_and_run.c | 20 | ||||
-rw-r--r-- | src/sbearssl/sbearssl_run.c | 6 | ||||
-rw-r--r-- | src/sbearssl/sbearssl_send_environment.c | 118 | ||||
-rw-r--r-- | src/sbearssl/sbearssl_server_init_and_run.c | 13 | ||||
-rw-r--r-- | src/sbearssl/sbearssl_x509_minimal_init_with_engine.c | 25 | ||||
-rw-r--r-- | src/sbearssl/sbearssl_x509_minimal_set_tai.c | 2 | ||||
-rw-r--r-- | src/sbearssl/sbearssl_x509_small_init_full.c | 40 | ||||
-rw-r--r-- | src/sbearssl/sbearssl_x509_small_vtable.c | 79 |
9 files changed, 256 insertions, 50 deletions
diff --git a/src/sbearssl/deps-lib/sbearssl b/src/sbearssl/deps-lib/sbearssl index a1ccbb7..68b3ce1 100644 --- a/src/sbearssl/deps-lib/sbearssl +++ b/src/sbearssl/deps-lib/sbearssl @@ -40,7 +40,8 @@ sbearssl_ta_readfile.o sbearssl_ta_to.o sbearssl_x500_name_len.o sbearssl_x500_from_ta.o -sbearssl_x509_minimal_init_with_engine.o sbearssl_x509_minimal_set_tai.o +sbearssl_x509_small_init_full.o +sbearssl_x509_small_vtable.o -lbearssl -lskarnet diff --git a/src/sbearssl/sbearssl_client_init_and_run.c b/src/sbearssl/sbearssl_client_init_and_run.c index db68096..e139820 100644 --- a/src/sbearssl/sbearssl_client_init_and_run.c +++ b/src/sbearssl/sbearssl_client_init_and_run.c @@ -13,7 +13,7 @@ #include <s6-networking/sbearssl.h> #include "sbearssl-internal.h" -void sbearssl_client_init_and_run (int *fds, tain_t const *tto, uint32_t preoptions, uint32_t options, unsigned int verbosity, char const *servername, sbearssl_handshake_cb_t_ref cb, unsigned int notif) +void sbearssl_client_init_and_run (int *fds, tain_t const *tto, uint32_t preoptions, uint32_t options, unsigned int verbosity, char const *servername, sbearssl_handshake_cbfunc_ref cb, sbearssl_handshake_cbarg *cbarg) { sbearssl_skey skey ; genalloc certs = GENALLOC_ZERO ; /* sbearssl_cert */ @@ -26,10 +26,9 @@ void sbearssl_client_init_and_run (int *fds, tain_t const *tto, uint32_t preopti stralloc_shrink(&storage) ; { - sbearssl_handshake_cb_context_t cbarg = { .notif = notif } ; union br_skey_u key ; br_ssl_client_context cc ; - br_x509_minimal_context xc ; + sbearssl_x509_small_context xc ; br_x509_certificate chain[chainlen ? chainlen : 1] ; br_x509_trust_anchor btas[n] ; unsigned char buf[BR_SSL_BUFSIZE_BIDI] ; @@ -41,8 +40,15 @@ void sbearssl_client_init_and_run (int *fds, tain_t const *tto, uint32_t preopti for (size_t i = 0 ; i < n ; i++) sbearssl_ta_to(genalloc_s(sbearssl_ta, &tas) + i, btas + i, storage.s) ; genalloc_free(sbearssl_ta, &tas) ; - - br_ssl_client_init_full(&cc, &xc, btas, n) ; + { + br_x509_minimal_context dummy ; /* wasteful but the only simple API we have */ + br_ssl_client_init_full(&cc, &dummy, btas, n) ; + } + sbearssl_x509_small_init_full(&xc, btas, n, &cbarg->eedn, &cbarg->eltstatus, cbarg->eehash) ; + if (!sbearssl_x509_small_set_tain(&xc, &STAMP)) + strerr_diefu1sys(111, "initialize validation time") ; + br_ssl_engine_set_x509(&cc.eng, &xc.vtable) ; + cbarg->exportmask |= 3 ; if (chainlen) { @@ -78,11 +84,9 @@ void sbearssl_client_init_and_run (int *fds, tain_t const *tto, uint32_t preopti random_finish() ; br_ssl_engine_inject_entropy(&cc.eng, buf, 32) ; br_ssl_engine_set_buffer(&cc.eng, buf, sizeof(buf), 1) ; - if (!sbearssl_x509_minimal_set_tain(&xc, &STAMP)) - strerr_diefu1sys(111, "initialize validation time") ; if (!br_ssl_client_reset(&cc, servername, 0)) strerr_diefu2x(97, "reset client context: ", sbearssl_error_str(br_ssl_engine_last_error(&cc.eng))) ; - sbearssl_run(&cc.eng, fds, tto, options, verbosity, cb, &cbarg) ; + sbearssl_run(&cc.eng, fds, tto, options, verbosity, cb, cbarg) ; } } diff --git a/src/sbearssl/sbearssl_run.c b/src/sbearssl/sbearssl_run.c index fda9f3e..c440060 100644 --- a/src/sbearssl/sbearssl_run.c +++ b/src/sbearssl/sbearssl_run.c @@ -11,10 +11,12 @@ #include <skalibs/iopause.h> #include <skalibs/djbunix.h> +#include <skalibs/lolstdio.h> + #include <s6-networking/sbearssl.h> #include "sbearssl-internal.h" -void sbearssl_run (br_ssl_engine_context *ctx, int *fds, tain_t const *tto, uint32_t options, unsigned int verbosity, sbearssl_handshake_cb_t_ref cb, sbearssl_handshake_cb_context_t *cbarg) +void sbearssl_run (br_ssl_engine_context *ctx, int *fds, tain_t const *tto, uint32_t options, unsigned int verbosity, sbearssl_handshake_cbfunc_ref cb, sbearssl_handshake_cbarg *cbarg) { iopause_fd x[4] ; unsigned int xindex[4] ; @@ -27,6 +29,7 @@ void sbearssl_run (br_ssl_engine_context *ctx, int *fds, tain_t const *tto, uint || ndelay_on(fds[3]) < 0) strerr_diefu1sys(111, "set fds non-blocking") ; + LOLDEBUG("entering engine") ; for (;;) { tain_t deadline = TAIN_INFINITE ; @@ -48,6 +51,7 @@ void sbearssl_run (br_ssl_engine_context *ctx, int *fds, tain_t const *tto, uint xindex[0] = j++ ; if (!handshake_done) { + LOLDEBUG("handshake done, calling cb") ; if (!(*cb)(ctx, cbarg)) strerr_diefu1sys(111, "post-handshake callback failed") ; handshake_done = 1 ; diff --git a/src/sbearssl/sbearssl_send_environment.c b/src/sbearssl/sbearssl_send_environment.c index bb0fb35..a998ee9 100644 --- a/src/sbearssl/sbearssl_send_environment.c +++ b/src/sbearssl/sbearssl_send_environment.c @@ -1,21 +1,98 @@ /* ISC license. */ +#include <stddef.h> +#include <stdint.h> + #include <skalibs/bytestr.h> #include <skalibs/buffer.h> +#include <skalibs/fmtscan.h> #include <bearssl.h> #include <s6-networking/sbearssl.h> -int sbearssl_send_environment (br_ssl_engine_context *ctx, int fd) +static uint8_t class (char c) +{ + switch (c) + { + case '\0' : return 0 ; + case ' ' : return 1 ; + case ',' : + case '=' : + case '\n' : + case '+' : + case '<' : + case '>' : + case '#' : + case '\\' : return 2 ; + default : return 3 ; + } +} + +static int print_element (buffer *b, char const *s) +{ + static uint8_t const table[3][4] = + { + { 0x03, 0x00, 0x19, 0x09 }, + { 0x03, 0x62, 0x19, 0x09 }, + { 0x03, 0x42, 0x99, 0x89 } + } ; + size_t counter = 0 ; + uint8_t state = 0 ; + while (state < 3) + { + char ch = *s++ ; + uint8_t c = table[state][class(ch)] ; + state = c & 3 ; + if (c & 0x10) if (buffer_put(b, "\\", 1) < 0) return 0 ; + if (c & 0x20) counter = 0 ; + if (c & 0x40) counter++ ; + if (c & 0x80) while (counter--) if (buffer_put(b, " ", 1) < 0) return 0 ; + if (c & 0x08) if (buffer_put(b, &ch, 1) < 0) return 0 ; + } + return 1 ; +} + +struct eltinfo_s +{ + char const *keyword ; + size_t offset ; +} ; + + +static int print_dn (buffer *b, sbearssl_dn const *dn, uint8_t eltstatus) +{ + static struct eltinfo_s const eltinfo[6] = + { + { .keyword = "C", .offset = offsetof(sbearssl_dn, c) }, + { .keyword = "ST", .offset = offsetof(sbearssl_dn, st) }, + { .keyword = "L", .offset = offsetof(sbearssl_dn, l) }, + { .keyword = "O", .offset = offsetof(sbearssl_dn, o) }, + { .keyword = "OU", .offset = offsetof(sbearssl_dn, ou) }, + { .keyword = "CN", .offset = offsetof(sbearssl_dn, cn) } + } ; + int got = 0 ; + unsigned int mask = 1 ; + for (unsigned int i = 0 ; i < 6 ; i++, mask <<= 1) if (eltstatus & mask) + { + if ((got && buffer_puts(b, ", ") < 0) + || buffer_puts(b, eltinfo[i].keyword) < 0 + || buffer_put(b, "=", 1) < 0 + || !print_element(b, (char const *)dn + eltinfo[i].offset)) + return 0 ; + got = 1 ; + } + return 1 ; +} + +int sbearssl_send_environment (br_ssl_engine_context *ctx, sbearssl_handshake_cbarg *p) { char buf[4096] ; - buffer b = BUFFER_INIT(&buffer_write, fd, buf, 4096) ; + buffer b = BUFFER_INIT(&buffer_write, p->notif, buf, 4096) ; unsigned int v = br_ssl_engine_get_version(ctx) ; char const *name = br_ssl_engine_get_server_name(ctx) ; char const *suite ; br_ssl_session_parameters params ; - br_ssl_engine_get_session_parameters(ctx, ¶ms) ; suite = sbearssl_suite_name(¶ms) ; byte_zzero((char *)params.master_secret, 48) ; @@ -26,16 +103,39 @@ int sbearssl_send_environment (br_ssl_engine_context *ctx, int fd) || buffer_put(&b, "", 1) < 0 || buffer_puts(&b, "SSL_CIPHER=") < 0 || buffer_puts(&b, suite) < 0 - || buffer_put(&b, "", 1) < 0 - || buffer_puts(&b, "SSL_TLS_SNI_SERVERNAME") < 0) - return 0 ; + || buffer_put(&b, "", 1) < 0) return 0 ; + + if (buffer_puts(&b, "SSL_TLS_SNI_SERVERNAME") < 0) return 0 ; if (name[0]) { if (buffer_put(&b, "=", 1) < 0 || buffer_puts(&b, name) < 0) return 0 ; } - if (buffer_putflush(&b, "\0", 2) < 0) - return 0 ; - return 1 ; + if (buffer_put(&b, "", 1) < 0) return 0 ; + + if (buffer_puts(&b, "SSL_PEER_CERT_HASH") < 0) return 0 ; + if (p->exportmask & 1) + { + char eehash[64] ; + ucharn_fmt(eehash, p->eehash, 32) ; + if (buffer_puts(&b, "=SHA256:") < 0 + || buffer_put(&b, eehash, 64) < 0) + return 0 ; + } + if (buffer_put(&b, "", 1) < 0) return 0 ; + + if (buffer_puts(&b, "SSL_PEER_CERT_SUBJECT") < 0) return 0 ; + if (p->exportmask & 2 && p->eltstatus) + { + if (buffer_put(&b, "=", 1) < 0) return 0 ; + if (p->eltstatus & 128) + { + if (buffer_puts(&b, "<invalid>") < 0) return 0 ; + } + else if (!print_dn(&b, &p->eedn, p->eltstatus)) return 0 ; + } + if (buffer_put(&b, "", 1) < 0) return 0 ; + + return buffer_putflush(&b, "\0", 2) >= 0 ; } diff --git a/src/sbearssl/sbearssl_server_init_and_run.c b/src/sbearssl/sbearssl_server_init_and_run.c index e6df30e..428efb8 100644 --- a/src/sbearssl/sbearssl_server_init_and_run.c +++ b/src/sbearssl/sbearssl_server_init_and_run.c @@ -13,7 +13,7 @@ #include <s6-networking/sbearssl.h> #include "sbearssl-internal.h" -void sbearssl_server_init_and_run (int *fds, tain_t const *tto, uint32_t preoptions, uint32_t options, unsigned int verbosity, sbearssl_handshake_cb_t_ref cb, unsigned int notif) +void sbearssl_server_init_and_run (int *fds, tain_t const *tto, uint32_t preoptions, uint32_t options, unsigned int verbosity, sbearssl_handshake_cbfunc_ref cb, sbearssl_handshake_cbarg *cbarg) { sbearssl_skey skey ; genalloc certs = GENALLOC_ZERO ; /* sbearssl_cert */ @@ -26,10 +26,9 @@ void sbearssl_server_init_and_run (int *fds, tain_t const *tto, uint32_t preopti stralloc_shrink(&storage) ; { - sbearssl_handshake_cb_context_t cbarg = { .notif = notif } ; union br_skey_u key ; br_ssl_server_context sc ; - br_x509_minimal_context xc ; + sbearssl_x509_small_context xc ; br_x509_certificate chain[chainlen] ; br_x509_trust_anchor btas[n ? n : 1] ; unsigned char buf[BR_SSL_BUFSIZE_BIDI] ; @@ -75,10 +74,12 @@ void sbearssl_server_init_and_run (int *fds, tain_t const *tto, uint32_t preopti if (n) { - sbearssl_x509_minimal_init_with_engine(&xc, &sc.eng, btas, n) ; - if (!sbearssl_x509_minimal_set_tain(&xc, &STAMP)) + sbearssl_x509_small_init_full(&xc, btas, n, &cbarg->eedn, &cbarg->eltstatus, cbarg->eehash) ; + if (!sbearssl_x509_small_set_tain(&xc, &STAMP)) strerr_diefu1sys(111, "initialize validation time") ; + br_ssl_engine_set_x509(&sc.eng, &xc.vtable) ; br_ssl_server_set_trust_anchor_names_alt(&sc, btas, n) ; + cbarg->exportmask |= 3 ; } random_string((char *)buf, 32) ; @@ -88,6 +89,6 @@ void sbearssl_server_init_and_run (int *fds, tain_t const *tto, uint32_t preopti if (!br_ssl_server_reset(&sc)) strerr_diefu2x(97, "reset server context: ", sbearssl_error_str(br_ssl_engine_last_error(&sc.eng))) ; - sbearssl_run(&sc.eng, fds, tto, options, verbosity, cb, &cbarg) ; + sbearssl_run(&sc.eng, fds, tto, options, verbosity, cb, cbarg) ; } } diff --git a/src/sbearssl/sbearssl_x509_minimal_init_with_engine.c b/src/sbearssl/sbearssl_x509_minimal_init_with_engine.c deleted file mode 100644 index 1b5c7a5..0000000 --- a/src/sbearssl/sbearssl_x509_minimal_init_with_engine.c +++ /dev/null @@ -1,25 +0,0 @@ -/* ISC license. */ - -#include <bearssl.h> - -#include <s6-networking/sbearssl.h> - -void sbearssl_x509_minimal_init_with_engine (br_x509_minimal_context *xc, br_ssl_engine_context *eng, br_x509_trust_anchor const *btas, size_t n) -{ - static const br_hash_class *hashes[] = - { - &br_md5_vtable, - &br_sha1_vtable, - &br_sha224_vtable, - &br_sha256_vtable, - &br_sha384_vtable, - &br_sha512_vtable - } ; - - br_x509_minimal_init(xc, &br_sha256_vtable, btas, n) ; - br_x509_minimal_set_rsa(xc, br_ssl_engine_get_rsavrfy(eng)) ; - br_x509_minimal_set_ecdsa(xc, br_ssl_engine_get_ec(eng), br_ssl_engine_get_ecdsa(eng)) ; - for (unsigned int id = br_md5_ID ; id <= br_sha512_ID ; id++) - br_x509_minimal_set_hash(xc, id, hashes[id-1]) ; - br_ssl_engine_set_x509(eng, &xc->vtable) ; -} diff --git a/src/sbearssl/sbearssl_x509_minimal_set_tai.c b/src/sbearssl/sbearssl_x509_minimal_set_tai.c index 1d9de2a..381e9d3 100644 --- a/src/sbearssl/sbearssl_x509_minimal_set_tai.c +++ b/src/sbearssl/sbearssl_x509_minimal_set_tai.c @@ -1,9 +1,11 @@ /* ISC license. */ #include <bearssl.h> + #include <skalibs/uint64.h> #include <skalibs/tai.h> #include <skalibs/djbtime.h> + #include <s6-networking/sbearssl.h> int sbearssl_x509_minimal_set_tai (br_x509_minimal_context *ctx, tai_t const *t) diff --git a/src/sbearssl/sbearssl_x509_small_init_full.c b/src/sbearssl/sbearssl_x509_small_init_full.c new file mode 100644 index 0000000..31906e5 --- /dev/null +++ b/src/sbearssl/sbearssl_x509_small_init_full.c @@ -0,0 +1,40 @@ +/* ISC license. */ + +#include <stddef.h> +#include <stdint.h> + +#include <bearssl.h> + +#include <s6-networking/sbearssl.h> + +struct eltinfo_s +{ + size_t offset ; + size_t size ; + unsigned char oid[4] ; +} ; + +static struct eltinfo_s const eltinfo[6] = +{ + { .offset = offsetof(sbearssl_dn, c), .size = sizeof(((sbearssl_dn *)0)->c), .oid = "\x03\x55\x04\x06" }, + { .offset = offsetof(sbearssl_dn, st), .size = sizeof(((sbearssl_dn *)0)->st), .oid = "\x03\x55\x04\x08" }, + { .offset = offsetof(sbearssl_dn, l), .size = sizeof(((sbearssl_dn *)0)->l), .oid = "\x03\x55\x04\x07" }, + { .offset = offsetof(sbearssl_dn, o), .size = sizeof(((sbearssl_dn *)0)->o), .oid = "\x03\x55\x04\x0a" }, + { .offset = offsetof(sbearssl_dn, ou), .size = sizeof(((sbearssl_dn *)0)->ou), .oid = "\x03\x55\x04\x0b" }, + { .offset = offsetof(sbearssl_dn, cn), .size = sizeof(((sbearssl_dn *)0)->cn), .oid = "\x03\x55\x04\x03" } +} ; + +void sbearssl_x509_small_init_full (sbearssl_x509_small_context *ctx, br_x509_trust_anchor *btas, size_t n, sbearssl_dn *eedn, uint8_t *eltstatus, char *eehash) +{ + ctx->vtable = &sbearssl_x509_small_vtable ; + br_x509_minimal_init_full(&ctx->minimal, btas, n) ; + for (unsigned int i = 0 ; i < 6 ; i++) + { + ctx->elts[i].oid = eltinfo[i].oid ; + ctx->elts[i].buf = (char *)ctx->eedn + eltinfo[i].offset ; + ctx->elts[i].len = eltinfo[i].size ; + } + br_x509_minimal_set_name_elements(&ctx->minimal, ctx->elts, 6) ; + ctx->eltstatus = eltstatus ; + ctx->eehash = eehash ; +} diff --git a/src/sbearssl/sbearssl_x509_small_vtable.c b/src/sbearssl/sbearssl_x509_small_vtable.c new file mode 100644 index 0000000..9946e7a --- /dev/null +++ b/src/sbearssl/sbearssl_x509_small_vtable.c @@ -0,0 +1,79 @@ +/* ISC license. */ + +#include <skalibs/lolstdio.h> + +#include <bearssl.h> + +#include <s6-networking/sbearssl.h> + +#define INSTANCE(c) ((sbearssl_x509_small_context *)(c)) + +static void start_chain (br_x509_class const **c, char const *server_name) +{ + sbearssl_x509_small_context *ctx = INSTANCE(c) ; + ctx->minimal.vtable->start_chain(&ctx->minimal.vtable, server_name) ; + + LOLDEBUG("small_context: start_chain") ; + ctx->i = 0 ; +} + +static void start_cert (br_x509_class const **c, uint32_t len) +{ + sbearssl_x509_small_context *ctx = INSTANCE(c) ; + ctx->minimal.vtable->start_cert(&ctx->minimal.vtable, len) ; + + LOLDEBUG("small_context: start_cert %u", ctx->i) ; + if (!ctx->i) br_sha256_init(&ctx->hashctx) ; +} + +static void append (br_x509_class const **c, unsigned char const *s, size_t len) +{ + sbearssl_x509_small_context *ctx = INSTANCE(c) ; + ctx->minimal.vtable->append(&ctx->minimal.vtable, s, len) ; + + LOLDEBUG("small_context: append") ; + if (!ctx->i) br_sha256_update(&ctx->hashctx, s, len) ; +} + +static void end_cert (br_x509_class const **c) +{ + sbearssl_x509_small_context *ctx = INSTANCE(c) ; + ctx->minimal.vtable->end_cert(&ctx->minimal.vtable) ; + + LOLDEBUG("small_context: end_cert") ; + if (!ctx->i) br_sha256_out(&ctx->hashctx, ctx->eehash) ; + ctx->i++ ; +} + +static unsigned int end_chain (br_x509_class const **c) +{ + sbearssl_x509_small_context *ctx = INSTANCE(c) ; + LOLDEBUG("small_context: end_chain") ; + unsigned int r = ctx->minimal.vtable->end_chain(&ctx->minimal.vtable) ; + if (!r) + { + uint8_t mask = 1 ; + for (unsigned int i = 0 ; i < 6 ; i++, mask <<= 1) + if (ctx->elts[i].status) + *ctx->eltstatus |= ctx->elts[i].status < 0 ? 128 : mask ; + } + return r ; +} + +static br_x509_pkey const *get_pkey(br_x509_class const *const *c, unsigned int *usages) +{ + sbearssl_x509_small_context *ctx = INSTANCE(c) ; + LOLDEBUG("small_context: get_pkey") ; + return ctx->minimal.vtable->get_pkey(&ctx->minimal.vtable, usages) ; +} + +br_x509_class const sbearssl_x509_small_vtable = +{ + .context_size = sizeof(sbearssl_x509_small_context), + .start_chain = &start_chain, + .start_cert = &start_cert, + .append = &append, + .end_cert = &end_cert, + .end_chain = &end_chain, + .get_pkey = &get_pkey, +} ; |