root/sys/sys/ktls.h
/*-
 * SPDX-License-Identifier: BSD-2-Clause
 *
 * Copyright (c) 2014-2019 Netflix Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */
#ifndef _SYS_KTLS_H_
#define _SYS_KTLS_H_

#ifdef _KERNEL
#include <sys/mbuf.h>
#include <sys/_null.h>
#include <sys/refcount.h>
#include <sys/_task.h>

#include <machine/param.h>
#endif

struct tls_record_layer {
        uint8_t  tls_type;
        uint8_t  tls_vmajor;
        uint8_t  tls_vminor;
        uint16_t tls_length;
        uint8_t  tls_data[0];
} __attribute__ ((packed));

#define TLS_MAX_MSG_SIZE_V10_2  16384
#define TLS_MAX_PARAM_SIZE      1024    /* Max key/mac/iv in sockopt */
#define TLS_AEAD_GCM_LEN        4
#define TLS_1_3_GCM_IV_LEN      12
#define TLS_CHACHA20_IV_LEN     12
#define TLS_CBC_IMPLICIT_IV_LEN 16

/* Type values for the record layer */
#define TLS_RLTYPE_ALERT        21
#define TLS_RLTYPE_HANDSHAKE    22
#define TLS_RLTYPE_APP          23

/*
 * Nonce for GCM for TLS 1.2 per RFC 5288.
 */
struct tls_nonce_data {
        uint8_t fixed[TLS_AEAD_GCM_LEN];
        uint64_t seq;
} __packed; 

/*
 * AEAD additional data format for TLS 1.2 per RFC 5246.
 */
struct tls_aead_data {
        uint64_t seq;   /* In network order */
        uint8_t type;
        uint8_t tls_vmajor;
        uint8_t tls_vminor;
        uint16_t tls_length;    
} __packed;

/*
 * AEAD additional data format for TLS 1.3 per RFC 8446.
 */
struct tls_aead_data_13 {
        uint8_t type;
        uint8_t tls_vmajor;
        uint8_t tls_vminor;
        uint16_t tls_length;
} __packed;

/*
 * Stream Cipher MAC additional data input.  This does not match the
 * exact data on the wire (the sequence number is not placed on the
 * wire, and any explicit IV after the record header is not covered by
 * the MAC).
 */
struct tls_mac_data {
        uint64_t seq;
        uint8_t type;
        uint8_t tls_vmajor;
        uint8_t tls_vminor;
        uint16_t tls_length;    
} __packed;

#define TLS_MAJOR_VER_ONE       3
#define TLS_MINOR_VER_ZERO      1       /* 3, 1 */
#define TLS_MINOR_VER_ONE       2       /* 3, 2 */
#define TLS_MINOR_VER_TWO       3       /* 3, 3 */
#define TLS_MINOR_VER_THREE     4       /* 3, 4 */

/* For TCP_TXTLS_ENABLE and TCP_RXTLS_ENABLE. */
#ifdef _KERNEL
struct tls_enable_v0 {
        const uint8_t *cipher_key;
        const uint8_t *iv;              /* Implicit IV. */
        const uint8_t *auth_key;
        int     cipher_algorithm;       /* e.g. CRYPTO_AES_CBC */
        int     cipher_key_len;
        int     iv_len;
        int     auth_algorithm;         /* e.g. CRYPTO_SHA2_256_HMAC */
        int     auth_key_len;
        int     flags;
        uint8_t tls_vmajor;
        uint8_t tls_vminor;
};
#endif

struct tls_enable {
        const uint8_t *cipher_key;
        const uint8_t *iv;              /* Implicit IV. */
        const uint8_t *auth_key;
        int     cipher_algorithm;       /* e.g. CRYPTO_AES_CBC */
        int     cipher_key_len;
        int     iv_len;
        int     auth_algorithm;         /* e.g. CRYPTO_SHA2_256_HMAC */
        int     auth_key_len;
        int     flags;
        uint8_t tls_vmajor;
        uint8_t tls_vminor;
        uint8_t rec_seq[8];
};

/* Structure for TLS_GET_RECORD. */
struct tls_get_record {
        /* TLS record header. */
        uint8_t  tls_type;
        uint8_t  tls_vmajor;
        uint8_t  tls_vminor;
        uint16_t tls_length;
};

#define XKTLS_SESSION_IV_BUF_LEN        32
struct xktls_session_onedir {
        uint64_t gen;
        uint64_t rsrv1[8];
        uint32_t rsrv2[8];
        uint8_t iv[XKTLS_SESSION_IV_BUF_LEN];
        int     cipher_algorithm;
        int     auth_algorithm;
        uint16_t cipher_key_len;
        uint16_t iv_len;
        uint16_t auth_key_len;
        uint16_t max_frame_len;
        uint8_t tls_vmajor;
        uint8_t tls_vminor;
        uint8_t tls_hlen;
        uint8_t tls_tlen;
        uint8_t tls_bs;
        uint8_t flags;
        uint16_t drv_st_len;
        char ifnet[16]; /* IFNAMSIZ */
};

