2 * Copyright (C) 2001 Nikos Mavroyanopoulos
4 * This file is part of GNUTLS.
6 * The GNUTLS library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library 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 GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; 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_cipher.h"
29 #include "gnutls_buffers.h"
30 #include "gnutls_kx.h"
31 #include "gnutls_handshake.h"
32 #include "gnutls_num.h"
33 #include "gnutls_hash_int.h"
34 #include "gnutls_db.h"
35 #include "gnutls_extensions.h"
36 #include "gnutls_random.h"
37 #include "gnutls_auth_int.h"
39 /* This selects the best supported ciphersuite from the ones provided */
40 static int _gnutls_handshake_select_v2_suite(GNUTLS_STATE state
, char *data
, int datalen
)
46 _data
= gnutls_malloc( datalen
);
49 return GNUTLS_E_MEMORY_ERROR
;
52 _gnutls_handshake_log( "HSK: Parsing a version 2.0 client hello.\n");
55 for (j
= 0; j
< datalen
; j
+= 3) {
57 memcpy( &_data
[i
], &data
[j
+1], 2);
63 ret
= _gnutls_server_select_suite( state
, _data
, _datalen
);
71 /* Read a v2 client hello. Some browsers still use that beast!
72 * However they set their version to 3.0 or 3.1.
74 int _gnutls_read_client_hello_v2(GNUTLS_STATE state
, opaque
* data
,
77 uint16 session_id_len
= 0;
81 GNUTLS_Version version
;
82 opaque random
[TLS_RANDOM_SIZE
];
86 opaque session_id
[TLS_MAX_SESSION_ID_SIZE
];
89 /* we only want to get here once - only in client hello */
90 state
->gnutls_internals
.v2_hello
= 0;
94 _gnutls_handshake_log( "HSK: SSL 2.0 Hello: Client's version: %d.%d\n", data
[pos
],
97 set_adv_version( state
, data
[pos
], data
[pos
+1]);
99 version
= _gnutls_version_get(data
[pos
], data
[pos
+ 1]);
101 /* if we do not support that version */
102 if (_gnutls_version_is_supported(state
, version
) == 0) {
103 ver
= _gnutls_version_lowest( state
);
108 if (ver
==GNUTLS_VERSION_UNKNOWN
|| ver
> version
) {
110 return GNUTLS_E_UNSUPPORTED_VERSION_PACKET
;
113 _gnutls_set_current_version(state
, ver
);
118 /* Read uint16 cipher_spec_length */
120 sizeOfSuites
= _gnutls_read_uint16( &data
[pos
]);
123 /* read session id length */
125 session_id_len
= _gnutls_read_uint16( &data
[pos
]);
128 if (session_id_len
> TLS_MAX_SESSION_ID_SIZE
) {
130 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH
;
133 /* read challenge length */
135 challenge
= _gnutls_read_uint16( &data
[pos
]);
138 if ( challenge
< 16 || challenge
> TLS_RANDOM_SIZE
) {
140 return GNUTLS_E_UNSUPPORTED_VERSION_PACKET
;
143 /* find an appropriate cipher suite */
145 DECR_LEN(len
, sizeOfSuites
);
146 ret
= _gnutls_handshake_select_v2_suite(state
, &data
[pos
], sizeOfSuites
);
154 /* check if the credentials (username, public key etc. are ok)
156 if (_gnutls_get_kx_cred( state
->gnutls_key
, _gnutls_cipher_suite_get_kx_algo(state
->security_parameters
.current_cipher_suite
), &err
) == NULL
&& err
!= 0) {
158 return GNUTLS_E_INSUFICIENT_CRED
;
161 /* set the MOD_AUTH_STRUCT to the appropriate struct
162 * according to the KX algorithm. This is needed since all the
163 * handshake functions are read from there;
165 state
->gnutls_internals
.auth_struct
=
166 _gnutls_kx_auth_struct(_gnutls_cipher_suite_get_kx_algo
167 (state
->security_parameters
.
168 current_cipher_suite
));
169 if (state
->gnutls_internals
.auth_struct
== NULL
) {
171 _gnutls_handshake_log(
172 "HSK: SSL 2.0 Hello: Cannot find the appropriate handler for the KX algorithm\n");
175 return GNUTLS_E_UNKNOWN_CIPHER_TYPE
;
180 /* read random new values -skip session id for now */
181 DECR_LEN(len
, session_id_len
); /* skip session id for now */
182 memcpy( session_id
, &data
[pos
], session_id_len
);
185 DECR_LEN(len
, challenge
);
186 memset( random
, 0, TLS_RANDOM_SIZE
);
188 memcpy( &random
[TLS_RANDOM_SIZE
-challenge
], &data
[pos
], challenge
);
190 _gnutls_set_client_random( state
, random
);
192 /* generate server random value */
194 _gnutls_create_random( random
);
195 _gnutls_set_server_random( state
, random
);
197 state
->security_parameters
.timestamp
= time(NULL
);
202 DECR_LEN(len
, session_id_len
);
203 ret
= _gnutls_server_restore_session(state
, session_id
, session_id_len
);
205 if (ret
== 0) { /* resumed! */
206 /* get the new random values */
207 memcpy(state
->gnutls_internals
.resumed_security_parameters
.server_random
,
208 state
->security_parameters
.server_random
, TLS_RANDOM_SIZE
);
209 memcpy(state
->gnutls_internals
.resumed_security_parameters
.client_random
,
210 state
->security_parameters
.client_random
, TLS_RANDOM_SIZE
);
212 state
->gnutls_internals
.resumed
= RESUME_TRUE
;
215 _gnutls_generate_session_id(state
->security_parameters
.
217 &state
->security_parameters
.
219 state
->gnutls_internals
.resumed
= RESUME_FALSE
;
222 state
->gnutls_internals
.compression_method
= GNUTLS_COMP_NULL
;