enable DTLS negotiation
David Woodhouse
dwmw2 at infradead.org
Fri Sep 16 08:30:48 PDT 2016
On Fri, 2016-09-16 at 15:07 +0200, Nikos Mavrogiannopoulos wrote:
>
> Ok. For openconnect client it would be fairly easy to handle this,
> only send an extension with fairly static data, as it only sends a
> username. However, there is a catch, we should do that for both
> openssl and gnutls. Ocserv would require to be able to parse the TLS
> client hello since the extension data are in variable positions,
> however that shouldn't be really hard. I could do the ocserv part and
> the gnutls part if you do the openssl part :)
Have I got the actual payload of the extension right? I've done it as
an ASN.1 SEQUENCE containing one or more (in our case just one) ASN.1
OCTET-STRINGs each with an identity.
(I note that TLS1.3 is different here, and each PskIdentity contains
also a PskKeyExchangeMode and a PskAuthenticationMode. Is that likely
to end up in the draft for 1.2 before it becomes final?)
I have hex-printed the identity since it's often going to be treated as
a printable string. The existing PSK callback for OpenSSL, for example,
assumes that it's a string. As does gnutls_psk_set_cient_credentials().
I need to check that the server returns the correct identity too. That
one would just be the OCTET-STRING with no SEQUENCE since there can be
only one?
diff --git a/openssl-dtls.c b/openssl-dtls.c
index 84682a4..b3922fb 100644
--- a/openssl-dtls.c
+++ b/openssl-dtls.c
@@ -182,15 +182,54 @@ static unsigned int psk_callback(SSL *ssl, const char *hint, char *identity,
unsigned int max_psk_len)
{
struct openconnect_info *vpninfo = SSL_get_app_data(ssl);
-
- if (!vpninfo || max_identity_len < 4 || max_psk_len < PSK_KEY_SIZE)
+ int i;
+ if (!vpninfo || max_identity_len <= sizeof(vpninfo->dtls_session_id) * 2 || max_psk_len < PSK_KEY_SIZE)
return 0;
vpn_progress(vpninfo, PRG_TRACE, _("PSK callback\n"));
- snprintf(identity, max_psk_len, "psk");
+ for (i = 0; i < sizeof(vpninfo->dtls_session_id); i++)
+ sprintf(identity + (i*2), "%02x", vpninfo->dtls_session_id[i]);
+
memcpy(psk, vpninfo->dtls_secret, PSK_KEY_SIZE);
return PSK_KEY_SIZE;
}
+
+static int pskident_add(SSL *s, unsigned int ext_type, const unsigned char **out, size_t *outlen,
+ int *al, void *add_arg)
+{
+ struct openconnect_info *vpninfo = add_arg;
+ unsigned char *buf;
+ int i;
+ buf = malloc(sizeof(vpninfo->dtls_session_id) * 2 + 5);
+ if (!buf) {
+ vpn_progress(vpninfo, PRG_ERR,
+ _("Failed to create identity extension for OpenSSL\n"));
+ return 0;
+ }
+ buf[0] = 0x30; /* SEQUENCE */
+ buf[1] = sizeof(vpninfo->dtls_session_id) * 2 + 2; /* length */
+ buf[2] = 0x04; /* OCTET-STRING */
+ buf[3] = sizeof(vpninfo->dtls_session_id) * 2; /* length */
+ for (i = 0; i < sizeof(vpninfo->dtls_session_id); i++)
+ sprintf((char *)buf + 4 + (i*2), "%02x", vpninfo->dtls_session_id[i]);
+
+ *out = buf;
+ *outlen = sizeof(vpninfo->dtls_session_id) * 2 + 4;
+
+ return 1;
+}
+
+static void pskident_free(SSL *s, unsigned int ext_type, const unsigned char *out, void *add_arg)
+{
+ free((void *)out);
+}
+
+static int pskident_parse(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen,
+ int *al, void *parse_arg)
+{
+ return 1;
+}
+
#endif
int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
@@ -268,6 +307,9 @@ int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
vpninfo->dtls_attempt_period = 0;
return -EINVAL;
}
+ SSL_CTX_add_client_custom_ext(vpninfo->dtls_ctx, 10015,
+ pskident_add, pskident_free, vpninfo,
+ pskident_parse, vpninfo);
/* For SSL_CTX_set_cipher_list() */
cipher = "PSK";
#endif
--
dwmw2
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/x-pkcs7-signature
Size: 5760 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/openconnect-devel/attachments/20160916/15351e95/attachment-0001.bin>
More information about the openconnect-devel
mailing list