2 * Copyright (C) 2000,2001,2002 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"
25 #include "gnutls_compress.h"
26 #include "gnutls_cipher.h"
27 #include "gnutls_buffers.h"
28 #include "gnutls_handshake.h"
29 #include "gnutls_hash_int.h"
30 #include "gnutls_cipher_int.h"
31 #include "gnutls_priority.h"
32 #include "gnutls_algorithms.h"
33 #include "gnutls_db.h"
34 #include "gnutls_auth_int.h"
35 #include "gnutls_num.h"
36 #include "gnutls_record.h"
37 #include "gnutls_datum.h"
38 #include "ext_max_record.h"
39 #include <gnutls_state.h>
40 #include <gnutls_alert.h>
41 #include <gnutls_dh.h>
44 * gnutls_protocol_get_version - Returns the version of the currently used protocol
45 * @state: is a &GNUTLS_STATE structure.
47 * Returns the version of the currently used protocol.
50 GNUTLS_Version
gnutls_protocol_get_version(GNUTLS_STATE state
) {
51 return state
->security_parameters
.version
;
54 void _gnutls_set_current_version(GNUTLS_STATE state
, GNUTLS_Version version
) {
55 state
->security_parameters
.version
= version
;
59 * gnutls_transport_set_lowat - Used to set the lowat value in order for select to check for pending data.
60 * @state: is a &GNUTLS_STATE structure.
61 * @num: is the low water value.
63 * Used to set the lowat value in order for select to check
64 * if there are pending data to socket buffer. Used only
65 * if you have changed the default low water value (default is 1).
66 * Normally you will not need that function.
67 * This function is only usefull if using berkeley style sockets.
68 * Otherwise it must be called and set lowat to zero.
71 void gnutls_transport_set_lowat(GNUTLS_STATE state
, int num
) {
72 state
->gnutls_internals
.lowat
= num
;
76 * gnutls_transport_set_ptr - Used to set first argument of the transport functions
77 * @state: is a &GNUTLS_STATE structure.
80 * Used to set the first argument of the transport function (like PUSH and
81 * PULL). In berkeley style sockets this function will set the connection
85 void gnutls_transport_set_ptr(GNUTLS_STATE state
, GNUTLS_TRANSPORT_PTR ptr
) {
86 state
->gnutls_internals
.transport_ptr
= ptr
;
90 * gnutls_transport_get_ptr - Used to return the first argument of the transport functions
91 * @state: is a &GNUTLS_STATE structure.
93 * Used to get the first argument of the transport function (like PUSH and
94 * PULL). This must have been set using gnutls_transport_set_ptr().
97 GNUTLS_TRANSPORT_PTR
gnutls_transport_get_ptr(GNUTLS_STATE state
) {
98 return state
->gnutls_internals
.transport_ptr
;
102 * gnutls_bye - This function terminates the current TLS/SSL connection.
103 * @state: is a &GNUTLS_STATE structure.
104 * @how: is an integer
106 * Terminates the current TLS/SSL connection. The connection should
107 * have been initiated using gnutls_handshake().
108 * 'how' should be one of GNUTLS_SHUT_RDWR, GNUTLS_SHUT_WR.
110 * In case of GNUTLS_SHUT_RDWR then the TLS connection gets terminated and
111 * further receives and sends will be disallowed. If the return
112 * value is zero you may continue using the connection.
113 * GNUTLS_SHUT_RDWR actually sends an alert containing a close request
114 * and waits for the peer to reply with the same message.
116 * In case of GNUTLS_SHUT_WR then the TLS connection gets terminated and
117 * further sends will be disallowed. In order to reuse the connection
118 * you should wait for an EOF from the peer.
119 * GNUTLS_SHUT_WR sends an alert containing a close request.
121 * This function may also return GNUTLS_E_AGAIN, or GNUTLS_E_INTERRUPTED.
124 int gnutls_bye( GNUTLS_STATE state
, GNUTLS_CloseRequest how
)
126 int ret
= 0, ret2
= 0;
131 if (STATE
==STATE60
) {
132 ret
= _gnutls_io_write_flush( state
);
134 ret
= gnutls_alert_send( state
, GNUTLS_AL_WARNING
, GNUTLS_A_CLOSE_NOTIFY
);
141 if ( how
== GNUTLS_SHUT_RDWR
&& ret
>= 0) {
142 ret2
= gnutls_recv_int( state
, GNUTLS_ALERT
, -1, NULL
, 0);
143 if (ret2
>= 0) state
->gnutls_internals
.may_read
= 1;
154 state
->gnutls_internals
.may_write
= 1;
159 static void _gnutls_session_invalidate( GNUTLS_STATE state
) {
160 state
->gnutls_internals
.valid_connection
= VALID_FALSE
;
165 static void _gnutls_session_unresumable( GNUTLS_STATE state
) {
166 state
->gnutls_internals
.resumable
= RESUME_FALSE
;
169 /* returns 0 if session is valid
172 static int _gnutls_session_is_valid( GNUTLS_STATE state
) {
173 if (state
->gnutls_internals
.valid_connection
==VALID_FALSE
)
174 return GNUTLS_E_INVALID_SESSION
;
180 ssize_t
_gnutls_create_empty_record( GNUTLS_STATE state
, ContentType type
,
181 opaque
* erecord
, int erecord_size
)
189 if (type
!=GNUTLS_APPLICATION_DATA
||
190 _gnutls_cipher_is_block( gnutls_cipher_get(state
))!=CIPHER_BLOCK
)
191 /* alert messages and stream ciphers
192 * do not need this protection
198 lver
= gnutls_protocol_get_version(state
);
199 if (lver
==GNUTLS_VERSION_UNKNOWN
) {
201 return GNUTLS_E_INTERNAL_ERROR
;
204 headers
[1]=_gnutls_version_get_major( lver
);
205 headers
[2]=_gnutls_version_get_minor( lver
);
209 cipher_size
= _gnutls_encrypt( state
, headers
, RECORD_HEADER_SIZE
, NULL
, 0, erecord
, erecord_size
, type
, 0);
210 if (cipher_size
<= 0) {
212 if (cipher_size
==0) cipher_size
= GNUTLS_E_ENCRYPTION_FAILED
;
213 return cipher_size
; /* error */
216 retval
= cipher_size
;
218 /* increase sequence number
220 if (_gnutls_uint64pp( &state
->connection_state
.write_sequence_number
) != 0) {
221 _gnutls_session_invalidate( state
);
223 return GNUTLS_E_RECORD_LIMIT_REACHED
;
229 /* This function behave exactly like write(). The only difference is
230 * that it accepts, the gnutls_state and the ContentType of data to
231 * send (if called by the user the Content is specific)
232 * It is intended to transfer data, under the current state.
234 * Oct 30 2001: Removed capability to send data more than MAX_RECORD_SIZE.
235 * This makes the function much easier to read, and more error resistant
236 * (there were cases were the old function could mess everything up).
240 ssize_t
gnutls_send_int( GNUTLS_STATE state
, ContentType type
, HandshakeType htype
, const void *_data
, size_t sizeofdata
)
247 const uint8
*data
=_data
;
249 int erecord_size
= 0;
250 opaque
* erecord
= NULL
;
252 if (sizeofdata
== 0 || _data
==NULL
) {
254 return GNUTLS_E_INVALID_PARAMETERS
;
257 if (type
!=GNUTLS_ALERT
) /* alert messages are sent anyway */
258 if ( _gnutls_session_is_valid( state
) || state
->gnutls_internals
.may_write
!= 0) {
259 return GNUTLS_E_INVALID_SESSION
;
266 lver
= gnutls_protocol_get_version(state
);
267 if (lver
==GNUTLS_VERSION_UNKNOWN
) {
269 return GNUTLS_E_INTERNAL_ERROR
;
272 headers
[1]=_gnutls_version_get_major( lver
);
273 headers
[2]=_gnutls_version_get_minor( lver
);
275 _gnutls_record_log( "REC: Sending Packet[%d] %s(%d) with length: %d\n",
276 (int) _gnutls_uint64touint32(&state
->connection_state
.write_sequence_number
), _gnutls_packet2str(type
), type
, sizeofdata
);
278 if ( sizeofdata
> MAX_RECORD_SIZE
)
279 data2send_size
= MAX_RECORD_SIZE
;
281 data2send_size
= sizeofdata
;
283 /* Only encrypt if we don't have data to send
284 * from the previous run. - probably interrupted.
286 if (state
->gnutls_internals
.record_send_buffer
.size
> 0) {
287 ret
= _gnutls_io_write_flush( state
);
288 if (ret
> 0) cipher_size
= ret
;
289 else cipher_size
= 0;
293 retval
= state
->gnutls_internals
.record_send_buffer_user_size
;
296 /* Prepend our packet with an empty record. This is to
297 * avoid the recent CBC attacks.
299 /* if this protection has been disabled
301 if (state
->gnutls_internals
.cbc_protection_hack
!=0) {
302 erecord_size
= MAX_RECORD_OVERHEAD
;
303 erecord
= gnutls_alloca( erecord_size
);
306 return GNUTLS_E_MEMORY_ERROR
;
310 _gnutls_create_empty_record( state
, type
, erecord
, erecord_size
);
311 if (erecord_size
< 0) {
317 /* now proceed to packet encryption
319 cipher_size
= data2send_size
+ MAX_RECORD_OVERHEAD
;
320 cipher
= gnutls_alloca( cipher_size
);
323 return GNUTLS_E_MEMORY_ERROR
;
326 cipher_size
= _gnutls_encrypt( state
, headers
, RECORD_HEADER_SIZE
, data
, data2send_size
, cipher
,
327 cipher_size
, type
, 1);
328 if (cipher_size
<= 0) {
330 if (cipher_size
==0) cipher_size
= GNUTLS_E_ENCRYPTION_FAILED
;
331 gnutls_afree( erecord
);
332 gnutls_afree( cipher
);
333 return cipher_size
; /* error */
336 retval
= data2send_size
;
337 state
->gnutls_internals
.record_send_buffer_user_size
= data2send_size
;
339 /* increase sequence number
341 if (_gnutls_uint64pp( &state
->connection_state
.write_sequence_number
) != 0) {
342 _gnutls_session_invalidate( state
);
344 gnutls_afree( erecord
);
345 gnutls_afree( cipher
);
346 return GNUTLS_E_RECORD_LIMIT_REACHED
;
349 ret
= _gnutls_io_write_buffered2( state
, erecord
, erecord_size
, cipher
, cipher_size
);
350 gnutls_afree( erecord
);
351 gnutls_afree( cipher
);
354 if ( ret
!= cipher_size
+ erecord_size
) {
355 if ( ret
< 0 && gnutls_error_is_fatal(ret
)==0) {
356 /* If we have sent any data then return
365 ret
= GNUTLS_E_UNKNOWN_ERROR
;
368 _gnutls_session_unresumable( state
);
369 _gnutls_session_invalidate( state
);
374 state
->gnutls_internals
.record_send_buffer_user_size
= 0;
376 _gnutls_record_log( "REC: Sent Packet[%d] %s(%d) with length: %d\n",
377 (int) _gnutls_uint64touint32(&state
->connection_state
.write_sequence_number
), _gnutls_packet2str(type
), type
, cipher_size
);
382 /* This function is to be called if the handshake was successfully
383 * completed. This sends a Change Cipher Spec packet to the peer.
385 ssize_t
_gnutls_send_change_cipher_spec( GNUTLS_STATE state
, int again
)
387 opaque data
[1] = { GNUTLS_TYPE_CHANGE_CIPHER_SPEC
};
389 _gnutls_handshake_log( "REC: Sent ChangeCipherSpec\n");
392 return gnutls_send_int( state
, GNUTLS_CHANGE_CIPHER_SPEC
, -1, data
, 1);
394 return _gnutls_io_write_flush( state
);
398 static int _gnutls_check_recv_type( ContentType recv_type
) {
400 case GNUTLS_CHANGE_CIPHER_SPEC
:
402 case GNUTLS_HANDSHAKE
:
403 case GNUTLS_APPLICATION_DATA
:
407 return GNUTLS_E_UNSUPPORTED_VERSION_PACKET
;
413 /* Checks if there are pending data into the record buffers. If there are
414 * then it copies the data.
416 static int _gnutls_check_buffers( GNUTLS_STATE state
, ContentType type
, opaque
* data
, int sizeofdata
) {
418 if ( (type
== GNUTLS_APPLICATION_DATA
|| type
== GNUTLS_HANDSHAKE
) && _gnutls_record_buffer_get_size(type
, state
) > 0) {
419 ret
= _gnutls_record_buffer_get(type
, state
, data
, sizeofdata
);
425 /* if the buffer just got empty */
426 if (_gnutls_record_buffer_get_size(type
, state
)==0) {
427 if ( (ret2
=_gnutls_io_clear_peeked_data( state
)) < 0) {
440 #define CHECK_RECORD_VERSION
442 /* Checks the record headers and returns the length, version and
445 static int _gnutls_check_record_headers( GNUTLS_STATE state
, uint8 headers
[RECORD_HEADER_SIZE
], ContentType type
,
446 HandshakeType htype
, /*output*/ ContentType
*recv_type
, GNUTLS_Version
*version
, uint16
*length
, uint16
* header_size
) {
448 /* Read the first two bytes to determine if this is a
452 if ( htype
== GNUTLS_CLIENT_HELLO
&& type
==GNUTLS_HANDSHAKE
&& headers
[0] > 127) {
454 /* if msb set and expecting handshake message
455 * it should be SSL 2 hello
457 *version
= GNUTLS_VERSION_UNKNOWN
; /* assume unknown version */
458 *length
= (((headers
[0] & 0x7f) << 8)) | headers
[1];
460 /* SSL 2.0 headers */
462 *recv_type
= GNUTLS_HANDSHAKE
; /* we accept only v2 client hello
465 /* in order to assist the handshake protocol.
466 * V2 compatibility is a mess.
468 state
->gnutls_internals
.v2_hello
= *length
;
470 _gnutls_record_log( "REC: V2 packet received. Length: %d\n", *length
);
475 *recv_type
= headers
[0];
476 #ifdef CHECK_RECORD_VERSION
477 *version
= _gnutls_version_get( headers
[1], headers
[2]);
480 /* No DECR_LEN, since headers has enough size.
482 *length
= _gnutls_read_uint16( &headers
[3]);
488 /* Here we check if the advertized version is the one we
489 * negotiated in the handshake.
492 static int _gnutls_check_record_version( GNUTLS_STATE state
, HandshakeType htype
, GNUTLS_Version version
)
494 #ifdef CHECK_RECORD_VERSION
495 if ( (htype
!=GNUTLS_CLIENT_HELLO
&& htype
!=GNUTLS_SERVER_HELLO
) && gnutls_protocol_get_version(state
) != version
) {
498 _gnutls_record_log( "REC: INVALID VERSION PACKET: (%d) %d.%d\n", htype
, _gnutls_version_get_major(version
), _gnutls_version_get_minor(version
));
500 return GNUTLS_E_UNSUPPORTED_VERSION_PACKET
;
507 /* This function will check if the received record type is
508 * the one we actually expecting for.
510 static int _gnutls_record_check_type( GNUTLS_STATE state
, ContentType recv_type
,
511 ContentType type
, HandshakeType htype
, opaque
* data
, int data_size
) {
515 if ( (recv_type
== type
) && (type
== GNUTLS_APPLICATION_DATA
|| type
== GNUTLS_HANDSHAKE
)) {
516 _gnutls_record_buffer_put(type
, state
, (void *) data
, data_size
);
521 _gnutls_record_log( "REC: Alert[%d|%d] - %s - was received\n", data
[0], data
[1], gnutls_alert_get_name((int)data
[1]));
523 state
->gnutls_internals
.last_alert
= data
[1];
525 /* if close notify is received and
526 * the alert is not fatal
528 if (data
[1] == GNUTLS_A_CLOSE_NOTIFY
&& data
[0] != GNUTLS_AL_FATAL
) {
529 /* If we have been expecting for an alert do
532 return GNUTLS_E_INT_RET_0
; /* EOF */
535 /* if the alert is FATAL or WARNING
536 * return the apropriate message
540 ret
= GNUTLS_E_WARNING_ALERT_RECEIVED
;
541 if (data
[0] == GNUTLS_AL_FATAL
) {
542 _gnutls_session_unresumable( state
);
543 _gnutls_session_invalidate( state
);
545 ret
= GNUTLS_E_FATAL_ALERT_RECEIVED
;
552 case GNUTLS_CHANGE_CIPHER_SPEC
:
553 /* this packet is now handled above */
556 return GNUTLS_E_UNEXPECTED_PACKET
;
558 case GNUTLS_APPLICATION_DATA
:
559 /* even if data is unexpected put it into the buffer */
560 if ( (ret
=_gnutls_record_buffer_put(recv_type
, state
, (void *) data
, data_size
)) < 0) {
567 /* the got_application data is only returned
568 * if expecting client hello (for rehandshake
569 * reasons). Otherwise it is an unexpected packet
571 if (htype
== GNUTLS_CLIENT_HELLO
&& type
==GNUTLS_HANDSHAKE
)
572 return GNUTLS_E_GOT_APPLICATION_DATA
;
573 else return GNUTLS_E_UNEXPECTED_PACKET
;
576 case GNUTLS_HANDSHAKE
:
577 /* This is only legal if HELLO_REQUEST is received - and we are a client
579 if ( state
->security_parameters
.entity
==GNUTLS_SERVER
) {
581 return GNUTLS_E_UNEXPECTED_PACKET
;
585 return _gnutls_recv_hello_request( state
, data
, data_size
);
590 _gnutls_record_log( "REC: Received Unknown packet %d expecting %d\n", recv_type
, type
);
593 return GNUTLS_E_UNKNOWN_ERROR
;
601 #define MAX_EMPTY_PACKETS_SEQUENCE 4
603 /* This function behave exactly like read(). The only difference is
604 * that it accepts, the gnutls_state and the ContentType of data to
605 * send (if called by the user the Content is Userdata only)
606 * It is intended to receive data, under the current state.
608 ssize_t
gnutls_recv_int( GNUTLS_STATE state
, ContentType type
, HandshakeType htype
, char *data
, size_t sizeofdata
)
612 GNUTLS_Version version
;
614 ContentType recv_type
;
620 int empty_packet
= 0;
624 if (empty_packet
> MAX_EMPTY_PACKETS_SEQUENCE
) {
626 return GNUTLS_E_TOO_MANY_EMPTY_PACKETS
;
629 /* default headers for TLS 1.0
631 header_size
= RECORD_HEADER_SIZE
;
634 if (sizeofdata
== 0 || data
== NULL
) {
635 return GNUTLS_E_INVALID_PARAMETERS
;
638 if ( _gnutls_session_is_valid(state
)!=0 || state
->gnutls_internals
.may_read
!=0) {
640 return GNUTLS_E_INVALID_SESSION
;
643 /* If we have enough data in the cache do not bother receiving
644 * a new packet. (in order to flush the cache)
646 ret
= _gnutls_check_buffers( state
, type
, data
, sizeofdata
);
651 if ( (ret
= _gnutls_io_read_buffered( state
, &headers
, header_size
, -1)) != header_size
) {
652 if (ret
< 0 && gnutls_error_is_fatal(ret
)==0) return ret
;
654 _gnutls_session_invalidate( state
);
655 if (type
==GNUTLS_ALERT
) {
657 return 0; /* we were expecting close notify */
659 _gnutls_session_unresumable( state
);
661 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH
;
664 if ( (ret
=_gnutls_check_record_headers( state
, headers
, type
, htype
, &recv_type
, &version
, &length
, &header_size
)) < 0) {
669 /* Here we check if the Type of the received packet is
672 if ( (ret
= _gnutls_check_recv_type( recv_type
)) < 0) {
678 /* Here we check if the advertized version is the one we
679 * negotiated in the handshake.
681 if ( (ret
=_gnutls_check_record_version( state
, htype
, version
)) < 0) {
683 _gnutls_session_invalidate( state
);
687 _gnutls_record_log( "REC: Expected Packet[%d] %s(%d) with length: %d\n",
688 (int) _gnutls_uint64touint32(&state
->connection_state
.read_sequence_number
), _gnutls_packet2str(type
), type
, sizeofdata
);
689 _gnutls_record_log( "REC: Received Packet[%d] %s(%d) with length: %d\n",
690 (int) _gnutls_uint64touint32(&state
->connection_state
.read_sequence_number
), _gnutls_packet2str(recv_type
), recv_type
, length
);
692 if (length
> MAX_RECV_SIZE
) {
694 _gnutls_record_log( "REC: FATAL ERROR: Received packet with length: %d\n", length
);
696 _gnutls_session_unresumable( state
);
697 _gnutls_session_invalidate( state
);
699 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH
;
702 /* check if we have that data into buffer.
704 if ( (ret
= _gnutls_io_read_buffered( state
, &recv_data
, header_size
+length
, recv_type
)) != length
+header_size
) {
705 if (ret
<0 && gnutls_error_is_fatal(ret
)==0) return ret
;
707 _gnutls_session_unresumable( state
);
708 _gnutls_session_invalidate( state
);
710 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH
;
713 /* ok now we are sure that we can read all the data - so
716 _gnutls_io_clear_read_buffer( state
);
717 ciphertext
= &recv_data
[header_size
];
719 /* decrypt the data we got
721 tmplen
= length
+ MAX_RECORD_OVERHEAD
;
722 tmpdata
= gnutls_alloca( tmplen
);
725 return GNUTLS_E_MEMORY_ERROR
;
728 tmplen
= _gnutls_decrypt( state
, ciphertext
, length
, tmpdata
, tmplen
, recv_type
);
730 _gnutls_session_unresumable( state
);
731 _gnutls_session_invalidate( state
);
732 gnutls_afree(tmpdata
);
737 /* Check if this is a CHANGE_CIPHER_SPEC
739 if (type
== GNUTLS_CHANGE_CIPHER_SPEC
&& recv_type
== GNUTLS_CHANGE_CIPHER_SPEC
) {
741 _gnutls_record_log( "REC: ChangeCipherSpec Packet was received\n");
743 if (tmplen
!=sizeofdata
) { /* sizeofdata should be 1 */
745 gnutls_afree(tmpdata
);
746 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH
;
748 memcpy( data
, tmpdata
, sizeofdata
);
749 gnutls_afree(tmpdata
);
754 _gnutls_record_log( "REC: Decrypted Packet[%d] %s(%d) with length: %d\n",
755 (int) _gnutls_uint64touint32(&state
->connection_state
.read_sequence_number
), _gnutls_packet2str(recv_type
), recv_type
, tmplen
);
757 /* increase sequence number */
758 if (_gnutls_uint64pp( &state
->connection_state
.read_sequence_number
)!=0) {
759 _gnutls_session_invalidate( state
);
760 gnutls_afree(tmpdata
);
762 return GNUTLS_E_RECORD_LIMIT_REACHED
;
765 if ( (ret
=_gnutls_record_check_type( state
, recv_type
, type
, htype
, tmpdata
, tmplen
)) < 0) {
766 gnutls_afree(tmpdata
);
768 if (ret
==GNUTLS_E_INT_RET_0
) return 0;
773 gnutls_afree(tmpdata
);
775 /* Get Application data from buffer */
776 if ((type
== GNUTLS_APPLICATION_DATA
|| type
== GNUTLS_HANDSHAKE
) && (recv_type
== type
)) {
778 ret
= _gnutls_record_buffer_get(type
, state
, data
, sizeofdata
);
784 /* if the buffer just got empty */
785 if (_gnutls_record_buffer_get_size(type
, state
)==0) {
786 if ( (ret2
= _gnutls_io_clear_peeked_data( state
)) < 0) {
794 ret
= GNUTLS_E_UNEXPECTED_PACKET
;
795 /* we didn't get what we wanted to
799 /* TLS 1.0 CBC protection. Read the next fragment.
810 /* Taken from libgcrypt */
813 parse_version_number( const char *s
, int *number
)
817 if( *s
== '0' && isdigit(s
[1]) )
818 return NULL
; /* leading zeros are not allowed */
819 for ( ; isdigit(*s
); s
++ ) {
824 return val
< 0? NULL
: s
;
829 parse_version_string( const char *s
, int *major
, int *minor
, int *micro
)
831 s
= parse_version_number( s
, major
);
832 if( !s
|| *s
!= '.' )
835 s
= parse_version_number( s
, minor
);
836 if( !s
|| *s
!= '.' )
839 s
= parse_version_number( s
, micro
);
842 return s
; /* patchlevel */
846 * Check that the the version of the library is at minimum the requested one
847 * and return the version string; return NULL if the condition is not
848 * satisfied. If a NULL is passed to this function, no check is done,
849 * but the version string is simply returned.
852 gnutls_check_version( const char *req_version
)
854 const char *ver
= GNUTLS_VERSION
;
855 int my_major
, my_minor
, my_micro
;
856 int rq_major
, rq_minor
, rq_micro
;
857 const char *my_plvl
, *rq_plvl
;
862 my_plvl
= parse_version_string( ver
, &my_major
, &my_minor
, &my_micro
);
864 return NULL
; /* very strange our own version is bogus */
865 rq_plvl
= parse_version_string( req_version
, &rq_major
, &rq_minor
,
868 return NULL
; /* req version string is invalid */
870 if ( my_major
> rq_major
871 || (my_major
== rq_major
&& my_minor
> rq_minor
)
872 || (my_major
== rq_major
&& my_minor
== rq_minor
873 && my_micro
> rq_micro
)
874 || (my_major
== rq_major
&& my_minor
== rq_minor
875 && my_micro
== rq_micro
876 && strcmp( my_plvl
, rq_plvl
) >= 0) ) {
884 * gnutls_record_send - sends to the peer the specified data
885 * @state: is a &GNUTLS_STATE structure.
886 * @data: contains the data to send
887 * @sizeofdata: is the length of the data
889 * This function has the similar semantics to write(). The only
890 * difference is that is accepts a GNUTLS state, and uses different
893 * If the EINTR is returned by the internal push function (write())
894 * then GNUTLS_E_INTERRUPTED, will be returned. If GNUTLS_E_INTERRUPTED or
895 * GNUTLS_E_AGAIN is returned you must call this function again, with the
896 * same parameters. Otherwise the write operation will be
897 * corrupted and the connection will be terminated.
899 * Returns the number of bytes sent, or a negative error code.
902 ssize_t
gnutls_record_send( GNUTLS_STATE state
, const void *data
, size_t sizeofdata
) {
903 return gnutls_send_int( state
, GNUTLS_APPLICATION_DATA
, -1, data
, sizeofdata
);
907 * gnutls_record_recv - reads data from the TLS record protocol
908 * @state: is a &GNUTLS_STATE structure.
909 * @data: contains the data to send
910 * @sizeofdata: is the length of the data
912 * This function has the similar semantics to read(). The only
913 * difference is that is accepts a GNUTLS state.
914 * Also returns the number of bytes received, zero on EOF, but
915 * a negative error code in case of an error.
917 * If this function returns GNUTLS_E_REHANDSHAKE, then you may
918 * ignore this message, send an alert containing NO_RENEGOTIATION,
919 * or perform a handshake again. (only a client may receive this message)
922 ssize_t
gnutls_record_recv( GNUTLS_STATE state
, void *data
, size_t sizeofdata
) {
923 return gnutls_recv_int( state
, GNUTLS_APPLICATION_DATA
, -1, data
, sizeofdata
);
927 * gnutls_record_get_max_size - returns the maximum record size
928 * @state: is a &GNUTLS_STATE structure.
930 * This function returns the maximum record size in this connection.
931 * The maximum record size is negotiated by the client after the
932 * first handshake message.
935 size_t gnutls_record_get_max_size( GNUTLS_STATE state
) {
936 return state
->security_parameters
.max_record_size
;
941 * gnutls_record_set_max_size - sets the maximum record size
942 * @state: is a &GNUTLS_STATE structure.
943 * @size: is the new size
945 * This function sets the maximum record size in this connection.
946 * This property can only be set to clients. The server may
947 * choose not to accept the requested size.
949 * Acceptable values are 2^9, 2^10, 2^11 and 2^12.
950 * Returns 0 on success. The requested record size does not
951 * get in effect immediately. It will be used after a successful
954 * This function uses a TLS extension called 'max record size'.
955 * Not all TLS implementations use or even understand this extension.
958 ssize_t
gnutls_record_set_max_size( GNUTLS_STATE state
, size_t size
) {
961 if (state
->security_parameters
.entity
==GNUTLS_SERVER
)
962 return GNUTLS_E_INVALID_REQUEST
;
964 new_size
= _gnutls_mre_record2num( size
);
971 state
->gnutls_internals
.proposed_record_size
= size
;