summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2021-05-18 11:19:19 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2021-05-18 11:19:19 +0000
commit6780eee3e0dbe37640f72ed1e37a95c506e23f8c (patch)
treefd89e47869fd422c6a2fb49e361c760a94b60668 /src
parent8f4d374c931ce12554beb9231c1af9171832e133 (diff)
downloads6-networking-6780eee3e0dbe37640f72ed1e37a95c506e23f8c.tar.xz
Prepare for 2.4.2.0; implement client certificates with bearssl
Also send a bit more environment with libtls
Diffstat (limited to 'src')
-rw-r--r--src/include/s6-networking/sbearssl.h5
-rw-r--r--src/sbearssl/deps-lib/sbearssl3
-rw-r--r--src/sbearssl/sbearssl-internal.h3
-rw-r--r--src/sbearssl/sbearssl_client_init_and_run.c82
-rw-r--r--src/sbearssl/sbearssl_get_keycert.c36
-rw-r--r--src/sbearssl/sbearssl_get_tas.c33
-rw-r--r--src/sbearssl/sbearssl_server_init_and_run.c64
-rw-r--r--src/sbearssl/sbearssl_x509_minimal_init_with_engine.c25
-rw-r--r--src/stls/stls_send_environment.c31
9 files changed, 199 insertions, 83 deletions
diff --git a/src/include/s6-networking/sbearssl.h b/src/include/s6-networking/sbearssl.h
index 5527696..e473e12 100644
--- a/src/include/s6-networking/sbearssl.h
+++ b/src/include/s6-networking/sbearssl.h
@@ -30,8 +30,13 @@
/* Utility functions */
extern int sbearssl_isder (unsigned char const *, size_t) ;
+
+
+ /* x509 QoL functions */
+
extern int sbearssl_x509_minimal_set_tai (br_x509_minimal_context *, tai_t const *) ;
#define sbearssl_x509_minimal_set_tain(ctx, a) sbearssl_x509_minimal_set_tai(ctx, tain_secp(a))
+extern void sbearssl_x509_minimal_init_with_engine (br_x509_minimal_context *, br_ssl_engine_context *, br_x509_trust_anchor const *, size_t) ;
/* Cipher suites */
diff --git a/src/sbearssl/deps-lib/sbearssl b/src/sbearssl/deps-lib/sbearssl
index dfa4f29..a1ccbb7 100644
--- a/src/sbearssl/deps-lib/sbearssl
+++ b/src/sbearssl/deps-lib/sbearssl
@@ -11,6 +11,8 @@ sbearssl_ec_pkey_to.o
sbearssl_ec_skey_from.o
sbearssl_ec_skey_to.o
sbearssl_error_str.o
+sbearssl_get_keycert.o
+sbearssl_get_tas.o
sbearssl_isder.o
sbearssl_pem_decode_from_buffer.o
sbearssl_pem_decode_from_string.o
@@ -38,6 +40,7 @@ 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
-lbearssl
-lskarnet
diff --git a/src/sbearssl/sbearssl-internal.h b/src/sbearssl/sbearssl-internal.h
index bfaad73..21a28d7 100644
--- a/src/sbearssl/sbearssl-internal.h
+++ b/src/sbearssl/sbearssl-internal.h
@@ -65,6 +65,9 @@ struct sbearssl_suiteinfo_s
uint16_t bits ;
} ;
+extern size_t sbearssl_get_tas (genalloc *, stralloc *) ;
+extern size_t sbearssl_get_keycert (sbearssl_skey *, genalloc *, stralloc *) ;
+
extern void sbearssl_drop (void) ;
extern void sbearssl_append (void *, void const *, size_t) ;
extern int sbearssl_pem_push (br_pem_decoder_context *, char const *, size_t, sbearssl_pemobject *, genalloc *, sbearssl_strallocerr *, int *) ;
diff --git a/src/sbearssl/sbearssl_client_init_and_run.c b/src/sbearssl/sbearssl_client_init_and_run.c
index d7bedec..db68096 100644
--- a/src/sbearssl/sbearssl_client_init_and_run.c
+++ b/src/sbearssl/sbearssl_client_init_and_run.c
@@ -15,50 +15,64 @@
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)
{
+ sbearssl_skey skey ;
+ genalloc certs = GENALLOC_ZERO ; /* sbearssl_cert */
+ genalloc tas = GENALLOC_ZERO ; /* sbearssl_ta */
stralloc storage = STRALLOC_ZERO ;
- genalloc tas = GENALLOC_ZERO ;
- size_t talen ;
-
- if (preoptions & 1)
- strerr_dief1x(100, "client certificates are not supported yet") ;
-
- {
- int r ;
- char const *x = getenv("CADIR") ;
- if (x)
- r = sbearssl_ta_readdir(x, &tas, &storage) ;
- else
- {
- x = getenv("CAFILE") ;
- if (!x) strerr_dienotset(100, "CADIR or CAFILE") ;
- r = sbearssl_ta_readfile(x, &tas, &storage) ;
- }
-
- if (r < 0)
- strerr_diefu2sys(111, "read trust anchors in ", x) ;
- else if (r)
- strerr_diefu4x(96, "read trust anchors in ", x, ": ", sbearssl_error_str(r)) ;
-
- talen = genalloc_len(sbearssl_ta, &tas) ;
- if (!talen)
- strerr_dief2x(96, "no trust anchor found in ", x) ;
- }
+ size_t chainlen = preoptions & 1 ? sbearssl_get_keycert(&skey, &certs, &storage) : 0 ;
+ size_t n = sbearssl_get_tas(&tas, &storage) ;
sbearssl_drop() ;
+ stralloc_shrink(&storage) ;
{
sbearssl_handshake_cb_context_t cbarg = { .notif = notif } ;
- unsigned char buf[BR_SSL_BUFSIZE_BIDI] ;
- br_x509_minimal_context xc ;
+ union br_skey_u key ;
br_ssl_client_context cc ;
- br_x509_trust_anchor btas[talen] ;
- size_t i = talen ;
+ br_x509_minimal_context xc ;
+ br_x509_certificate chain[chainlen ? chainlen : 1] ;
+ br_x509_trust_anchor btas[n] ;
+ unsigned char buf[BR_SSL_BUFSIZE_BIDI] ;
+
+ for (size_t i = 0 ; i < chainlen ; i++)
+ sbearssl_cert_to(genalloc_s(sbearssl_cert, &certs) + i, chain + i, storage.s) ;
+ genalloc_free(sbearssl_cert, &certs) ;
- stralloc_shrink(&storage) ;
- while (i--)
+ 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, talen) ;
+
+ br_ssl_client_init_full(&cc, &xc, btas, n) ;
+
+ if (chainlen)
+ {
+ switch (skey.type)
+ {
+ case BR_KEYTYPE_RSA :
+ sbearssl_rsa_skey_to(&skey.data.rsa, &key.rsa, storage.s) ;
+ br_ssl_client_set_single_rsa(&cc, chain, chainlen, &key.rsa, br_rsa_pkcs1_sign_get_default()) ;
+ break ;
+ case BR_KEYTYPE_EC :
+ {
+ int kt, r ;
+ sbearssl_ec_skey_to(&skey.data.ec, &key.ec, storage.s) ;
+ r = sbearssl_ec_issuer_keytype(&kt, &chain[0]) ;
+ switch (r)
+ {
+ case -2 : strerr_dief1x(96, "certificate issuer key type not recognized") ;
+ case -1 : strerr_diefu1sys(111, "get certificate issuer key type") ;
+ case 0 : break ;
+ default : strerr_diefu3x(96, "get certificate issuer key type", ": ", sbearssl_error_str(r)) ;
+ }
+
+ br_ssl_client_set_single_ec(&cc, chain, chainlen, &key.ec, BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN, kt, br_ec_get_default(), br_ecdsa_sign_asn1_get_default()) ;
+ break ;
+ }
+ default :
+ strerr_dief1x(96, "unsupported private key type") ;
+ }
+ }
+
br_ssl_engine_add_flags(&cc.eng, BR_OPT_NO_RENEGOTIATION) ;
random_string((char *)buf, 32) ;
random_finish() ;
diff --git a/src/sbearssl/sbearssl_get_keycert.c b/src/sbearssl/sbearssl_get_keycert.c
new file mode 100644
index 0000000..96e826c
--- /dev/null
+++ b/src/sbearssl/sbearssl_get_keycert.c
@@ -0,0 +1,36 @@
+/* ISC license. */
+
+#include <stdlib.h>
+
+#include <skalibs/strerr2.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/genalloc.h>
+
+#include <s6-networking/sbearssl.h>
+#include "sbearssl-internal.h"
+
+size_t sbearssl_get_keycert (sbearssl_skey *skey, genalloc *certs, stralloc *storage)
+{
+ size_t chainlen ;
+ int r ;
+ char const *x = getenv("CERTFILE") ;
+ if (!x) strerr_dienotset(100, "CERTFILE") ;
+ r = sbearssl_cert_readbigpem(x, certs, storage) ;
+ if (r < 0)
+ strerr_diefu2sys(111, "read certificate chain in ", x) ;
+ else if (r)
+ strerr_diefu4sys(96, "read certificate chain in ", x, ": ", sbearssl_error_str(r)) ;
+ chainlen = genalloc_len(sbearssl_cert, certs) ;
+ if (!chainlen)
+ strerr_diefu2x(96, "find a certificate in ", x) ;
+
+ x = getenv("KEYFILE") ;
+ if (!x) strerr_dienotset(100, "KEYFILE") ;
+ r = sbearssl_skey_readfile(x, skey, storage) ;
+ if (r < 0)
+ strerr_diefu2sys(111, "read private key in ", x) ;
+ else if (r)
+ strerr_diefu4x(96, "decode private key in ", x, ": ", sbearssl_error_str(r)) ;
+
+ return chainlen ;
+}
diff --git a/src/sbearssl/sbearssl_get_tas.c b/src/sbearssl/sbearssl_get_tas.c
new file mode 100644
index 0000000..aa8f63b
--- /dev/null
+++ b/src/sbearssl/sbearssl_get_tas.c
@@ -0,0 +1,33 @@
+/* ISC license. */
+
+#include <stdlib.h>
+
+#include <skalibs/strerr2.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/genalloc.h>
+
+#include <s6-networking/sbearssl.h>
+#include "sbearssl-internal.h"
+
+size_t sbearssl_get_tas (genalloc *tas, stralloc *storage)
+{
+ size_t talen ;
+ int r ;
+ char const *x = getenv("CADIR") ;
+ if (x) r = sbearssl_ta_readdir(x, tas, storage) ;
+ else
+ {
+ x = getenv("CAFILE") ;
+ if (!x) strerr_dienotset(100, "CADIR or CAFILE") ;
+ r = sbearssl_ta_readfile(x, tas, storage) ;
+ }
+
+ if (r < 0)
+ strerr_diefu2sys(111, "read trust anchors in ", x) ;
+ else if (r)
+ strerr_diefu4x(96, "read trust anchors in ", x, ": ", sbearssl_error_str(r)) ;
+
+ talen = genalloc_len(sbearssl_ta, tas) ;
+ if (!talen) strerr_dief2x(96, "no trust anchor found in ", x) ;
+ return talen ;
+}
diff --git a/src/sbearssl/sbearssl_server_init_and_run.c b/src/sbearssl/sbearssl_server_init_and_run.c
index a7ae22b..e6df30e 100644
--- a/src/sbearssl/sbearssl_server_init_and_run.c
+++ b/src/sbearssl/sbearssl_server_init_and_run.c
@@ -15,51 +15,33 @@
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)
{
- stralloc storage = STRALLOC_ZERO ;
sbearssl_skey skey ;
- genalloc certs = GENALLOC_ZERO ;
- size_t chainlen ;
-
- if (preoptions & 1)
- strerr_dief1x(100, "client certificates are not supported yet") ;
-
- {
- char const *x = getenv("KEYFILE") ;
- int r ;
- if (!x) strerr_dienotset(100, "KEYFILE") ;
- r = sbearssl_skey_readfile(x, &skey, &storage) ;
- if (r < 0)
- strerr_diefu2sys(111, "read private key in ", x) ;
- else if (r)
- strerr_diefu4x(96, "decode private key in ", x, ": ", sbearssl_error_str(r)) ;
-
- x = getenv("CERTFILE") ;
- if (!x) strerr_dienotset(100, "CERTFILE") ;
- r = sbearssl_cert_readbigpem(x, &certs, &storage) ;
- if (r < 0)
- strerr_diefu2sys(111, "read certificate chain in ", x) ;
- else if (r)
- strerr_diefu4sys(96, "read certificate chain in ", x, ": ", sbearssl_error_str(r)) ;
- chainlen = genalloc_len(sbearssl_cert, &certs) ;
- if (!chainlen)
- strerr_diefu2x(96, "find a certificate in ", x) ;
- }
+ genalloc certs = GENALLOC_ZERO ; /* sbearssl_cert */
+ genalloc tas = GENALLOC_ZERO ; /* sbearssl_ta */
+ stralloc storage = STRALLOC_ZERO ;
+ size_t chainlen = sbearssl_get_keycert(&skey, &certs, &storage) ;
+ size_t n = preoptions & 1 ? sbearssl_get_tas(&tas, &storage) : 0 ;
sbearssl_drop() ;
+ stralloc_shrink(&storage) ;
{
sbearssl_handshake_cb_context_t cbarg = { .notif = notif } ;
- unsigned char buf[BR_SSL_BUFSIZE_BIDI] ;
- br_ssl_server_context sc ;
union br_skey_u key ;
+ br_ssl_server_context sc ;
+ br_x509_minimal_context xc ;
br_x509_certificate chain[chainlen] ;
- size_t i = chainlen ;
+ br_x509_trust_anchor btas[n ? n : 1] ;
+ unsigned char buf[BR_SSL_BUFSIZE_BIDI] ;
- stralloc_shrink(&storage) ;
- while (i--)
+ for (size_t i = 0 ; i < chainlen ; i++)
sbearssl_cert_to(genalloc_s(sbearssl_cert, &certs) + i, chain + i, storage.s) ;
genalloc_free(sbearssl_cert, &certs) ;
+ 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) ;
+
switch (skey.type)
{
case BR_KEYTYPE_RSA :
@@ -82,19 +64,23 @@ void sbearssl_server_init_and_run (int *fds, tain_t const *tto, uint32_t preopti
break ;
}
default :
- strerr_dief1x(96, "unsupported private key type") ;
+ strerr_dief1x(96, "unsupported private key type") ;
}
{
uint32_t flags = BR_OPT_ENFORCE_SERVER_PREFERENCES | BR_OPT_NO_RENEGOTIATION ;
- if (preoptions & 1)
- {
- /* br_ssl_server_set_trust_anchor_names(&sc, x500names, x500n) ; */
- if (!(preoptions & 2)) flags |= BR_OPT_TOLERATE_NO_CLIENT_AUTH ;
- }
+ if (!(preoptions & 2)) flags |= BR_OPT_TOLERATE_NO_CLIENT_AUTH ;
br_ssl_engine_add_flags(&sc.eng, flags) ;
}
+ if (n)
+ {
+ sbearssl_x509_minimal_init_with_engine(&xc, &sc.eng, btas, n) ;
+ if (!sbearssl_x509_minimal_set_tain(&xc, &STAMP))
+ strerr_diefu1sys(111, "initialize validation time") ;
+ br_ssl_server_set_trust_anchor_names_alt(&sc, btas, n) ;
+ }
+
random_string((char *)buf, 32) ;
random_finish() ;
br_ssl_engine_inject_entropy(&sc.eng, buf, 32) ;
diff --git a/src/sbearssl/sbearssl_x509_minimal_init_with_engine.c b/src/sbearssl/sbearssl_x509_minimal_init_with_engine.c
new file mode 100644
index 0000000..1b5c7a5
--- /dev/null
+++ b/src/sbearssl/sbearssl_x509_minimal_init_with_engine.c
@@ -0,0 +1,25 @@
+/* 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/stls/stls_send_environment.c b/src/stls/stls_send_environment.c
index c7cb9c7..ab7fba2 100644
--- a/src/stls/stls_send_environment.c
+++ b/src/stls/stls_send_environment.c
@@ -9,9 +9,22 @@
#include <s6-networking/stls.h>
+static int add (buffer *b, int h, char const *key, char const *value)
+{
+ if (buffer_puts(b, key) < 0) return 0 ;
+ if (h && value && value[0])
+ {
+ if (buffer_put(b, "=", 1) < 0
+ || buffer_puts(b, value) < 0)
+ return 0 ;
+ }
+ if (buffer_put(b, "", 1) < 0) return 0 ;
+ return 1 ;
+}
+
+
int stls_send_environment (struct tls *ctx, int fd)
{
- char const *name = tls_conn_servername(ctx) ;
char buf[4096] ;
buffer b = BUFFER_INIT(&buffer_write, fd, buf, 4096) ;
if (buffer_puts(&b, "SSL_PROTOCOL=") < 0
@@ -19,15 +32,13 @@ int stls_send_environment (struct tls *ctx, int fd)
|| buffer_put(&b, "", 1) < 0
|| buffer_puts(&b, "SSL_CIPHER=") < 0
|| buffer_puts(&b, tls_conn_cipher(ctx)) < 0
- || buffer_put(&b, "", 1) < 0
- || buffer_puts(&b, "SSL_TLS_SNI_SERVERNAME") < 0)
+ || buffer_put(&b, "", 1) < 0)
return 0 ;
- if (name && name[0])
- {
- if (buffer_put(&b, "=", 1) < 0
- || buffer_puts(&b, name) < 0)
- return 0 ;
- }
- if (buffer_putflush(&b, "\0", 2) < 0) return 0 ;
+
+ if (!add(&b, 1, "SSL_TLS_SNI_SERVERNAME", tls_conn_servername(ctx))) return 0 ;
+ if (!add(&b, tls_peer_cert_provided(ctx), "SSL_PEER_CERT_HASH", tls_peer_cert_hash(ctx))) return 0 ;
+ if (!add(&b, tls_peer_cert_provided(ctx), "SSL_PEER_CERT_SUBJECT", tls_peer_cert_subject(ctx))) return 0 ;
+
+ if (buffer_putflush(&b, "", 1) < 0) return 0 ;
return 1 ;
}