1 |
diff -up openssl-fips-0.9.8f-dev/ssl/dtls1.h.dtls-fixes openssl-fips-0.9.8f-dev/ssl/dtls1.h |
2 |
--- openssl-fips-0.9.8f-dev/ssl/dtls1.h.dtls-fixes 2008-07-15 21:01:29.000000000 +0200 |
3 |
+++ openssl-fips-0.9.8f-dev/ssl/dtls1.h 2008-07-15 21:01:29.000000000 +0200 |
4 |
@@ -67,9 +67,8 @@ |
5 |
extern "C" { |
6 |
#endif |
7 |
|
8 |
-#define DTLS1_VERSION 0x0100 |
9 |
-#define DTLS1_VERSION_MAJOR 0x01 |
10 |
-#define DTLS1_VERSION_MINOR 0x00 |
11 |
+#define DTLS1_VERSION 0xFEFF |
12 |
+#define DTLS1_BAD_VER 0x0100 |
13 |
|
14 |
#define DTLS1_AD_MISSING_HANDSHAKE_MESSAGE 110 |
15 |
|
16 |
@@ -83,7 +82,7 @@ extern "C" { |
17 |
#define DTLS1_HM_BAD_FRAGMENT -2 |
18 |
#define DTLS1_HM_FRAGMENT_RETRY -3 |
19 |
|
20 |
-#define DTLS1_CCS_HEADER_LENGTH 3 |
21 |
+#define DTLS1_CCS_HEADER_LENGTH 1 |
22 |
|
23 |
#define DTLS1_AL_HEADER_LENGTH 7 |
24 |
|
25 |
diff -up openssl-fips-0.9.8f-dev/ssl/d1_lib.c.dtls-fixes openssl-fips-0.9.8f-dev/ssl/d1_lib.c |
26 |
--- openssl-fips-0.9.8f-dev/ssl/d1_lib.c.dtls-fixes 2007-01-21 17:07:25.000000000 +0100 |
27 |
+++ openssl-fips-0.9.8f-dev/ssl/d1_lib.c 2008-07-15 21:01:29.000000000 +0200 |
28 |
@@ -188,3 +188,23 @@ void dtls1_clear(SSL *s) |
29 |
ssl3_clear(s); |
30 |
s->version=DTLS1_VERSION; |
31 |
} |
32 |
+ |
33 |
+/* |
34 |
+ * As it's impossible to use stream ciphers in "datagram" mode, this |
35 |
+ * simple filter is designed to disengage them in DTLS. Unfortunately |
36 |
+ * there is no universal way to identify stream SSL_CIPHER, so we have |
37 |
+ * to explicitly list their SSL_* codes. Currently RC4 is the only one |
38 |
+ * available, but if new ones emerge, they will have to be added... |
39 |
+ */ |
40 |
+SSL_CIPHER *dtls1_get_cipher(unsigned int u) |
41 |
+ { |
42 |
+ SSL_CIPHER *ciph = ssl3_get_cipher(u); |
43 |
+ |
44 |
+ if (ciph != NULL) |
45 |
+ { |
46 |
+ if ((ciph->algorithms&SSL_ENC_MASK) == SSL_RC4) |
47 |
+ return NULL; |
48 |
+ } |
49 |
+ |
50 |
+ return ciph; |
51 |
+ } |
52 |
diff -up openssl-fips-0.9.8f-dev/ssl/d1_srvr.c.dtls-fixes openssl-fips-0.9.8f-dev/ssl/d1_srvr.c |
53 |
--- openssl-fips-0.9.8f-dev/ssl/d1_srvr.c.dtls-fixes 2007-09-19 02:02:49.000000000 +0200 |
54 |
+++ openssl-fips-0.9.8f-dev/ssl/d1_srvr.c 2008-07-15 21:01:29.000000000 +0200 |
55 |
@@ -285,6 +285,10 @@ int dtls1_accept(SSL *s) |
56 |
s->d1->send_cookie = 0; |
57 |
s->state=SSL3_ST_SW_FLUSH; |
58 |
s->s3->tmp.next_state=SSL3_ST_SR_CLNT_HELLO_A; |
59 |
+ |
60 |
+ /* HelloVerifyRequests resets Finished MAC */ |
61 |
+ if (s->client_version != DTLS1_BAD_VER) |
62 |
+ ssl3_init_finished_mac(s); |
63 |
break; |
64 |
|
65 |
case SSL3_ST_SW_SRVR_HELLO_A: |
66 |
@@ -620,10 +624,13 @@ int dtls1_send_hello_verify_request(SSL |
67 |
buf = (unsigned char *)s->init_buf->data; |
68 |
|
69 |
msg = p = &(buf[DTLS1_HM_HEADER_LENGTH]); |
70 |
- *(p++) = s->version >> 8; |
71 |
- *(p++) = s->version & 0xFF; |
72 |
+ if (s->client_version == DTLS1_BAD_VER) |
73 |
+ *(p++) = DTLS1_BAD_VER>>8, |
74 |
+ *(p++) = DTLS1_BAD_VER&0xff; |
75 |
+ else |
76 |
+ *(p++) = s->version >> 8, |
77 |
+ *(p++) = s->version & 0xFF; |
78 |
|
79 |
- *(p++) = (unsigned char) s->d1->cookie_len; |
80 |
if ( s->ctx->app_gen_cookie_cb != NULL && |
81 |
s->ctx->app_gen_cookie_cb(s, s->d1->cookie, |
82 |
&(s->d1->cookie_len)) == 0) |
83 |
@@ -634,6 +641,7 @@ int dtls1_send_hello_verify_request(SSL |
84 |
/* else the cookie is assumed to have |
85 |
* been initialized by the application */ |
86 |
|
87 |
+ *(p++) = (unsigned char) s->d1->cookie_len; |
88 |
memcpy(p, s->d1->cookie, s->d1->cookie_len); |
89 |
p += s->d1->cookie_len; |
90 |
msg_len = p - msg; |
91 |
@@ -672,8 +680,12 @@ int dtls1_send_server_hello(SSL *s) |
92 |
/* Do the message type and length last */ |
93 |
d=p= &(buf[DTLS1_HM_HEADER_LENGTH]); |
94 |
|
95 |
- *(p++)=s->version>>8; |
96 |
- *(p++)=s->version&0xff; |
97 |
+ if (s->client_version == DTLS1_BAD_VER) |
98 |
+ *(p++)=DTLS1_BAD_VER>>8, |
99 |
+ *(p++)=DTLS1_BAD_VER&0xff; |
100 |
+ else |
101 |
+ *(p++)=s->version>>8, |
102 |
+ *(p++)=s->version&0xff; |
103 |
|
104 |
/* Random stuff */ |
105 |
memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE); |
106 |
diff -up openssl-fips-0.9.8f-dev/ssl/s3_srvr.c.dtls-fixes openssl-fips-0.9.8f-dev/ssl/s3_srvr.c |
107 |
--- openssl-fips-0.9.8f-dev/ssl/s3_srvr.c.dtls-fixes 2007-03-22 01:39:14.000000000 +0100 |
108 |
+++ openssl-fips-0.9.8f-dev/ssl/s3_srvr.c 2008-07-15 21:01:29.000000000 +0200 |
109 |
@@ -699,7 +699,8 @@ int ssl3_get_client_hello(SSL *s) |
110 |
s->client_version=(((int)p[0])<<8)|(int)p[1]; |
111 |
p+=2; |
112 |
|
113 |
- if (s->client_version < s->version) |
114 |
+ if ((s->version == DTLS1_VERSION && s->client_version > s->version) || |
115 |
+ (s->version != DTLS1_VERSION && s->client_version < s->version)) |
116 |
{ |
117 |
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_WRONG_VERSION_NUMBER); |
118 |
if ((s->client_version>>8) == SSL3_VERSION_MAJOR) |
119 |
@@ -750,7 +751,7 @@ int ssl3_get_client_hello(SSL *s) |
120 |
|
121 |
p+=j; |
122 |
|
123 |
- if (SSL_version(s) == DTLS1_VERSION) |
124 |
+ if (s->version == DTLS1_VERSION) |
125 |
{ |
126 |
/* cookie stuff */ |
127 |
cookie_len = *(p++); |
128 |
@@ -1713,8 +1714,9 @@ int ssl3_get_client_key_exchange(SSL *s) |
129 |
rsa=pkey->pkey.rsa; |
130 |
} |
131 |
|
132 |
- /* TLS */ |
133 |
- if (s->version > SSL3_VERSION) |
134 |
+ /* TLS and [incidentally] DTLS, including pre-0.9.8f */ |
135 |
+ if (s->version > SSL3_VERSION && |
136 |
+ s->client_version != DTLS1_BAD_VER) |
137 |
{ |
138 |
n2s(p,i); |
139 |
if (n != i+2) |
140 |
diff -up openssl-fips-0.9.8f-dev/ssl/ssl_locl.h.dtls-fixes openssl-fips-0.9.8f-dev/ssl/ssl_locl.h |
141 |
--- openssl-fips-0.9.8f-dev/ssl/ssl_locl.h.dtls-fixes 2008-07-15 21:01:29.000000000 +0200 |
142 |
+++ openssl-fips-0.9.8f-dev/ssl/ssl_locl.h 2008-07-15 21:01:29.000000000 +0200 |
143 |
@@ -680,7 +680,7 @@ SSL_METHOD *func_name(void) \ |
144 |
ssl3_put_cipher_by_char, \ |
145 |
ssl3_pending, \ |
146 |
ssl3_num_ciphers, \ |
147 |
- ssl3_get_cipher, \ |
148 |
+ dtls1_get_cipher, \ |
149 |
s_get_meth, \ |
150 |
dtls1_default_timeout, \ |
151 |
&DTLSv1_enc_data, \ |
152 |
@@ -845,6 +845,8 @@ void dtls1_get_message_header(unsigned c |
153 |
void dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr); |
154 |
void dtls1_reset_seq_numbers(SSL *s, int rw); |
155 |
long dtls1_default_timeout(void); |
156 |
+SSL_CIPHER *dtls1_get_cipher(unsigned int u); |
157 |
+ |
158 |
|
159 |
|
160 |
/* some client-only functions */ |
161 |
diff -up openssl-fips-0.9.8f-dev/ssl/t1_enc.c.dtls-fixes openssl-fips-0.9.8f-dev/ssl/t1_enc.c |
162 |
--- openssl-fips-0.9.8f-dev/ssl/t1_enc.c.dtls-fixes 2007-03-22 01:39:15.000000000 +0100 |
163 |
+++ openssl-fips-0.9.8f-dev/ssl/t1_enc.c 2008-07-15 21:01:29.000000000 +0200 |
164 |
@@ -740,15 +740,35 @@ int tls1_mac(SSL *ssl, unsigned char *md |
165 |
md_size=EVP_MD_size(hash); |
166 |
|
167 |
buf[0]=rec->type; |
168 |
- buf[1]=TLS1_VERSION_MAJOR; |
169 |
- buf[2]=TLS1_VERSION_MINOR; |
170 |
+ if (ssl->version == DTLS1_VERSION && ssl->client_version == DTLS1_BAD_VER) |
171 |
+ { |
172 |
+ buf[1]=TLS1_VERSION_MAJOR; |
173 |
+ buf[2]=TLS1_VERSION_MINOR; |
174 |
+ } |
175 |
+ else { |
176 |
+ buf[1]=(unsigned char)(ssl->version>>8); |
177 |
+ buf[2]=(unsigned char)(ssl->version); |
178 |
+ } |
179 |
+ |
180 |
buf[3]=rec->length>>8; |
181 |
buf[4]=rec->length&0xff; |
182 |
|
183 |
/* I should fix this up TLS TLS TLS TLS TLS XXXXXXXX */ |
184 |
HMAC_CTX_init(&hmac); |
185 |
HMAC_Init_ex(&hmac,mac_sec,EVP_MD_size(hash),hash,NULL); |
186 |
- HMAC_Update(&hmac,seq,8); |
187 |
+ |
188 |
+ if (ssl->version == DTLS1_VERSION && ssl->client_version != DTLS1_BAD_VER) |
189 |
+ { |
190 |
+ unsigned char dtlsseq[8],*p=dtlsseq; |
191 |
+ |
192 |
+ s2n(send?ssl->d1->w_epoch:ssl->d1->r_epoch, p); |
193 |
+ memcpy (p,&seq[2],6); |
194 |
+ |
195 |
+ HMAC_Update(&hmac,dtlsseq,8); |
196 |
+ } |
197 |
+ else |
198 |
+ HMAC_Update(&hmac,seq,8); |
199 |
+ |
200 |
HMAC_Update(&hmac,buf,5); |
201 |
HMAC_Update(&hmac,rec->input,rec->length); |
202 |
HMAC_Final(&hmac,md,&md_size); |
203 |
@@ -765,8 +785,8 @@ printf("rec="); |
204 |
{unsigned int z; for (z=0; z<rec->length; z++) printf("%02X ",buf[z]); printf("\n"); } |
205 |
#endif |
206 |
|
207 |
- if ( SSL_version(ssl) != DTLS1_VERSION) |
208 |
- { |
209 |
+ if ( SSL_version(ssl) != DTLS1_VERSION) |
210 |
+ { |
211 |
for (i=7; i>=0; i--) |
212 |
{ |
213 |
++seq[i]; |
214 |
diff -up openssl-fips-0.9.8f-dev/ssl/ssl.h.dtls-fixes openssl-fips-0.9.8f-dev/ssl/ssl.h |
215 |
--- openssl-fips-0.9.8f-dev/ssl/ssl.h.dtls-fixes 2008-07-15 21:01:29.000000000 +0200 |
216 |
+++ openssl-fips-0.9.8f-dev/ssl/ssl.h 2008-07-15 21:01:29.000000000 +0200 |
217 |
@@ -1554,6 +1554,7 @@ void ERR_load_SSL_strings(void); |
218 |
#define SSL_F_DTLS1_GET_MESSAGE_FRAGMENT 253 |
219 |
#define SSL_F_DTLS1_GET_RECORD 254 |
220 |
#define SSL_F_DTLS1_OUTPUT_CERT_CHAIN 255 |
221 |
+#define SSL_F_DTLS1_PREPROCESS_FRAGMENT 277 |
222 |
#define SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE 256 |
223 |
#define SSL_F_DTLS1_PROCESS_RECORD 257 |
224 |
#define SSL_F_DTLS1_READ_BYTES 258 |
225 |
diff -up openssl-fips-0.9.8f-dev/ssl/d1_pkt.c.dtls-fixes openssl-fips-0.9.8f-dev/ssl/d1_pkt.c |
226 |
--- openssl-fips-0.9.8f-dev/ssl/d1_pkt.c.dtls-fixes 2006-11-29 15:45:13.000000000 +0100 |
227 |
+++ openssl-fips-0.9.8f-dev/ssl/d1_pkt.c 2008-07-15 21:01:29.000000000 +0200 |
228 |
@@ -120,6 +120,7 @@ |
229 |
#include <openssl/evp.h> |
230 |
#include <openssl/buffer.h> |
231 |
#include <openssl/pqueue.h> |
232 |
+#include <openssl/rand.h> |
233 |
|
234 |
static int have_handshake_fragment(SSL *s, int type, unsigned char *buf, |
235 |
int len, int peek); |
236 |
@@ -486,9 +487,9 @@ int dtls1_get_record(SSL *s) |
237 |
SSL3_RECORD *rr; |
238 |
SSL_SESSION *sess; |
239 |
unsigned char *p; |
240 |
- short version; |
241 |
+ unsigned short version; |
242 |
DTLS1_BITMAP *bitmap; |
243 |
- unsigned int is_next_epoch; |
244 |
+ unsigned int is_next_epoch; |
245 |
|
246 |
rr= &(s->s3->rrec); |
247 |
sess=s->session; |
248 |
@@ -524,7 +525,7 @@ again: |
249 |
ssl_minor= *(p++); |
250 |
version=(ssl_major<<8)|ssl_minor; |
251 |
|
252 |
- /* sequence number is 64 bits, with top 2 bytes = epoch */ |
253 |
+ /* sequence number is 64 bits, with top 2 bytes = epoch */ |
254 |
n2s(p,rr->epoch); |
255 |
|
256 |
memcpy(&(s->s3->read_sequence[2]), p, 6); |
257 |
@@ -535,7 +536,7 @@ again: |
258 |
/* Lets check version */ |
259 |
if (!s->first_packet) |
260 |
{ |
261 |
- if (version != s->version) |
262 |
+ if (version != s->version && version != DTLS1_BAD_VER) |
263 |
{ |
264 |
SSLerr(SSL_F_DTLS1_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER); |
265 |
/* Send back error using their |
266 |
@@ -546,7 +547,8 @@ again: |
267 |
} |
268 |
} |
269 |
|
270 |
- if ((version & 0xff00) != (DTLS1_VERSION & 0xff00)) |
271 |
+ if ((version & 0xff00) != (DTLS1_VERSION & 0xff00) && |
272 |
+ (version & 0xff00) != (DTLS1_BAD_VER & 0xff00)) |
273 |
{ |
274 |
SSLerr(SSL_F_DTLS1_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER); |
275 |
goto err; |
276 |
@@ -559,6 +561,7 @@ again: |
277 |
goto f_err; |
278 |
} |
279 |
|
280 |
+ s->client_version = version; |
281 |
/* now s->rstate == SSL_ST_READ_BODY */ |
282 |
} |
283 |
|
284 |
@@ -973,47 +976,40 @@ start: |
285 |
} |
286 |
|
287 |
if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC) |
288 |
- { |
289 |
- struct ccs_header_st ccs_hdr; |
290 |
+ { |
291 |
+ struct ccs_header_st ccs_hdr; |
292 |
|
293 |
dtls1_get_ccs_header(rr->data, &ccs_hdr); |
294 |
|
295 |
- if ( ccs_hdr.seq == s->d1->handshake_read_seq) |
296 |
+ /* 'Change Cipher Spec' is just a single byte, so we know |
297 |
+ * exactly what the record payload has to look like */ |
298 |
+ /* XDTLS: check that epoch is consistent */ |
299 |
+ if ( (s->client_version == DTLS1_BAD_VER && rr->length != 3) || |
300 |
+ (s->client_version != DTLS1_BAD_VER && rr->length != DTLS1_CCS_HEADER_LENGTH) || |
301 |
+ (rr->off != 0) || (rr->data[0] != SSL3_MT_CCS)) |
302 |
{ |
303 |
- /* 'Change Cipher Spec' is just a single byte, so we know |
304 |
- * exactly what the record payload has to look like */ |
305 |
- /* XDTLS: check that epoch is consistent */ |
306 |
- if ( (rr->length != DTLS1_CCS_HEADER_LENGTH) || |
307 |
- (rr->off != 0) || (rr->data[0] != SSL3_MT_CCS)) |
308 |
- { |
309 |
- i=SSL_AD_ILLEGAL_PARAMETER; |
310 |
- SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC); |
311 |
- goto err; |
312 |
- } |
313 |
- |
314 |
- rr->length=0; |
315 |
- |
316 |
- if (s->msg_callback) |
317 |
- s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, |
318 |
- rr->data, 1, s, s->msg_callback_arg); |
319 |
- |
320 |
- s->s3->change_cipher_spec=1; |
321 |
- if (!ssl3_do_change_cipher_spec(s)) |
322 |
- goto err; |
323 |
- |
324 |
- /* do this whenever CCS is processed */ |
325 |
- dtls1_reset_seq_numbers(s, SSL3_CC_READ); |
326 |
- |
327 |
- /* handshake read seq is reset upon handshake completion */ |
328 |
- s->d1->handshake_read_seq++; |
329 |
- |
330 |
- goto start; |
331 |
- } |
332 |
- else |
333 |
- { |
334 |
- rr->length = 0; |
335 |
- goto start; |
336 |
+ i=SSL_AD_ILLEGAL_PARAMETER; |
337 |
+ SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC); |
338 |
+ goto err; |
339 |
} |
340 |
+ |
341 |
+ rr->length=0; |
342 |
+ |
343 |
+ if (s->msg_callback) |
344 |
+ s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, |
345 |
+ rr->data, 1, s, s->msg_callback_arg); |
346 |
+ |
347 |
+ s->s3->change_cipher_spec=1; |
348 |
+ if (!ssl3_do_change_cipher_spec(s)) |
349 |
+ goto err; |
350 |
+ |
351 |
+ /* do this whenever CCS is processed */ |
352 |
+ dtls1_reset_seq_numbers(s, SSL3_CC_READ); |
353 |
+ |
354 |
+ if (s->client_version == DTLS1_BAD_VER) |
355 |
+ s->d1->handshake_read_seq++; |
356 |
+ |
357 |
+ goto start; |
358 |
} |
359 |
|
360 |
/* Unexpected handshake message (Client Hello, or protocol violation) */ |
361 |
@@ -1341,8 +1337,12 @@ int do_dtls1_write(SSL *s, int type, con |
362 |
*(p++)=type&0xff; |
363 |
wr->type=type; |
364 |
|
365 |
- *(p++)=(s->version>>8); |
366 |
- *(p++)=s->version&0xff; |
367 |
+ if (s->client_version == DTLS1_BAD_VER) |
368 |
+ *(p++) = DTLS1_BAD_VER>>8, |
369 |
+ *(p++) = DTLS1_BAD_VER&0xff; |
370 |
+ else |
371 |
+ *(p++)=(s->version>>8), |
372 |
+ *(p++)=s->version&0xff; |
373 |
|
374 |
/* field where we are to write out packet epoch, seq num and len */ |
375 |
pseq=p; |
376 |
@@ -1397,8 +1397,14 @@ int do_dtls1_write(SSL *s, int type, con |
377 |
|
378 |
|
379 |
/* ssl3_enc can only have an error on read */ |
380 |
- wr->length += bs; /* bs != 0 in case of CBC. The enc fn provides |
381 |
- * the randomness */ |
382 |
+ if (bs) /* bs != 0 in case of CBC */ |
383 |
+ { |
384 |
+ RAND_pseudo_bytes(p,bs); |
385 |
+ /* master IV and last CBC residue stand for |
386 |
+ * the rest of randomness */ |
387 |
+ wr->length += bs; |
388 |
+ } |
389 |
+ |
390 |
s->method->ssl3_enc->enc(s,1); |
391 |
|
392 |
/* record length after mac and block padding */ |
393 |
diff -up openssl-fips-0.9.8f-dev/ssl/ssl_err.c.dtls-fixes openssl-fips-0.9.8f-dev/ssl/ssl_err.c |
394 |
--- openssl-fips-0.9.8f-dev/ssl/ssl_err.c.dtls-fixes 2006-11-21 21:14:46.000000000 +0100 |
395 |
+++ openssl-fips-0.9.8f-dev/ssl/ssl_err.c 2008-07-15 21:01:29.000000000 +0200 |
396 |
@@ -87,6 +87,7 @@ static ERR_STRING_DATA SSL_str_functs[]= |
397 |
{ERR_FUNC(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT), "DTLS1_GET_MESSAGE_FRAGMENT"}, |
398 |
{ERR_FUNC(SSL_F_DTLS1_GET_RECORD), "DTLS1_GET_RECORD"}, |
399 |
{ERR_FUNC(SSL_F_DTLS1_OUTPUT_CERT_CHAIN), "DTLS1_OUTPUT_CERT_CHAIN"}, |
400 |
+{ERR_FUNC(SSL_F_DTLS1_PREPROCESS_FRAGMENT), "DTLS1_PREPROCESS_FRAGMENT"}, |
401 |
{ERR_FUNC(SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE), "DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE"}, |
402 |
{ERR_FUNC(SSL_F_DTLS1_PROCESS_RECORD), "DTLS1_PROCESS_RECORD"}, |
403 |
{ERR_FUNC(SSL_F_DTLS1_READ_BYTES), "DTLS1_READ_BYTES"}, |
404 |
diff -up openssl-fips-0.9.8f-dev/ssl/s3_clnt.c.dtls-fixes openssl-fips-0.9.8f-dev/ssl/s3_clnt.c |
405 |
--- openssl-fips-0.9.8f-dev/ssl/s3_clnt.c.dtls-fixes 2007-03-22 01:39:14.000000000 +0100 |
406 |
+++ openssl-fips-0.9.8f-dev/ssl/s3_clnt.c 2008-07-15 21:08:43.000000000 +0200 |
407 |
@@ -1847,6 +1847,13 @@ int ssl3_send_client_key_exchange(SSL *s |
408 |
{ |
409 |
DH *dh_srvr,*dh_clnt; |
410 |
|
411 |
+ if (s->session->sess_cert == NULL) |
412 |
+ { |
413 |
+ ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE); |
414 |
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE); |
415 |
+ goto err; |
416 |
+ } |
417 |
+ |
418 |
if (s->session->sess_cert->peer_dh_tmp != NULL) |
419 |
dh_srvr=s->session->sess_cert->peer_dh_tmp; |
420 |
else |
421 |
diff -up openssl-fips-0.9.8f-dev/ssl/d1_both.c.dtls-fixes openssl-fips-0.9.8f-dev/ssl/d1_both.c |
422 |
--- openssl-fips-0.9.8f-dev/ssl/d1_both.c.dtls-fixes 2007-06-22 14:17:52.000000000 +0200 |
423 |
+++ openssl-fips-0.9.8f-dev/ssl/d1_both.c 2008-07-15 21:01:29.000000000 +0200 |
424 |
@@ -138,38 +138,40 @@ static void dtls1_set_message_header_int |
425 |
unsigned long frag_len); |
426 |
static int dtls1_retransmit_buffered_messages(SSL *s); |
427 |
static long dtls1_get_message_fragment(SSL *s, int st1, int stn, |
428 |
- long max, int *ok); |
429 |
-static void dtls1_process_handshake_fragment(SSL *s, int frag_len); |
430 |
+ long max, int *ok); |
431 |
|
432 |
static hm_fragment * |
433 |
dtls1_hm_fragment_new(unsigned long frag_len) |
434 |
- { |
435 |
- hm_fragment *frag = NULL; |
436 |
- unsigned char *buf = NULL; |
437 |
+ { |
438 |
+ hm_fragment *frag = NULL; |
439 |
+ unsigned char *buf = NULL; |
440 |
|
441 |
- frag = (hm_fragment *)OPENSSL_malloc(sizeof(hm_fragment)); |
442 |
- if ( frag == NULL) |
443 |
- return NULL; |
444 |
+ frag = (hm_fragment *)OPENSSL_malloc(sizeof(hm_fragment)); |
445 |
+ if ( frag == NULL) |
446 |
+ return NULL; |
447 |
|
448 |
- buf = (unsigned char *)OPENSSL_malloc(frag_len |
449 |
- + DTLS1_HM_HEADER_LENGTH); |
450 |
- if ( buf == NULL) |
451 |
- { |
452 |
- OPENSSL_free(frag); |
453 |
- return NULL; |
454 |
- } |
455 |
- |
456 |
- frag->fragment = buf; |
457 |
+ if (frag_len) |
458 |
+ { |
459 |
+ buf = (unsigned char *)OPENSSL_malloc(frag_len); |
460 |
+ if ( buf == NULL) |
461 |
+ { |
462 |
+ OPENSSL_free(frag); |
463 |
+ return NULL; |
464 |
+ } |
465 |
+ } |
466 |
|
467 |
- return frag; |
468 |
- } |
469 |
+ /* zero length fragment gets zero frag->fragment */ |
470 |
+ frag->fragment = buf; |
471 |
+ |
472 |
+ return frag; |
473 |
+ } |
474 |
|
475 |
static void |
476 |
dtls1_hm_fragment_free(hm_fragment *frag) |
477 |
- { |
478 |
- OPENSSL_free(frag->fragment); |
479 |
- OPENSSL_free(frag); |
480 |
- } |
481 |
+ { |
482 |
+ if (frag->fragment) OPENSSL_free(frag->fragment); |
483 |
+ OPENSSL_free(frag); |
484 |
+ } |
485 |
|
486 |
/* send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC) */ |
487 |
int dtls1_do_write(SSL *s, int type) |
488 |
@@ -180,7 +182,7 @@ int dtls1_do_write(SSL *s, int type) |
489 |
|
490 |
/* AHA! Figure out the MTU, and stick to the right size */ |
491 |
if ( ! (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) |
492 |
- { |
493 |
+ { |
494 |
s->d1->mtu = |
495 |
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); |
496 |
|
497 |
@@ -207,7 +209,7 @@ int dtls1_do_write(SSL *s, int type) |
498 |
mtu = curr_mtu; |
499 |
else if ( ( ret = BIO_flush(SSL_get_wbio(s))) <= 0) |
500 |
return ret; |
501 |
- |
502 |
+ |
503 |
if ( BIO_wpending(SSL_get_wbio(s)) + s->init_num >= mtu) |
504 |
{ |
505 |
ret = BIO_flush(SSL_get_wbio(s)); |
506 |
@@ -254,11 +256,11 @@ int dtls1_do_write(SSL *s, int type) |
507 |
s->init_off -= DTLS1_HM_HEADER_LENGTH; |
508 |
s->init_num += DTLS1_HM_HEADER_LENGTH; |
509 |
|
510 |
- /* write atleast DTLS1_HM_HEADER_LENGTH bytes */ |
511 |
+ /* write atleast DTLS1_HM_HEADER_LENGTH bytes */ |
512 |
if ( len <= DTLS1_HM_HEADER_LENGTH) |
513 |
len += DTLS1_HM_HEADER_LENGTH; |
514 |
} |
515 |
- |
516 |
+ |
517 |
dtls1_fix_message_header(s, frag_off, |
518 |
len - DTLS1_HM_HEADER_LENGTH); |
519 |
|
520 |
@@ -286,18 +288,40 @@ int dtls1_do_write(SSL *s, int type) |
521 |
} |
522 |
else |
523 |
{ |
524 |
- |
525 |
+ |
526 |
/* bad if this assert fails, only part of the handshake |
527 |
* message got sent. but why would this happen? */ |
528 |
- OPENSSL_assert(len == (unsigned int)ret); |
529 |
- |
530 |
+ OPENSSL_assert(len == (unsigned int)ret); |
531 |
+ |
532 |
if (type == SSL3_RT_HANDSHAKE && ! s->d1->retransmitting) |
533 |
+ { |
534 |
/* should not be done for 'Hello Request's, but in that case |
535 |
* we'll ignore the result anyway */ |
536 |
- ssl3_finish_mac(s, |
537 |
- (unsigned char *)&s->init_buf->data[s->init_off + |
538 |
- DTLS1_HM_HEADER_LENGTH], ret - DTLS1_HM_HEADER_LENGTH); |
539 |
- |
540 |
+ unsigned char *p = &s->init_buf->data[s->init_off]; |
541 |
+ const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr; |
542 |
+ int len; |
543 |
+ |
544 |
+ if (frag_off == 0 && s->client_version != DTLS1_BAD_VER) |
545 |
+ { |
546 |
+ /* reconstruct message header is if it |
547 |
+ * is being sent in single fragment */ |
548 |
+ *p++ = msg_hdr->type; |
549 |
+ l2n3(msg_hdr->msg_len,p); |
550 |
+ s2n (msg_hdr->seq,p); |
551 |
+ l2n3(0,p); |
552 |
+ l2n3(msg_hdr->msg_len,p); |
553 |
+ p -= DTLS1_HM_HEADER_LENGTH; |
554 |
+ len = ret; |
555 |
+ } |
556 |
+ else |
557 |
+ { |
558 |
+ p += DTLS1_HM_HEADER_LENGTH; |
559 |
+ len = ret - DTLS1_HM_HEADER_LENGTH; |
560 |
+ } |
561 |
+ |
562 |
+ ssl3_finish_mac(s, p, len); |
563 |
+ } |
564 |
+ |
565 |
if (ret == s->init_num) |
566 |
{ |
567 |
if (s->msg_callback) |
568 |
@@ -307,7 +331,7 @@ int dtls1_do_write(SSL *s, int type) |
569 |
|
570 |
s->init_off = 0; /* done writing this message */ |
571 |
s->init_num = 0; |
572 |
- |
573 |
+ |
574 |
return(1); |
575 |
} |
576 |
s->init_off+=ret; |
577 |
@@ -327,6 +351,7 @@ int dtls1_do_write(SSL *s, int type) |
578 |
long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) |
579 |
{ |
580 |
int i, al; |
581 |
+ struct hm_header_st *msg_hdr; |
582 |
|
583 |
/* s3->tmp is used to store messages that are unexpected, caused |
584 |
* by the absence of an optional handshake message */ |
585 |
@@ -344,25 +369,56 @@ long dtls1_get_message(SSL *s, int st1, |
586 |
s->init_num = (int)s->s3->tmp.message_size; |
587 |
return s->init_num; |
588 |
} |
589 |
- |
590 |
+ |
591 |
+ msg_hdr = &s->d1->r_msg_hdr; |
592 |
do |
593 |
{ |
594 |
- if ( s->d1->r_msg_hdr.frag_off == 0) |
595 |
+ if ( msg_hdr->frag_off == 0) |
596 |
{ |
597 |
/* s->d1->r_message_header.msg_len = 0; */ |
598 |
- memset(&(s->d1->r_msg_hdr), 0x00, sizeof(struct hm_header_st)); |
599 |
+ memset(msg_hdr, 0x00, sizeof(struct hm_header_st)); |
600 |
} |
601 |
|
602 |
i = dtls1_get_message_fragment(s, st1, stn, max, ok); |
603 |
if ( i == DTLS1_HM_BAD_FRAGMENT || |
604 |
- i == DTLS1_HM_FRAGMENT_RETRY) /* bad fragment received */ |
605 |
+ i == DTLS1_HM_FRAGMENT_RETRY) /* bad fragment received */ |
606 |
continue; |
607 |
else if ( i <= 0 && !*ok) |
608 |
return i; |
609 |
|
610 |
- if (s->d1->r_msg_hdr.msg_len == (unsigned int)s->init_num - DTLS1_HM_HEADER_LENGTH) |
611 |
+ /* Note that s->init_sum is used as a counter summing |
612 |
+ * up fragments' lengths: as soon as they sum up to |
613 |
+ * handshake packet length, we assume we have got all |
614 |
+ * the fragments. Overlapping fragments would cause |
615 |
+ * premature termination, so we don't expect overlaps. |
616 |
+ * Well, handling overlaps would require something more |
617 |
+ * drastic. Indeed, as it is now there is no way to |
618 |
+ * tell if out-of-order fragment from the middle was |
619 |
+ * the last. '>=' is the best/least we can do to control |
620 |
+ * the potential damage caused by malformed overlaps. */ |
621 |
+ if ((unsigned int)s->init_num >= msg_hdr->msg_len) |
622 |
{ |
623 |
- memset(&(s->d1->r_msg_hdr), 0x00, sizeof(struct hm_header_st)); |
624 |
+ unsigned char *p = s->init_buf->data; |
625 |
+ unsigned long msg_len = msg_hdr->msg_len; |
626 |
+ |
627 |
+ /* reconstruct message header as if it was |
628 |
+ * sent in single fragment */ |
629 |
+ *(p++) = msg_hdr->type; |
630 |
+ l2n3(msg_len,p); |
631 |
+ s2n (msg_hdr->seq,p); |
632 |
+ l2n3(0,p); |
633 |
+ l2n3(msg_len,p); |
634 |
+ if (s->client_version != DTLS1_BAD_VER) |
635 |
+ p -= DTLS1_HM_HEADER_LENGTH, |
636 |
+ msg_len += DTLS1_HM_HEADER_LENGTH; |
637 |
+ |
638 |
+ ssl3_finish_mac(s, p, msg_len); |
639 |
+ if (s->msg_callback) |
640 |
+ s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, |
641 |
+ p, msg_len, |
642 |
+ s, s->msg_callback_arg); |
643 |
+ |
644 |
+ memset(msg_hdr, 0x00, sizeof(struct hm_header_st)); |
645 |
|
646 |
s->d1->handshake_read_seq++; |
647 |
/* we just read a handshake message from the other side: |
648 |
@@ -379,11 +435,11 @@ long dtls1_get_message(SSL *s, int st1, |
649 |
* first data segment, but is there a better way? */ |
650 |
dtls1_clear_record_buffer(s); |
651 |
|
652 |
- s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH; |
653 |
- return s->init_num - DTLS1_HM_HEADER_LENGTH; |
654 |
+ s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH; |
655 |
+ return s->init_num; |
656 |
} |
657 |
else |
658 |
- s->d1->r_msg_hdr.frag_off = i; |
659 |
+ msg_hdr->frag_off = i; |
660 |
} while(1) ; |
661 |
|
662 |
f_err: |
663 |
@@ -393,161 +449,183 @@ f_err: |
664 |
} |
665 |
|
666 |
|
667 |
-static int |
668 |
-dtls1_retrieve_buffered_fragment(SSL *s, unsigned long *copied) |
669 |
- { |
670 |
- /* (0) check whether the desired fragment is available |
671 |
- * if so: |
672 |
- * (1) copy over the fragment to s->init_buf->data[] |
673 |
- * (2) update s->init_num |
674 |
- */ |
675 |
- pitem *item; |
676 |
- hm_fragment *frag; |
677 |
- unsigned long overlap; |
678 |
- unsigned char *p; |
679 |
- |
680 |
- item = pqueue_peek(s->d1->buffered_messages); |
681 |
- if ( item == NULL) |
682 |
- return 0; |
683 |
+static int dtls1_preprocess_fragment(SSL *s,struct hm_header_st *msg_hdr,int max) |
684 |
+ { |
685 |
+ size_t frag_off,frag_len,msg_len; |
686 |
|
687 |
- frag = (hm_fragment *)item->data; |
688 |
- |
689 |
- if ( s->d1->handshake_read_seq == frag->msg_header.seq && |
690 |
- frag->msg_header.frag_off <= (unsigned int)s->init_num - DTLS1_HM_HEADER_LENGTH) |
691 |
- { |
692 |
- pqueue_pop(s->d1->buffered_messages); |
693 |
- overlap = s->init_num - DTLS1_HM_HEADER_LENGTH |
694 |
- - frag->msg_header.frag_off; |
695 |
- |
696 |
- p = frag->fragment; |
697 |
- |
698 |
- memcpy(&s->init_buf->data[s->init_num], |
699 |
- p + DTLS1_HM_HEADER_LENGTH + overlap, |
700 |
- frag->msg_header.frag_len - overlap); |
701 |
- |
702 |
- OPENSSL_free(frag->fragment); |
703 |
- OPENSSL_free(frag); |
704 |
- pitem_free(item); |
705 |
+ msg_len = msg_hdr->msg_len; |
706 |
+ frag_off = msg_hdr->frag_off; |
707 |
+ frag_len = msg_hdr->frag_len; |
708 |
|
709 |
- *copied = frag->msg_header.frag_len - overlap; |
710 |
- return *copied; |
711 |
- } |
712 |
- else |
713 |
- return 0; |
714 |
- } |
715 |
+ /* sanity checking */ |
716 |
+ if ( (frag_off+frag_len) > msg_len) |
717 |
+ { |
718 |
+ SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE); |
719 |
+ return SSL_AD_ILLEGAL_PARAMETER; |
720 |
+ } |
721 |
|
722 |
+ if ( (frag_off+frag_len) > (unsigned long)max) |
723 |
+ { |
724 |
+ SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE); |
725 |
+ return SSL_AD_ILLEGAL_PARAMETER; |
726 |
+ } |
727 |
|
728 |
-static int |
729 |
-dtls1_buffer_handshake_fragment(SSL *s, struct hm_header_st* msg_hdr) |
730 |
-{ |
731 |
- hm_fragment *frag = NULL; |
732 |
- pitem *item = NULL; |
733 |
- PQ_64BIT seq64; |
734 |
+ if ( s->d1->r_msg_hdr.frag_off == 0) /* first fragment */ |
735 |
+ { |
736 |
+ /* msg_len is limited to 2^24, but is effectively checked |
737 |
+ * against max above */ |
738 |
+ if (!BUF_MEM_grow_clean(s->init_buf,(int)msg_len+DTLS1_HM_HEADER_LENGTH)) |
739 |
+ { |
740 |
+ SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,ERR_R_BUF_LIB); |
741 |
+ return SSL_AD_INTERNAL_ERROR; |
742 |
+ } |
743 |
|
744 |
- frag = dtls1_hm_fragment_new(msg_hdr->frag_len); |
745 |
- if ( frag == NULL) |
746 |
- goto err; |
747 |
+ s->s3->tmp.message_size = msg_len; |
748 |
+ s->d1->r_msg_hdr.msg_len = msg_len; |
749 |
+ s->s3->tmp.message_type = msg_hdr->type; |
750 |
+ s->d1->r_msg_hdr.type = msg_hdr->type; |
751 |
+ s->d1->r_msg_hdr.seq = msg_hdr->seq; |
752 |
+ } |
753 |
+ else if (msg_len != s->d1->r_msg_hdr.msg_len) |
754 |
+ { |
755 |
+ /* They must be playing with us! BTW, failure to enforce |
756 |
+ * upper limit would open possibility for buffer overrun. */ |
757 |
+ SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE); |
758 |
+ return SSL_AD_ILLEGAL_PARAMETER; |
759 |
+ } |
760 |
|
761 |
- memcpy(frag->fragment, &(s->init_buf->data[s->init_num]), |
762 |
- msg_hdr->frag_len + DTLS1_HM_HEADER_LENGTH); |
763 |
+ return 0; /* no error */ |
764 |
+ } |
765 |
|
766 |
- memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr)); |
767 |
|
768 |
- pq_64bit_init(&seq64); |
769 |
- pq_64bit_assign_word(&seq64, msg_hdr->seq); |
770 |
+static int |
771 |
+dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok) |
772 |
+ { |
773 |
+ /* (0) check whether the desired fragment is available |
774 |
+ * if so: |
775 |
+ * (1) copy over the fragment to s->init_buf->data[] |
776 |
+ * (2) update s->init_num |
777 |
+ */ |
778 |
+ pitem *item; |
779 |
+ hm_fragment *frag; |
780 |
+ int al; |
781 |
|
782 |
- item = pitem_new(seq64, frag); |
783 |
- if ( item == NULL) |
784 |
- goto err; |
785 |
+ *ok = 0; |
786 |
+ item = pqueue_peek(s->d1->buffered_messages); |
787 |
+ if ( item == NULL) |
788 |
+ return 0; |
789 |
|
790 |
- pq_64bit_free(&seq64); |
791 |
+ frag = (hm_fragment *)item->data; |
792 |
|
793 |
- pqueue_insert(s->d1->buffered_messages, item); |
794 |
- return 1; |
795 |
+ if ( s->d1->handshake_read_seq == frag->msg_header.seq) |
796 |
+ { |
797 |
+ pqueue_pop(s->d1->buffered_messages); |
798 |
|
799 |
-err: |
800 |
- if ( frag != NULL) dtls1_hm_fragment_free(frag); |
801 |
- if ( item != NULL) OPENSSL_free(item); |
802 |
- return 0; |
803 |
-} |
804 |
+ al=dtls1_preprocess_fragment(s,&frag->msg_header,max); |
805 |
|
806 |
+ if (al==0) /* no alert */ |
807 |
+ { |
808 |
+ unsigned char *p = s->init_buf->data+DTLS1_HM_HEADER_LENGTH; |
809 |
+ memcpy(&p[frag->msg_header.frag_off], |
810 |
+ frag->fragment,frag->msg_header.frag_len); |
811 |
+ } |
812 |
|
813 |
-static void |
814 |
-dtls1_process_handshake_fragment(SSL *s, int frag_len) |
815 |
- { |
816 |
- unsigned char *p; |
817 |
+ dtls1_hm_fragment_free(frag); |
818 |
+ pitem_free(item); |
819 |
|
820 |
- p = (unsigned char *)s->init_buf->data; |
821 |
+ if (al==0) |
822 |
+ { |
823 |
+ *ok = 1; |
824 |
+ return frag->msg_header.frag_len; |
825 |
+ } |
826 |
|
827 |
- ssl3_finish_mac(s, &p[s->init_num - frag_len], frag_len); |
828 |
- } |
829 |
+ ssl3_send_alert(s,SSL3_AL_FATAL,al); |
830 |
+ s->init_num = 0; |
831 |
+ *ok = 0; |
832 |
+ return -1; |
833 |
+ } |
834 |
+ else |
835 |
+ return 0; |
836 |
+ } |
837 |
|
838 |
|
839 |
static int |
840 |
-dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st *msg_hdr, int *ok) |
841 |
- { |
842 |
- int i; |
843 |
- unsigned char *p; |
844 |
- |
845 |
- /* make sure there's enough room to read this fragment */ |
846 |
- if ( (int)msg_hdr->frag_len && !BUF_MEM_grow_clean(s->init_buf, |
847 |
- (int)msg_hdr->frag_len + DTLS1_HM_HEADER_LENGTH + s->init_num)) |
848 |
- { |
849 |
- SSLerr(SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE,ERR_R_BUF_LIB); |
850 |
- goto err; |
851 |
- } |
852 |
+dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok) |
853 |
+{ |
854 |
+ int i=-1; |
855 |
+ hm_fragment *frag = NULL; |
856 |
+ pitem *item = NULL; |
857 |
+ PQ_64BIT seq64; |
858 |
+ unsigned long frag_len = msg_hdr->frag_len; |
859 |
|
860 |
- p = (unsigned char *)s->init_buf->data; |
861 |
+ if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len) |
862 |
+ goto err; |
863 |
|
864 |
- /* read the body of the fragment (header has already been read */ |
865 |
- if ( msg_hdr->frag_len > 0) |
866 |
+ if (msg_hdr->seq <= s->d1->handshake_read_seq) |
867 |
{ |
868 |
- i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE, |
869 |
- &p[s->init_num], |
870 |
- msg_hdr->frag_len,0); |
871 |
- if (i <= 0) |
872 |
+ unsigned char devnull [256]; |
873 |
+ |
874 |
+ while (frag_len) |
875 |
{ |
876 |
- *ok = 0; |
877 |
- return i; |
878 |
+ i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE, |
879 |
+ devnull, |
880 |
+ frag_len>sizeof(devnull)?sizeof(devnull):frag_len,0); |
881 |
+ if (i<=0) goto err; |
882 |
+ frag_len -= i; |
883 |
} |
884 |
} |
885 |
|
886 |
- if ( msg_hdr->seq > s->d1->handshake_read_seq) |
887 |
- dtls1_buffer_handshake_fragment(s, msg_hdr); |
888 |
- else |
889 |
- OPENSSL_assert(msg_hdr->seq < s->d1->handshake_read_seq); |
890 |
+ frag = dtls1_hm_fragment_new(frag_len); |
891 |
+ if ( frag == NULL) |
892 |
+ goto err; |
893 |
+ |
894 |
+ memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr)); |
895 |
+ |
896 |
+ if (frag_len) |
897 |
+ { |
898 |
+ /* read the body of the fragment (header has already been read */ |
899 |
+ i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE, |
900 |
+ frag->fragment,frag_len,0); |
901 |
+ if (i<=0 || i!=frag_len) |
902 |
+ goto err; |
903 |
+ } |
904 |
+ |
905 |
+ pq_64bit_init(&seq64); |
906 |
+ pq_64bit_assign_word(&seq64, msg_hdr->seq); |
907 |
+ |
908 |
+ item = pitem_new(seq64, frag); |
909 |
+ pq_64bit_free(&seq64); |
910 |
+ if ( item == NULL) |
911 |
+ goto err; |
912 |
+ |
913 |
+ pqueue_insert(s->d1->buffered_messages, item); |
914 |
+ return DTLS1_HM_FRAGMENT_RETRY; |
915 |
|
916 |
- return DTLS1_HM_FRAGMENT_RETRY; |
917 |
err: |
918 |
- *ok = 0; |
919 |
- return -1; |
920 |
- } |
921 |
+ if ( frag != NULL) dtls1_hm_fragment_free(frag); |
922 |
+ if ( item != NULL) OPENSSL_free(item); |
923 |
+ *ok = 0; |
924 |
+ return i; |
925 |
+ } |
926 |
|
927 |
|
928 |
static long |
929 |
dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) |
930 |
{ |
931 |
- unsigned char *p; |
932 |
+ unsigned char wire[DTLS1_HM_HEADER_LENGTH]; |
933 |
unsigned long l, frag_off, frag_len; |
934 |
int i,al; |
935 |
struct hm_header_st msg_hdr; |
936 |
- unsigned long overlap; |
937 |
- |
938 |
- /* see if we have the required fragment already */ |
939 |
- if (dtls1_retrieve_buffered_fragment(s, &l)) |
940 |
- { |
941 |
- /* compute MAC, remove fragment headers */ |
942 |
- dtls1_process_handshake_fragment(s, l); |
943 |
- s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH; |
944 |
- s->state = stn; |
945 |
- return 1; |
946 |
- } |
947 |
|
948 |
- /* get a handshake fragment from the record layer */ |
949 |
- p = (unsigned char *)s->init_buf->data; |
950 |
+ /* see if we have the required fragment already */ |
951 |
+ if ((frag_len = dtls1_retrieve_buffered_fragment(s,max,ok)) || *ok) |
952 |
+ { |
953 |
+ if (*ok) s->init_num += frag_len; |
954 |
+ return frag_len; |
955 |
+ } |
956 |
|
957 |
- /* read handshake message header */ |
958 |
- i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,&p[s->init_num], |
959 |
+ /* read handshake message header */ |
960 |
+ i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,wire, |
961 |
DTLS1_HM_HEADER_LENGTH, 0); |
962 |
if (i <= 0) /* nbio, or an error */ |
963 |
{ |
964 |
@@ -555,130 +633,61 @@ dtls1_get_message_fragment(SSL *s, int s |
965 |
*ok = 0; |
966 |
return i; |
967 |
} |
968 |
- |
969 |
OPENSSL_assert(i == DTLS1_HM_HEADER_LENGTH); |
970 |
|
971 |
- p += s->init_num; |
972 |
- /* parse the message fragment header */ |
973 |
- |
974 |
- dtls1_get_message_header(p, &msg_hdr); |
975 |
+ /* parse the message fragment header */ |
976 |
+ dtls1_get_message_header(wire, &msg_hdr); |
977 |
|
978 |
- /* |
979 |
- * if this is a future (or stale) message it gets buffered |
980 |
- * (or dropped)--no further processing at this time |
981 |
- */ |
982 |
- if ( msg_hdr.seq != s->d1->handshake_read_seq) |
983 |
- return dtls1_process_out_of_seq_message(s, &msg_hdr, ok); |
984 |
+ /* |
985 |
+ * if this is a future (or stale) message it gets buffered |
986 |
+ * (or dropped)--no further processing at this time |
987 |
+ */ |
988 |
+ if ( msg_hdr.seq != s->d1->handshake_read_seq) |
989 |
+ return dtls1_process_out_of_seq_message(s, &msg_hdr, ok); |
990 |
|
991 |
- l = msg_hdr.msg_len; |
992 |
- frag_off = msg_hdr.frag_off; |
993 |
+ l = msg_hdr.msg_len; |
994 |
+ frag_off = msg_hdr.frag_off; |
995 |
frag_len = msg_hdr.frag_len; |
996 |
|
997 |
- /* sanity checking */ |
998 |
- if ( frag_off + frag_len > l) |
999 |
- { |
1000 |
- al=SSL_AD_ILLEGAL_PARAMETER; |
1001 |
- SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE); |
1002 |
- goto f_err; |
1003 |
- } |
1004 |
- |
1005 |
if (!s->server && s->d1->r_msg_hdr.frag_off == 0 && |
1006 |
- p[0] == SSL3_MT_HELLO_REQUEST) |
1007 |
- { |
1008 |
- /* The server may always send 'Hello Request' messages -- |
1009 |
- * we are doing a handshake anyway now, so ignore them |
1010 |
- * if their format is correct. Does not count for |
1011 |
- * 'Finished' MAC. */ |
1012 |
- if (p[1] == 0 && p[2] == 0 &&p[3] == 0) |
1013 |
- { |
1014 |
- if (s->msg_callback) |
1015 |
- s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, |
1016 |
- p, DTLS1_HM_HEADER_LENGTH, s, |
1017 |
- s->msg_callback_arg); |
1018 |
- |
1019 |
- s->init_num = 0; |
1020 |
- return dtls1_get_message_fragment(s, st1, stn, |
1021 |
- max, ok); |
1022 |
- } |
1023 |
- else /* Incorrectly formated Hello request */ |
1024 |
- { |
1025 |
- al=SSL_AD_UNEXPECTED_MESSAGE; |
1026 |
- SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_UNEXPECTED_MESSAGE); |
1027 |
- goto f_err; |
1028 |
- } |
1029 |
- } |
1030 |
- |
1031 |
- /* XDTLS: do a sanity check on the fragment */ |
1032 |
- |
1033 |
- s->init_num += i; |
1034 |
- |
1035 |
- if ( s->d1->r_msg_hdr.frag_off == 0) /* first fragment */ |
1036 |
+ wire[0] == SSL3_MT_HELLO_REQUEST) |
1037 |
{ |
1038 |
- /* BUF_MEM_grow takes an 'int' parameter */ |
1039 |
- if (l > (INT_MAX-DTLS1_HM_HEADER_LENGTH)) |
1040 |
+ /* The server may always send 'Hello Request' messages -- |
1041 |
+ * we are doing a handshake anyway now, so ignore them |
1042 |
+ * if their format is correct. Does not count for |
1043 |
+ * 'Finished' MAC. */ |
1044 |
+ if (wire[1] == 0 && wire[2] == 0 && wire[3] == 0) |
1045 |
{ |
1046 |
- al=SSL_AD_ILLEGAL_PARAMETER; |
1047 |
- SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE); |
1048 |
- goto f_err; |
1049 |
- } |
1050 |
- if (l && !BUF_MEM_grow_clean(s->init_buf,(int)l |
1051 |
- + DTLS1_HM_HEADER_LENGTH)) |
1052 |
- { |
1053 |
- SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,ERR_R_BUF_LIB); |
1054 |
- goto err; |
1055 |
+ if (s->msg_callback) |
1056 |
+ s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, |
1057 |
+ wire, DTLS1_HM_HEADER_LENGTH, s, |
1058 |
+ s->msg_callback_arg); |
1059 |
+ |
1060 |
+ s->init_num = 0; |
1061 |
+ return dtls1_get_message_fragment(s, st1, stn, |
1062 |
+ max, ok); |
1063 |
} |
1064 |
- /* Only do this test when we're reading the expected message. |
1065 |
- * Stale messages will be dropped and future messages will be buffered */ |
1066 |
- if ( l > (unsigned long)max) |
1067 |
+ else /* Incorrectly formated Hello request */ |
1068 |
{ |
1069 |
- al=SSL_AD_ILLEGAL_PARAMETER; |
1070 |
- SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE); |
1071 |
+ al=SSL_AD_UNEXPECTED_MESSAGE; |
1072 |
+ SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_UNEXPECTED_MESSAGE); |
1073 |
goto f_err; |
1074 |
} |
1075 |
- |
1076 |
- s->s3->tmp.message_size=l; |
1077 |
} |
1078 |
|
1079 |
- if ( frag_len > (unsigned long)max) |
1080 |
- { |
1081 |
- al=SSL_AD_ILLEGAL_PARAMETER; |
1082 |
- SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE); |
1083 |
- goto f_err; |
1084 |
- } |
1085 |
- if ( frag_len + s->init_num > (INT_MAX - DTLS1_HM_HEADER_LENGTH)) |
1086 |
- { |
1087 |
- al=SSL_AD_ILLEGAL_PARAMETER; |
1088 |
- SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE); |
1089 |
- goto f_err; |
1090 |
- } |
1091 |
- |
1092 |
- if ( frag_len & !BUF_MEM_grow_clean(s->init_buf, (int)frag_len |
1093 |
- + DTLS1_HM_HEADER_LENGTH + s->init_num)) |
1094 |
- { |
1095 |
- SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,ERR_R_BUF_LIB); |
1096 |
- goto err; |
1097 |
- } |
1098 |
- |
1099 |
- if ( s->d1->r_msg_hdr.frag_off == 0) |
1100 |
- { |
1101 |
- s->s3->tmp.message_type = msg_hdr.type; |
1102 |
- s->d1->r_msg_hdr.type = msg_hdr.type; |
1103 |
- s->d1->r_msg_hdr.msg_len = l; |
1104 |
- /* s->d1->r_msg_hdr.seq = seq_num; */ |
1105 |
- } |
1106 |
+ if ((al=dtls1_preprocess_fragment(s,&msg_hdr,max))) |
1107 |
+ goto f_err; |
1108 |
|
1109 |
/* XDTLS: ressurect this when restart is in place */ |
1110 |
s->state=stn; |
1111 |
- |
1112 |
- /* next state (stn) */ |
1113 |
- p = (unsigned char *)s->init_buf->data; |
1114 |
|
1115 |
if ( frag_len > 0) |
1116 |
{ |
1117 |
+ unsigned char *p=s->init_buf->data+DTLS1_HM_HEADER_LENGTH; |
1118 |
+ |
1119 |
i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE, |
1120 |
- &p[s->init_num], |
1121 |
- frag_len,0); |
1122 |
- /* XDTLS: fix this--message fragments cannot span multiple packets */ |
1123 |
+ &p[frag_off],frag_len,0); |
1124 |
+ /* XDTLS: fix this--message fragments cannot span multiple packets */ |
1125 |
if (i <= 0) |
1126 |
{ |
1127 |
s->rwstate=SSL_READING; |
1128 |
@@ -689,70 +698,23 @@ dtls1_get_message_fragment(SSL *s, int s |
1129 |
else |
1130 |
i = 0; |
1131 |
|
1132 |
- /* XDTLS: an incorrectly formatted fragment should cause the |
1133 |
- * handshake to fail */ |
1134 |
+ /* XDTLS: an incorrectly formatted fragment should cause the |
1135 |
+ * handshake to fail */ |
1136 |
OPENSSL_assert(i == (int)frag_len); |
1137 |
|
1138 |
-#if 0 |
1139 |
- /* Successfully read a fragment. |
1140 |
- * It may be (1) out of order, or |
1141 |
- * (2) it's a repeat, in which case we dump it |
1142 |
- * (3) the one we are expecting next (maybe with overlap) |
1143 |
- * If it is next one, it may overlap with previously read bytes |
1144 |
- */ |
1145 |
+ *ok = 1; |
1146 |
|
1147 |
- /* case (1): buffer the future fragment |
1148 |
- * (we can treat fragments from a future message the same |
1149 |
- * as future fragments from the message being currently read, since |
1150 |
- * they are sematically simply out of order. |
1151 |
- */ |
1152 |
- if ( msg_hdr.seq > s->d1->handshake_read_seq || |
1153 |
- frag_off > s->init_num - DTLS1_HM_HEADER_LENGTH) |
1154 |
- { |
1155 |
- dtls1_buffer_handshake_fragment(s, &msg_hdr); |
1156 |
- return DTLS1_HM_FRAGMENT_RETRY; |
1157 |
- } |
1158 |
- |
1159 |
- /* case (2): drop the entire fragment, and try again */ |
1160 |
- if ( msg_hdr.seq < s->d1->handshake_read_seq || |
1161 |
- frag_off + frag_len < s->init_num - DTLS1_HM_HEADER_LENGTH) |
1162 |
- { |
1163 |
- s->init_num -= DTLS1_HM_HEADER_LENGTH; |
1164 |
- return DTLS1_HM_FRAGMENT_RETRY; |
1165 |
- } |
1166 |
-#endif |
1167 |
- |
1168 |
- /* case (3): received a immediately useful fragment. Determine the |
1169 |
- * possible overlap and copy the fragment. |
1170 |
- */ |
1171 |
- overlap = (s->init_num - DTLS1_HM_HEADER_LENGTH) - frag_off; |
1172 |
- |
1173 |
- /* retain the header for the first fragment */ |
1174 |
- if ( s->init_num > DTLS1_HM_HEADER_LENGTH) |
1175 |
- { |
1176 |
- memmove(&(s->init_buf->data[s->init_num]), |
1177 |
- &(s->init_buf->data[s->init_num + DTLS1_HM_HEADER_LENGTH + overlap]), |
1178 |
- frag_len - overlap); |
1179 |
- |
1180 |
- s->init_num += frag_len - overlap; |
1181 |
- } |
1182 |
- else |
1183 |
- s->init_num += frag_len; |
1184 |
- |
1185 |
- dtls1_process_handshake_fragment(s, frag_len - overlap); |
1186 |
- |
1187 |
- if (s->msg_callback) |
1188 |
- s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data, |
1189 |
- (size_t)s->init_num, s, |
1190 |
- s->msg_callback_arg); |
1191 |
- *ok=1; |
1192 |
- |
1193 |
- return s->init_num; |
1194 |
+ /* Note that s->init_num is *not* used as current offset in |
1195 |
+ * s->init_buf->data, but as a counter summing up fragments' |
1196 |
+ * lengths: as soon as they sum up to handshake packet |
1197 |
+ * length, we assume we have got all the fragments. */ |
1198 |
+ s->init_num += frag_len; |
1199 |
+ return frag_len; |
1200 |
|
1201 |
f_err: |
1202 |
ssl3_send_alert(s,SSL3_AL_FATAL,al); |
1203 |
- s->init_num = 0; |
1204 |
-err: |
1205 |
+ s->init_num = 0; |
1206 |
+ |
1207 |
*ok=0; |
1208 |
return(-1); |
1209 |
} |
1210 |
@@ -790,7 +752,7 @@ int dtls1_send_finished(SSL *s, int a, i |
1211 |
|
1212 |
/* buffer the message to handle re-xmits */ |
1213 |
dtls1_buffer_message(s, 0); |
1214 |
- |
1215 |
+ |
1216 |
s->state=b; |
1217 |
} |
1218 |
|
1219 |
@@ -815,10 +777,15 @@ int dtls1_send_change_cipher_spec(SSL *s |
1220 |
p=(unsigned char *)s->init_buf->data; |
1221 |
*p++=SSL3_MT_CCS; |
1222 |
s->d1->handshake_write_seq = s->d1->next_handshake_write_seq; |
1223 |
- s->d1->next_handshake_write_seq++; |
1224 |
- s2n(s->d1->handshake_write_seq,p); |
1225 |
- |
1226 |
s->init_num=DTLS1_CCS_HEADER_LENGTH; |
1227 |
+ |
1228 |
+ if (s->client_version == DTLS1_BAD_VER) |
1229 |
+ { |
1230 |
+ s->d1->next_handshake_write_seq++; |
1231 |
+ s2n(s->d1->handshake_write_seq,p); |
1232 |
+ s->init_num+=2; |
1233 |
+ } |
1234 |
+ |
1235 |
s->init_off=0; |
1236 |
|
1237 |
dtls1_set_message_header_int(s, SSL3_MT_CCS, 0, |
1238 |
@@ -1044,6 +1011,7 @@ dtls1_buffer_message(SSL *s, int is_ccs) |
1239 |
pitem *item; |
1240 |
hm_fragment *frag; |
1241 |
PQ_64BIT seq64; |
1242 |
+ unsigned int epoch = s->d1->w_epoch; |
1243 |
|
1244 |
/* this function is called immediately after a message has |
1245 |
* been serialized */ |
1246 |
@@ -1056,7 +1024,8 @@ dtls1_buffer_message(SSL *s, int is_ccs) |
1247 |
if ( is_ccs) |
1248 |
{ |
1249 |
OPENSSL_assert(s->d1->w_msg_hdr.msg_len + |
1250 |
- DTLS1_CCS_HEADER_LENGTH == (unsigned int)s->init_num); |
1251 |
+ DTLS1_CCS_HEADER_LENGTH <= (unsigned int)s->init_num); |
1252 |
+ epoch++; |
1253 |
} |
1254 |
else |
1255 |
{ |
1256 |
@@ -1072,7 +1041,7 @@ dtls1_buffer_message(SSL *s, int is_ccs) |
1257 |
frag->msg_header.is_ccs = is_ccs; |
1258 |
|
1259 |
pq_64bit_init(&seq64); |
1260 |
- pq_64bit_assign_word(&seq64, frag->msg_header.seq); |
1261 |
+ pq_64bit_assign_word(&seq64, epoch<<16 | frag->msg_header.seq); |
1262 |
|
1263 |
item = pitem_new(seq64, frag); |
1264 |
pq_64bit_free(&seq64); |
1265 |
@@ -1259,5 +1228,4 @@ dtls1_get_ccs_header(unsigned char *data |
1266 |
memset(ccs_hdr, 0x00, sizeof(struct ccs_header_st)); |
1267 |
|
1268 |
ccs_hdr->type = *(data++); |
1269 |
- n2s(data, ccs_hdr->seq); |
1270 |
} |
1271 |
diff -up openssl-fips-0.9.8f-dev/ssl/d1_clnt.c.dtls-fixes openssl-fips-0.9.8f-dev/ssl/d1_clnt.c |
1272 |
--- openssl-fips-0.9.8f-dev/ssl/d1_clnt.c.dtls-fixes 2005-12-05 18:32:19.000000000 +0100 |
1273 |
+++ openssl-fips-0.9.8f-dev/ssl/d1_clnt.c 2008-07-15 21:01:29.000000000 +0200 |
1274 |
@@ -214,17 +214,21 @@ int dtls1_connect(SSL *s) |
1275 |
|
1276 |
/* don't push the buffering BIO quite yet */ |
1277 |
|
1278 |
- ssl3_init_finished_mac(s); |
1279 |
- |
1280 |
s->state=SSL3_ST_CW_CLNT_HELLO_A; |
1281 |
s->ctx->stats.sess_connect++; |
1282 |
s->init_num=0; |
1283 |
+ /* mark client_random uninitialized */ |
1284 |
+ memset(s->s3->client_random,0,sizeof(s->s3->client_random)); |
1285 |
break; |
1286 |
|
1287 |
case SSL3_ST_CW_CLNT_HELLO_A: |
1288 |
case SSL3_ST_CW_CLNT_HELLO_B: |
1289 |
|
1290 |
s->shutdown=0; |
1291 |
+ |
1292 |
+ /* every DTLS ClientHello resets Finished MAC */ |
1293 |
+ ssl3_init_finished_mac(s); |
1294 |
+ |
1295 |
ret=dtls1_client_hello(s); |
1296 |
if (ret <= 0) goto end; |
1297 |
|
1298 |
@@ -422,6 +426,9 @@ int dtls1_connect(SSL *s) |
1299 |
s->s3->tmp.next_state=SSL3_ST_CR_FINISHED_A; |
1300 |
} |
1301 |
s->init_num=0; |
1302 |
+ /* mark client_random uninitialized */ |
1303 |
+ memset (s->s3->client_random,0,sizeof(s->s3->client_random)); |
1304 |
+ |
1305 |
break; |
1306 |
|
1307 |
case SSL3_ST_CR_FINISHED_A: |
1308 |
@@ -544,9 +551,15 @@ int dtls1_client_hello(SSL *s) |
1309 |
/* else use the pre-loaded session */ |
1310 |
|
1311 |
p=s->s3->client_random; |
1312 |
- Time=(unsigned long)time(NULL); /* Time */ |
1313 |
- l2n(Time,p); |
1314 |
- RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-sizeof(Time)); |
1315 |
+ /* if client_random is initialized, reuse it, we are |
1316 |
+ * required to use same upon reply to HelloVerify */ |
1317 |
+ for (i=0;p[i]=='\0' && i<sizeof(s->s3->client_random);i++) ; |
1318 |
+ if (i==sizeof(s->s3->client_random)) |
1319 |
+ { |
1320 |
+ Time=(unsigned long)time(NULL); /* Time */ |
1321 |
+ l2n(Time,p); |
1322 |
+ RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4); |
1323 |
+ } |
1324 |
|
1325 |
/* Do the message type and length last */ |
1326 |
d=p= &(buf[DTLS1_HM_HEADER_LENGTH]); |