I am using the code for anonymous TLS connection as provided in gnutls.org. The server is implemented on an ubuntu machine, the client is an ARM Cortex A8 embedded device. Server and Client are in the same LAN.
Each time the client starts a connection the error (-58) is generated during the handshake which means GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION i.e. "An illegal TLS extension was received.".
From the server side i get the error:
*** Handshake has failed (Error in the pull function.)
However, when I run both server and client on the ubuntu machine (I use the loopback address as destination in the client), everything is fine.
In the same way, if I run both server and client on the embedded board (always with the loopback address as destination in the client), everything is fine.
The embedded board uses gnutls ver 3.6.4. In the ubuntu host there is the gnutls 3.6.13.
Is there a way to find the "illegal" tls extension?
This is a wireshark capture of the wrong transaction:
"No.","Time","Source","Destination","Protocol","Length","Info"
"148","22.907515133","192.168.0.47","192.168.0.184","TCP","74","53378 > 2525 [SYN] Seq=0 Win=29200 Len=0 MSS=1460 SACK_PERM=1 TSval=2912635975 TSecr=0 WS=32"
"149","22.907546972","192.168.0.184","192.168.0.47","TCP","74","2525 > 53378 [SYN, ACK] Seq=0 Ack=1 Win=65160 Len=0 MSS=1460 SACK_PERM=1 TSval=2543059266 TSecr=2912635975 WS=128"
"150","22.908244578","192.168.0.47","192.168.0.184","TCP","66","53378 > 2525 [ACK] Seq=1 Ack=1 Win=29216 Len=0 TSval=2912635976 TSecr=2543059266"
"151","22.909329144","192.168.0.47","192.168.0.184","TLSv1.2","232","Client Hello"
"152","22.909344645","192.168.0.184","192.168.0.47","TCP","66","2525 > 53378 [ACK] Seq=1 Ack=167 Win=65024 Len=0 TSval=2543059267 TSecr=2912635977"
"153","22.909772038","192.168.0.184","192.168.0.47","TLSv1.2","259","Server Hello, Server Key Exchange, Server Hello Done"
"154","22.910430333","192.168.0.47","192.168.0.184","TCP","66","53378 > 2525 [ACK] Seq=167 Ack=194 Win=30272 Len=0 TSval=2912635978 TSecr=2543059268"
"155","22.911259314","192.168.0.47","192.168.0.184","TCP","66","53378 > 2525 [RST, ACK] Seq=167 Ack=194 Win=30272 Len=0 TSval=2912635979 TSecr=2543059268"
The Wireshark capture of the loopback sucessful transaction:
"No.","Time","Source","Destination","Protocol","Length","Info"
"1","0.000000000","127.0.0.1","127.0.0.1","TCP","74","48226 > 2525 [SYN] Seq=0 Win=65495 Len=0 MSS=65495 SACK_PERM=1 TSval=4110066202 TSecr=0 WS=128"
"2","0.000015551","127.0.0.1","127.0.0.1","TCP","74","2525 > 48226 [SYN, ACK] Seq=0 Ack=1 Win=65483 Len=0 MSS=65495 SACK_PERM=1 TSval=4110066202 TSecr=4110066202 WS=128"
"3","0.000029625","127.0.0.1","127.0.0.1","TCP","66","48226 > 2525 [ACK] Seq=1 Ack=1 Win=65536 Len=0 TSval=4110066202 TSecr=4110066202"
"4","0.000149840","127.0.0.1","127.0.0.1","TLSv1.2","236","Client Hello"
"5","0.000156259","127.0.0.1","127.0.0.1","TCP","66","2525 > 48226 [ACK] Seq=1 Ack=171 Win=65408 Len=0 TSval=4110066202 TSecr=4110066202"
"6","0.000390203","127.0.0.1","127.0.0.1","TLSv1.2","259","Server Hello, Server Key Exchange, Server Hello Done"
"7","0.000434564","127.0.0.1","127.0.0.1","TCP","66","48226 > 2525 [ACK] Seq=171 Ack=194 Win=65408 Len=0 TSval=4110066202 TSecr=4110066202"
"8","0.001128440","127.0.0.1","127.0.0.1","TLSv1.2","220","Client Key Exchange, Change Cipher Spec, Encrypted Handshake Message"
"9","0.001174055","127.0.0.1","127.0.0.1","TCP","66","2525 > 48226 [ACK] Seq=194 Ack=325 Win=65408 Len=0 TSval=4110066203 TSecr=4110066203"
"10","0.001695368","127.0.0.1","127.0.0.1","TLSv1.2","145","Change Cipher Spec, Encrypted Handshake Message"
"11","0.001739096","127.0.0.1","127.0.0.1","TCP","66","48226 > 2525 [ACK] Seq=325 Ack=273 Win=65536 Len=0 TSval=4110066204 TSecr=4110066204"
"12","0.001880330","127.0.0.1","127.0.0.1","TLSv1.2","139","Application Data"
"13","0.001885804","127.0.0.1","127.0.0.1","TCP","66","2525 > 48226 [ACK] Seq=273 Ack=398 Win=65536 Len=0 TSval=4110066204 TSecr=4110066204"
"14","0.001942348","127.0.0.1","127.0.0.1","TLSv1.2","139","Application Data"
"15","0.001947752","127.0.0.1","127.0.0.1","TCP","66","48226 > 2525 [ACK] Seq=398 Ack=346 Win=65536 Len=0 TSval=4110066204 TSecr=4110066204"
"16","0.002100239","127.0.0.1","127.0.0.1","TLSv1.2","123","Encrypted Alert"
"17","0.002105316","127.0.0.1","127.0.0.1","TCP","66","2525 > 48226 [ACK] Seq=346 Ack=455 Win=65536 Len=0 TSval=4110066204 TSecr=4110066204"
"18","0.002188593","127.0.0.1","127.0.0.1","TLSv1.2","123","Encrypted Alert"
"19","0.002193722","127.0.0.1","127.0.0.1","TCP","66","48226 > 2525 [ACK] Seq=455 Ack=403 Win=65536 Len=0 TSval=4110066204 TSecr=4110066204"
"20","0.002243619","127.0.0.1","127.0.0.1","TCP","66","2525 > 48226 [FIN, ACK] Seq=403 Ack=455 Win=65536 Len=0 TSval=4110066204 TSecr=4110066204"
"21","0.002278856","127.0.0.1","127.0.0.1","TCP","66","48226 > 2525 [FIN, ACK] Seq=455 Ack=404 Win=65536 Len=0 TSval=4110066204 TSecr=4110066204"
"22","0.002287692","127.0.0.1","127.0.0.1","TCP","66","2525 > 48226 [ACK] Seq=404 Ack=456 Win=65536 Len=0 TSval=4110066204 TSecr=4110066204"
Here the code for the client:
int tlsSendPacket_anonymous(void)
{
int ret, sd, ii;
gnutls_certificate_type_t gnu_certificate_type;
gnutls_anon_client_credentials_t anoncred;
/* Need to enable anonymous KX specifically. */
//moved before thread start
//gnutls_global_init();
ret = gnutls_anon_allocate_client_credentials(&anoncred);
if (GNUTLS_E_SUCCESS != ret)
{
SEND_MESSAGE(DBG_ERROR,"TLS ALLOCATION ERROR\n");
return ret;
}
/* Initialize TLS session
*/
ret = gnutls_init(&session, GNUTLS_CLIENT);
if (GNUTLS_E_SUCCESS != ret)
{
SEND_MESSAGE(DBG_ERROR,"TLS INIT ERROR\n");
return ret;
}
/* Use default priorities */
ret = gnutls_priority_set_direct(session,
"PERFORMANCE:+ANON-ECDH:+ANON-DH",
NULL);
if (GNUTLS_E_SUCCESS != ret)
{
SEND_MESSAGE(DBG_ERROR,"TLS PRIORITY SET ERROR\n");
return ret;
}
/* put the anonymous credentials to the current session
*/
ret = gnutls_credentials_set(session, GNUTLS_CRD_ANON, anoncred);
if (GNUTLS_E_SUCCESS != ret)
{
SEND_MESSAGE(DBG_ERROR,"TLS CREDENTIAL SET ERROR\n");
return ret;
}
/* connect to the peer
*/
sd = tcp_connect();
if (sd <= 0)
{
SEND_MESSAGE(DBG_ERROR,"TLS TCP CONNECTION ERROR\n");
return sd;
}
gnutls_transport_set_int(session, sd);
gnutls_handshake_set_timeout(session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
/* Perform the TLS handshake
*/
do {
ret = gnutls_handshake(session);
}
while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
if (ret < 0) {
fprintf(stderr, "*** Handshake failed\n");
gnutls_perror(ret);
goto end;
} else {
char *desc;
desc = gnutls_session_get_desc(session);
printf("- Session info: %s\n", desc);
gnutls_free(desc);
}
LOOP_CHECK(ret, gnutls_record_send(session, MSG, strlen(MSG)));
LOOP_CHECK(ret, gnutls_record_recv(session, buffer, MAX_BUF));
if (ret == 0) {
printf("- Peer has closed the TLS connection\n");
goto end;
} else if (ret < 0 && gnutls_error_is_fatal(ret) == 0) {
fprintf(stderr, "*** Warning: %s\n", gnutls_strerror(ret));
} else if (ret < 0) {
fprintf(stderr, "*** Error: %s\n", gnutls_strerror(ret));
goto end;
}
if (ret > 0) {
printf("- Received %d bytes: ", ret);
for (ii = 0; ii < ret; ii++) {
fputc(buffer[ii], stdout);
}
fputs("\n", stdout);
}
LOOP_CHECK(ret, gnutls_bye(session, GNUTLS_SHUT_RDWR));
end:
tcp_close(sd);
gnutls_deinit(session);
gnutls_anon_free_client_credentials(anoncred);
//Moved at thread end
//gnutls_global_deinit();
return 0;
}
And the server:
/* This example code is placed in the public domain. */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <gnutls/gnutls.h>
/* This is a sample TLS 1.0 echo server, for anonymous authentication only.
*/
#define SOCKET_ERR(err,s) if(err==-1) {perror(s);return(1);}
#define MAX_BUF 1024
#define PORT 2525 //5556 /* listen to 5556 port */
int main(void)
{
int err, listen_sd;
int sd, ret;
struct sockaddr_in sa_serv;
struct sockaddr_in sa_cli;
socklen_t client_len;
char topbuf[512];
gnutls_session_t session;
gnutls_anon_server_credentials_t anoncred;
char buffer[MAX_BUF + 1];
int optval = 1;
if (gnutls_check_version("3.1.4") == NULL) {
fprintf(stderr, "GnuTLS 3.1.4 or later is required for this example\n");
exit(1);
}
/* for backwards compatibility with gnutls < 3.3.0 */
gnutls_global_init();
gnutls_anon_allocate_server_credentials(&anoncred);
gnutls_anon_set_server_known_dh_params(anoncred, GNUTLS_SEC_PARAM_MEDIUM);
/* Socket operations
*/
listen_sd = socket(AF_INET, SOCK_STREAM, 0);
SOCKET_ERR(listen_sd, "socket");
memset(&sa_serv, '\0', sizeof(sa_serv));
sa_serv.sin_family = AF_INET;
sa_serv.sin_addr.s_addr = INADDR_ANY;
sa_serv.sin_port = htons(PORT); /* Server Port number */
setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR, (void *) &optval,
sizeof(int));
err =
bind(listen_sd, (struct sockaddr *) &sa_serv, sizeof(sa_serv));
SOCKET_ERR(err, "bind");
err = listen(listen_sd, 1024);
SOCKET_ERR(err, "listen");
printf("Server ready. Listening to port '%d'.\n\n", PORT);
client_len = sizeof(sa_cli);
for (;;) {
gnutls_init(&session, GNUTLS_SERVER);
gnutls_priority_set_direct(session,
"NORMAL:+ANON-ECDH:+ANON-DH",
NULL);
gnutls_credentials_set(session, GNUTLS_CRD_ANON, anoncred);
sd = accept(listen_sd, (struct sockaddr *) &sa_cli,
&client_len);
printf("- connection from %s, port %d\n",
inet_ntop(AF_INET, &sa_cli.sin_addr, topbuf,
sizeof(topbuf)), ntohs(sa_cli.sin_port));
gnutls_transport_set_int(session, sd);
do {
ret = gnutls_handshake(session);
}
while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
if (ret < 0) {
close(sd);
gnutls_deinit(session);
fprintf(stderr,
"*** Handshake has failed (%s)\n\n",
gnutls_strerror(ret));
continue;
}
printf("- Handshake was completed\n");
/* see the Getting peer's information example */
/* print_info(session); */
for (;;) {
ret = gnutls_record_recv(session, buffer, MAX_BUF);
if (ret == 0) {
printf
("\n- Peer has closed the GnuTLS connection\n");
break;
} else if (ret < 0
&& gnutls_error_is_fatal(ret) == 0) {
fprintf(stderr, "*** Warning: %s\n",
gnutls_strerror(ret));
} else if (ret < 0) {
fprintf(stderr, "\n*** Received corrupted "
"data(%d). Closing the connection.\n\n",
ret);
break;
} else if (ret > 0) {
/* echo data back to the client
*/
gnutls_record_send(session, buffer, ret);
}
}
printf("\n");
/* do not wait for the peer to close the connection.
*/
gnutls_bye(session, GNUTLS_SHUT_WR);
close(sd);
gnutls_deinit(session);
}
close(listen_sd);
gnutls_anon_free_server_credentials(anoncred);
gnutls_global_deinit();
return 0;
}