diff options
author | Dave Watson <davejwatson@fb.com> | 2019-01-30 21:58:31 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-02-01 15:00:55 -0800 |
commit | 130b392c6cd6b2aed1b7eb32253d4920babb4891 (patch) | |
tree | 99a8b337cdf5fcb3f23374b3100ed8e3ea295e19 /include | |
parent | fedf201e12960bd2fab0596422851b20a8d80d20 (diff) | |
download | linux-130b392c6cd6b2aed1b7eb32253d4920babb4891.tar.bz2 |
net: tls: Add tls 1.3 support
TLS 1.3 has minor changes from TLS 1.2 at the record layer.
* Header now hardcodes the same version and application content type in
the header.
* The real content type is appended after the data, before encryption (or
after decryption).
* The IV is xored with the sequence number, instead of concatinating four
bytes of IV with the explicit IV.
* Zero-padding: No exlicit length is given, we search backwards from the
end of the decrypted data for the first non-zero byte, which is the
content type. Currently recv supports reading zero-padding, but there
is no way for send to add zero padding.
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
-rw-r--r-- | include/net/tls.h | 66 | ||||
-rw-r--r-- | include/uapi/linux/tls.h | 4 |
2 files changed, 53 insertions, 17 deletions
diff --git a/include/net/tls.h b/include/net/tls.h index 754b130672f0..004bf01ce868 100644 --- a/include/net/tls.h +++ b/include/net/tls.h @@ -119,6 +119,9 @@ struct tls_rec { /* AAD | msg_encrypted.sg.data (data contains overhead for hdr & iv & tag) */ struct scatterlist sg_aead_out[2]; + char content_type; + struct scatterlist sg_content_type; + char aad_space[TLS_AAD_SPACE_SIZE]; u8 iv_data[TLS_CIPHER_AES_GCM_128_IV_SIZE + TLS_CIPHER_AES_GCM_128_SALT_SIZE]; @@ -203,6 +206,7 @@ struct cipher_context { u16 rec_seq_size; char *rec_seq; u16 aad_size; + u16 tail_size; }; union tls_crypto_context { @@ -397,49 +401,77 @@ static inline bool tls_bigint_increment(unsigned char *seq, int len) } static inline void tls_advance_record_sn(struct sock *sk, - struct cipher_context *ctx) + struct cipher_context *ctx, + int version) { if (tls_bigint_increment(ctx->rec_seq, ctx->rec_seq_size)) tls_err_abort(sk, EBADMSG); - tls_bigint_increment(ctx->iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE, - ctx->iv_size); + + if (version != TLS_1_3_VERSION) { + tls_bigint_increment(ctx->iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE, + ctx->iv_size); + } } static inline void tls_fill_prepend(struct tls_context *ctx, char *buf, size_t plaintext_len, - unsigned char record_type) + unsigned char record_type, + int version) { size_t pkt_len, iv_size = ctx->tx.iv_size; - pkt_len = plaintext_len + iv_size + ctx->tx.tag_size; + pkt_len = plaintext_len + ctx->tx.tag_size; + if (version != TLS_1_3_VERSION) { + pkt_len += iv_size; + + memcpy(buf + TLS_NONCE_OFFSET, + ctx->tx.iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE, iv_size); + } /* we cover nonce explicit here as well, so buf should be of * size KTLS_DTLS_HEADER_SIZE + KTLS_DTLS_NONCE_EXPLICIT_SIZE */ - buf[0] = record_type; - buf[1] = TLS_VERSION_MINOR(ctx->crypto_send.info.version); - buf[2] = TLS_VERSION_MAJOR(ctx->crypto_send.info.version); + buf[0] = version == TLS_1_3_VERSION ? + TLS_RECORD_TYPE_DATA : record_type; + /* Note that VERSION must be TLS_1_2 for both TLS1.2 and TLS1.3 */ + buf[1] = TLS_1_2_VERSION_MINOR; + buf[2] = TLS_1_2_VERSION_MAJOR; /* we can use IV for nonce explicit according to spec */ buf[3] = pkt_len >> 8; buf[4] = pkt_len & 0xFF; - memcpy(buf + TLS_NONCE_OFFSET, - ctx->tx.iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE, iv_size); } static inline void tls_make_aad(char *buf, size_t size, char *record_sequence, int record_sequence_size, - unsigned char record_type) + unsigned char record_type, + int version) +{ + if (version != TLS_1_3_VERSION) { + memcpy(buf, record_sequence, record_sequence_size); + buf += 8; + } else { + size += TLS_CIPHER_AES_GCM_128_TAG_SIZE; + } + + buf[0] = version == TLS_1_3_VERSION ? + TLS_RECORD_TYPE_DATA : record_type; + buf[1] = TLS_1_2_VERSION_MAJOR; + buf[2] = TLS_1_2_VERSION_MINOR; + buf[3] = size >> 8; + buf[4] = size & 0xFF; +} + +static inline void xor_iv_with_seq(int version, char *iv, char *seq) { - memcpy(buf, record_sequence, record_sequence_size); + int i; - buf[8] = record_type; - buf[9] = TLS_1_2_VERSION_MAJOR; - buf[10] = TLS_1_2_VERSION_MINOR; - buf[11] = size >> 8; - buf[12] = size & 0xFF; + if (version == TLS_1_3_VERSION) { + for (i = 0; i < 8; i++) + iv[i + 4] ^= seq[i]; + } } static inline struct tls_context *tls_get_ctx(const struct sock *sk) diff --git a/include/uapi/linux/tls.h b/include/uapi/linux/tls.h index 9affceaa3db4..401d6f01de6a 100644 --- a/include/uapi/linux/tls.h +++ b/include/uapi/linux/tls.h @@ -51,6 +51,10 @@ #define TLS_1_2_VERSION_MINOR 0x3 #define TLS_1_2_VERSION TLS_VERSION_NUMBER(TLS_1_2) +#define TLS_1_3_VERSION_MAJOR 0x3 +#define TLS_1_3_VERSION_MINOR 0x4 +#define TLS_1_3_VERSION TLS_VERSION_NUMBER(TLS_1_3) + /* Supported ciphers */ #define TLS_CIPHER_AES_GCM_128 51 #define TLS_CIPHER_AES_GCM_128_IV_SIZE 8 |