#ifdef _KERNEL

struct tls_session_params {
        uint8_t *cipher_key;
        uint8_t *auth_key;
        uint8_t iv[TLS_CBC_IMPLICIT_IV_LEN];
        int     cipher_algorithm;
        int     auth_algorithm;
        uint16_t cipher_key_len;
        uint16_t iv_len;
        uint16_t auth_key_len;
        uint16_t max_frame_len;
        uint8_t tls_vmajor;
        uint8_t tls_vminor;
        uint8_t tls_hlen;
        uint8_t tls_tlen;
        uint8_t tls_bs;
        uint8_t flags;
};

/* Used in APIs to request RX vs TX sessions. */
#define KTLS_TX         1
#define KTLS_RX         2

struct iovec;
struct ktls_ocf_encrypt_state;
struct ktls_ocf_session;
struct ktls_session;
struct m_snd_tag;
struct mbuf;
struct sockbuf;
struct socket;
struct sockopt;

struct ktls_session {
        struct ktls_ocf_session *ocf_session;
        struct m_snd_tag *snd_tag;
        struct tls_session_params params;
        u_int   wq_index;
        volatile u_int refcount;
        int mode;

        struct task reset_tag_task;
        struct task disable_ifnet_task;
        union {
                struct inpcb *inp;      /* Used by transmit tasks. */
                struct socket *so;      /* Used by receive task. */
        };
        struct ifnet *rx_ifp;
        u_short rx_vlan_id;
        bool reset_pending;
        bool tx;
        bool sync_dispatch;
        bool sequential_records;
        union {
                /* Only used for TLS 1.0. */
                uint64_t next_seqno;
                /* Needed by some ktls offload NICs */
                uint64_t initial_offload_seqno;
        };
        STAILQ_HEAD(, mbuf) pending_records;

        /* Used to destroy any kTLS session */
        struct task destroy_task;

        uint64_t gen;
} __aligned(CACHE_LINE_SIZE);

extern unsigned int ktls_ifnet_max_rexmit_pct;

void ktls_check_rx(struct sockbuf *sb);
void ktls_cleanup_tls_enable(struct tls_enable *tls);
int ktls_copyin_tls_enable(struct sockopt *sopt, struct tls_enable *tls);
void ktls_disable_ifnet(void *arg);
int ktls_enable_rx(struct socket *so, struct tls_enable *en);
int ktls_enable_tx(struct socket *so, struct tls_enable *en);
void ktls_enqueue(struct mbuf *m, struct socket *so, int page_count);
void ktls_enqueue_to_free(struct mbuf *m);
void ktls_destroy(struct ktls_session *tls);
void ktls_frame(struct mbuf *m, struct ktls_session *tls, int *enqueue_cnt,
    uint8_t record_type);
int ktls_get_rx_mode(struct socket *so, int *modep);
int ktls_get_tx_mode(struct socket *so, int *modep);
int ktls_get_rx_sequence(struct inpcb *inp, uint32_t *tcpseq, uint64_t *tlsseq);
void ktls_input_ifp_mismatch(struct sockbuf *sb, struct ifnet *ifp);
#ifdef RATELIMIT
int ktls_modify_txrtlmt(struct ktls_session *tls, uint64_t max_pacing_rate);
#endif
int ktls_output_eagain(struct inpcb *inp, struct ktls_session *tls);
bool ktls_pending_rx_info(struct sockbuf *sb, uint64_t *seqnop, size_t *residp);
bool ktls_permit_empty_frames(struct ktls_session *tls);
void ktls_seq(struct sockbuf *sb, struct mbuf *m);
int ktls_set_tx_mode(struct socket *so, int mode);

static inline struct ktls_session *
ktls_hold(struct ktls_session *tls)
{

        if (tls != NULL)
                refcount_acquire(&tls->refcount);
        return (tls);
}

static inline void
ktls_free(struct ktls_session *tls)
{

        if (refcount_release(&tls->refcount))
                ktls_destroy(tls);
}

static inline void
ktls_release_snd_tag(struct ktls_session *tls)
{
        struct m_snd_tag *mst;

        mst = tls->snd_tag;
        tls->snd_tag = NULL;
        if (mst != NULL)
                m_snd_tag_rele(mst);
}

void ktls_session_to_xktls_onedir(const struct ktls_session *ks,
    bool export_keys, struct xktls_session_onedir *xktls_od);
void ktls_session_copy_keys(const struct ktls_session *ktls,
    uint8_t *data, size_t *sz);

#endif /* !_KERNEL */
#endif /* !_SYS_KTLS_H_ */