Commit | Line | Data |
---|---|---|
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 | ||
62efe6ec MD |
41 | /*************************************************************************** |
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 | */ | |
72 | struct 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 | ||
85 | typedef 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 | |
9ab15106 MD |
103 | /*************************************************************************** |
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 |
119 | struct hammer2_iocom; |
120 | struct hammer2_persist; | |
8c280d5d | 121 | struct hammer2_state; |
90e8cd1d | 122 | struct hammer2_router; |
8c280d5d | 123 | struct hammer2_msg; |
4a2e0eae | 124 | |
8c280d5d | 125 | TAILQ_HEAD(hammer2_state_queue, hammer2_state); |
78476205 MD |
126 | TAILQ_HEAD(hammer2_msg_queue, hammer2_msg); |
127 | RB_HEAD(hammer2_state_tree, hammer2_state); | |
90e8cd1d | 128 | RB_HEAD(hammer2_router_tree, hammer2_router); |
78476205 | 129 | |
8c280d5d | 130 | struct h2span_link; |
90e8cd1d | 131 | struct h2span_relay; |
8c280d5d MD |
132 | struct h2span_connect; |
133 | ||
78476205 MD |
134 | struct 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; | |
148 | struct h2span_connect *conn; | |
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 |
157 | struct 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 | ||
167 | typedef struct hammer2_state hammer2_state_t; | |
168 | typedef struct hammer2_msg hammer2_msg_t; | |
9ab15106 MD |
169 | typedef struct hammer2_msg_queue hammer2_msg_queue_t; |
170 | ||
78476205 MD |
171 | int hammer2_state_cmp(hammer2_state_t *state1, hammer2_state_t *state2); |
172 | RB_PROTOTYPE(hammer2_state_tree, hammer2_state, rbnode, hammer2_state_cmp); | |
9ab15106 MD |
173 | |
174 | /* | |
175 | * hammer2_ioq - An embedded component of hammer2_connect, holds state | |
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 | */ |
181 | struct 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 | ||
203 | typedef 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 | ||
29ead430 MD |
228 | /* |
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 | */ |
236 | struct 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 |
255 | typedef struct hammer2_router hammer2_router_t; |
256 | ||
90e8cd1d MD |
257 | int hammer2_router_cmp(hammer2_router_t *router1, hammer2_router_t *router2); |
258 | RB_PROTOTYPE(hammer2_router_tree, hammer2_router, rbnode, hammer2_router_cmp); | |
259 | ||
9ab15106 MD |
260 | /* |
261 | * hammer2_iocom - governs a messaging stream connection | |
262 | */ | |
263 | struct 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 | ||
278 | typedef 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 | ||
295 | typedef int (*algo_init_fn)(hammer2_ioq_t *, char *, int, char *, int, int); | |
296 | typedef int (*algo_enc_fn)(hammer2_ioq_t *, char *, char *, int, int *); | |
297 | typedef int (*algo_dec_fn)(hammer2_ioq_t *, char *, char *, int, int *); | |
298 | ||
299 | struct 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 | }; |