added some support for session resuming (in client)
[gnutls:gnutls.git] / lib / gnutls_handshake.c
1 /*
2  *      Copyright (C) 2000 Nikos Mavroyanopoulos
3  *
4  * This file is part of GNUTLS.
5  *
6  * GNUTLS is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GNUTLS is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <defines.h>
22 #include "gnutls_int.h"
23 #include "gnutls_errors.h"
24 #include "gnutls_dh.h"
25 #include "debug.h"
26 #include "gnutls_algorithms.h"
27 #include "gnutls_compress.h"
28 #include "gnutls_plaintext.h"
29 #include "gnutls_cipher.h"
30 #include "gnutls_buffers.h"
31 #include "gnutls_kx.h"
32 #include "gnutls_handshake.h"
33 #include "gnutls_num.h"
34 #include "gnutls_hash_int.h"
35
36 #ifdef DEBUG
37 #define ERR(x, y) fprintf(stderr, "GNUTLS Error: %s (%d)\n", x,y)
38 #else
39 #define ERR(x, y)
40 #endif
41
42
43 /* Calculate The SSL3 Finished message */
44 #define SSL3_CLIENT_MSG "CLNT"
45 #define SSL3_SERVER_MSG "SRVR"
46 void* _gnutls_ssl3_finished( GNUTLS_STATE state, int type, int skip) {
47         int siz;
48         GNUTLS_MAC_HANDLE td;
49         GNUTLS_MAC_HANDLE td2;
50         char* data;
51         char* concat=gnutls_malloc(36);
52         char *mesg;
53         
54         td = gnutls_mac_init_ssl3_handshake( GNUTLS_MAC_MD5, state->security_parameters.master_secret, 48);
55         td2 = gnutls_mac_init_ssl3_handshake( GNUTLS_MAC_SHA, state->security_parameters.master_secret, 48);
56                         
57         siz = gnutls_getHashDataBufferSize( state) - skip;
58         data = gnutls_malloc( siz);
59
60         gnutls_readHashDataFromBuffer( state, data, siz);
61
62         gnutls_mac_ssl3(td, data, siz);
63         gnutls_mac_ssl3(td2, data, siz);
64         gnutls_free(data);
65         
66         if (type==GNUTLS_SERVER) {
67                 mesg = SSL3_SERVER_MSG;
68         } else {
69                 mesg = SSL3_CLIENT_MSG;
70         }
71         siz = strlen(mesg);
72         gnutls_mac_ssl3(td, mesg, siz);
73         gnutls_mac_ssl3(td2, mesg, siz);
74
75         data = gnutls_mac_deinit_ssl3_handshake(td);
76         memcpy( concat, data, 16);
77         gnutls_free(data);
78                         
79         data = gnutls_mac_deinit_ssl3_handshake(td2);
80
81         memcpy( &concat[16], data, 20);
82         gnutls_free(data);
83         return concat;
84 }
85
86 /* Hash the handshake messages as required by TLS 1.0 */
87 #define SERVER_MSG "server finished"
88 #define CLIENT_MSG "client finished"
89 void* _gnutls_finished( GNUTLS_STATE state, int type, int skip) {
90         int siz;
91         GNUTLS_MAC_HANDLE td;
92         GNUTLS_MAC_HANDLE td2;
93         char* data;
94         char concat[36];
95         char *mesg;
96         
97         td = gnutls_hash_init( GNUTLS_MAC_MD5);
98         td2 = gnutls_hash_init( GNUTLS_MAC_SHA);
99         
100         siz = gnutls_getHashDataBufferSize( state) - skip;
101         data = gnutls_malloc( siz);
102
103         gnutls_readHashDataFromBuffer( state, data, siz);
104
105         gnutls_hash(td, data, siz);
106         gnutls_hash(td2, data, siz);
107                         
108         gnutls_free(data);
109         
110         data = gnutls_hash_deinit(td);
111         memcpy( concat, data, 16);
112         gnutls_free(data);
113                         
114         data = gnutls_hash_deinit(td2);
115
116         memcpy( &concat[16], data, 20);
117         gnutls_free(data);
118
119         if (type==GNUTLS_SERVER) {
120                 mesg=SERVER_MSG;
121         } else {
122                 mesg=CLIENT_MSG;
123         }
124         data =
125             gnutls_PRF( state->security_parameters.master_secret,
126                48, mesg, strlen(mesg), concat,
127                36, 12);                 
128         return data;
129 }
130
131
132 /* This is to be called after sending CHANGE CIPHER SPEC packet
133  * and initializing encryption. This is the first encrypted message
134  * we send.
135  */
136 int _gnutls_send_finished(int cd, GNUTLS_STATE state)
137 {
138         uint8 *data;
139         int ret;
140         int data_size;
141
142         if (_gnutls_version_ssl3(state->connection_state.version) == 0) {
143                 data = _gnutls_ssl3_finished( state, state->security_parameters.entity, 0);
144                 data_size = 36;
145         } else { /* TLS 1.0 */
146                 data = _gnutls_finished( state, state->security_parameters.entity, 0);
147                 data_size=12;
148         }
149
150         ret = _gnutls_send_handshake(cd, state, data, data_size, GNUTLS_FINISHED);
151 #ifdef HANDSHAKE_DEBUG
152         fprintf(stderr, "Send finished\n");
153 #endif
154         gnutls_free(data);
155
156         return ret;
157 }
158
159 /* This is to be called after sending our finished message. If everything
160  * went fine we have negotiated a secure connection 
161  */
162 #define HANDSHAKE_HEADERS_SIZE 4
163 int _gnutls_recv_finished(int cd, GNUTLS_STATE state)
164 {
165         uint8 *data, *vrfy;
166         int data_size;
167         uint8* concat;  /* md5+sha1 */
168         int ret;
169         int vrfysize;
170
171         ret = 0;
172
173         ret = _gnutls_recv_handshake(cd, state, &vrfy, &vrfysize, GNUTLS_FINISHED);
174         if (ret < 0) {
175                 ERR("recv finished int", ret);
176                 return ret;
177         }
178
179         if (_gnutls_version_ssl3(state->connection_state.version) == 0) {
180                 data_size=36;
181         } else {
182                 data_size=12;
183         }
184         
185         if (vrfysize != data_size) {
186                 gnutls_assert();
187                 return GNUTLS_E_ERROR_IN_FINISHED_PACKET;
188         }
189
190         if (_gnutls_version_ssl3(state->connection_state.version) == 0) {
191                 /* skip the bytes from the last message */
192                 data = _gnutls_ssl3_finished( state, (state->security_parameters.entity+1)%2, vrfysize + HANDSHAKE_HEADERS_SIZE);
193         } else { /* TLS 1.0 */
194                 data = _gnutls_finished( state, (state->security_parameters.entity+1)%2, vrfysize + HANDSHAKE_HEADERS_SIZE);
195         }
196
197         if (memcmp(vrfy, data, data_size) != 0) {
198                 gnutls_assert();
199                 ret = GNUTLS_E_ERROR_IN_FINISHED_PACKET;
200         }
201
202         gnutls_free(data);
203         gnutls_free(vrfy);
204         
205         return ret;
206 }
207
208
209 /* This selects the best supported ciphersuite from the ones provided */
210 static int SelectSuite(GNUTLS_STATE state, opaque ret[2], char *data, int datalen)
211 {
212         int x, i, j;
213         GNUTLS_CipherSuite *ciphers;
214
215         x = _gnutls_supported_ciphersuites(state, &ciphers);
216 #ifdef HARD_DEBUG
217         fprintf(stderr, "Requested cipher suites: \n");
218         for (j=0;j<datalen;j+=2) fprintf(stderr, "\t%s\n", _gnutls_cipher_suite_get_name( *((GNUTLS_CipherSuite*)&data[j]) ));
219         fprintf(stderr, "Supported cipher suites: \n");
220         for (j=0;j<x;j++) fprintf(stderr, "\t%s\n", _gnutls_cipher_suite_get_name(ciphers[j]));
221 #endif
222         memset(ret, '\0', sizeof(GNUTLS_CipherSuite));
223
224         for (j = 0; j < datalen; j += 2) {
225                 for (i = 0; i < x; i++) {
226                         if (memcmp(&ciphers[i].CipherSuite, &data[j], 2) == 0) {
227 #ifdef HARD_DEBUG
228                                 fprintf(stderr, "Selected cipher suite: ");
229                                 fprintf(stderr, "%s\n", _gnutls_cipher_suite_get_name( *((GNUTLS_CipherSuite*)&data[j]) ));
230 #endif
231                                 memmove(ret, &ciphers[i].CipherSuite, 2);
232                                 gnutls_free(ciphers);
233                                 
234                                 return 0;
235                         }
236                 }
237         }
238
239
240         gnutls_free(ciphers);
241         gnutls_assert();
242         return GNUTLS_E_UNKNOWN_CIPHER_SUITE;
243
244 }
245
246 /* This selects the best supported compression method from the ones provided */
247 static int SelectCompMethod(GNUTLS_STATE state, CompressionMethod * ret, opaque *data, int datalen)
248 {
249         int x, i, j;
250         CompressionMethod *ciphers;
251
252         x = _gnutls_supported_compression_methods(state, &ciphers);
253         memset(ret, '\0', sizeof(CompressionMethod));
254
255         for (j = 0; j < datalen; j++) {
256                 for (i = 0; i < x; i++) {
257                         if ( ciphers[i] == data[j]) {
258                                 *ret = ciphers[i];
259                                 gnutls_free(ciphers);
260                                 return 0;
261                         }
262                 }
263         }
264
265         /* we were not able to find a compatible compression
266          * algorithm
267          */
268         gnutls_free(ciphers);
269         gnutls_assert();
270         return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
271
272 }
273
274 int _gnutls_send_handshake(int cd, GNUTLS_STATE state, void *i_data,
275                            uint32 i_datasize, HandshakeType type)
276 {
277         int ret;
278         uint8 *data;
279         uint24 length;
280         uint32 datasize;
281         int pos = 0;
282
283
284 #ifdef WORDS_BIGENDIAN
285         datasize = i_datasize;
286 #else
287         datasize = byteswap32(i_datasize);
288 #endif
289
290         length = uint32touint24(datasize);
291
292         i_datasize += HANDSHAKE_HEADERS_SIZE;
293         data = gnutls_malloc(i_datasize);
294
295         memmove(&data[pos++], &type, 1);
296         memmove(&data[pos++], &length.pint[0], 1);
297         memmove(&data[pos++], &length.pint[1], 1);
298         memmove(&data[pos++], &length.pint[2], 1);
299
300         if (i_datasize > 4)
301                 memmove(&data[pos], i_data, i_datasize - 4);
302
303 #ifdef HANDSHAKE_DEBUG
304         fprintf(stderr, "Send HANDSHAKE[%d] of %d bytes\n", type, i_datasize+4);
305 #endif
306
307         /* Here we keep the handshake messages in order to hash them later!
308          */
309         if (type!=GNUTLS_HELLO_REQUEST)
310                 gnutls_insertHashDataBuffer( state, data, i_datasize);
311
312         ret =
313                 _gnutls_Send_int(cd, state, GNUTLS_HANDSHAKE, data, i_datasize);
314
315         gnutls_free(data);
316         return ret;
317 }
318
319
320 /* This function will receive handshake messages of the given types,
321  * and will pass the message to the right place in order to be processed.
322  * Eg. for the SERVER_HELLO message (if it is expected), it will be
323  * send to _gnutls_recv_hello().
324  */
325 int _gnutls_recv_handshake(int cd, GNUTLS_STATE state, uint8 **data,
326                                 int* datalen, HandshakeType type)
327 {
328         int ret;
329         uint32 length32 = 0, sum=0;
330         uint8 *dataptr;
331         uint24 num;
332
333
334         if (type==GNUTLS_CERTIFICATE) {
335         /* If the ciphersuite does not support certificate just quit */
336                 if (state->security_parameters.entity == GNUTLS_CLIENT) {
337                         if ( _gnutls_kx_server_certificate( 
338                                 _gnutls_cipher_suite_get_kx_algo(state->gnutls_internals.current_cipher_suite)) ==0 )
339                         return 0;
340                 } else { /* server */
341                         if (_gnutls_kx_client_certificate( _gnutls_cipher_suite_get_kx_algo(state->gnutls_internals.current_cipher_suite)==0))
342                         return 0;
343                 }
344         }
345
346         dataptr = gnutls_malloc(HANDSHAKE_HEADERS_SIZE);
347         
348         ret = _gnutls_Recv_int(cd, state, GNUTLS_HANDSHAKE, dataptr, HANDSHAKE_HEADERS_SIZE);
349         if (ret < 0) {
350                 gnutls_free(dataptr);
351                 return ret;
352         }
353         if (ret!=HANDSHAKE_HEADERS_SIZE) {
354                 gnutls_assert();
355                 gnutls_free(dataptr);
356                 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
357         }
358
359         if (dataptr[0]!=type) {
360                 gnutls_assert();
361                 gnutls_free(dataptr);
362                 return GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET;
363         }
364         
365         num.pint[0] = dataptr[1];
366         num.pint[1] = dataptr[2];
367         num.pint[2] = dataptr[3];
368         length32 = uint24touint32(num);
369
370 #ifndef WORDS_BIGENDIAN
371         length32 = byteswap32(length32);
372 #endif
373 #ifdef HANDSHAKE_DEBUG
374         fprintf(stderr, "Received HANDSHAKE[%d] of %d bytes\n", dataptr[0], length32+4);
375 #endif
376
377         dataptr = gnutls_realloc( dataptr, length32+HANDSHAKE_HEADERS_SIZE);
378         if (length32>0 && data!=NULL)
379                 *data = gnutls_malloc( length32);
380
381         if (datalen!=NULL) *datalen = length32;
382
383         sum=HANDSHAKE_HEADERS_SIZE;
384         do {
385                 ret = _gnutls_Recv_int(cd, state, GNUTLS_HANDSHAKE, &dataptr[sum], length32);
386                 sum += ret;
387         } while( ( (sum-HANDSHAKE_HEADERS_SIZE) < length32) && (ret > 0) );
388
389         if (ret < 0) {
390                 gnutls_assert();
391                 gnutls_free(dataptr);
392                 return ret;
393         }
394         ret = GNUTLS_E_UNKNOWN_ERROR;
395
396         if (length32 > 0 && data!=NULL)
397                 memmove( *data, &dataptr[HANDSHAKE_HEADERS_SIZE], length32);
398
399         /* here we buffer the handshake messages - needed at Finished message */
400         gnutls_insertHashDataBuffer( state, dataptr, length32+HANDSHAKE_HEADERS_SIZE);
401
402         switch (dataptr[0]) {
403         case GNUTLS_CLIENT_HELLO:
404         case GNUTLS_SERVER_HELLO:
405                 ret = _gnutls_recv_hello(cd, state, &dataptr[HANDSHAKE_HEADERS_SIZE],
406                                                length32);
407                 break;
408         case GNUTLS_CERTIFICATE:
409                 ret = _gnutls_recv_certificate(cd, state, &dataptr[HANDSHAKE_HEADERS_SIZE],
410                                                length32);
411                 break;
412         case GNUTLS_SERVER_HELLO_DONE:
413                 ret = 0;
414                 break;
415         case GNUTLS_FINISHED:
416                 ret = length32;
417                 break;
418         case GNUTLS_SERVER_KEY_EXCHANGE:
419                 ret = length32;
420                 break;
421         case GNUTLS_CLIENT_KEY_EXCHANGE:
422                 ret = length32;
423                 break;
424         case GNUTLS_CERTIFICATE_REQUEST:
425 #ifdef HARD_DEBUG
426                 fprintf(stderr, "Requested Client Certificate!\n");
427 #endif
428         /* FIXME: just ignore that message for the time being 
429          * we have to parse it and the store the needed information
430          */
431                 state->gnutls_internals.certificate_requested = 1;
432                 ret = length32;
433                 break;
434         default:
435                 gnutls_assert();
436                 ret = GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET;
437         }
438         gnutls_free(dataptr);
439         return ret;
440 }
441
442 int _gnutls_send_hello_request(int cd, GNUTLS_STATE state)
443 {
444         return _gnutls_send_handshake(cd, state, NULL, 0,
445                                       GNUTLS_HELLO_REQUEST);
446 }
447
448 int _gnutls_send_client_certificate(int cd, GNUTLS_STATE state)
449 {
450         char data[1];
451         int ret;
452         
453         if (state->gnutls_internals.certificate_requested==0) return 0;
454
455         /* we do not have that functionality yet */
456         state->gnutls_internals.certificate_verify_needed = 0;
457 #ifdef HARD_DEBUG
458         fprintf(stderr, "Sending Client Certificate\n");
459 #endif
460
461 /* Here since we do not support certificates yet we
462  * do not have that functionality.
463  */
464         data[0] = 0;
465         ret = _gnutls_send_handshake(cd, state, &data, 1,
466                                       GNUTLS_CERTIFICATE);
467                                       
468         return ret;
469 }
470
471
472 int _gnutls_send_hello(int cd, GNUTLS_STATE state, opaque * SessionID,
473                        uint8 SessionIDLen)
474 {
475         char *rand;
476         char *data = NULL;
477         uint8 session_id_len, z;
478         uint32 cur_time;
479         int pos = 0;
480         GNUTLS_CipherSuite *cipher_suites;
481         CompressionMethod *compression_methods;
482         int i, datalen, ret = 0;
483         uint16 x;
484
485         session_id_len = SessionIDLen;
486         if (SessionID == NULL)
487                 session_id_len = 0;
488
489         rand = gcry_random_bytes(28, GCRY_STRONG_RANDOM);
490
491         if (state->security_parameters.entity == GNUTLS_CLIENT) {
492
493                 datalen = 2 + 4 + (session_id_len + 1) + 28 + 3;
494                 /* 2 for version, 4 for unix time, 28 for random bytes 2 for cipher suite's
495                  * size and 1 for compression method's size 
496                  */
497                 data = gnutls_malloc(datalen);
498
499                 data[pos++] = state->connection_state.version.major;
500                 data[pos++] = state->connection_state.version.minor;
501 #ifdef WORDS_BIGENDIAN
502                 cur_time = time(NULL);
503 #else
504                 cur_time = byteswap32(time(NULL));
505 #endif
506                 memmove(state->security_parameters.client_random,
507                         &cur_time, 4);
508                 memmove(&state->security_parameters.client_random[4], rand,
509                         28);
510
511                 memmove(&data[pos], &cur_time, 4);
512                 pos += 4;
513                 memmove(&data[pos], rand, 28);
514                 pos += 28;
515
516                 memmove(&data[pos++], &session_id_len, 1);
517
518                 if (session_id_len > 0) {
519                         memmove(&data[pos], SessionID, session_id_len);
520                 }
521                 pos += session_id_len;
522
523                 x = _gnutls_supported_ciphersuites(state, &cipher_suites);
524                 x *= sizeof(uint16); /* in order to get bytes */
525 #ifdef WORDS_BIGENDIAN
526                 memmove(&data[pos], &x, sizeof(uint16));
527 #else
528                 x = byteswap16(x);
529                 memmove(&data[pos], &x, sizeof(uint16));
530                 x = byteswap16(x);
531 #endif
532                 pos += sizeof(uint16);
533
534                 datalen += x;
535                 data = gnutls_realloc(data, datalen);
536
537                 for (i = 0; i < x/2; i++) {
538                         memmove(&data[pos], &cipher_suites[i].CipherSuite,
539                                 2);
540                         pos += 2;
541                 }
542
543                 z = _gnutls_supported_compression_methods
544                     (state, &compression_methods);
545                 memmove(&data[pos++], &z, 1); /* put the number of compression methods */
546
547                 datalen += z; 
548                 data = gnutls_realloc(data, datalen);
549                 
550                 for (i = 0; i < z; i++) {
551                         memmove(&data[pos++], &compression_methods[i], 1);
552                 }
553
554                 gcry_free(rand);
555                 gnutls_free(cipher_suites);
556                 gnutls_free(compression_methods);
557
558                 ret =
559                     _gnutls_send_handshake(cd, state, data, datalen,
560                                            GNUTLS_CLIENT_HELLO);
561                 gnutls_free(data);
562
563
564         } else {                /* SERVER */
565                 datalen = 2 + sizeof(uint32) + session_id_len + 1 + 28;
566                 data = gnutls_malloc(datalen);
567
568                 data[pos++] = state->connection_state.version.major;
569                 data[pos++] = state->connection_state.version.minor;
570 #ifdef WORDS_BIGENDIAN
571                 cur_time = time(NULL);
572 #else
573                 cur_time = byteswap32(time(NULL));
574 #endif
575                 memmove(state->security_parameters.server_random,
576                         &cur_time, 4);
577                 memmove(&state->security_parameters.server_random[4], rand,
578                         28);
579
580                 memmove(&data[pos], &cur_time, sizeof(uint32));
581                 pos += sizeof(uint32);
582                 memmove(&data[pos], rand, 28);
583                 pos += 28;
584
585                 memmove(&data[pos++], &session_id_len, sizeof(uint8));
586                 if (session_id_len > 0) {
587                         memmove(&data[pos], SessionID, session_id_len);
588                 }
589                 pos += session_id_len;
590
591                 datalen += 2;
592                 data = gnutls_realloc(data, datalen);
593                 memmove(&data[pos],
594                         &state->gnutls_internals.
595                         current_cipher_suite.CipherSuite, 2);
596                 pos += 2;
597
598                 datalen += 1;
599                 data = gnutls_realloc(data, datalen);
600                 memmove(&data[pos++],
601                         &state->gnutls_internals.compression_method, 1);
602
603                 gcry_free(rand);
604                 ret =
605                     _gnutls_send_handshake(cd, state, data, datalen,
606                                            GNUTLS_SERVER_HELLO);
607                 gnutls_free(data);
608
609         }
610
611         return ret;
612 }
613
614
615 /* RECEIVE A HELLO MESSAGE. This should be called from gnutls_recv_handshake_int only if a
616  * hello message is expected. It uses the gnutls_internals.current_cipher_suite
617  * and gnutls_internals.compression_method.
618  */
619 int _gnutls_recv_hello(int cd, GNUTLS_STATE state, char *data, int datalen)
620 {
621         uint8 session_id_len = 0, z;
622         int pos = 0;
623         GNUTLS_CipherSuite cipher_suite, *cipher_suites;
624         CompressionMethod compression_method, *compression_methods;
625         int i, ret=0;
626         uint16 x, sizeOfSuites;
627         GNUTLS_Version version;
628
629         if (state->security_parameters.entity == GNUTLS_CLIENT) {
630                 if (datalen < 38) {
631                         gnutls_assert();
632                         return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
633                 }
634
635 #ifdef DEBUG
636                 fprintf(stderr, "Server's version: %d.%d\n", data[pos], data[pos+1]);
637 #endif
638                 version.local = 0; /* TLS 1.0 / SSL 3.0 */
639                 version.major = data[pos];
640                 version.minor = data[pos+1];
641                 if ( _gnutls_version_is_supported( state, version) == 0) {
642                         gnutls_assert();
643                         return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
644                 } else {
645                         gnutls_set_current_version(state, version);
646                 }
647                 pos+=2;
648                 
649                 memmove(state->security_parameters.server_random,
650                         &data[pos], 32);
651                 pos += 32;
652
653                 memmove(&session_id_len, &data[pos++], 1);
654
655                 if (datalen < 38 + session_id_len) {
656                         gnutls_assert();
657                         return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
658                 }
659 #ifdef HARD_DEBUG
660                 fprintf(stderr, "SessionID length: %d\n", session_id_len);
661                 fprintf(stderr, "SessionID: %s\n",
662                         _gnutls_bin2hex(&data[pos], session_id_len));
663 #endif
664                 if ( (state->gnutls_internals.resumed_security_parameters.session_id_size>0) 
665                         && memcmp(&data[pos], state->gnutls_internals.resumed_security_parameters.session_id, session_id_len)==0) {
666                         /* resume session */
667                         
668 #ifdef DEBUG
669                         fprintf(stderr, "Resuming session\n");
670 #endif
671                          state->gnutls_internals.resumed=RESUME_TRUE; /* we are resuming */
672                          return 0;
673                 } else {
674                         /* keep the session id */
675                         state->gnutls_internals.resumed=RESUME_FALSE; /* we are not resuming */
676                         state->security_parameters.session_id_size = session_id_len;
677                         memcpy( state->security_parameters.session_id, &data[pos], session_id_len);
678                 }
679
680                 pos += session_id_len;
681
682                 memmove(&cipher_suite.CipherSuite, &data[pos], 2);
683                 pos += 2;
684
685                 z = 1;
686                 x = _gnutls_supported_ciphersuites(state, &cipher_suites);
687                 for (i = 0; i < x; i++) {
688                         if (memcmp
689                             (&cipher_suites[i], cipher_suite.CipherSuite,
690                              2) == 0) {
691                                 z = 0;
692
693                         }
694                 }
695                 if (z != 0)
696                         return GNUTLS_E_UNKNOWN_CIPHER_TYPE;
697                 memmove(state->gnutls_internals.
698                         current_cipher_suite.CipherSuite,
699                         cipher_suite.CipherSuite, 2);
700 #ifdef HARD_DEBUG
701                                 fprintf(stderr, "Selected cipher suite: ");
702                                 fprintf(stderr, "%s\n", _gnutls_cipher_suite_get_name(state->gnutls_internals.current_cipher_suite ) );
703 #endif
704                 z = 1;
705                 memmove(&compression_method, &data[pos++], 1);
706                 z =
707                     _gnutls_supported_compression_methods
708                     (state, &compression_methods);
709                 for (i = 0; i < z; i++) {
710                         if (memcmp
711                             (&compression_methods[i], &compression_method,
712                              1) == 0) {
713                                 z = 0;
714
715                         }
716                 }
717                 if (z != 0)
718                         return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
719                 memmove(&state->gnutls_internals.compression_method,
720                         &compression_method, 1);
721
722
723                 gnutls_free(cipher_suites);
724                 gnutls_free(compression_methods);
725
726         } else {                /* Server side reading a client hello */
727                 if (datalen < 35) {
728                         gnutls_assert();
729                         return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
730                 }
731
732 #ifdef DEBUG
733                 fprintf(stderr, "Client's version: %d.%d\n", data[pos], data[pos+1]);
734 #endif
735                 version.local = 0; /* TLS 1.0 / SSL 3.0 */
736                 version.major = data[pos];
737                 version.minor = data[pos+1];
738                 if ( _gnutls_version_is_supported( state, version) == 0) {
739                         gnutls_assert();
740                         return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
741                 } else {
742                         gnutls_set_current_version(state, version);
743                 }
744                 pos+=2;
745                 
746                 memmove(state->security_parameters.client_random,
747                         &data[pos], 32);
748                 pos += 32;
749
750                 memmove(&session_id_len, &data[pos++], 1);
751                 pos += session_id_len;
752
753                 /* We should resume an old connection here. This is not
754                  * implemented yet.
755                  */
756
757
758                 /* Select a ciphersuite */
759                 memmove(&sizeOfSuites, &data[pos], 2);
760                 pos += 2;
761 #ifndef WORDS_BIGENDIAN
762                 sizeOfSuites = byteswap16(sizeOfSuites);
763 #endif
764                 ret = SelectSuite(state, state->gnutls_internals.
765                             current_cipher_suite.CipherSuite, &data[pos],
766                             sizeOfSuites); 
767
768                 if (ret<0) return ret;
769                 
770                 pos += sizeOfSuites;
771
772                 memmove(&z, &data[pos++], 1); /* z is the number of compression methods */
773                 ret = SelectCompMethod(state, &state->
774                                  gnutls_internals.compression_method,
775                                  &data[pos], z);
776                 pos+=z;
777                 
778                 if (ret < 0) {
779                         return ret;
780                 }
781         }
782
783         return ret;
784 }
785
786 int _gnutls_recv_certificate(int cd, GNUTLS_STATE state, char *data, int datalen)
787 {
788         uint8 session_id_len = 0, z;
789         int pos = 0;
790         char* certificate_list;
791         int i, ret=0;
792         uint16 x;
793         uint32 sizeOfCert;
794         uint24 num;
795         
796         if (state->security_parameters.entity == GNUTLS_CLIENT) {
797                 if (datalen < 2) {
798                         gnutls_assert();
799                         return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
800                 }
801
802                 num.pint[0] = data[pos];
803                 num.pint[1] = data[pos+1];
804                 num.pint[2] = data[pos+2];
805                 sizeOfCert = uint24touint32(num);
806                 
807                 pos+=3;
808 #ifndef WORDS_BIGENDIAN
809                 sizeOfCert=byteswap32(sizeOfCert);
810 #endif
811                 if (sizeOfCert > MAX24) {
812                         gnutls_assert();
813                         return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
814                 }
815                 certificate_list = gnutls_malloc(sizeOfCert);
816                 
817                 memmove( certificate_list, &data[pos], sizeOfCert);
818                 
819                 /* Verify certificates !!! */
820                 
821                 gnutls_free(certificate_list); /* oooops! */
822
823         } else {                /* Server side reading a client certificate */
824                 /* actually this is not complete */
825                 if (datalen < 1) {
826                         gnutls_assert();
827                         return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
828                 }
829
830                 ret = 0;
831         }
832
833         return ret;
834 }
835
836
837 /* This is the main function in the handshake protocol. This does actually
838  * everything. (exchange hello messages etc).
839  */
840 int gnutls_handshake(int cd, GNUTLS_STATE state) {
841         int ret;
842         
843         ret = gnutls_handshake_begin( cd, state);
844         /* FIXME: check certificate */
845         if (ret==0) ret = gnutls_handshake_finish( cd, state);
846         
847         return ret;
848 }
849
850 /* in this function we initiate the handshake and we receive - 
851  * if requested - the certificate. This certificate should be checked
852  * somehow.
853  */
854 int gnutls_handshake_begin(int cd, GNUTLS_STATE state)
855 {
856         int ret;
857         char *session_id;
858         uint8 session_id_size;
859
860         if (state->security_parameters.entity == GNUTLS_CLIENT) {
861 #ifdef HARD_DEBUG
862                 if (state->gnutls_internals.resumed_security_parameters.session_id_size>0) 
863                 fprintf(stderr, "Ask to resume: %s\n", _gnutls_bin2hex(state->gnutls_internals.resumed_security_parameters.session_id, state->gnutls_internals.resumed_security_parameters.session_id_size));
864 #endif
865                 ret = _gnutls_send_hello(cd, state, state->gnutls_internals.resumed_security_parameters.session_id, state->gnutls_internals.resumed_security_parameters.session_id_size);
866                 if (ret < 0) {
867                         ERR("send hello", ret);
868                         gnutls_clearHashDataBuffer( state);
869                         return ret;
870                 }
871
872                 /* receive the server hello */
873                 ret =
874                     _gnutls_recv_handshake(cd, state, NULL, NULL, GNUTLS_SERVER_HELLO);
875                 if (ret < 0) {
876                         ERR("recv hello", ret);
877                         gnutls_clearHashDataBuffer( state);
878                         return ret;
879                 }
880
881                 /* RECV CERTIFICATE */
882                 if (state->gnutls_internals.resumed==RESUME_FALSE) /* if we are not resuming */
883                 ret =
884                     _gnutls_recv_handshake(cd, state, NULL, NULL, GNUTLS_CERTIFICATE);
885                 if (ret < 0) {
886                         ERR("recv server certificate", ret);
887                         gnutls_clearHashDataBuffer( state);
888                         return ret;
889                 }
890                 return 0;
891         } else {                /* SERVER */
892
893                 ret =
894                     _gnutls_recv_handshake(cd, state, NULL, NULL,
895                                            GNUTLS_CLIENT_HELLO);
896                 if (ret < 0) {
897                         ERR("recv hello", ret);
898                         gnutls_clearHashDataBuffer( state);
899                         return ret;
900                 }
901
902                 _gnutls_generate_session_id(&session_id, &session_id_size);
903                 ret =
904                     _gnutls_send_hello(cd, state, session_id,
905                                        session_id_size);
906                 if (ret < 0) {
907                         ERR("send hello", ret);
908                         gnutls_clearHashDataBuffer( state);
909                         return ret;
910                 }
911                 gnutls_free(session_id);
912
913                 /* FIXME: send our certificate - if required */
914
915                 /* SEND CERTIFICATE + KEYEXCHANGE + CERTIFICATE_REQUEST */
916                 ret = _gnutls_send_server_kx_message(cd, state);
917                 if (ret < 0) {
918                         ERR("send server kx", ret);
919                         gnutls_clearHashDataBuffer( state);
920                         return ret;
921                 }
922
923                 /* FIXME: request - and get - a client certificate */
924                 return 0;
925         }
926 }
927
928 /* in this function we finish the handshake procedure
929  * This should happen only if we trust the peer. (check certificate)
930  */
931 int gnutls_handshake_finish(int cd, GNUTLS_STATE state)
932 {
933         int ret=0;
934         char *session_id;
935         uint8 session_id_size;
936
937         if (state->security_parameters.entity == GNUTLS_CLIENT) {
938
939                 /* receive the server key exchange */
940                 if (state->gnutls_internals.resumed==RESUME_FALSE) /* if we are not resuming */
941                 ret = _gnutls_recv_server_kx_message(cd, state);
942                 if (ret < 0) {
943                         ERR("recv server kx message", ret);
944                         gnutls_clearHashDataBuffer( state);
945                         return ret;
946                 }
947
948                 /* FIXME: receive certificate request */
949
950                 /* receive the server hello done */
951                 if (state->gnutls_internals.resumed==RESUME_FALSE) /* if we are not resuming */
952                 ret =
953                     _gnutls_recv_handshake(cd, state, NULL, NULL,
954                                            GNUTLS_SERVER_HELLO_DONE);
955                 if (ret < 0) {
956                         ERR("recv server hello done", ret);
957                         gnutls_clearHashDataBuffer( state);
958                         return ret;
959                 }
960
961                 /* send our certificate - if any */
962                 if (state->gnutls_internals.resumed==RESUME_FALSE) /* if we are not resuming */
963                 ret = _gnutls_send_client_certificate(cd, state);
964                 if (ret < 0) {
965                         ERR("send client certificate", ret);
966                         gnutls_clearHashDataBuffer( state);
967                         return ret;
968                 }
969
970                 if (state->gnutls_internals.resumed==RESUME_FALSE) /* if we are not resuming */
971                 ret = _gnutls_send_client_kx_message(cd, state);
972                 if (ret < 0) {
973                         ERR("send client kx", ret);
974                         gnutls_clearHashDataBuffer( state);
975                         return ret;
976                 }
977
978                 /* send client certificate verify */
979                 if (state->gnutls_internals.resumed==RESUME_FALSE) /* if we are not resuming */
980                 ret = _gnutls_send_client_certificate_verify( cd, state);
981                 if (ret < 0) {
982                         ERR("send client certificate verify", ret);
983                         gnutls_clearHashDataBuffer( state);
984                         return ret;
985                 }
986
987                 /* Send the CHANGE CIPHER SPEC PACKET */
988                 ret = _gnutls_send_change_cipher_spec(cd, state);
989                 if (ret < 0) {
990                         ERR("send ChangeCipherSpec", ret);
991                         gnutls_clearHashDataBuffer( state);
992                         return ret;
993                 }
994
995                 /* Initialize the connection state (start encryption) */
996                 ret = _gnutls_connection_state_init(state);
997                 if (ret<0) {
998                         gnutls_assert();
999                         gnutls_clearHashDataBuffer( state);
1000                         return ret;
1001                 }
1002
1003                 /* send the finished message */
1004
1005                 ret = _gnutls_send_finished(cd, state);
1006                 if (ret < 0) {
1007                         ERR("send Finished", ret);
1008                         gnutls_clearHashDataBuffer( state);
1009                         return ret;
1010                 }
1011
1012                 ret =
1013                     gnutls_recv_int(cd, state, GNUTLS_CHANGE_CIPHER_SPEC,
1014                                     NULL, 0);
1015                 if (ret < 0) {
1016                         ERR("recv ChangeCipherSpec", ret);
1017                         gnutls_clearHashDataBuffer( state);
1018                         return ret;
1019                 }
1020
1021                 ret = _gnutls_recv_finished(cd, state);
1022                 if (ret < 0) {
1023                         ERR("recv finished", ret);
1024                         gnutls_clearHashDataBuffer( state);
1025                         return ret;
1026                 }
1027
1028         } else { /* SERVER SIDE */
1029
1030                 /* send the server hello done */
1031                 ret =
1032                     _gnutls_send_handshake(cd, state, NULL, 0,
1033                                            GNUTLS_SERVER_HELLO_DONE);
1034                 if (ret < 0) {
1035                         ERR("send server hello done", ret);
1036                         gnutls_clearHashDataBuffer( state);
1037                         return ret;
1038                 }
1039
1040                 /* RECV CERTIFICATE + KEYEXCHANGE + CERTIFICATE_VERIFY */
1041                 
1042                 ret = _gnutls_recv_client_kx_message(cd, state);
1043                 if (ret < 0) {
1044                         ERR("recv client kx", ret);
1045                         gnutls_clearHashDataBuffer( state);
1046                         return ret;
1047                 }
1048
1049                 ret =
1050                     gnutls_recv_int(cd, state, GNUTLS_CHANGE_CIPHER_SPEC,
1051                                     NULL, 0);
1052                 if (ret < 0) {
1053                         ERR("recv ChangeCipherSpec", ret);
1054                         return ret;
1055                 }
1056
1057                 /* Initialize the connection state (start encryption) */
1058                 ret = _gnutls_connection_state_init(state);
1059                 if (ret<0) {
1060                         gnutls_clearHashDataBuffer( state);
1061                         return ret;
1062                 }
1063
1064                 ret = _gnutls_recv_finished(cd, state);
1065                 if (ret < 0) {
1066                         ERR("recv finished", ret);
1067                         gnutls_clearHashDataBuffer( state);
1068                         return ret;
1069                 }
1070
1071                 ret = _gnutls_send_change_cipher_spec(cd, state);
1072                 if (ret < 0) {
1073                         ERR("send ChangeCipherSpec", ret);
1074                         gnutls_clearHashDataBuffer( state);
1075                         return ret;
1076                 }
1077
1078                 ret = _gnutls_send_finished(cd, state);
1079                 if (ret < 0) {
1080                         ERR("send finished", ret);
1081                         gnutls_clearHashDataBuffer( state);
1082                         return ret;
1083                 }
1084
1085         }
1086         /* clear handshake buffer */
1087         gnutls_clearHashDataBuffer( state);
1088         return ret;
1089
1090 }
1091
1092 int _gnutls_generate_session_id(char **session_id, uint8 * len)
1093 {
1094         char *rand;
1095         *session_id = gnutls_malloc(32);
1096         rand = gcry_random_bytes(32, GCRY_WEAK_RANDOM);
1097
1098         memmove(*session_id, rand, 32);
1099         gcry_free(rand);
1100         *len = 32;
1101
1102 #ifdef HARD_DEBUG
1103         fprintf(stderr, "SessionID: %s\n", _gnutls_bin2hex(*session_id, 32));
1104 #endif
1105         return 0;
1106 }