net/tcp: Support initial sequence number described in RFC 6528

Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
This commit is contained in:
Zhe Weng 2023-11-01 11:30:36 +08:00 committed by Xiang Xiao
parent 5096a2c9fd
commit d1c73b6ed6
4 changed files with 94 additions and 13 deletions

View File

@ -158,6 +158,17 @@ config NET_TCP_CC_NEWRENO
The TCP Congestion Control defines four congestion control algorithms, The TCP Congestion Control defines four congestion control algorithms,
slow start, congestion avoidance, fast retransmit, and fast recovery. slow start, congestion avoidance, fast retransmit, and fast recovery.
config NET_TCP_ISN_RFC6528
bool "Use Initial Sequence Number Algorithm from RFC 6528"
default n
depends on CRYPTO
---help---
Initial Sequence Number Generation Algorithm from RFC 6528:
ISN = M + F(localip, localport, remoteip, remoteport, secretkey)
M is the 4 microsecond timer, and F() is a pseudorandom
function (PRF) which is MD5 (suggested by RFC 6528).
config NET_TCP_WINDOW_SCALE config NET_TCP_WINDOW_SCALE
bool "Enable TCP/IP Window Scale Option" bool "Enable TCP/IP Window Scale Option"
default n default n

View File

@ -896,7 +896,7 @@ uint32_t tcp_addsequence(FAR uint8_t *seqno, uint16_t len);
* *
****************************************************************************/ ****************************************************************************/
void tcp_initsequence(FAR uint8_t *seqno); void tcp_initsequence(FAR struct tcp_conn_s *conn);
/**************************************************************************** /****************************************************************************
* Name: tcp_nextsequence * Name: tcp_nextsequence

View File

@ -1200,7 +1200,7 @@ FAR struct tcp_conn_s *tcp_alloc_accept(FAR struct net_driver_s *dev,
conn->rport = tcp->srcport; conn->rport = tcp->srcport;
conn->tcpstateflags = TCP_SYN_RCVD; conn->tcpstateflags = TCP_SYN_RCVD;
tcp_initsequence(conn->sndseq); tcp_initsequence(conn);
#if !defined(CONFIG_NET_TCP_WRITE_BUFFERS) #if !defined(CONFIG_NET_TCP_WRITE_BUFFERS)
conn->rexmit_seq = tcp_getsequence(conn->sndseq); conn->rexmit_seq = tcp_getsequence(conn->sndseq);
#endif #endif
@ -1506,13 +1506,6 @@ int tcp_connect(FAR struct tcp_conn_s *conn, FAR const struct sockaddr *addr)
*/ */
conn->tcpstateflags = TCP_SYN_SENT; conn->tcpstateflags = TCP_SYN_SENT;
tcp_initsequence(conn->sndseq);
/* Save initial sndseq to rexmit_seq, otherwise it will be zero */
#if !defined(CONFIG_NET_TCP_WRITE_BUFFERS)
conn->rexmit_seq = tcp_getsequence(conn->sndseq);
#endif
conn->tx_unacked = 1; /* TCP length of the SYN is one. */ conn->tx_unacked = 1; /* TCP length of the SYN is one. */
conn->nrtx = 0; conn->nrtx = 0;
@ -1528,6 +1521,16 @@ int tcp_connect(FAR struct tcp_conn_s *conn, FAR const struct sockaddr *addr)
conn->sndseq_max = 0; conn->sndseq_max = 0;
#endif #endif
/* Set initial sndseq when we have both local/remote addr and port */
tcp_initsequence(conn);
/* Save initial sndseq to rexmit_seq, otherwise it will be zero */
#if !defined(CONFIG_NET_TCP_WRITE_BUFFERS)
conn->rexmit_seq = tcp_getsequence(conn->sndseq);
#endif
#ifdef CONFIG_NET_TCP_CC_NEWRENO #ifdef CONFIG_NET_TCP_CC_NEWRENO
/* Initialize the variables of congestion control. */ /* Initialize the variables of congestion control. */

View File

