From: Marcel Holtmann <marcel@holtmann.org>
To: ell@lists.linux.dev
Cc: andrew.zaborowski@intel.com
Subject: [PATCH 3/3] tls: Add support l_tls_set_alpn_list() and ALPN extension
Date: Tue, 3 Jan 2023 23:02:50 +0100 [thread overview]
Message-ID: <20230103220250.717876-3-marcel@holtmann.org> (raw)
Add support for application layer protocol negotiation (ALPN) and
provide API for setting the list of client protocols and for getting the
server selected protocol.
---
ell/ell.sym | 2 ++
ell/tls-extensions.c | 73 ++++++++++++++++++++++++++++++++++++++++++++
ell/tls-private.h | 2 ++
ell/tls.c | 21 +++++++++++++
ell/tls.h | 3 ++
5 files changed, 101 insertions(+)
diff --git a/ell/ell.sym b/ell/ell.sym
index f8148f257eb1..81c0cb7f5b94 100644
--- a/ell/ell.sym
+++ b/ell/ell.sym
@@ -515,6 +515,8 @@ global:
l_tls_close;
l_tls_reset;
l_tls_set_server_name;
+ l_tls_set_alpn_list;
+ l_tls_get_alpn;
l_tls_set_cacert;
l_tls_set_auth_data;
l_tls_set_version_range;
diff --git a/ell/tls-extensions.c b/ell/tls-extensions.c
index 75f47f6ba548..e5a7c7994b7d 100644
--- a/ell/tls-extensions.c
+++ b/ell/tls-extensions.c
@@ -52,6 +52,70 @@ static ssize_t tls_server_name_client_write(struct l_tls *tls,
return hlen + 5;
}
+static ssize_t tls_alpn_client_write(struct l_tls *tls,
+ uint8_t *buf, size_t len)
+{
+ uint8_t *ptr = buf + 2;
+ uint16_t ext_len = 0;
+ int i;
+
+ if (!tls->alpn_list)
+ return -ENOMSG;
+
+ if (len < 2)
+ return -ENOMEM;
+
+ for (i = 0; tls->alpn_list[i]; i++) {
+ uint8_t str_len = strlen(tls->alpn_list[i]);
+ l_put_u8(str_len, ptr);
+ memcpy(ptr + 1, tls->alpn_list[i], str_len);
+ ptr += str_len + 1;
+ ext_len += str_len + 1;
+ }
+
+ l_put_be16(ext_len, buf);
+
+ return ext_len + 2;
+}
+
+static bool tls_alpn_server_handle(struct l_tls *tls,
+ const uint8_t *buf, size_t len)
+{
+ uint16_t ext_len;
+ uint8_t str_len;
+
+ if (len < 2)
+ return false;
+
+ ext_len = l_get_be16(buf);
+ if (ext_len != len - 2)
+ return false;
+
+ str_len = l_get_u8(buf + 2);
+ if (str_len != len - 3)
+ return false;
+
+ l_free(tls->selected_alpn);
+ tls->selected_alpn = l_strndup((const char *) buf + 3, str_len);
+
+ TLS_DEBUG("Negotiated ALPN %s", tls->selected_alpn);
+
+ return true;
+}
+
+static bool tls_alpn_server_absent(struct l_tls *tls)
+{
+ if (!tls->alpn_list)
+ return false;
+
+ l_free(tls->selected_alpn);
+ tls->selected_alpn = NULL;
+
+ TLS_DEBUG("ALPN not supported");
+
+ return true;
+}
+
/* Most extensions are not used when resuming a cached session */
#define SKIP_ON_RESUMPTION() \
do { \
@@ -1025,6 +1089,15 @@ const struct tls_hello_extension tls_extensions[] = {
tls_signature_algorithms_client_absent,
NULL, NULL, NULL,
},
+ {
+ "ALPN", "application_layer_protocol_negotiation", 16,
+ tls_alpn_client_write,
+ NULL,
+ NULL,
+ NULL,
+ tls_alpn_server_handle,
+ tls_alpn_server_absent,
+ },
{
"Secure Renegotiation", "renegotiation_info", 0xff01,
tls_renegotiation_info_client_write,
diff --git a/ell/tls-private.h b/ell/tls-private.h
index ac477885c5f7..dbc5457ef091 100644
--- a/ell/tls-private.h
+++ b/ell/tls-private.h
@@ -218,6 +218,8 @@ struct l_tls {
struct tls_cipher_suite **cipher_suite_pref_list;
char *server_name;
+ char **alpn_list;
+ char *selected_alpn;
struct l_settings *session_settings;
char *session_prefix;
diff --git a/ell/tls.c b/ell/tls.c
index 9556efd932bc..8c1c9040ff89 100644
--- a/ell/tls.c
+++ b/ell/tls.c
@@ -3421,6 +3421,8 @@ LIB_EXPORT void l_tls_free(struct l_tls *tls)
l_free(tls->cipher_suite_pref_list);
l_free(tls->server_name);
+ l_strv_free(tls->alpn_list);
+ l_free(tls->selected_alpn);
l_free(tls);
}
@@ -3668,6 +3670,25 @@ LIB_EXPORT bool l_tls_set_server_name(struct l_tls *tls, const char *name)
return true;
}
+LIB_EXPORT bool l_tls_set_alpn_list(struct l_tls *tls, const char **list)
+{
+ if (!tls)
+ return false;
+
+ l_strv_free(tls->alpn_list);
+ tls->alpn_list = l_strv_copy((char **) list);
+
+ return true;
+}
+
+LIB_EXPORT const char *l_tls_get_alpn(struct l_tls *tls)
+{
+ if (!tls)
+ return NULL;
+
+ return tls->selected_alpn;
+}
+
LIB_EXPORT bool l_tls_set_cacert(struct l_tls *tls, struct l_queue *ca_certs)
{
if (tls->ca_certs) {
diff --git a/ell/tls.h b/ell/tls.h
index c931b5db0a54..e33f7c070008 100644
--- a/ell/tls.h
+++ b/ell/tls.h
@@ -105,6 +105,9 @@ void l_tls_handle_rx(struct l_tls *tls, const uint8_t *data, size_t len);
bool l_tls_set_server_name(struct l_tls *tls, const char *name);
+bool l_tls_set_alpn_list(struct l_tls *tls, const char **list);
+const char *l_tls_get_alpn(struct l_tls *tls);
+
/*
* If peer is to be authenticated, supply the CA certificates. On success
* the l_tls object takes ownership of the queue and the individual l_cert
--
2.39.0
next reply other threads:[~2023-01-03 22:02 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-01-03 22:02 Marcel Holtmann [this message]
2023-01-04 21:08 ` [PATCH 3/3] tls: Add support l_tls_set_alpn_list() and ALPN extension Andrew Zaborowski
2023-01-05 15:15 ` Marcel Holtmann
2023-01-09 12:21 ` Andrew Zaborowski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230103220250.717876-3-marcel@holtmann.org \
--to=marcel@holtmann.org \
--cc=andrew.zaborowski@intel.com \
--cc=ell@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).