hammer2 - Add peer_type field to LNK_CONN and LNK_SPAN
[dragonfly.git] / sbin / hammer2 / network.h
CommitLineData
9ab15106
MD
1/*
2 * Copyright (c) 2011-2012 The DragonFly Project. All rights reserved.
3 *
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@dragonflybsd.org>
6 * by Venkatesh Srinivas <vsrinivas@dragonflybsd.org>
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * 3. Neither the name of The DragonFly Project nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific, prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
5cf97ec5
MD
36#include <openssl/rsa.h> /* public/private key functions */
37#include <openssl/pem.h> /* public/private key file load */
38#include <openssl/err.h>
39#include <openssl/evp.h> /* aes_256_cbc functions */
40
9ab15106 41/***************************************************************************
62efe6ec
MD
42 * CRYPTO HANDSHAKE *
43 ***************************************************************************
44 *
45 * The initial public-key exchange is implementing by transmitting a
46 * 512-byte buffer to the other side in a symmetrical fashion. This
47 * buffer contains the following:
48 *
5cf97ec5
MD
49 * (1) A random session key. 512 bits is specified. We use aes_256_cbc()
50 * and initialize the key with the first 256 bits and the iv[] with
51 * the second. Note that the transmitted and received session
52 * keys are XOR'd together to create the session key used for
53 * communications (so even if the verifier is compromised the session
54 * will still be gobbly gook if the public key has not been completely
55 * broken).
62efe6ec
MD
56 *
57 * (2) A verifier to determine that the decode was successful. It encodes
58 * an XOR of each group of 4 bytes from the session key.
59 *
60 * (3) Additional configuration and additional random data.
61 *
62 * - The hammer2 message header magic for endian detect
63 *
64 * - The hammer2 protocol version. The two sides agree on the
65 * smaller of the two.
66 *
67 * - All unused fields (junk*) are filled with random data.
68 *
69 * This structure must be exactly 512 bytes and expects to use 256-byte
70 * RSA keys.
71 */
72struct hammer2_handshake {
73 char pad1[8]; /* 000 */
74 uint16_t magic; /* 008 HAMMER2_MSGHDR_MAGIC for endian detect */
75 uint16_t version; /* 00A hammer2 protocol version */
76 uint32_t flags; /* 00C protocol extension flags */
77 uint8_t sess[64]; /* 010 512-bit session key */
78 uint8_t verf[16]; /* 050 verifier = ~sess */
79 char quickmsg[32]; /* 060 reason for connecting */
80 char junk080[128]; /* 080-0FF */
81 char pad2[8]; /* 100-107 */
82 char junk100[256-8]; /* 108-1FF */
83};
84
85typedef struct hammer2_handshake hammer2_handshake_t;
86
487b3235
AH
87
88#define HAMMER2_CRYPTO_CHUNK_SIZE HAMMER2_MSG_ALIGN
89#define HAMMER2_MAX_IV_SIZE 32
90
91#define HAMMER2_CRYPTO_GCM_IV_FIXED_SIZE 4
92#define HAMMER2_CRYPTO_GCM_IV_SIZE 12
93#define HAMMER2_CRYPTO_GCM_KEY_SIZE 32
94#define HAMMER2_CRYPTO_GCM_TAG_SIZE 16
95
96#define HAMMER2_CRYPTO_ALGO_GCM_IDX 0
97
98#define HAMMER2_CRYPTO_ALGO HAMMER2_CRYPTO_ALGO_GCM_IDX
99
100
101
5cf97ec5 102
62efe6ec 103/***************************************************************************
9ab15106
MD
104 * LOW LEVEL MESSAGING *
105 ***************************************************************************
106 *
107 * hammer2_msg - A standalone copy of a message, typically referenced by
108 * or embedded in other structures, or used with I/O queues.
109 *
110 * These structures are strictly temporary, so they do not have to be
111 * particularly optimized for size. All possible message headers are
112 * directly embedded (any), and the message may contain a reference
113 * to allocated auxillary data. The structure is recycled quite often
114 * by a connection.
115 *
116 * This structure is typically not used for storing persistent message
4a2e0eae 117 * state (see hammer2_persist for that).
9ab15106 118 */
4a2e0eae
MD
119struct hammer2_iocom;
120struct hammer2_persist;
8c280d5d 121struct hammer2_state;
90e8cd1d 122struct hammer2_router;
8c280d5d 123struct hammer2_msg;
4a2e0eae 124
8c280d5d 125TAILQ_HEAD(hammer2_state_queue, hammer2_state);
78476205
MD
126TAILQ_HEAD(hammer2_msg_queue, hammer2_msg);
127RB_HEAD(hammer2_state_tree, hammer2_state);
90e8cd1d 128RB_HEAD(hammer2_router_tree, hammer2_router);
78476205 129
8c280d5d 130struct h2span_link;
90e8cd1d 131struct h2span_relay;
2063f4d7 132struct h2span_conn;
8c280d5d 133
78476205
MD
134struct hammer2_state {
135 RB_ENTRY(hammer2_state) rbnode; /* indexed by msgid */
4a2e0eae 136 struct hammer2_iocom *iocom;
10c86c4e 137 struct hammer2_router *router; /* if routed */
78476205
MD
138 uint32_t txcmd; /* mostly for CMDF flags */
139 uint32_t rxcmd; /* mostly for CMDF flags */
8c280d5d 140 uint64_t msgid; /* {spanid,msgid} uniq */
9ab15106 141 int flags;
78476205
MD
142 int error;
143 struct hammer2_msg *msg;
29ead430 144 void (*func)(struct hammer2_msg *);
8c280d5d
MD
145 union {
146 void *any;
147 struct h2span_link *link;
2063f4d7 148 struct h2span_conn *conn;
8c280d5d
MD
149 struct h2span_relay *relay;
150 } any;
151};
152
78476205
MD
153#define HAMMER2_STATE_INSERTED 0x0001
154#define HAMMER2_STATE_DYNAMIC 0x0002
8c280d5d 155#define HAMMER2_STATE_NODEID 0x0004 /* manages a node id */
9ab15106 156
78476205
MD
157struct hammer2_msg {
158 TAILQ_ENTRY(hammer2_msg) qentry;
29ead430 159 struct hammer2_router *router;
78476205
MD
160 struct hammer2_state *state;
161 size_t hdr_size;
162 size_t aux_size;
163 char *aux_data;
1b195a98 164 hammer2_msg_any_t any;
78476205
MD
165};
166
167typedef struct hammer2_state hammer2_state_t;
168typedef struct hammer2_msg hammer2_msg_t;
9ab15106
MD
169typedef struct hammer2_msg_queue hammer2_msg_queue_t;
170
78476205
MD
171int hammer2_state_cmp(hammer2_state_t *state1, hammer2_state_t *state2);
172RB_PROTOTYPE(hammer2_state_tree, hammer2_state, rbnode, hammer2_state_cmp);
9ab15106
MD
173
174/*
2063f4d7 175 * hammer2_ioq - An embedded component of hammer2_conn, holds state
9ab15106 176 * for the buffering and parsing of incoming and outgoing messages.
3033ecc8
MD
177 *
178 * cdx - beg - processed buffer data, encrypted or decrypted
179 * end - cdn - unprocessed buffer data not yet encrypted or decrypted
9ab15106
MD
180 */
181struct hammer2_ioq {
182 enum { HAMMER2_MSGQ_STATE_HEADER1,
183 HAMMER2_MSGQ_STATE_HEADER2,
184 HAMMER2_MSGQ_STATE_AUXDATA1,
185 HAMMER2_MSGQ_STATE_AUXDATA2,
186 HAMMER2_MSGQ_STATE_ERROR } state;
3033ecc8
MD
187 size_t fifo_beg; /* buffered data */
188 size_t fifo_cdx; /* cdx-beg processed */
189 size_t fifo_cdn; /* end-cdn unprocessed */
190 size_t fifo_end;
78476205
MD
191 size_t hbytes; /* header size */
192 size_t abytes; /* aux_data size */
9ab15106
MD
193 int error;
194 int seq; /* salt sequencer */
195 int msgcount;
5cf97ec5 196 EVP_CIPHER_CTX ctx;
487b3235 197 char iv[HAMMER2_MAX_IV_SIZE]; /* encrypt or decrypt iv[] */
9ab15106
MD
198 hammer2_msg_t *msg;
199 hammer2_msg_queue_t msgq;
5cf97ec5 200 char buf[HAMMER2_MSGBUF_SIZE]; /* staging buffer */
9ab15106
MD
201};
202
203typedef struct hammer2_ioq hammer2_ioq_t;
204
62efe6ec
MD
205#define HAMMER2_IOQ_ERROR_SYNC 1 /* bad magic / out of sync */
206#define HAMMER2_IOQ_ERROR_EOF 2 /* unexpected EOF */
207#define HAMMER2_IOQ_ERROR_SOCK 3 /* read() error on socket */
208#define HAMMER2_IOQ_ERROR_FIELD 4 /* invalid field */
209#define HAMMER2_IOQ_ERROR_HCRC 5 /* core header crc bad */
210#define HAMMER2_IOQ_ERROR_XCRC 6 /* ext header crc bad */
211#define HAMMER2_IOQ_ERROR_ACRC 7 /* aux data crc bad */
212#define HAMMER2_IOQ_ERROR_STATE 8 /* bad state */
213#define HAMMER2_IOQ_ERROR_NOPEER 9 /* bad socket peer */
214#define HAMMER2_IOQ_ERROR_NORKEY 10 /* no remote keyfile found */
215#define HAMMER2_IOQ_ERROR_NOLKEY 11 /* no local keyfile found */
216#define HAMMER2_IOQ_ERROR_KEYXCHGFAIL 12 /* key exchange failed */
217#define HAMMER2_IOQ_ERROR_KEYFMT 13 /* key file format problem */
218#define HAMMER2_IOQ_ERROR_BADURANDOM 14 /* /dev/urandom is bad */
5cf97ec5 219#define HAMMER2_IOQ_ERROR_MSGSEQ 15 /* message sequence error */
78476205
MD
220#define HAMMER2_IOQ_ERROR_EALREADY 16 /* ignore this message */
221#define HAMMER2_IOQ_ERROR_TRANS 17 /* state transaction issue */
fd1d02a5
AH
222#define HAMMER2_IOQ_ERROR_IVWRAP 18 /* IVs exhaused */
223#define HAMMER2_IOQ_ERROR_MACFAIL 19 /* MAC of encryption algorithm failed */
224#define HAMMER2_IOQ_ERROR_ALGO 20 /* Misc. encryption algorithm error */
9ab15106
MD
225
226#define HAMMER2_IOQ_MAXIOVEC 16
227
228/*
29ead430
MD
229 * hammer2_router - governs the routing of a message. Passed into
230 * hammer2_msg_write.
231 *
232 * The router is either connected to an iocom (socket) directly, or
90e8cd1d
MD
233 * connected to a SPAN transaction (h2span_link structure for outgoing)
234 * or to a SPAN transaction (h2span_relay structure for incoming).
29ead430
MD
235 */
236struct hammer2_router {
10c86c4e 237 RB_ENTRY(hammer2_router) rbnode; /* indexed by target */
29ead430 238 struct hammer2_iocom *iocom;
90e8cd1d
MD
239 struct h2span_link *link; /* may be NULL */
240 struct h2span_relay *relay; /* may be NULL */
29ead430
MD
241 void (*signal_callback)(struct hammer2_router *);
242 void (*rcvmsg_callback)(struct hammer2_msg *);
243 void (*altmsg_callback)(struct hammer2_iocom *);
244 struct hammer2_state_tree staterd_tree; /* active messages */
245 struct hammer2_state_tree statewr_tree; /* active messages */
246 hammer2_msg_queue_t txmsgq; /* tx msgq from remote */
10c86c4e 247 uint64_t target; /* for routing */
1a34728c
MD
248 int flags;
249 int refs; /* refs prevent destruction */
29ead430
MD
250};
251
90e8cd1d
MD
252#define HAMMER2_ROUTER_CONNECTED 0x0001 /* on global RB tree */
253#define HAMMER2_ROUTER_DELETED 0x0002 /* parent structure destroyed */
254
29ead430
MD
255typedef struct hammer2_router hammer2_router_t;
256
90e8cd1d
MD
257int hammer2_router_cmp(hammer2_router_t *router1, hammer2_router_t *router2);
258RB_PROTOTYPE(hammer2_router_tree, hammer2_router, rbnode, hammer2_router_cmp);
259
29ead430 260/*
9ab15106
MD
261 * hammer2_iocom - governs a messaging stream connection
262 */
263struct hammer2_iocom {
264 hammer2_ioq_t ioq_rx;
265 hammer2_ioq_t ioq_tx;
266 hammer2_msg_queue_t freeq; /* free msgs hdr only */
267 hammer2_msg_queue_t freeq_aux; /* free msgs w/aux_data */
9ab15106
MD
268 int sock_fd; /* comm socket or pipe */
269 int alt_fd; /* thread signal, tty, etc */
7dc0f844 270 int wakeupfds[2]; /* pipe wakes up iocom thread */
9ab15106 271 int flags;
62efe6ec
MD
272 int rxmisc;
273 int txmisc;
90e8cd1d 274 struct hammer2_router *router;
7dc0f844 275 pthread_mutex_t mtx; /* mutex for state*tree/rmsgq */
9ab15106
MD
276};
277
278typedef struct hammer2_iocom hammer2_iocom_t;
279
280#define HAMMER2_IOCOMF_EOF 0x00000001 /* EOF or ERROR on desc */
281#define HAMMER2_IOCOMF_RREQ 0x00000002 /* request read-data event */
282#define HAMMER2_IOCOMF_WREQ 0x00000004 /* request write-avail event */
7dc0f844
MD
283#define HAMMER2_IOCOMF_RWORK 0x00000008 /* immediate work pending */
284#define HAMMER2_IOCOMF_WWORK 0x00000010 /* immediate work pending */
285#define HAMMER2_IOCOMF_PWORK 0x00000020 /* immediate work pending */
286#define HAMMER2_IOCOMF_ARWORK 0x00000040 /* immediate work pending */
287#define HAMMER2_IOCOMF_AWWORK 0x00000080 /* immediate work pending */
5903497c
MD
288#define HAMMER2_IOCOMF_SWORK 0x00000100 /* immediate work pending */
289#define HAMMER2_IOCOMF_CRYPTED 0x00000200 /* encrypt enabled */
487b3235 290
487b3235
AH
291/*
292 * Crypto algorithm table and related typedefs.
293 */
294
295typedef int (*algo_init_fn)(hammer2_ioq_t *, char *, int, char *, int, int);
296typedef int (*algo_enc_fn)(hammer2_ioq_t *, char *, char *, int, int *);
297typedef int (*algo_dec_fn)(hammer2_ioq_t *, char *, char *, int, int *);
298
299struct crypto_algo {
300 const char *name;
301 int keylen;
302 int taglen;
303 algo_init_fn init;
304 algo_enc_fn enc_chunk;
305 algo_dec_fn dec_chunk;
306};