1 /* ssl/dtls1.h */
2 /*
3  * DTLS implementation written by Nagendra Modadugu
4  * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
5  */
6 /* ====================================================================
7  * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  *   notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *   notice, this list of conditions and the following disclaimer in
18  *   the documentation and/or other materials provided with the
19  *   distribution.
20  *
21  * 3. All advertising materials mentioning features or use of this
22  *   software must display the following acknowledgment:
23  *   "This product includes software developed by the OpenSSL Project
24  *   for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25  *
26  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27  *   endorse or promote products derived from this software without
28  *   prior written permission. For written permission, please contact
29  *   openssl-core@OpenSSL.org.
30  *
31  * 5. Products derived from this software may not be called "OpenSSL"
32  *   nor may "OpenSSL" appear in their names without prior written
33  *   permission of the OpenSSL Project.
34  *
35  * 6. Redistributions of any form whatsoever must retain the following
36  *   acknowledgment:
37  *   "This product includes software developed by the OpenSSL Project
38  *   for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39  *
40  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51  * OF THE POSSIBILITY OF SUCH DAMAGE.
52  * ====================================================================
53  *
54  * This product includes cryptographic software written by Eric Young
55  * (eay@cryptsoft.com).  This product includes software written by Tim
56  * Hudson (tjh@cryptsoft.com).
57  *
58  */
59 
60 module deimos.openssl.dtls1;
61 
62 import deimos.openssl._d_util;
63 
64 import deimos.openssl.comp; // Needed for COMP_CTX.
65 import deimos.openssl.ssl; // Needed for SSL_SESSION.
66 import deimos.openssl.ssl3; // Needed for SSL3_BUFFER.
67 
68 public import deimos.openssl.buffer;
69 public import deimos.openssl.pqueue;
70 // #ifdef OPENSSL_SYS_VMS
71 // #include <resource.h>
72 // #include <sys/timeb.h>
73 // #endif
74 version (Windows) {
75 /* Needed for timeval */
76 static if (__VERSION__ >= 2070)
77 	import core.sys.windows.winsock2;
78 else
79 	import std.c.windows.winsock;
80 // #elif defined(OPENSSL_SYS_NETWARE) && !defined(_WINSOCK2API_)
81 // #include <sys/timeval.h>
82 // #else
83 // #if defined(OPENSSL_SYS_VXWORKS)
84 // #include <sys/times.h>
85 // #else
86 } else version (Win64) {
87 import core.sys.windows.winsock2;
88 } else {
89 import core.sys.posix.sys.time;
90 }
91 
92 extern (C):
93 nothrow:
94 
95 enum DTLS1_VERSION = 0xFEFF;
96 enum DTLS1_BAD_VER = 0x0100;
97 
98 version (none) {
99 /* this alert description is not specified anywhere... */
100 enum DTLS1_AD_MISSING_HANDSHAKE_MESSAGE = 110;
101 }
102 
103 /* lengths of messages */
104 enum DTLS1_COOKIE_LENGTH = 256;
105 
106 enum DTLS1_RT_HEADER_LENGTH = 13;
107 
108 enum DTLS1_HM_HEADER_LENGTH = 12;
109 
110 enum DTLS1_HM_BAD_FRAGMENT = -2;
111 enum DTLS1_HM_FRAGMENT_RETRY = -3;
112 
113 enum DTLS1_CCS_HEADER_LENGTH = 1;
114 
115 version (none) { // #ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
116 enum DTLS1_AL_HEADER_LENGTH = 7;
117 } else {
118 enum DTLS1_AL_HEADER_LENGTH = 2;
119 }
120 
121 version(OPENSSL_NO_SSL_INTERN) {} else {
122 
123 version(OPENSSL_NO_SCTP) {} else {
124     enum DTLS1_SCTP_AUTH_LABEL = "EXPORTER_DTLS_OVER_SCTP";
125 }
126 
127 struct dtls1_bitmap_st {
128 	c_ulong map;		/* track 32 packets on 32-bit systems
129 					   and 64 - on 64-bit systems */
130 	ubyte[8] max_seq_num;	/* max record number seen so far,
131 					   64-bit value in big-endian
132 					   encoding */
133 	}
134 alias dtls1_bitmap_st DTLS1_BITMAP;
135 
136 struct dtls1_retransmit_state
137 	{
138 	EVP_CIPHER_CTX* enc_write_ctx;	/* cryptographic state */
139 	EVP_MD_CTX* write_hash;			/* used for mac generation */
140 version(OPENSSL_NO_COMP) {
141 	char* compress;
142 } else {
143 	COMP_CTX* compress;				/* compression */
144 }
145 	SSL_SESSION* session;
146 	ushort epoch;
147 	};
148 
149 struct hm_header_st
150 	{
151 	ubyte type;
152 	c_ulong msg_len;
153 	ushort seq;
154 	c_ulong frag_off;
155 	c_ulong frag_len;
156 	uint is_ccs;
157 	dtls1_retransmit_state saved_retransmit_state;
158 	};
159 
160 struct ccs_header_st
161 	{
162 	ubyte type;
163 	ushort seq;
164 	};
165 
166 struct dtls1_timeout_st
167 	{
168 	/* Number of read timeouts so far */
169 	uint read_timeouts;
170 
171 	/* Number of write timeouts so far */
172 	uint write_timeouts;
173 
174 	/* Number of alerts received so far */
175 	uint num_alerts;
176 	};
177 
178 struct record_pqueue_st {
179 	ushort epoch;
180 	pqueue q;
181 	}
182 alias record_pqueue_st record_pqueue;
183 
184 struct hm_fragment_st {
185 	hm_header_st msg_header;
186 	ubyte* fragment;
187 	ubyte* reassembly;
188 	}
189 alias hm_fragment_st hm_fragment;
190 
191 struct dtls1_state_st {
192 	uint send_cookie;
193 	ubyte[DTLS1_COOKIE_LENGTH] cookie;
194 	ubyte[DTLS1_COOKIE_LENGTH] rcvd_cookie;
195 	uint cookie_len;
196 
197 	/*
198 	 * The current data and handshake epoch.  This is initially
199 	 * undefined, and starts at zero once the initial handshake is
200 	 * completed
201 	 */
202 	ushort r_epoch;
203 	ushort w_epoch;
204 
205 	/* records being received in the current epoch */
206 	DTLS1_BITMAP bitmap;
207 
208 	/* renegotiation starts a new set of sequence numbers */
209 	DTLS1_BITMAP next_bitmap;
210 
211 	/* handshake message numbers */
212 	ushort handshake_write_seq;
213 	ushort next_handshake_write_seq;
214 
215 	ushort handshake_read_seq;
216 
217 	/* save last sequence number for retransmissions */
218 	ubyte[8] last_write_sequence;
219 
220 	/* Received handshake records (processed and unprocessed) */
221 	record_pqueue unprocessed_rcds;
222 	record_pqueue processed_rcds;
223 
224 	/* Buffered handshake messages */
225 	pqueue buffered_messages;
226 
227 	/* Buffered (sent) handshake records */
228 	pqueue sent_messages;
229 
230 	/* Buffered application records.
231 	 * Only for records between CCS and Finished
232 	 * to prevent either protocol violation or
233 	 * unnecessary message loss.
234 	 */
235 	record_pqueue buffered_app_data;
236 
237 	/* Is set when listening for new connections with dtls1_listen() */
238 	uint listen;
239 
240 	uint mtu; /* max DTLS packet size */
241 
242 	hm_header_st w_msg_hdr;
243 	hm_header_st r_msg_hdr;
244 
245 	dtls1_timeout_st timeout;
246 
247 	/* Indicates when the last handshake msg or heartbeat sent will timeout */
248 	timeval next_timeout;
249 
250 	/* Timeout duration */
251 	ushort timeout_duration;
252 
253 	/* storage for Alert/Handshake protocol data received but not
254 	 * yet processed by ssl3_read_bytes: */
255 	ubyte[DTLS1_AL_HEADER_LENGTH] alert_fragment;
256 	uint alert_fragment_len;
257 	ubyte[DTLS1_HM_HEADER_LENGTH] handshake_fragment;
258 	uint handshake_fragment_len;
259 
260 	uint retransmitting;
261 	uint change_cipher_spec_ok;
262 
263 version(OPENSSL_NO_SCTP) {} else {
264 	/* used when SSL_ST_XX_FLUSH is entered */
265 	int next_state;
266 
267 	int shutdown_received;
268 }
269 
270 	}
271 alias dtls1_state_st DTLS1_STATE;
272 
273 struct dtls1_record_data_st {
274 	ubyte* packet;
275 	uint   packet_length;
276 	SSL3_BUFFER    rbuf;
277 	SSL3_RECORD    rrec;
278     version(OPENSSL_NO_SCTP) {} else {
279 	bio_dgram_sctp_rcvinfo recordinfo;
280     }
281 	}
282 alias dtls1_record_data_st DTLS1_RECORD_DATA;
283 
284 }
285 
286 /* Timeout multipliers (timeout slice is defined in apps/timeouts.h */
287 enum DTLS1_TMO_READ_COUNT = 2;
288 enum DTLS1_TMO_WRITE_COUNT = 2;
289 
290 enum DTLS1_TMO_ALERT_COUNT = 12;