1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116: #include <stdio.h>
117: #include "ssl_locl.h"
118: #include "kssl_lcl.h"
119: #include <openssl/buffer.h>
120: #include <openssl/rand.h>
121: #include <openssl/objects.h>
122: #include <openssl/evp.h>
123: #include <openssl/md5.h>
124: #ifndef OPENSSL_NO_DH
125: #include <openssl/dh.h>
126: #endif
127:
128: static SSL_METHOD *dtls1_get_client_method(int ver);
129: static int dtls1_get_hello_verify(SSL *s);
130:
131: static SSL_METHOD *dtls1_get_client_method(int ver)
132: {
133: if (ver == DTLS1_VERSION)
134: return(DTLSv1_client_method());
135: else
136: return(NULL);
137: }
138:
139: IMPLEMENT_dtls1_meth_func(DTLSv1_client_method,
140: ssl_undefined_function,
141: dtls1_connect,
142: dtls1_get_client_method)
143:
144: int dtls1_connect(SSL *s)
145: {
146: BUF_MEM *buf=NULL;
147: unsigned long Time=(unsigned long)time(NULL),l;
148: long num1;
149: void (*cb)(const SSL *ssl,int type,int val)=NULL;
150: int ret= -1;
151: int new_state,state,skip=0;;
152:
153: RAND_add(&Time,sizeof(Time),0);
154: ERR_clear_error();
155: clear_sys_error();
156:
157: if (s->info_callback != NULL)
158: cb=s->info_callback;
159: else if (s->ctx->info_callback != NULL)
160: cb=s->ctx->info_callback;
161:
162: s->in_handshake++;
163: if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);
164:
165: for (;;)
166: {
167: state=s->state;
168:
169: switch(s->state)
170: {
171: case SSL_ST_RENEGOTIATE:
172: s->new_session=1;
173: s->state=SSL_ST_CONNECT;
174: s->ctx->stats.sess_connect_renegotiate++;
175:
176: case SSL_ST_BEFORE:
177: case SSL_ST_CONNECT:
178: case SSL_ST_BEFORE|SSL_ST_CONNECT:
179: case SSL_ST_OK|SSL_ST_CONNECT:
180:
181: s->server=0;
182: if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
183:
184: if ((s->version & 0xff00 ) != (DTLS1_VERSION & 0xff00))
185: {
186: SSLerr(SSL_F_DTLS1_CONNECT, ERR_R_INTERNAL_ERROR);
187: ret = -1;
188: goto end;
189: }
190:
191:
192: s->type=SSL_ST_CONNECT;
193:
194: if (s->init_buf == NULL)
195: {
196: if ((buf=BUF_MEM_new()) == NULL)
197: {
198: ret= -1;
199: goto end;
200: }
201: if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH))
202: {
203: ret= -1;
204: goto end;
205: }
206: s->init_buf=buf;
207: buf=NULL;
208: }
209:
210: if (!ssl3_setup_buffers(s)) { ret= -1; goto end; }
211:
212:
213: if (!ssl_init_wbio_buffer(s,0)) { ret= -1; goto end; }
214:
215:
216:
217: s->state=SSL3_ST_CW_CLNT_HELLO_A;
218: s->ctx->stats.sess_connect++;
219: s->init_num=0;
220:
221: memset(s->s3->client_random,0,sizeof(s->s3->client_random));
222: break;
223:
224: case SSL3_ST_CW_CLNT_HELLO_A:
225: case SSL3_ST_CW_CLNT_HELLO_B:
226:
227: s->shutdown=0;
228:
229:
230: ssl3_init_finished_mac(s);
231:
232: ret=dtls1_client_hello(s);
233: if (ret <= 0) goto end;
234:
235: if ( s->d1->send_cookie)
236: {
237: s->state=SSL3_ST_CW_FLUSH;
238: s->s3->tmp.next_state=SSL3_ST_CR_SRVR_HELLO_A;
239: }
240: else
241: s->state=SSL3_ST_CR_SRVR_HELLO_A;
242:
243: s->init_num=0;
244:
245:
246: if (s->bbio != s->wbio)
247: s->wbio=BIO_push(s->bbio,s->wbio);
248:
249: break;
250:
251: case SSL3_ST_CR_SRVR_HELLO_A:
252: case SSL3_ST_CR_SRVR_HELLO_B:
253: ret=ssl3_get_server_hello(s);
254: if (ret <= 0) goto end;
255: else
256: {
257: if (s->hit)
258: s->state=SSL3_ST_CR_FINISHED_A;
259: else
260: s->state=DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A;
261: }
262: s->init_num=0;
263: break;
264:
265: case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A:
266: case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B:
267:
268: ret = dtls1_get_hello_verify(s);
269: if ( ret <= 0)
270: goto end;
271: if ( s->d1->send_cookie)
272: s->state=SSL3_ST_CW_CLNT_HELLO_A;
273: else
274: s->state = SSL3_ST_CR_CERT_A;
275: s->init_num = 0;
276: break;
277:
278: case SSL3_ST_CR_CERT_A:
279: case SSL3_ST_CR_CERT_B:
280:
281: if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL))
282: {
283: ret=ssl3_get_server_certificate(s);
284: if (ret <= 0) goto end;
285: }
286: else
287: skip=1;
288: s->state=SSL3_ST_CR_KEY_EXCH_A;
289: s->init_num=0;
290: break;
291:
292: case SSL3_ST_CR_KEY_EXCH_A:
293: case SSL3_ST_CR_KEY_EXCH_B:
294: ret=ssl3_get_key_exchange(s);
295: if (ret <= 0) goto end;
296: s->state=SSL3_ST_CR_CERT_REQ_A;
297: s->init_num=0;
298:
299:
300:
301: if (!ssl3_check_cert_and_algorithm(s))
302: {
303: ret= -1;
304: goto end;
305: }
306: break;
307:
308: case SSL3_ST_CR_CERT_REQ_A:
309: case SSL3_ST_CR_CERT_REQ_B:
310: ret=ssl3_get_certificate_request(s);
311: if (ret <= 0) goto end;
312: s->state=SSL3_ST_CR_SRVR_DONE_A;
313: s->init_num=0;
314: break;
315:
316: case SSL3_ST_CR_SRVR_DONE_A:
317: case SSL3_ST_CR_SRVR_DONE_B:
318: ret=ssl3_get_server_done(s);
319: if (ret <= 0) goto end;
320: if (s->s3->tmp.cert_req)
321: s->state=SSL3_ST_CW_CERT_A;
322: else
323: s->state=SSL3_ST_CW_KEY_EXCH_A;
324: s->init_num=0;
325:
326: break;
327:
328: case SSL3_ST_CW_CERT_A:
329: case SSL3_ST_CW_CERT_B:
330: case SSL3_ST_CW_CERT_C:
331: case SSL3_ST_CW_CERT_D:
332: ret=dtls1_send_client_certificate(s);
333: if (ret <= 0) goto end;
334: s->state=SSL3_ST_CW_KEY_EXCH_A;
335: s->init_num=0;
336: break;
337:
338: case SSL3_ST_CW_KEY_EXCH_A:
339: case SSL3_ST_CW_KEY_EXCH_B:
340: ret=dtls1_send_client_key_exchange(s);
341: if (ret <= 0) goto end;
342: l=s->s3->tmp.new_cipher->algorithms;
343:
344:
345:
346:
347: if (s->s3->tmp.cert_req == 1)
348: {
349: s->state=SSL3_ST_CW_CERT_VRFY_A;
350: }
351: else
352: {
353: s->state=SSL3_ST_CW_CHANGE_A;
354: s->s3->change_cipher_spec=0;
355: }
356:
357: s->init_num=0;
358: break;
359:
360: case SSL3_ST_CW_CERT_VRFY_A:
361: case SSL3_ST_CW_CERT_VRFY_B:
362: ret=dtls1_send_client_verify(s);
363: if (ret <= 0) goto end;
364: s->state=SSL3_ST_CW_CHANGE_A;
365: s->init_num=0;
366: s->s3->change_cipher_spec=0;
367: break;
368:
369: case SSL3_ST_CW_CHANGE_A:
370: case SSL3_ST_CW_CHANGE_B:
371: ret=dtls1_send_change_cipher_spec(s,
372: SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B);
373: if (ret <= 0) goto end;
374: s->state=SSL3_ST_CW_FINISHED_A;
375: s->init_num=0;
376:
377: s->session->cipher=s->s3->tmp.new_cipher;
378: #ifdef OPENSSL_NO_COMP
379: s->session->compress_meth=0;
380: #else
381: if (s->s3->tmp.new_compression == NULL)
382: s->session->compress_meth=0;
383: else
384: s->session->compress_meth=
385: s->s3->tmp.new_compression->id;
386: #endif
387: if (!s->method->ssl3_enc->setup_key_block(s))
388: {
389: ret= -1;
390: goto end;
391: }
392:
393: if (!s->method->ssl3_enc->change_cipher_state(s,
394: SSL3_CHANGE_CIPHER_CLIENT_WRITE))
395: {
396: ret= -1;
397: goto end;
398: }
399:
400: dtls1_reset_seq_numbers(s, SSL3_CC_WRITE);
401: break;
402:
403: case SSL3_ST_CW_FINISHED_A:
404: case SSL3_ST_CW_FINISHED_B:
405: ret=dtls1_send_finished(s,
406: SSL3_ST_CW_FINISHED_A,SSL3_ST_CW_FINISHED_B,
407: s->method->ssl3_enc->client_finished_label,
408: s->method->ssl3_enc->client_finished_label_len);
409: if (ret <= 0) goto end;
410: s->state=SSL3_ST_CW_FLUSH;
411:
412:
413: s->s3->flags&= ~SSL3_FLAGS_POP_BUFFER;
414: if (s->hit)
415: {
416: s->s3->tmp.next_state=SSL_ST_OK;
417: if (s->s3->flags & SSL3_FLAGS_DELAY_CLIENT_FINISHED)
418: {
419: s->state=SSL_ST_OK;
420: s->s3->flags|=SSL3_FLAGS_POP_BUFFER;
421: s->s3->delay_buf_pop_ret=0;
422: }
423: }
424: else
425: {
426: s->s3->tmp.next_state=SSL3_ST_CR_FINISHED_A;
427: }
428: s->init_num=0;
429:
430: memset (s->s3->client_random,0,sizeof(s->s3->client_random));
431:
432: break;
433:
434: case SSL3_ST_CR_FINISHED_A:
435: case SSL3_ST_CR_FINISHED_B:
436:
437: ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A,
438: SSL3_ST_CR_FINISHED_B);
439: if (ret <= 0) goto end;
440:
441: if (s->hit)
442: s->state=SSL3_ST_CW_CHANGE_A;
443: else
444: s->state=SSL_ST_OK;
445: s->init_num=0;
446: break;
447:
448: case SSL3_ST_CW_FLUSH:
449:
450: num1=BIO_ctrl(s->wbio,BIO_CTRL_INFO,0,NULL);
451: if (num1 > 0)
452: {
453: s->rwstate=SSL_WRITING;
454: num1=BIO_flush(s->wbio);
455: if (num1 <= 0) { ret= -1; goto end; }
456: s->rwstate=SSL_NOTHING;
457: }
458:
459: s->state=s->s3->tmp.next_state;
460: break;
461:
462: case SSL_ST_OK:
463:
464: ssl3_cleanup_key_block(s);
465:
466: #if 0
467: if (s->init_buf != NULL)
468: {
469: BUF_MEM_free(s->init_buf);
470: s->init_buf=NULL;
471: }
472: #endif
473:
474:
475:
476: if (!(s->s3->flags & SSL3_FLAGS_POP_BUFFER))
477: ssl_free_wbio_buffer(s);
478:
479:
480: s->init_num=0;
481: s->new_session=0;
482:
483: ssl_update_cache(s,SSL_SESS_CACHE_CLIENT);
484: if (s->hit) s->ctx->stats.sess_hit++;
485:
486: ret=1;
487:
488: s->handshake_func=dtls1_connect;
489: s->ctx->stats.sess_connect_good++;
490:
491: if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1);
492:
493:
494: s->d1->handshake_read_seq = 0;
495: goto end;
496:
497:
498: default:
499: SSLerr(SSL_F_DTLS1_CONNECT,SSL_R_UNKNOWN_STATE);
500: ret= -1;
501: goto end;
502:
503: }
504:
505:
506: if (!s->s3->tmp.reuse_message && !skip)
507: {
508: if (s->debug)
509: {
510: if ((ret=BIO_flush(s->wbio)) <= 0)
511: goto end;
512: }
513:
514: if ((cb != NULL) && (s->state != state))
515: {
516: new_state=s->state;
517: s->state=state;
518: cb(s,SSL_CB_CONNECT_LOOP,1);
519: s->state=new_state;
520: }
521: }
522: skip=0;
523: }
524: end:
525: s->in_handshake--;
526: if (buf != NULL)
527: BUF_MEM_free(buf);
528: if (cb != NULL)
529: cb(s,SSL_CB_CONNECT_EXIT,ret);
530: return(ret);
531: }
532:
533: int dtls1_client_hello(SSL *s)
534: {
535: unsigned char *buf;
536: unsigned char *p,*d;
537: unsigned int i,j;
538: unsigned long Time,l;
539: SSL_COMP *comp;
540:
541: buf=(unsigned char *)s->init_buf->data;
542: if (s->state == SSL3_ST_CW_CLNT_HELLO_A)
543: {
544: if ((s->session == NULL) ||
545: (s->session->ssl_version != s->version) ||
546: (s->session->not_resumable))
547: {
548: if (!ssl_get_new_session(s,0))
549: goto err;
550: }
551:
552:
553: p=s->s3->client_random;
554:
555:
556: for (i=0;p[i]=='\0' && i<sizeof(s->s3->client_random);i++) ;
557: if (i==sizeof(