messages.h (3395B)
1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. 4 */ 5 6#ifndef _WG_MESSAGES_H 7#define _WG_MESSAGES_H 8 9#include <crypto/curve25519.h> 10#include <crypto/chacha20poly1305.h> 11#include <crypto/blake2s.h> 12 13#include <linux/kernel.h> 14#include <linux/param.h> 15#include <linux/skbuff.h> 16 17enum noise_lengths { 18 NOISE_PUBLIC_KEY_LEN = CURVE25519_KEY_SIZE, 19 NOISE_SYMMETRIC_KEY_LEN = CHACHA20POLY1305_KEY_SIZE, 20 NOISE_TIMESTAMP_LEN = sizeof(u64) + sizeof(u32), 21 NOISE_AUTHTAG_LEN = CHACHA20POLY1305_AUTHTAG_SIZE, 22 NOISE_HASH_LEN = BLAKE2S_HASH_SIZE 23}; 24 25#define noise_encrypted_len(plain_len) ((plain_len) + NOISE_AUTHTAG_LEN) 26 27enum cookie_values { 28 COOKIE_SECRET_MAX_AGE = 2 * 60, 29 COOKIE_SECRET_LATENCY = 5, 30 COOKIE_NONCE_LEN = XCHACHA20POLY1305_NONCE_SIZE, 31 COOKIE_LEN = 16 32}; 33 34enum counter_values { 35 COUNTER_BITS_TOTAL = 8192, 36 COUNTER_REDUNDANT_BITS = BITS_PER_LONG, 37 COUNTER_WINDOW_SIZE = COUNTER_BITS_TOTAL - COUNTER_REDUNDANT_BITS 38}; 39 40enum limits { 41 REKEY_AFTER_MESSAGES = 1ULL << 60, 42 REJECT_AFTER_MESSAGES = U64_MAX - COUNTER_WINDOW_SIZE - 1, 43 REKEY_TIMEOUT = 5, 44 REKEY_TIMEOUT_JITTER_MAX_JIFFIES = HZ / 3, 45 REKEY_AFTER_TIME = 120, 46 REJECT_AFTER_TIME = 180, 47 INITIATIONS_PER_SECOND = 50, 48 MAX_PEERS_PER_DEVICE = 1U << 20, 49 KEEPALIVE_TIMEOUT = 10, 50 MAX_TIMER_HANDSHAKES = 90 / REKEY_TIMEOUT, 51 MAX_QUEUED_INCOMING_HANDSHAKES = 4096, /* TODO: replace this with DQL */ 52 MAX_STAGED_PACKETS = 128, 53 MAX_QUEUED_PACKETS = 1024 /* TODO: replace this with DQL */ 54}; 55 56enum message_type { 57 MESSAGE_INVALID = 0, 58 MESSAGE_HANDSHAKE_INITIATION = 1, 59 MESSAGE_HANDSHAKE_RESPONSE = 2, 60 MESSAGE_HANDSHAKE_COOKIE = 3, 61 MESSAGE_DATA = 4 62}; 63 64struct message_header { 65 /* The actual layout of this that we want is: 66 * u8 type 67 * u8 reserved_zero[3] 68 * 69 * But it turns out that by encoding this as little endian, 70 * we achieve the same thing, and it makes checking faster. 71 */ 72 __le32 type; 73}; 74 75struct message_macs { 76 u8 mac1[COOKIE_LEN]; 77 u8 mac2[COOKIE_LEN]; 78}; 79 80struct message_handshake_initiation { 81 struct message_header header; 82 __le32 sender_index; 83 u8 unencrypted_ephemeral[NOISE_PUBLIC_KEY_LEN]; 84 u8 encrypted_static[noise_encrypted_len(NOISE_PUBLIC_KEY_LEN)]; 85 u8 encrypted_timestamp[noise_encrypted_len(NOISE_TIMESTAMP_LEN)]; 86 struct message_macs macs; 87}; 88 89struct message_handshake_response { 90 struct message_header header; 91 __le32 sender_index; 92 __le32 receiver_index; 93 u8 unencrypted_ephemeral[NOISE_PUBLIC_KEY_LEN]; 94 u8 encrypted_nothing[noise_encrypted_len(0)]; 95 struct message_macs macs; 96}; 97 98struct message_handshake_cookie { 99 struct message_header header; 100 __le32 receiver_index; 101 u8 nonce[COOKIE_NONCE_LEN]; 102 u8 encrypted_cookie[noise_encrypted_len(COOKIE_LEN)]; 103}; 104 105struct message_data { 106 struct message_header header; 107 __le32 key_idx; 108 __le64 counter; 109 u8 encrypted_data[]; 110}; 111 112#define message_data_len(plain_len) \ 113 (noise_encrypted_len(plain_len) + sizeof(struct message_data)) 114 115enum message_alignments { 116 MESSAGE_PADDING_MULTIPLE = 16, 117 MESSAGE_MINIMUM_LENGTH = message_data_len(0) 118}; 119 120#define SKB_HEADER_LEN \ 121 (max(sizeof(struct iphdr), sizeof(struct ipv6hdr)) + \ 122 sizeof(struct udphdr) + NET_SKB_PAD) 123#define DATA_PACKET_HEAD_ROOM \ 124 ALIGN(sizeof(struct message_data) + SKB_HEADER_LEN, 4) 125 126enum { HANDSHAKE_DSCP = 0x88 /* AF41, plus 00 ECN */ }; 127 128#endif /* _WG_MESSAGES_H */