2 * Copyright (C) 2000 Nikos Mavroyanopoulos
4 * This file is part of GNUTLS.
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.
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.
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
22 #include "gnutls_int.h"
23 #include "gnutls_errors.h"
24 #include "gnutls_dh.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"
37 #define ERR(x, y) fprintf(stderr, "GNUTLS Error: %s (%d)\n", x,y)
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) {
49 GNUTLS_MAC_HANDLE td2;
51 char* concat=gnutls_malloc(36);
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);
57 siz = gnutls_getHashDataBufferSize( state) - skip;
58 data = gnutls_malloc( siz);
60 gnutls_readHashDataFromBuffer( state, data, siz);
62 gnutls_mac_ssl3(td, data, siz);
63 gnutls_mac_ssl3(td2, data, siz);
66 if (type==GNUTLS_SERVER) {
67 mesg = SSL3_SERVER_MSG;
69 mesg = SSL3_CLIENT_MSG;
72 gnutls_mac_ssl3(td, mesg, siz);
73 gnutls_mac_ssl3(td2, mesg, siz);
75 data = gnutls_mac_deinit_ssl3_handshake(td);
76 memcpy( concat, data, 16);
79 data = gnutls_mac_deinit_ssl3_handshake(td2);
81 memcpy( &concat[16], data, 20);
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) {
92 GNUTLS_MAC_HANDLE td2;
97 td = gnutls_hash_init( GNUTLS_MAC_MD5);
98 td2 = gnutls_hash_init( GNUTLS_MAC_SHA);
100 siz = gnutls_getHashDataBufferSize( state) - skip;
101 data = gnutls_malloc( siz);
103 gnutls_readHashDataFromBuffer( state, data, siz);
105 gnutls_hash(td, data, siz);
106 gnutls_hash(td2, data, siz);
110 data = gnutls_hash_deinit(td);
111 memcpy( concat, data, 16);
114 data = gnutls_hash_deinit(td2);
116 memcpy( &concat[16], data, 20);
119 if (type==GNUTLS_SERVER) {
125 gnutls_PRF( state->security_parameters.master_secret,
126 48, mesg, strlen(mesg), concat,
132 /* This is to be called after sending CHANGE CIPHER SPEC packet
133 * and initializing encryption. This is the first encrypted message
136 int _gnutls_send_finished(int cd, GNUTLS_STATE state)
142 if (_gnutls_version_ssl3(state->connection_state.version) == 0) {
143 data = _gnutls_ssl3_finished( state, state->security_parameters.entity, 0);
145 } else { /* TLS 1.0 */
146 data = _gnutls_finished( state, state->security_parameters.entity, 0);
150 ret = _gnutls_send_handshake(cd, state, data, data_size, GNUTLS_FINISHED);
151 #ifdef HANDSHAKE_DEBUG
152 fprintf(stderr, "Send finished\n");
159 /* This is to be called after sending our finished message. If everything
160 * went fine we have negotiated a secure connection
162 #define HANDSHAKE_HEADERS_SIZE 4
163 int _gnutls_recv_finished(int cd, GNUTLS_STATE state)
167 uint8* concat; /* md5+sha1 */
173 ret = _gnutls_recv_handshake(cd, state, &vrfy, &vrfysize, GNUTLS_FINISHED);
175 ERR("recv finished int", ret);
179 if (_gnutls_version_ssl3(state->connection_state.version) == 0) {
185 if (vrfysize != data_size) {
187 return GNUTLS_E_ERROR_IN_FINISHED_PACKET;
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);
197 if (memcmp(vrfy, data, data_size) != 0) {
199 ret = GNUTLS_E_ERROR_IN_FINISHED_PACKET;
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)
213 GNUTLS_CipherSuite *ciphers;
215 x = _gnutls_supported_ciphersuites(state, &ciphers);
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]));
222 memset(ret, '\0', sizeof(GNUTLS_CipherSuite));
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) {
228 fprintf(stderr, "Selected cipher suite: ");
229 fprintf(stderr, "%s\n", _gnutls_cipher_suite_get_name( *((GNUTLS_CipherSuite*)&data[j]) ));
231 memmove(ret, &ciphers[i].CipherSuite, 2);
232 gnutls_free(ciphers);
240 gnutls_free(ciphers);
242 return GNUTLS_E_UNKNOWN_CIPHER_SUITE;
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)
250 CompressionMethod *ciphers;
252 x = _gnutls_supported_compression_methods(state, &ciphers);
253 memset(ret, '\0', sizeof(CompressionMethod));
255 for (j = 0; j < datalen; j++) {
256 for (i = 0; i < x; i++) {
257 if ( ciphers[i] == data[j]) {
259 gnutls_free(ciphers);
265 /* we were not able to find a compatible compression
268 gnutls_free(ciphers);
270 return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
274 int _gnutls_send_handshake(int cd, GNUTLS_STATE state, void *i_data,
275 uint32 i_datasize, HandshakeType type)
284 #ifdef WORDS_BIGENDIAN
285 datasize = i_datasize;
287 datasize = byteswap32(i_datasize);
290 length = uint32touint24(datasize);
292 i_datasize += HANDSHAKE_HEADERS_SIZE;
293 data = gnutls_malloc(i_datasize);
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);
301 memmove(&data[pos], i_data, i_datasize - 4);
303 #ifdef HANDSHAKE_DEBUG
304 fprintf(stderr, "Send HANDSHAKE[%d] of %d bytes\n", type, i_datasize+4);
307 /* Here we keep the handshake messages in order to hash them later!
309 if (type!=GNUTLS_HELLO_REQUEST)
310 gnutls_insertHashDataBuffer( state, data, i_datasize);
313 _gnutls_Send_int(cd, state, GNUTLS_HANDSHAKE, data, i_datasize);
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().
325 int _gnutls_recv_handshake(int cd, GNUTLS_STATE state, uint8 **data,
326 int* datalen, HandshakeType type)
329 uint32 length32 = 0, sum=0;
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 )
340 } else { /* server */
341 if (_gnutls_kx_client_certificate( _gnutls_cipher_suite_get_kx_algo(state->gnutls_internals.current_cipher_suite)==0))
346 dataptr = gnutls_malloc(HANDSHAKE_HEADERS_SIZE);
348 ret = _gnutls_Recv_int(cd, state, GNUTLS_HANDSHAKE, dataptr, HANDSHAKE_HEADERS_SIZE);
350 gnutls_free(dataptr);
353 if (ret!=HANDSHAKE_HEADERS_SIZE) {
355 gnutls_free(dataptr);
356 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
359 if (dataptr[0]!=type) {
361 gnutls_free(dataptr);
362 return GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET;
365 num.pint[0] = dataptr[1];
366 num.pint[1] = dataptr[2];
367 num.pint[2] = dataptr[3];
368 length32 = uint24touint32(num);
370 #ifndef WORDS_BIGENDIAN
371 length32 = byteswap32(length32);
373 #ifdef HANDSHAKE_DEBUG
374 fprintf(stderr, "Received HANDSHAKE[%d] of %d bytes\n", dataptr[0], length32+4);
377 dataptr = gnutls_realloc( dataptr, length32+HANDSHAKE_HEADERS_SIZE);
378 if (length32>0 && data!=NULL)
379 *data = gnutls_malloc( length32);
381 if (datalen!=NULL) *datalen = length32;
383 sum=HANDSHAKE_HEADERS_SIZE;
385 ret = _gnutls_Recv_int(cd, state, GNUTLS_HANDSHAKE, &dataptr[sum], length32);
387 } while( ( (sum-HANDSHAKE_HEADERS_SIZE) < length32) && (ret > 0) );
391 gnutls_free(dataptr);
394 ret = GNUTLS_E_UNKNOWN_ERROR;
396 if (length32 > 0 && data!=NULL)
397 memmove( *data, &dataptr[HANDSHAKE_HEADERS_SIZE], length32);
399 /* here we buffer the handshake messages - needed at Finished message */
400 gnutls_insertHashDataBuffer( state, dataptr, length32+HANDSHAKE_HEADERS_SIZE);
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],
408 case GNUTLS_CERTIFICATE:
409 ret = _gnutls_recv_certificate(cd, state, &dataptr[HANDSHAKE_HEADERS_SIZE],
412 case GNUTLS_SERVER_HELLO_DONE:
415 case GNUTLS_FINISHED:
418 case GNUTLS_SERVER_KEY_EXCHANGE:
421 case GNUTLS_CLIENT_KEY_EXCHANGE:
424 case GNUTLS_CERTIFICATE_REQUEST:
426 fprintf(stderr, "Requested Client Certificate!\n");
428 /* FIXME: just ignore that message for the time being
429 * we have to parse it and the store the needed information
431 state->gnutls_internals.certificate_requested = 1;
436 ret = GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET;
438 gnutls_free(dataptr);
442 int _gnutls_send_hello_request(int cd, GNUTLS_STATE state)
444 return _gnutls_send_handshake(cd, state, NULL, 0,
445 GNUTLS_HELLO_REQUEST);
448 int _gnutls_send_client_certificate(int cd, GNUTLS_STATE state)
453 if (state->gnutls_internals.certificate_requested==0) return 0;
455 /* we do not have that functionality yet */
456 state->gnutls_internals.certificate_verify_needed = 0;
458 fprintf(stderr, "Sending Client Certificate\n");
461 /* Here since we do not support certificates yet we
462 * do not have that functionality.
465 ret = _gnutls_send_handshake(cd, state, &data, 1,
472 int _gnutls_send_hello(int cd, GNUTLS_STATE state, opaque * SessionID,
477 uint8 session_id_len, z;
480 GNUTLS_CipherSuite *cipher_suites;
481 CompressionMethod *compression_methods;
482 int i, datalen, ret = 0;
485 session_id_len = SessionIDLen;
486 if (SessionID == NULL)
489 rand = gcry_random_bytes(28, GCRY_STRONG_RANDOM);
491 if (state->security_parameters.entity == GNUTLS_CLIENT) {
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
497 data = gnutls_malloc(datalen);
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);
504 cur_time = byteswap32(time(NULL));
506 memmove(state->security_parameters.client_random,
508 memmove(&state->security_parameters.client_random[4], rand,
511 memmove(&data[pos], &cur_time, 4);
513 memmove(&data[pos], rand, 28);
516 memmove(&data[pos++], &session_id_len, 1);
518 if (session_id_len > 0) {
519 memmove(&data[pos], SessionID, session_id_len);
521 pos += session_id_len;
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));
529 memmove(&data[pos], &x, sizeof(uint16));
532 pos += sizeof(uint16);
535 data = gnutls_realloc(data, datalen);
537 for (i = 0; i < x/2; i++) {
538 memmove(&data[pos], &cipher_suites[i].CipherSuite,
543 z = _gnutls_supported_compression_methods
544 (state, &compression_methods);
545 memmove(&data[pos++], &z, 1); /* put the number of compression methods */
548 data = gnutls_realloc(data, datalen);
550 for (i = 0; i < z; i++) {
551 memmove(&data[pos++], &compression_methods[i], 1);
555 gnutls_free(cipher_suites);
556 gnutls_free(compression_methods);
559 _gnutls_send_handshake(cd, state, data, datalen,
560 GNUTLS_CLIENT_HELLO);
564 } else { /* SERVER */
565 datalen = 2 + sizeof(uint32) + session_id_len + 1 + 28;
566 data = gnutls_malloc(datalen);
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);
573 cur_time = byteswap32(time(NULL));
575 memmove(state->security_parameters.server_random,
577 memmove(&state->security_parameters.server_random[4], rand,
580 memmove(&data[pos], &cur_time, sizeof(uint32));
581 pos += sizeof(uint32);
582 memmove(&data[pos], rand, 28);
585 memmove(&data[pos++], &session_id_len, sizeof(uint8));
586 if (session_id_len > 0) {
587 memmove(&data[pos], SessionID, session_id_len);
589 pos += session_id_len;
592 data = gnutls_realloc(data, datalen);
594 &state->gnutls_internals.
595 current_cipher_suite.CipherSuite, 2);
599 data = gnutls_realloc(data, datalen);
600 memmove(&data[pos++],
601 &state->gnutls_internals.compression_method, 1);
605 _gnutls_send_handshake(cd, state, data, datalen,
606 GNUTLS_SERVER_HELLO);
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.
619 int _gnutls_recv_hello(int cd, GNUTLS_STATE state, char *data, int datalen)
621 uint8 session_id_len = 0, z;
623 GNUTLS_CipherSuite cipher_suite, *cipher_suites;
624 CompressionMethod compression_method, *compression_methods;
626 uint16 x, sizeOfSuites;
627 GNUTLS_Version version;
629 if (state->security_parameters.entity == GNUTLS_CLIENT) {
632 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
636 fprintf(stderr, "Server's version: %d.%d\n", data[pos], data[pos+1]);
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) {
643 return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
645 gnutls_set_current_version(state, version);
649 memmove(state->security_parameters.server_random,
653 memmove(&session_id_len, &data[pos++], 1);
655 if (datalen < 38 + session_id_len) {
657 return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
660 fprintf(stderr, "SessionID length: %d\n", session_id_len);
661 fprintf(stderr, "SessionID: %s\n",
662 _gnutls_bin2hex(&data[pos], session_id_len));
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) {
669 fprintf(stderr, "Resuming session\n");
671 state->gnutls_internals.resumed=RESUME_TRUE; /* we are resuming */
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);
680 pos += session_id_len;
682 memmove(&cipher_suite.CipherSuite, &data[pos], 2);
686 x = _gnutls_supported_ciphersuites(state, &cipher_suites);
687 for (i = 0; i < x; i++) {
689 (&cipher_suites[i], cipher_suite.CipherSuite,
696 return GNUTLS_E_UNKNOWN_CIPHER_TYPE;
697 memmove(state->gnutls_internals.
698 current_cipher_suite.CipherSuite,
699 cipher_suite.CipherSuite, 2);
701 fprintf(stderr, "Selected cipher suite: ");
702 fprintf(stderr, "%s\n", _gnutls_cipher_suite_get_name(state->gnutls_internals.current_cipher_suite ) );
705 memmove(&compression_method, &data[pos++], 1);
707 _gnutls_supported_compression_methods
708 (state, &compression_methods);
709 for (i = 0; i < z; i++) {
711 (&compression_methods[i], &compression_method,
718 return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
719 memmove(&state->gnutls_internals.compression_method,
720 &compression_method, 1);
723 gnutls_free(cipher_suites);
724 gnutls_free(compression_methods);
726 } else { /* Server side reading a client hello */
729 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
733 fprintf(stderr, "Client's version: %d.%d\n", data[pos], data[pos+1]);
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) {
740 return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
742 gnutls_set_current_version(state, version);
746 memmove(state->security_parameters.client_random,
750 memmove(&session_id_len, &data[pos++], 1);
751 pos += session_id_len;
753 /* We should resume an old connection here. This is not
758 /* Select a ciphersuite */
759 memmove(&sizeOfSuites, &data[pos], 2);
761 #ifndef WORDS_BIGENDIAN
762 sizeOfSuites = byteswap16(sizeOfSuites);
764 ret = SelectSuite(state, state->gnutls_internals.
765 current_cipher_suite.CipherSuite, &data[pos],
768 if (ret<0) return ret;
772 memmove(&z, &data[pos++], 1); /* z is the number of compression methods */
773 ret = SelectCompMethod(state, &state->
774 gnutls_internals.compression_method,
786 int _gnutls_recv_certificate(int cd, GNUTLS_STATE state, char *data, int datalen)
788 uint8 session_id_len = 0, z;
790 char* certificate_list;
796 if (state->security_parameters.entity == GNUTLS_CLIENT) {
799 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
802 num.pint[0] = data[pos];
803 num.pint[1] = data[pos+1];
804 num.pint[2] = data[pos+2];
805 sizeOfCert = uint24touint32(num);
808 #ifndef WORDS_BIGENDIAN
809 sizeOfCert=byteswap32(sizeOfCert);
811 if (sizeOfCert > MAX24) {
813 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
815 certificate_list = gnutls_malloc(sizeOfCert);
817 memmove( certificate_list, &data[pos], sizeOfCert);
819 /* Verify certificates !!! */
821 gnutls_free(certificate_list); /* oooops! */
823 } else { /* Server side reading a client certificate */
824 /* actually this is not complete */
827 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
837 /* This is the main function in the handshake protocol. This does actually
838 * everything. (exchange hello messages etc).
840 int gnutls_handshake(int cd, GNUTLS_STATE state) {
843 ret = gnutls_handshake_begin( cd, state);
844 /* FIXME: check certificate */
845 if (ret==0) ret = gnutls_handshake_finish( cd, state);
850 /* in this function we initiate the handshake and we receive -
851 * if requested - the certificate. This certificate should be checked
854 int gnutls_handshake_begin(int cd, GNUTLS_STATE state)
858 uint8 session_id_size;
860 if (state->security_parameters.entity == GNUTLS_CLIENT) {
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));
865 ret = _gnutls_send_hello(cd, state, state->gnutls_internals.resumed_security_parameters.session_id, state->gnutls_internals.resumed_security_parameters.session_id_size);
867 ERR("send hello", ret);
868 gnutls_clearHashDataBuffer( state);
872 /* receive the server hello */
874 _gnutls_recv_handshake(cd, state, NULL, NULL, GNUTLS_SERVER_HELLO);
876 ERR("recv hello", ret);
877 gnutls_clearHashDataBuffer( state);
881 /* RECV CERTIFICATE */
882 if (state->gnutls_internals.resumed==RESUME_FALSE) /* if we are not resuming */
884 _gnutls_recv_handshake(cd, state, NULL, NULL, GNUTLS_CERTIFICATE);
886 ERR("recv server certificate", ret);
887 gnutls_clearHashDataBuffer( state);
891 } else { /* SERVER */
894 _gnutls_recv_handshake(cd, state, NULL, NULL,
895 GNUTLS_CLIENT_HELLO);
897 ERR("recv hello", ret);
898 gnutls_clearHashDataBuffer( state);
902 _gnutls_generate_session_id(&session_id, &session_id_size);
904 _gnutls_send_hello(cd, state, session_id,
907 ERR("send hello", ret);
908 gnutls_clearHashDataBuffer( state);
911 gnutls_free(session_id);
913 /* FIXME: send our certificate - if required */
915 /* SEND CERTIFICATE + KEYEXCHANGE + CERTIFICATE_REQUEST */
916 ret = _gnutls_send_server_kx_message(cd, state);
918 ERR("send server kx", ret);
919 gnutls_clearHashDataBuffer( state);
923 /* FIXME: request - and get - a client certificate */
928 /* in this function we finish the handshake procedure
929 * This should happen only if we trust the peer. (check certificate)
931 int gnutls_handshake_finish(int cd, GNUTLS_STATE state)
935 uint8 session_id_size;
937 if (state->security_parameters.entity == GNUTLS_CLIENT) {
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);
943 ERR("recv server kx message", ret);
944 gnutls_clearHashDataBuffer( state);
948 /* FIXME: receive certificate request */
950 /* receive the server hello done */
951 if (state->gnutls_internals.resumed==RESUME_FALSE) /* if we are not resuming */
953 _gnutls_recv_handshake(cd, state, NULL, NULL,
954 GNUTLS_SERVER_HELLO_DONE);
956 ERR("recv server hello done", ret);
957 gnutls_clearHashDataBuffer( state);
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);
965 ERR("send client certificate", ret);
966 gnutls_clearHashDataBuffer( state);
970 if (state->gnutls_internals.resumed==RESUME_FALSE) /* if we are not resuming */
971 ret = _gnutls_send_client_kx_message(cd, state);
973 ERR("send client kx", ret);
974 gnutls_clearHashDataBuffer( state);
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);
982 ERR("send client certificate verify", ret);
983 gnutls_clearHashDataBuffer( state);
987 /* Send the CHANGE CIPHER SPEC PACKET */
988 ret = _gnutls_send_change_cipher_spec(cd, state);
990 ERR("send ChangeCipherSpec", ret);
991 gnutls_clearHashDataBuffer( state);
995 /* Initialize the connection state (start encryption) */
996 ret = _gnutls_connection_state_init(state);
999 gnutls_clearHashDataBuffer( state);
1003 /* send the finished message */
1005 ret = _gnutls_send_finished(cd, state);
1007 ERR("send Finished", ret);
1008 gnutls_clearHashDataBuffer( state);
1013 gnutls_recv_int(cd, state, GNUTLS_CHANGE_CIPHER_SPEC,
1016 ERR("recv ChangeCipherSpec", ret);
1017 gnutls_clearHashDataBuffer( state);
1021 ret = _gnutls_recv_finished(cd, state);
1023 ERR("recv finished", ret);
1024 gnutls_clearHashDataBuffer( state);
1028 } else { /* SERVER SIDE */
1030 /* send the server hello done */
1032 _gnutls_send_handshake(cd, state, NULL, 0,
1033 GNUTLS_SERVER_HELLO_DONE);
1035 ERR("send server hello done", ret);
1036 gnutls_clearHashDataBuffer( state);
1040 /* RECV CERTIFICATE + KEYEXCHANGE + CERTIFICATE_VERIFY */
1042 ret = _gnutls_recv_client_kx_message(cd, state);
1044 ERR("recv client kx", ret);
1045 gnutls_clearHashDataBuffer( state);
1050 gnutls_recv_int(cd, state, GNUTLS_CHANGE_CIPHER_SPEC,
1053 ERR("recv ChangeCipherSpec", ret);
1057 /* Initialize the connection state (start encryption) */
1058 ret = _gnutls_connection_state_init(state);
1060 gnutls_clearHashDataBuffer( state);
1064 ret = _gnutls_recv_finished(cd, state);
1066 ERR("recv finished", ret);
1067 gnutls_clearHashDataBuffer( state);
1071 ret = _gnutls_send_change_cipher_spec(cd, state);
1073 ERR("send ChangeCipherSpec", ret);
1074 gnutls_clearHashDataBuffer( state);
1078 ret = _gnutls_send_finished(cd, state);
1080 ERR("send finished", ret);
1081 gnutls_clearHashDataBuffer( state);
1086 /* clear handshake buffer */
1087 gnutls_clearHashDataBuffer( state);
1092 int _gnutls_generate_session_id(char **session_id, uint8 * len)
1095 *session_id = gnutls_malloc(32);
1096 rand = gcry_random_bytes(32, GCRY_WEAK_RANDOM);
1098 memmove(*session_id, rand, 32);
1103 fprintf(stderr, "SessionID: %s\n", _gnutls_bin2hex(*session_id, 32));