2 * Copyright (C) 2000-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
8 * The GnuTLS is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 3 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 /* Contains functions that are supposed to pack and unpack session data,
24 * before and after they are sent to the database backend.
27 #include <gnutls_int.h>
34 #include <auth/anon.h>
35 #include <auth/cert.h>
36 #include <gnutls_errors.h>
37 #include <gnutls_auth.h>
38 #include <gnutls_session_pack.h>
39 #include <gnutls_datum.h>
40 #include <gnutls_num.h>
41 #include <gnutls_extensions.h>
42 #include <gnutls_constate.h>
43 #include <algorithms.h>
45 static int pack_certificate_auth_info (gnutls_session_t
,
46 gnutls_buffer_st
* packed_session
);
47 static int unpack_certificate_auth_info (gnutls_session_t
,
48 gnutls_buffer_st
* packed_session
);
50 static int unpack_srp_auth_info (gnutls_session_t session
,
51 gnutls_buffer_st
* packed_session
);
52 static int pack_srp_auth_info (gnutls_session_t session
,
53 gnutls_buffer_st
* packed_session
);
55 static int unpack_psk_auth_info (gnutls_session_t session
,
56 gnutls_buffer_st
* packed_session
);
57 static int pack_psk_auth_info (gnutls_session_t session
,
58 gnutls_buffer_st
* packed_session
);
60 static int unpack_anon_auth_info (gnutls_session_t session
,
61 gnutls_buffer_st
* packed_session
);
62 static int pack_anon_auth_info (gnutls_session_t session
,
63 gnutls_buffer_st
* packed_session
);
65 static int unpack_security_parameters (gnutls_session_t session
,
66 gnutls_buffer_st
* packed_session
);
67 static int pack_security_parameters (gnutls_session_t session
,
68 gnutls_buffer_st
* packed_session
);
71 /* Since auth_info structures contain malloced data, this function
72 * is required in order to pack these structures in a vector in
73 * order to store them to the DB.
75 * packed_session will contain the session data.
77 * The data will be in a platform independent format.
80 _gnutls_session_pack (gnutls_session_t session
,
81 gnutls_datum_t
* packed_session
)
87 if (packed_session
== NULL
)
90 return GNUTLS_E_INTERNAL_ERROR
;
93 _gnutls_buffer_init (&sb
);
95 id
= gnutls_auth_get_type (session
);
96 BUFFER_APPEND (&sb
, &id
, 1);
102 ret
= pack_srp_auth_info (session
, &sb
);
112 ret
= pack_psk_auth_info (session
, &sb
);
121 case GNUTLS_CRD_ANON
:
122 ret
= pack_anon_auth_info (session
, &sb
);
130 case GNUTLS_CRD_CERTIFICATE
:
131 ret
= pack_certificate_auth_info (session
, &sb
);
139 return GNUTLS_E_INTERNAL_ERROR
;
143 /* Auth_info structures copied. Now copy security_parameters_st.
144 * packed_session must have allocated space for the security parameters.
146 ret
= pack_security_parameters (session
, &sb
);
153 ret
= _gnutls_ext_pack (session
, &sb
);
160 return _gnutls_buffer_to_datum (&sb
, packed_session
);
163 _gnutls_buffer_clear (&sb
);
168 /* Load session data from a buffer.
171 _gnutls_session_unpack (gnutls_session_t session
,
172 const gnutls_datum_t
* packed_session
)
178 _gnutls_buffer_init (&sb
);
180 if (packed_session
== NULL
|| packed_session
->size
== 0)
183 return GNUTLS_E_INTERNAL_ERROR
;
187 _gnutls_buffer_append_data (&sb
, packed_session
->data
,
188 packed_session
->size
);
195 if (_gnutls_get_auth_info (session
) != NULL
)
197 _gnutls_free_auth_info (session
);
200 BUFFER_POP (&sb
, &id
, 1);
206 ret
= unpack_srp_auth_info (session
, &sb
);
216 ret
= unpack_psk_auth_info (session
, &sb
);
225 case GNUTLS_CRD_ANON
:
226 ret
= unpack_anon_auth_info (session
, &sb
);
234 case GNUTLS_CRD_CERTIFICATE
:
235 ret
= unpack_certificate_auth_info (session
, &sb
);
244 ret
= GNUTLS_E_INTERNAL_ERROR
;
249 /* Auth_info structures copied. Now copy security_parameters_st.
250 * packed_session must have allocated space for the security parameters.
252 ret
= unpack_security_parameters (session
, &sb
);
259 ret
= _gnutls_ext_unpack (session
, &sb
);
269 _gnutls_buffer_clear (&sb
);
277 * 1 byte the credentials type
278 * 4 bytes the size of the whole structure
280 * 2 bytes the size of secret key in bits
281 * 4 bytes the size of the prime
283 * 4 bytes the size of the generator
284 * x bytes the generator
285 * 4 bytes the size of the public key
286 * x bytes the public key
288 * 4 bytes the size of the modulus
289 * x bytes the modulus
290 * 4 bytes the size of the exponent
291 * x bytes the exponent
293 * 4 bytes the length of the certificate list
294 * 4 bytes the size of first certificate
295 * x bytes the certificate
299 pack_certificate_auth_info (gnutls_session_t session
, gnutls_buffer_st
* ps
)
303 cert_auth_info_t info
= _gnutls_get_auth_info (session
);
306 size_offset
= ps
->length
;
307 BUFFER_APPEND_NUM (ps
, 0);
308 cur_size
= ps
->length
;
313 BUFFER_APPEND_NUM (ps
, info
->dh
.secret_bits
);
314 BUFFER_APPEND_PFX4 (ps
, info
->dh
.prime
.data
, info
->dh
.prime
.size
);
315 BUFFER_APPEND_PFX4 (ps
, info
->dh
.generator
.data
,
316 info
->dh
.generator
.size
);
317 BUFFER_APPEND_PFX4 (ps
, info
->dh
.public_key
.data
,
318 info
->dh
.public_key
.size
);
319 BUFFER_APPEND_PFX4 (ps
, info
->rsa_export
.modulus
.data
,
320 info
->rsa_export
.modulus
.size
);
321 BUFFER_APPEND_PFX4 (ps
, info
->rsa_export
.exponent
.data
,
322 info
->rsa_export
.exponent
.size
);
324 BUFFER_APPEND_NUM (ps
, info
->ncerts
);
326 for (i
= 0; i
< info
->ncerts
; i
++)
327 BUFFER_APPEND_PFX4 (ps
, info
->raw_certificate_list
[i
].data
,
328 info
->raw_certificate_list
[i
].size
);
331 /* write the real size */
332 _gnutls_write_uint32 (ps
->length
- cur_size
, ps
->data
+ size_offset
);
338 /* Upack certificate info.
341 unpack_certificate_auth_info (gnutls_session_t session
, gnutls_buffer_st
* ps
)
344 unsigned int i
= 0, j
= 0;
346 cert_auth_info_t info
= NULL
;
348 BUFFER_POP_NUM (ps
, pack_size
);
351 return 0; /* nothing to be done */
353 /* client and server have the same auth_info here
356 _gnutls_auth_info_set (session
, GNUTLS_CRD_CERTIFICATE
,
357 sizeof (cert_auth_info_st
), 1);
364 info
= _gnutls_get_auth_info (session
);
366 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR
);
368 BUFFER_POP_NUM (ps
, info
->dh
.secret_bits
);
370 BUFFER_POP_DATUM (ps
, &info
->dh
.prime
);
371 BUFFER_POP_DATUM (ps
, &info
->dh
.generator
);
372 BUFFER_POP_DATUM (ps
, &info
->dh
.public_key
);
373 BUFFER_POP_DATUM (ps
, &info
->rsa_export
.modulus
);
374 BUFFER_POP_DATUM (ps
, &info
->rsa_export
.exponent
);
376 BUFFER_POP_NUM (ps
, info
->ncerts
);
378 if (info
->ncerts
> 0)
380 info
->raw_certificate_list
=
381 gnutls_calloc (info
->ncerts
, sizeof (gnutls_datum_t
));
382 if (info
->raw_certificate_list
== NULL
)
385 ret
= GNUTLS_E_MEMORY_ERROR
;
390 for (i
= 0; i
< info
->ncerts
; i
++)
392 BUFFER_POP_DATUM (ps
, &info
->raw_certificate_list
[i
]);
400 _gnutls_free_datum (&info
->dh
.prime
);
401 _gnutls_free_datum (&info
->dh
.generator
);
402 _gnutls_free_datum (&info
->dh
.public_key
);
404 _gnutls_free_datum (&info
->rsa_export
.modulus
);
405 _gnutls_free_datum (&info
->rsa_export
.exponent
);
407 for (j
= 0; j
< i
; j
++)
408 _gnutls_free_datum (&info
->raw_certificate_list
[j
]);
410 gnutls_free (info
->raw_certificate_list
);
418 /* Packs the SRP session authentication data.
422 * 1 byte the credentials type
423 * 4 bytes the size of the SRP username (x)
424 * x bytes the SRP username
427 pack_srp_auth_info (gnutls_session_t session
, gnutls_buffer_st
* ps
)
429 srp_server_auth_info_t info
= _gnutls_get_auth_info (session
);
433 const char* username
= NULL
;
435 if (info
&& info
->username
)
437 username
= info
->username
;
438 len
= strlen (info
->username
) + 1; /* include the terminating null */
443 size_offset
= ps
->length
;
444 BUFFER_APPEND_NUM (ps
, 0);
445 cur_size
= ps
->length
;
447 BUFFER_APPEND_PFX4 (ps
, username
, len
);
449 /* write the real size */
450 _gnutls_write_uint32 (ps
->length
- cur_size
, ps
->data
+ size_offset
);
457 unpack_srp_auth_info (gnutls_session_t session
, gnutls_buffer_st
* ps
)
459 size_t username_size
;
461 srp_server_auth_info_t info
;
463 BUFFER_POP_NUM (ps
, username_size
);
464 if (username_size
> sizeof (info
->username
))
467 return GNUTLS_E_INTERNAL_ERROR
;
471 _gnutls_auth_info_set (session
, GNUTLS_CRD_SRP
,
472 sizeof (srp_server_auth_info_st
), 1);
479 info
= _gnutls_get_auth_info (session
);
481 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR
);
483 BUFFER_POP (ps
, info
->username
, username_size
);
484 if (username_size
== 0)
485 info
->username
[0] = 0;
496 /* Packs the ANON session authentication data.
500 * 1 byte the credentials type
501 * 4 bytes the size of the whole structure
502 * 2 bytes the size of secret key in bits
503 * 4 bytes the size of the prime
505 * 4 bytes the size of the generator
506 * x bytes the generator
507 * 4 bytes the size of the public key
508 * x bytes the public key
511 pack_anon_auth_info (gnutls_session_t session
, gnutls_buffer_st
* ps
)
514 anon_auth_info_t info
= _gnutls_get_auth_info (session
);
517 size_offset
= ps
->length
;
518 BUFFER_APPEND_NUM (ps
, 0);
519 cur_size
= ps
->length
;
523 BUFFER_APPEND_NUM (ps
, info
->dh
.secret_bits
);
524 BUFFER_APPEND_PFX4 (ps
, info
->dh
.prime
.data
, info
->dh
.prime
.size
);
525 BUFFER_APPEND_PFX4 (ps
, info
->dh
.generator
.data
,
526 info
->dh
.generator
.size
);
527 BUFFER_APPEND_PFX4 (ps
, info
->dh
.public_key
.data
,
528 info
->dh
.public_key
.size
);
531 /* write the real size */
532 _gnutls_write_uint32 (ps
->length
- cur_size
, ps
->data
+ size_offset
);
539 unpack_anon_auth_info (gnutls_session_t session
, gnutls_buffer_st
* ps
)
543 anon_auth_info_t info
= NULL
;
545 BUFFER_POP_NUM (ps
, pack_size
);
548 return 0; /* nothing to be done */
550 /* client and server have the same auth_info here
553 _gnutls_auth_info_set (session
, GNUTLS_CRD_ANON
,
554 sizeof (anon_auth_info_st
), 1);
561 info
= _gnutls_get_auth_info (session
);
563 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR
);
565 BUFFER_POP_NUM (ps
, info
->dh
.secret_bits
);
567 BUFFER_POP_DATUM (ps
, &info
->dh
.prime
);
568 BUFFER_POP_DATUM (ps
, &info
->dh
.generator
);
569 BUFFER_POP_DATUM (ps
, &info
->dh
.public_key
);
576 _gnutls_free_datum (&info
->dh
.prime
);
577 _gnutls_free_datum (&info
->dh
.generator
);
578 _gnutls_free_datum (&info
->dh
.public_key
);
586 /* Packs the PSK session authentication data.
590 * 1 byte the credentials type
591 * 4 bytes the size of the whole structure
593 * 4 bytes the size of the PSK username (x)
594 * x bytes the PSK username
595 * 2 bytes the size of secret key in bits
596 * 4 bytes the size of the prime
598 * 4 bytes the size of the generator
599 * x bytes the generator
600 * 4 bytes the size of the public key
601 * x bytes the public key
604 pack_psk_auth_info (gnutls_session_t session
, gnutls_buffer_st
* ps
)
606 psk_auth_info_t info
;
612 info
= _gnutls_get_auth_info (session
);
614 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR
);
617 username_len
= strlen (info
->username
) + 1; /* include the terminating null */
622 hint_len
= strlen (info
->hint
) + 1; /* include the terminating null */
626 size_offset
= ps
->length
;
627 BUFFER_APPEND_NUM (ps
, 0);
628 cur_size
= ps
->length
;
630 BUFFER_APPEND_PFX4 (ps
, info
->username
, username_len
);
631 BUFFER_APPEND_PFX4 (ps
, info
->hint
, hint_len
);
633 BUFFER_APPEND_NUM (ps
, info
->dh
.secret_bits
);
634 BUFFER_APPEND_PFX4 (ps
, info
->dh
.prime
.data
, info
->dh
.prime
.size
);
635 BUFFER_APPEND_PFX4 (ps
, info
->dh
.generator
.data
, info
->dh
.generator
.size
);
636 BUFFER_APPEND_PFX4 (ps
, info
->dh
.public_key
.data
, info
->dh
.public_key
.size
);
638 /* write the real size */
639 _gnutls_write_uint32 (ps
->length
- cur_size
, ps
->data
+ size_offset
);
645 unpack_psk_auth_info (gnutls_session_t session
, gnutls_buffer_st
* ps
)
647 size_t username_size
, hint_size
;
649 psk_auth_info_t info
;
652 _gnutls_auth_info_set (session
, GNUTLS_CRD_PSK
,
653 sizeof (psk_auth_info_st
), 1);
660 info
= _gnutls_get_auth_info (session
);
662 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR
);
664 BUFFER_POP_NUM (ps
, username_size
);
665 if (username_size
> sizeof (info
->username
))
668 return GNUTLS_E_INTERNAL_ERROR
;
671 BUFFER_POP (ps
, info
->username
, username_size
);
673 BUFFER_POP_NUM (ps
, hint_size
);
674 if (hint_size
> sizeof (info
->hint
))
677 return GNUTLS_E_INTERNAL_ERROR
;
679 BUFFER_POP (ps
, info
->hint
, hint_size
);
681 BUFFER_POP_NUM (ps
, info
->dh
.secret_bits
);
683 BUFFER_POP_DATUM (ps
, &info
->dh
.prime
);
684 BUFFER_POP_DATUM (ps
, &info
->dh
.generator
);
685 BUFFER_POP_DATUM (ps
, &info
->dh
.public_key
);
690 _gnutls_free_datum (&info
->dh
.prime
);
691 _gnutls_free_datum (&info
->dh
.generator
);
692 _gnutls_free_datum (&info
->dh
.public_key
);
699 /* Packs the security parameters.
703 * 4 bytes the total security data size
704 * 1 byte the entity type (client/server)
705 * 1 byte the key exchange algorithm used
706 * 1 byte the read cipher algorithm
707 * 1 byte the read mac algorithm
708 * 1 byte the read compression algorithm
710 * 1 byte the write cipher algorithm
711 * 1 byte the write mac algorithm
712 * 1 byte the write compression algorithm
714 * 1 byte the certificate type
715 * 1 byte the protocol version
717 * 2 bytes the cipher suite
719 * 48 bytes the master secret
721 * 32 bytes the client random
722 * 32 bytes the server random
724 * 1 byte the session ID size
725 * x bytes the session ID (32 bytes max)
727 * 4 bytes a timestamp
728 * 4 bytes the ECC curve
729 * -------------------
734 pack_security_parameters (gnutls_session_t session
, gnutls_buffer_st
* ps
)
740 record_parameters_st
*params
;
742 if (session
->security_parameters
.epoch_read
743 != session
->security_parameters
.epoch_write
)
746 return GNUTLS_E_INVALID_REQUEST
;
749 ret
= _gnutls_epoch_get (session
, EPOCH_READ_CURRENT
, ¶ms
);
756 /* move after the auth info stuff.
758 size_offset
= ps
->length
;
759 BUFFER_APPEND_NUM (ps
, 0);
760 cur_size
= ps
->length
;
763 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.entity
);
764 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.kx_algorithm
);
766 session
->security_parameters
.cipher_suite
, 2);
767 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.compression_method
);
768 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.cert_type
);
769 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.version
);
771 BUFFER_APPEND (ps
, session
->security_parameters
.master_secret
,
773 BUFFER_APPEND (ps
, session
->security_parameters
.client_random
,
775 BUFFER_APPEND (ps
, session
->security_parameters
.server_random
,
778 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.session_id_size
);
779 BUFFER_APPEND (ps
, session
->security_parameters
.session_id
,
780 session
->security_parameters
.session_id_size
);
782 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.max_record_send_size
);
783 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.max_record_recv_size
);
784 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.timestamp
);
785 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.ecc_curve
);
787 _gnutls_write_uint32 (ps
->length
- cur_size
, ps
->data
+ size_offset
);
793 unpack_security_parameters (gnutls_session_t session
, gnutls_buffer_st
* ps
)
797 time_t timestamp
= gnutls_time (0);
799 BUFFER_POP_NUM (ps
, pack_size
);
802 return GNUTLS_E_INVALID_REQUEST
;
804 memset (&session
->internals
.resumed_security_parameters
, 0,
805 sizeof (session
->internals
.resumed_security_parameters
));
807 BUFFER_POP_NUM (ps
, session
->internals
.resumed_security_parameters
.entity
);
809 session
->internals
.resumed_security_parameters
.kx_algorithm
);
812 resumed_security_parameters
.cipher_suite
, 2);
813 BUFFER_POP_NUM (ps
, session
->internals
.resumed_security_parameters
.compression_method
);
814 BUFFER_POP_NUM (ps
, session
->internals
.resumed_security_parameters
.cert_type
);
815 BUFFER_POP_NUM (ps
, session
->internals
.resumed_security_parameters
.version
);
818 session
->internals
.resumed_security_parameters
.master_secret
,
822 session
->internals
.resumed_security_parameters
.client_random
,
825 session
->internals
.resumed_security_parameters
.server_random
,
829 resumed_security_parameters
.session_id_size
);
831 BUFFER_POP (ps
, session
->internals
.resumed_security_parameters
.session_id
,
832 session
->internals
.resumed_security_parameters
.session_id_size
);
836 resumed_security_parameters
.max_record_send_size
);
839 resumed_security_parameters
.max_record_recv_size
);
841 session
->internals
.resumed_security_parameters
.timestamp
);
844 session
->internals
.resumed_security_parameters
.ecc_curve
);
846 if (timestamp
- session
->internals
.resumed_security_parameters
.timestamp
>
847 session
->internals
.expire_time
848 || session
->internals
.resumed_security_parameters
.timestamp
> timestamp
)
851 return GNUTLS_E_EXPIRED
;
861 * gnutls_session_set_premaster:
862 * @session: is a #gnutls_session_t structure.
863 * @entity: GNUTLS_SERVER or GNUTLS_CLIENT
864 * @version: the TLS protocol version
865 * @kx: the key exchange method
866 * @cipher: the cipher
867 * @mac: the MAC algorithm
868 * @comp: the compression method
869 * @master: the master key to use
870 * @session_id: the session identifier
872 * This function sets the premaster secret in a session. This is
873 * a function intended for exceptional uses. Do not use this
874 * function unless you are implementing a legacy protocol.
875 * Use gnutls_session_set_data() instead.
877 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
878 * an error code is returned.
881 gnutls_session_set_premaster (gnutls_session_t session
, unsigned int entity
,
882 gnutls_protocol_t version
,
883 gnutls_kx_algorithm_t kx
,
884 gnutls_cipher_algorithm_t cipher
,
885 gnutls_mac_algorithm_t mac
,
886 gnutls_compression_method_t comp
,
887 const gnutls_datum_t
* master
,
888 const gnutls_datum_t
* session_id
)
892 memset (&session
->internals
.resumed_security_parameters
, 0,
893 sizeof (session
->internals
.resumed_security_parameters
));
895 session
->internals
.resumed_security_parameters
.entity
= entity
;
896 session
->internals
.resumed_security_parameters
.kx_algorithm
= kx
;
898 ret
= _gnutls_cipher_suite_get_id(kx
, cipher
, mac
, session
->internals
.resumed_security_parameters
.cipher_suite
);
900 return gnutls_assert_val(ret
);
902 session
->internals
.resumed_security_parameters
.compression_method
= comp
;
903 session
->internals
.resumed_security_parameters
.cert_type
= GNUTLS_CRT_UNKNOWN
;
904 session
->internals
.resumed_security_parameters
.version
= version
;
906 if (master
->size
!= GNUTLS_MASTER_SIZE
)
907 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST
);
909 memcpy(session
->internals
.resumed_security_parameters
.master_secret
, master
->data
, master
->size
);
911 if (session_id
->size
> GNUTLS_MAX_SESSION_ID
)
912 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST
);
914 session
->internals
.resumed_security_parameters
.session_id_size
= session_id
->size
;
915 memcpy(session
->internals
.resumed_security_parameters
.session_id
, session_id
->data
, session_id
->size
);
917 session
->internals
.resumed_security_parameters
.max_record_send_size
=
918 session
->internals
.resumed_security_parameters
.max_record_recv_size
= DEFAULT_MAX_RECORD_SIZE
;
920 session
->internals
.resumed_security_parameters
.timestamp
= time(0);
922 session
->internals
.resumed_security_parameters
.ecc_curve
= GNUTLS_ECC_CURVE_INVALID
;
924 session
->internals
.premaster_set
= 1;