lkml.org 
[lkml]   [2022]   [Jul]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v6 12/26] tcp: authopt: Add support for signing skb-less replies
    Date
    This is required because tcp ipv4 sometimes sends replies without
    allocating a full skb that can be signed by tcp authopt.

    Handle this with additional code in tcp authopt.

    Signed-off-by: Leonard Crestez <cdleonard@gmail.com>
    ---
    include/net/tcp_authopt.h | 7 ++
    net/ipv4/tcp_authopt.c | 144 ++++++++++++++++++++++++++++++++++++++
    2 files changed, 151 insertions(+)

    diff --git a/include/net/tcp_authopt.h b/include/net/tcp_authopt.h
    index 1fa1b968c80c..9bc0f58a78cb 100644
    --- a/include/net/tcp_authopt.h
    +++ b/include/net/tcp_authopt.h
    @@ -114,10 +114,17 @@ static inline struct tcp_authopt_key_info *tcp_authopt_select_key(
    int tcp_authopt_hash(
    char *hash_location,
    struct tcp_authopt_key_info *key,
    struct tcp_authopt_info *info,
    struct sock *sk, struct sk_buff *skb);
    +int tcp_v4_authopt_hash_reply(
    + char *hash_location,
    + struct tcp_authopt_info *info,
    + struct tcp_authopt_key_info *key,
    + __be32 saddr,
    + __be32 daddr,
    + struct tcphdr *th);
    int __tcp_authopt_openreq(struct sock *newsk, const struct sock *oldsk, struct request_sock *req);
    static inline int tcp_authopt_openreq(
    struct sock *newsk,
    const struct sock *oldsk,
    struct request_sock *req)
    diff --git a/net/ipv4/tcp_authopt.c b/net/ipv4/tcp_authopt.c
    index 2a216356d280..2af6265041b4 100644
    --- a/net/ipv4/tcp_authopt.c
    +++ b/net/ipv4/tcp_authopt.c
    @@ -944,10 +944,72 @@ static int tcp_authopt_get_traffic_key(struct sock *sk,
    out:
    tcp_authopt_put_kdf_pool(key, pool);
    return err;
    }

    +struct tcp_v4_authopt_context_data {
    + __be32 saddr;
    + __be32 daddr;
    + __be16 sport;
    + __be16 dport;
    + __be32 sisn;
    + __be32 disn;
    + __be16 digestbits;
    +} __packed;
    +
    +static int tcp_v4_authopt_get_traffic_key_noskb(struct tcp_authopt_key_info *key,
    + __be32 saddr,
    + __be32 daddr,
    + __be16 sport,
    + __be16 dport,
    + __be32 sisn,
    + __be32 disn,
    + u8 *traffic_key)
    +{
    + int err;
    + struct tcp_authopt_alg_pool *pool;
    + struct tcp_v4_authopt_context_data data;
    +
    + BUILD_BUG_ON(sizeof(data) != 22);
    +
    + pool = tcp_authopt_get_kdf_pool(key);
    + if (IS_ERR(pool))
    + return PTR_ERR(pool);
    +
    + err = tcp_authopt_setkey(pool, key);
    + if (err)
    + goto out;
    + err = crypto_ahash_init(pool->req);
    + if (err)
    + goto out;
    +
    + // RFC5926 section 3.1.1.1
    + // Separate to keep alignment semi-sane
    + err = crypto_ahash_buf(pool->req, "\x01TCP-AO", 7);
    + if (err)
    + return err;
    + data.saddr = saddr;
    + data.daddr = daddr;
    + data.sport = sport;
    + data.dport = dport;
    + data.sisn = sisn;
    + data.disn = disn;
    + data.digestbits = htons(crypto_ahash_digestsize(pool->tfm) * 8);
    +
    + err = crypto_ahash_buf(pool->req, (u8 *)&data, sizeof(data));
    + if (err)
    + goto out;
    + ahash_request_set_crypt(pool->req, NULL, traffic_key, 0);
    + err = crypto_ahash_final(pool->req);
    + if (err)
    + goto out;
    +
    +out:
    + tcp_authopt_put_kdf_pool(key, pool);
    + return err;
    +}
    +
    static int crypto_ahash_buf_zero(struct ahash_request *req, int len)
    {
    u8 zeros[TCP_AUTHOPT_MACLEN] = {0};
    int buflen, err;

    @@ -1214,10 +1276,92 @@ int tcp_authopt_hash(char *hash_location,
    return err;
    }
    EXPORT_SYMBOL(tcp_authopt_hash);

    /**
    + * tcp_v4_authopt_hash_reply - Hash tcp+ipv4 header without SKB
    + *
    + * @hash_location: output buffer
    + * @info: sending socket's tcp_authopt_info
    + * @key: signing key, from tcp_authopt_select_key.
    + * @saddr: source address
    + * @daddr: destination address
    + * @th: Pointer to TCP header and options
    + */
    +int tcp_v4_authopt_hash_reply(char *hash_location,
    + struct tcp_authopt_info *info,
    + struct tcp_authopt_key_info *key,
    + __be32 saddr,
    + __be32 daddr,
    + struct tcphdr *th)
    +{
    + struct tcp_authopt_alg_pool *pool;
    + u8 macbuf[TCP_AUTHOPT_MAXMACBUF];
    + u8 traffic_key[TCP_AUTHOPT_MAX_TRAFFIC_KEY_LEN];
    + __be32 sne = 0;
    + int err;
    +
    + /* Call special code path for computing traffic key without skb
    + * This can be called from tcp_v4_reqsk_send_ack so caching would be
    + * difficult here.
    + */
    + err = tcp_v4_authopt_get_traffic_key_noskb(key, saddr, daddr,
    + th->source, th->dest,
    + htonl(info->src_isn), htonl(info->dst_isn),
    + traffic_key);
    + if (err)
    + goto out_err_traffic_key;
    +
    + /* Init mac shash */
    + pool = tcp_authopt_get_mac_pool(key);
    + if (IS_ERR(pool))
    + return PTR_ERR(pool);
    + err = crypto_ahash_setkey(pool->tfm, traffic_key, key->alg->traffic_key_len);
    + if (err)
    + goto out_err;
    + err = crypto_ahash_init(pool->req);
    + if (err)
    + return err;
    +
    + err = crypto_ahash_buf(pool->req, (u8 *)&sne, 4);
    + if (err)
    + return err;
    +
    + err = tcp_authopt_hash_tcp4_pseudoheader(pool, saddr, daddr, th->doff * 4);
    + if (err)
    + return err;
    +
    + // TCP header with checksum set to zero. Caller ensures this.
    + if (WARN_ON_ONCE(th->check != 0))
    + goto out_err;
    + err = crypto_ahash_buf(pool->req, (u8 *)th, sizeof(*th));
    + if (err)
    + goto out_err;
    +
    + // TCP options
    + err = tcp_authopt_hash_opts(pool, th, (struct tcphdr_authopt *)(hash_location - 4),
    + !(key->flags & TCP_AUTHOPT_KEY_EXCLUDE_OPTS));
    + if (err)
    + goto out_err;
    +
    + ahash_request_set_crypt(pool->req, NULL, macbuf, 0);
    + err = crypto_ahash_final(pool->req);
    + if (err)
    + goto out_err;
    + memcpy(hash_location, macbuf, TCP_AUTHOPT_MACLEN);
    +
    + tcp_authopt_put_mac_pool(key, pool);
    + return 0;
    +
    +out_err:
    + tcp_authopt_put_mac_pool(key, pool);
    +out_err_traffic_key:
    + memset(hash_location, 0, TCP_AUTHOPT_MACLEN);
    + return err;
    +}
    +
    +/*
    * tcp_authopt_lookup_recv - lookup key for receive
    *
    * @sk: Receive socket
    * @skb: Packet, used to compare addr and iface
    * @net: Per-namespace information containing keys
    --
    2.25.1
    \
     
     \ /
      Last update: 2022-07-26 08:19    [W:4.089 / U:0.584 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site