@ -43,23 +43,84 @@
#include <nuttx/config.h> #include <nuttx/config.h>
#if defined(CONFIG_NET) && defined(CONFIG_NET_TCP) #if defined(CONFIG_NET) && defined(CONFIG_NET_TCP)
#include <stdint.h> #include <crypto/md5.h>
#include <debug.h> #include <debug.h>
#include <stdint.h>
#include <nuttx/clock.h> #include <nuttx/clock.h>
#include <nuttx/net/netconfig.h> #include <nuttx/net/netconfig.h>
#include <nuttx/net/netdev.h> #include <nuttx/net/netdev.h>
#include "devif/devif.h" #include "devif/devif.h"
#include "tcp/tcp.h"
#include "utils/utils.h" #include "utils/utils.h"
/**************************************************************************** /****************************************************************************
* Private Data * Private Data
****************************************************************************/ ****************************************************************************/
/* g_tcpsequence is used to generate initial TCP sequence numbers */ /* These fields are used to generate initial TCP sequence numbers */
#ifdef CONFIG_NET_TCP_ISN_RFC6528
/* RFC 6528, Section 3: Key lengths of 128 bits should be adequate. */
static uint32_t g_tcp_isnkey[4];
#else
static uint32_t g_tcpsequence; static uint32_t g_tcpsequence;
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: tcp_isn_rfc6528
*
* Description:
* Calculate the initial sequence number described in RFC 6528.
* ISN = M + F(localip, localport, remoteip, remoteport, secretkey)
*
****************************************************************************/
#ifdef CONFIG_NET_TCP_ISN_RFC6528
static uint32_t tcp_isn_rfc6528(FAR struct tcp_conn_s *conn)
{
const size_t addrlen = net_ip_domain_select(conn->domain,
sizeof(in_addr_t), sizeof(net_ipv6addr_t));
MD5_CTX ctx;
uint32_t digest[MD5_DIGEST_LENGTH / 4];
uint32_t m;
/* Make sure we have a secret key */
if (g_tcp_isnkey[0] == 0)
{
net_getrandom(g_tcp_isnkey, sizeof(g_tcp_isnkey));
}
/* M is the 4 microsecond timer */
m = TICK2USEC(clock_systime_ticks()) / 4;
/* F() is suggested to be MD5 */
md5init(&ctx);
/* Calculate F(localip, localport, remoteip, remoteport, secretkey) */
md5update(&ctx, net_ip_binding_laddr(&conn->u, conn->domain), addrlen);
md5update(&ctx, &conn->lport, sizeof(conn->lport));
md5update(&ctx, net_ip_binding_raddr(&conn->u, conn->domain), addrlen);
md5update(&ctx, &conn->rport, sizeof(conn->rport));
md5update(&ctx, g_tcp_isnkey, sizeof(g_tcp_isnkey));
md5final((FAR uint8_t *)digest, &ctx);
/* ISN = M + F(localip, localport, remoteip, remoteport, secretkey) */
return m + digest[0];
}
#endif
/**************************************************************************** /****************************************************************************
* Public Functions * Public Functions
@ -142,8 +203,11 @@ uint32_t tcp_addsequence(FAR uint8_t *seqno, uint16_t len)
* *
****************************************************************************/ ****************************************************************************/
void tcp_initsequence(FAR uint8_t *seqno) void tcp_initsequence(FAR struct tcp_conn_s *conn)
{ {
#ifdef CONFIG_NET_TCP_ISN_RFC6528
tcp_setsequence(conn->sndseq, tcp_isn_rfc6528(conn));
#else
/* If g_tcpsequence is already initialized, just copy it */ /* If g_tcpsequence is already initialized, just copy it */
if (g_tcpsequence == 0) if (g_tcpsequence == 0)
@ -164,7 +228,8 @@ void tcp_initsequence(FAR uint8_t *seqno)
} }
} }
tcp_setsequence(seqno, g_tcpsequence); tcp_setsequence(conn->sndseq, g_tcpsequence);
#endif
} }
/**************************************************************************** /****************************************************************************
@ -180,7 +245,9 @@ void tcp_initsequence(FAR uint8_t *seqno)
void tcp_nextsequence(void) void tcp_nextsequence(void)
{ {
#ifndef CONFIG_NET_TCP_ISN_RFC6528
g_tcpsequence++; g_tcpsequence++;
#endif
} }
#endif /* CONFIG_NET && CONFIG_NET_TCP */ #endif /* CONFIG_NET && CONFIG_NET_TCP */