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>