summaryrefslogtreecommitdiff
path: root/src/sbearssl
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2021-05-20 10:55:18 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2021-05-20 10:55:18 +0000
commit4aae040b1a8aecddcd0e1e959c77bb262fe6b850 (patch)
tree37c985cc6ff250ec486c3eaa09428eb5bf08cdb2 /src/sbearssl
parent6780eee3e0dbe37640f72ed1e37a95c506e23f8c (diff)
downloads6-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/sbearssl3
-rw-r--r--src/sbearssl/sbearssl_client_init_and_run.c20
-rw-r--r--src/sbearssl/sbearssl_run.c6
-rw-r--r--src/sbearssl/sbearssl_send_environment.c118
-rw-r--r--src/sbearssl/sbearssl_server_init_and_run.c13
-rw-r--r--src/sbearssl/sbearssl_x509_minimal_init_with_engine.c25
-rw-r--r--src/sbearssl/sbearssl_x509_minimal_set_tai.c2
-rw-r--r--src/sbearssl/sbearssl_x509_small_init_full.c40
-rw-r--r--src/sbearssl/sbearssl_x509_small_vtable.c79
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, &params) ;
suite = sbearssl_suite_name(&params) ;
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,
+} ;