tls: change APIs to use l_cert/l_certchain/l_key
PATCH 1/4 tls: change APIs to use l_cert/l_certchain/l_key
l_tls_set_auth_data/l_tls_set_cacert both expected file paths to be passed in, and the certs/keys would be loaded internally. This prevents the caller from loading certs any way but from files. This makes loading certs/keys from data impossible if using TLS. For example, a certificate may be embedded inside a file which has additional data.
To handle both file/data cases its now up to the caller to load the cert/key as an l_cert/l_certchain/l_key/l_queue and pass that structure in directly.
The structure being passed in will now be owned by l_tls, and will be freed on l_tls_free.
--- ell/tls.c | 42 +++++++++++++----------------------------- ell/tls.h | 11 +++++++---- 2 files changed, 20 insertions(+), 33 deletions(-)
ell/tls.c +13 -29
@@ -2591,7 +2591,7 @@ LIB_EXPORT void l_tls_free(struct l_tls *tls) }l_tls_set_cacert (tls,NULL ); -l_tls_set_auth_data (tls,NULL ,NULL ,NULL ); +l_tls_set_auth_data (tls,NULL ,NULL );l_tls_set_domain_mask (tls,NULL );tls_reset_handshake (tls);
@@ -2806,9 +2806,9 @@ LIB_EXPORT void l_tls_close(struct l_tls *tls)TLS_DISCONNECT (TLS_ALERT_CLOSE_NOTIFY ,0 ,"Closing session" ); } -LIB_EXPORT bool l_tls_set_cacert(struct l_tls *tls, const char *ca_cert_path) +LIB_EXPORT bool l_tls_set_cacert(struct l_tls *tls, struct l_queue *ca_certs) { -TLS_DEBUG ("ca-cert-path=%s" , ca_cert_path); +TLS_DEBUG ("ca-certs=%p" , ca_certs);if (tls->ca_certs) { l_queue_destroy(tls->ca_certs,
@@ -2816,29 +2816,24 @@ LIB_EXPORT bool l_tls_set_cacert(struct l_tls *tls, const char *ca_cert_path) tls->ca_certs =NULL ; } -if (ca_cert_path) { +if (ca_certs) {if (!l_key_is_supported (L_KEY_FEATURE_RESTRICT )) {TLS_DEBUG ("keyctl restrict support missing, " "check kernel configuration" );return false; } - tls->ca_certs =l_pem_load_certificate_list (ca_cert_path); -if (!tls->ca_certs) { -TLS_DEBUG ("Error loading %s" , ca_cert_path); -return false; - } + tls->ca_certs = ca_certs; }return true; } -LIB_EXPORT bool l_tls_set_auth_data(struct l_tls *tls, const char *cert_path, -const char *priv_key_path, -const char *priv_key_passphrase) +LIB_EXPORT bool l_tls_set_auth_data(struct l_tls *tls, +struct l_certchain *certchain, +struct l_key *priv_key) { -TLS_DEBUG ("cert-path=%s priv-key-path=%s priv-key-passphrase=%p" , - cert_path, priv_key_path, priv_key_passphrase); +TLS_DEBUG ("certchain=%p priv-key=%p" , certchain, priv_key);if (tls->cert) {l_certchain_free (tls->cert);
@@ -2851,24 +2846,13 @@ LIB_EXPORT bool l_tls_set_auth_data(struct l_tls *tls, const char *cert_path, tls->priv_key_size =0 ; } -if (cert_path) { - tls->cert =l_pem_load_certificate_chain (cert_path); -if (!tls->cert) { -TLS_DEBUG ("Error loading %s" , cert_path); -return false; - } - } +if (certchain) + tls->cert = certchain; - if (priv_key_path) { + if (priv_key) { bool is_public = true; - tls->priv_key = l_pem_load_private_key(priv_key_path, - priv_key_passphrase, - NULL); - if (!tls->priv_key) { - TLS_DEBUG("Error loading %s", priv_key_path); - return false; - } + tls->priv_key = priv_key; if (!l_key_get_info(tls->priv_key, L_KEY_RSA_PKCS1_V1_5, L_CHECKSUM_NONE, &tls->priv_key_size,
ell/tls.h +7 -4
@@ -33,6 +33,9 @@ enum l_tls_version { };struct l_tls ; +struct l_key ; +struct l_certchain ; +struct l_queue ;enum l_tls_alert_desc {TLS_ALERT_CLOSE_NOTIFY =0 ,
@@ -96,7 +99,7 @@ void l_tls_write(struct l_tls *tls, const uint8_t *data, size_t len);void l_tls_handle_rx (struct l_tls *tls,const uint8_t *data,size_t len);/* If peer is to be authenticated, supply the CA certificates */ -bool l_tls_set_cacert (struct l_tls *tls,const char *ca_cert_path); +bool l_tls_set_cacert (struct l_tls *tls,struct l_queue *ca_certs);/* * If we are to be authenticated, supply our certificate, private key and
@@ -109,9 +112,9 @@ bool l_tls_set_cacert(struct l_tls *tls, const char *ca_cert_path);* one certificate of each type so they can be used depending on which * is compatible with the negotiated parameters. */ -bool l_tls_set_auth_data (struct l_tls *tls,const char *cert_path, -const char *priv_key_path, -const char *priv_key_passphrase); +bool l_tls_set_auth_data (struct l_tls *tls, +struct l_certchain *certchain, +struct l_key *priv_key); void l_tls_set_version_range(struct l_tls *tls, enum l_tls_version min_version,
Signature · 1 line
2.17.1
PATCH 2/4 unit: update test-tls to use new API definition
--- unit/test-tls.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-)
unit/test-tls.c +24 -8
@@ -528,6 +528,13 @@ static void test_tls_with_ver(const struct tls_conn_test *test, }, }; +struct l_certchain *server_cert; +struct l_certchain *client_cert; +struct l_key *server_key; +struct l_key *client_key; +struct l_queue *server_ca; +struct l_queue *client_ca; +/* Server */ s[0 ].tls =l_tls_new (true, tls_test_new_data, tls_test_write, tls_test_ready, tls_test_disconnected, &s[0 ]);
@@ -556,16 +563,25 @@ static void test_tls_with_ver(const struct tls_conn_test *test,if (getenv ("TLS_DEBUG" ))l_tls_set_debug (s[1 ].tls, tls_debug_cb,"client" ,NULL ); - auth_ok =l_tls_set_auth_data (s[0 ].tls, test->server_cert_path, - test->server_key_path, - test->server_key_passphrase); + server_cert =l_pem_load_certificate_chain (test->server_cert_path); + client_cert =l_pem_load_certificate_chain (test->client_cert_path); + + server_key =l_pem_load_private_key (test->server_key_path, + test->server_key_passphrase, +NULL ); + client_key =l_pem_load_private_key (test->client_key_path, + test->client_key_passphrase, +NULL ); + + server_ca =l_pem_load_certificate_list (test->server_ca_cert_path); + client_ca =l_pem_load_certificate_list (test->client_ca_cert_path); + + auth_ok =l_tls_set_auth_data (s[0 ].tls, server_cert, server_key);assert (auth_ok); - auth_ok =l_tls_set_auth_data (s[1 ].tls, test->client_cert_path, - test->client_key_path, - test->client_key_passphrase); + auth_ok =l_tls_set_auth_data (s[1 ].tls, client_cert, client_key);assert (auth_ok); -assert (l_tls_set_cacert (s[0 ].tls, test->server_ca_cert_path)); -assert (l_tls_set_cacert (s[1 ].tls, test->client_ca_cert_path)); +assert (l_tls_set_cacert (s[0 ].tls, server_ca)); +assert (l_tls_set_cacert (s[1 ].tls, client_ca));if (test->client_domain_mask)l_tls_set_domain_mask (s[1 ].tls, test->client_domain_mask);
Signature · 1 line
2.17.1
PATCH 3/4 examples: update https server/client with new TLS APIs
In reply to James Prestwood--- examples/https-client-test.c | 11 +++++++++-- examples/https-server-test.c | 11 +++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-)
examples/https-client-test.c +9 -2
@@ -134,6 +134,9 @@ int main(int argc, char *argv[])struct sockaddr_in addr;int fd;bool auth_ok; +struct l_certchain *cert; +struct l_key *priv_key; +struct l_queue *ca_cert;if (argc !=2 && argc !=3 && argc !=6 ) { printf("Usage: %s <https-host-name> [<ca-cert-path> "
@@ -189,9 +192,13 @@ int main(int argc, char *argv[])if (getenv ("TLS_DEBUG" ))l_tls_set_debug (tls, https_tls_debug_cb,NULL ,NULL ); - auth_ok = (argc <=2 ||l_tls_set_cacert (tls, argv[2 ])) && + ca_cert =l_pem_load_certificate_list (argv[2 ]); + cert =l_pem_load_certificate_chain (argv[3 ]); + priv_key =l_pem_load_private_key (argv[4 ], argv[5 ],NULL ); + + auth_ok = (argc <=2 ||l_tls_set_cacert (tls, ca_cert)) && (argc <=5 || -l_tls_set_auth_data (tls, argv[3 ], argv[4 ], argv[5 ])) && +l_tls_set_auth_data (tls, cert, priv_key)) &&l_tls_start (tls);if (tls && auth_ok)
examples/https-server-test.c +9 -2
@@ -120,6 +120,9 @@ int main(int argc, char *argv[])struct sockaddr_in addr;int fd, listenfd;bool auth_ok; +struct l_certchain *cert; +struct l_key *priv_key; +struct l_queue *ca_cert;if (argc !=4 && argc !=5 ) { printf("Usage: %s <server-cert-path> <server-key-path> "
@@ -174,8 +177,12 @@ int main(int argc, char *argv[])if (getenv ("TLS_DEBUG" ))l_tls_set_debug (tls, https_tls_debug_cb,NULL ,NULL ); - auth_ok =l_tls_set_auth_data (tls, argv[1 ], argv[2 ], argv[3 ]) && - (argc <=4 ||l_tls_set_cacert (tls, argv[4 ])) && + cert =l_pem_load_certificate_chain (argv[1 ]); + priv_key =l_pem_load_private_key (argv[2 ], argv[3 ],NULL ); + ca_cert =l_pem_load_certificate_list (argv[4 ]); + + auth_ok =l_tls_set_auth_data (tls, cert, priv_key) && + (argc <=4 ||l_tls_set_cacert (tls, ca_cert)) &&l_tls_start (tls);if (tls && auth_ok)
Signature · 1 line
2.17.1
PATCH 4/4 cert: allow l_certchain_free use in l_queue_destroy
In reply to James Prestwoodl_pem_load_certificate_list returns a queue of l_certchains and cleaning up this queue requires l_certchain_free to be wrapped in a queue destroy function.
This patch changes l_certchain_free to take a void * so it can be used directly in l_queue_destroy.
--- ell/cert.c | 4 +++- ell/cert.h | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-)
ell/cert.c +3 -1
@@ -304,8 +304,10 @@ static struct l_cert *certchain_pop_ca(struct l_certchain *chain)return ca; } -LIB_EXPORT void l_certchain_free(struct l_certchain *chain) +LIB_EXPORT void l_certchain_free(void *data) { +struct l_certchain *chain = data; +while (chain && chain->ca)l_cert_free (certchain_pop_ca (chain));
ell/cert.h +1 -1
@@ -48,7 +48,7 @@ const uint8_t *l_cert_get_dn(struct l_cert *cert, size_t *out_len);enum l_cert_key_type l_cert_get_pubkey_type (struct l_cert *cert);struct l_key *l_cert_get_pubkey (struct l_cert *cert); -void l_certchain_free (struct l_certchain *chain); +void l_certchain_free (void *data);struct l_cert *l_certchain_get_leaf (struct l_certchain *chain); void l_certchain_walk_from_leaf(struct l_certchain *chain,
Signature · 1 line
2.17.1