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
);
150 _gnutls_buffer_clear (&sb
);
154 ret
= _gnutls_ext_pack (session
, &sb
);
158 _gnutls_buffer_clear (&sb
);
162 ret
= _gnutls_buffer_to_datum (&sb
, packed_session
);
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_PFX (ps
, info
->dh
.prime
.data
, info
->dh
.prime
.size
);
315 BUFFER_APPEND_PFX (ps
, info
->dh
.generator
.data
,
316 info
->dh
.generator
.size
);
317 BUFFER_APPEND_PFX (ps
, info
->dh
.public_key
.data
,
318 info
->dh
.public_key
.size
);
319 BUFFER_APPEND_PFX (ps
, info
->rsa_export
.modulus
.data
,
320 info
->rsa_export
.modulus
.size
);
321 BUFFER_APPEND_PFX (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_PFX (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
);
368 return GNUTLS_E_INTERNAL_ERROR
;
371 BUFFER_POP_NUM (ps
, info
->dh
.secret_bits
);
373 BUFFER_POP_DATUM (ps
, &info
->dh
.prime
);
374 BUFFER_POP_DATUM (ps
, &info
->dh
.generator
);
375 BUFFER_POP_DATUM (ps
, &info
->dh
.public_key
);
376 BUFFER_POP_DATUM (ps
, &info
->rsa_export
.modulus
);
377 BUFFER_POP_DATUM (ps
, &info
->rsa_export
.exponent
);
379 BUFFER_POP_NUM (ps
, info
->ncerts
);
381 if (info
->ncerts
> 0)
383 info
->raw_certificate_list
=
384 gnutls_calloc (info
->ncerts
, sizeof (gnutls_datum_t
));
385 if (info
->raw_certificate_list
== NULL
)
388 ret
= GNUTLS_E_MEMORY_ERROR
;
393 for (i
= 0; i
< info
->ncerts
; i
++)
395 BUFFER_POP_DATUM (ps
, &info
->raw_certificate_list
[i
]);
403 _gnutls_free_datum (&info
->dh
.prime
);
404 _gnutls_free_datum (&info
->dh
.generator
);
405 _gnutls_free_datum (&info
->dh
.public_key
);
407 _gnutls_free_datum (&info
->rsa_export
.modulus
);
408 _gnutls_free_datum (&info
->rsa_export
.exponent
);
410 for (j
= 0; j
< i
; j
++)
411 _gnutls_free_datum (&info
->raw_certificate_list
[j
]);
413 gnutls_free (info
->raw_certificate_list
);
421 /* Packs the SRP session authentication data.
425 * 1 byte the credentials type
426 * 4 bytes the size of the SRP username (x)
427 * x bytes the SRP username
430 pack_srp_auth_info (gnutls_session_t session
, gnutls_buffer_st
* ps
)
432 srp_server_auth_info_t info
= _gnutls_get_auth_info (session
);
437 if (info
&& info
->username
)
438 len
= strlen (info
->username
) + 1; /* include the terminating null */
442 size_offset
= ps
->length
;
443 BUFFER_APPEND_NUM (ps
, 0);
444 cur_size
= ps
->length
;
446 BUFFER_APPEND_PFX (ps
, info
->username
, len
);
448 /* write the real size */
449 _gnutls_write_uint32 (ps
->length
- cur_size
, ps
->data
+ size_offset
);
456 unpack_srp_auth_info (gnutls_session_t session
, gnutls_buffer_st
* ps
)
458 size_t username_size
;
460 srp_server_auth_info_t info
;
462 BUFFER_POP_NUM (ps
, username_size
);
463 if (username_size
> sizeof (info
->username
))
466 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
);
483 return GNUTLS_E_INTERNAL_ERROR
;
486 BUFFER_POP (ps
, info
->username
, username_size
);
497 /* Packs the ANON session authentication data.
501 * 1 byte the credentials type
502 * 4 bytes the size of the whole structure
503 * 2 bytes the size of secret key in bits
504 * 4 bytes the size of the prime
506 * 4 bytes the size of the generator
507 * x bytes the generator
508 * 4 bytes the size of the public key
509 * x bytes the public key
512 pack_anon_auth_info (gnutls_session_t session
, gnutls_buffer_st
* ps
)
515 anon_auth_info_t info
= _gnutls_get_auth_info (session
);
518 size_offset
= ps
->length
;
519 BUFFER_APPEND_NUM (ps
, 0);
520 cur_size
= ps
->length
;
524 BUFFER_APPEND_NUM (ps
, info
->dh
.secret_bits
);
525 BUFFER_APPEND_PFX (ps
, info
->dh
.prime
.data
, info
->dh
.prime
.size
);
526 BUFFER_APPEND_PFX (ps
, info
->dh
.generator
.data
,
527 info
->dh
.generator
.size
);
528 BUFFER_APPEND_PFX (ps
, info
->dh
.public_key
.data
,
529 info
->dh
.public_key
.size
);
532 /* write the real size */
533 _gnutls_write_uint32 (ps
->length
- cur_size
, ps
->data
+ size_offset
);
540 unpack_anon_auth_info (gnutls_session_t session
, gnutls_buffer_st
* ps
)
544 anon_auth_info_t info
= NULL
;
546 BUFFER_POP_NUM (ps
, pack_size
);
549 return 0; /* nothing to be done */
551 /* client and server have the same auth_info here
554 _gnutls_auth_info_set (session
, GNUTLS_CRD_ANON
,
555 sizeof (anon_auth_info_st
), 1);
562 info
= _gnutls_get_auth_info (session
);
566 return GNUTLS_E_INTERNAL_ERROR
;
569 BUFFER_POP_NUM (ps
, info
->dh
.secret_bits
);
571 BUFFER_POP_DATUM (ps
, &info
->dh
.prime
);
572 BUFFER_POP_DATUM (ps
, &info
->dh
.generator
);
573 BUFFER_POP_DATUM (ps
, &info
->dh
.public_key
);
580 _gnutls_free_datum (&info
->dh
.prime
);
581 _gnutls_free_datum (&info
->dh
.generator
);
582 _gnutls_free_datum (&info
->dh
.public_key
);
590 /* Packs the PSK session authentication data.
594 * 1 byte the credentials type
595 * 4 bytes the size of the whole structure
597 * 4 bytes the size of the PSK username (x)
598 * x bytes the PSK username
599 * 2 bytes the size of secret key in bits
600 * 4 bytes the size of the prime
602 * 4 bytes the size of the generator
603 * x bytes the generator
604 * 4 bytes the size of the public key
605 * x bytes the public key
608 pack_psk_auth_info (gnutls_session_t session
, gnutls_buffer_st
* ps
)
610 psk_auth_info_t info
;
616 info
= _gnutls_get_auth_info (session
);
618 if (info
&& info
->username
)
619 username_len
= strlen (info
->username
) + 1; /* include the terminating null */
623 if (info
&& info
->hint
)
624 hint_len
= strlen (info
->hint
) + 1; /* include the terminating null */
628 size_offset
= ps
->length
;
629 BUFFER_APPEND_NUM (ps
, 0);
630 cur_size
= ps
->length
;
632 BUFFER_APPEND_PFX (ps
, info
->username
, username_len
);
633 BUFFER_APPEND_PFX (ps
, info
->hint
, hint_len
);
635 BUFFER_APPEND_NUM (ps
, info
->dh
.secret_bits
);
636 BUFFER_APPEND_PFX (ps
, info
->dh
.prime
.data
, info
->dh
.prime
.size
);
637 BUFFER_APPEND_PFX (ps
, info
->dh
.generator
.data
, info
->dh
.generator
.size
);
638 BUFFER_APPEND_PFX (ps
, info
->dh
.public_key
.data
, info
->dh
.public_key
.size
);
640 /* write the real size */
641 _gnutls_write_uint32 (ps
->length
- cur_size
, ps
->data
+ size_offset
);
647 unpack_psk_auth_info (gnutls_session_t session
, gnutls_buffer_st
* ps
)
649 size_t username_size
, hint_size
;
651 psk_auth_info_t info
;
654 _gnutls_auth_info_set (session
, GNUTLS_CRD_PSK
,
655 sizeof (psk_auth_info_st
), 1);
662 info
= _gnutls_get_auth_info (session
);
666 return GNUTLS_E_INTERNAL_ERROR
;
669 BUFFER_POP_NUM (ps
, username_size
);
670 if (username_size
> sizeof (info
->username
))
673 return GNUTLS_E_INTERNAL_ERROR
;
676 BUFFER_POP (ps
, info
->username
, username_size
);
678 BUFFER_POP_NUM (ps
, hint_size
);
679 if (hint_size
> sizeof (info
->hint
))
682 return GNUTLS_E_INTERNAL_ERROR
;
684 BUFFER_POP (ps
, info
->hint
, hint_size
);
686 BUFFER_POP_NUM (ps
, info
->dh
.secret_bits
);
688 BUFFER_POP_DATUM (ps
, &info
->dh
.prime
);
689 BUFFER_POP_DATUM (ps
, &info
->dh
.generator
);
690 BUFFER_POP_DATUM (ps
, &info
->dh
.public_key
);
695 _gnutls_free_datum (&info
->dh
.prime
);
696 _gnutls_free_datum (&info
->dh
.generator
);
697 _gnutls_free_datum (&info
->dh
.public_key
);
704 /* Packs the security parameters.
708 * 4 bytes the total security data size
709 * 1 byte the entity type (client/server)
710 * 1 byte the key exchange algorithm used
711 * 1 byte the read cipher algorithm
712 * 1 byte the read mac algorithm
713 * 1 byte the read compression algorithm
715 * 1 byte the write cipher algorithm
716 * 1 byte the write mac algorithm
717 * 1 byte the write compression algorithm
719 * 1 byte the certificate type
720 * 1 byte the protocol version
722 * 2 bytes the cipher suite
724 * 48 bytes the master secret
726 * 32 bytes the client random
727 * 32 bytes the server random
729 * 1 byte the session ID size
730 * x bytes the session ID (32 bytes max)
732 * 4 bytes a timestamp
733 * 4 bytes the ECC curve
734 * -------------------
739 pack_security_parameters (gnutls_session_t session
, gnutls_buffer_st
* ps
)
745 record_parameters_st
*params
;
747 if (session
->security_parameters
.epoch_read
748 != session
->security_parameters
.epoch_write
)
751 return GNUTLS_E_INVALID_REQUEST
;
754 ret
= _gnutls_epoch_get (session
, EPOCH_READ_CURRENT
, ¶ms
);
761 /* move after the auth info stuff.
763 size_offset
= ps
->length
;
764 BUFFER_APPEND_NUM (ps
, 0);
765 cur_size
= ps
->length
;
768 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.entity
);
769 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.kx_algorithm
);
771 session
->security_parameters
.cipher_suite
, 2);
772 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.compression_method
);
773 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.cert_type
);
774 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.version
);
776 BUFFER_APPEND (ps
, session
->security_parameters
.master_secret
,
778 BUFFER_APPEND (ps
, session
->security_parameters
.client_random
,
780 BUFFER_APPEND (ps
, session
->security_parameters
.server_random
,
783 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.session_id_size
);
784 BUFFER_APPEND (ps
, session
->security_parameters
.session_id
,
785 session
->security_parameters
.session_id_size
);
787 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.max_record_send_size
);
788 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.max_record_recv_size
);
789 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.timestamp
);
790 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.ecc_curve
);
792 _gnutls_write_uint32 (ps
->length
- cur_size
, ps
->data
+ size_offset
);
798 unpack_security_parameters (gnutls_session_t session
, gnutls_buffer_st
* ps
)
802 time_t timestamp
= gnutls_time (0);
804 BUFFER_POP_NUM (ps
, pack_size
);
807 return GNUTLS_E_INVALID_REQUEST
;
809 memset (&session
->internals
.resumed_security_parameters
, 0,
810 sizeof (session
->internals
.resumed_security_parameters
));
812 BUFFER_POP_NUM (ps
, session
->internals
.resumed_security_parameters
.entity
);
814 session
->internals
.resumed_security_parameters
.kx_algorithm
);
817 resumed_security_parameters
.cipher_suite
, 2);
818 BUFFER_POP_NUM (ps
, session
->internals
.resumed_security_parameters
.compression_method
);
819 BUFFER_POP_NUM (ps
, session
->internals
.resumed_security_parameters
.cert_type
);
820 BUFFER_POP_NUM (ps
, session
->internals
.resumed_security_parameters
.version
);
823 session
->internals
.resumed_security_parameters
.master_secret
,
827 session
->internals
.resumed_security_parameters
.client_random
,
830 session
->internals
.resumed_security_parameters
.server_random
,
834 resumed_security_parameters
.session_id_size
);
836 BUFFER_POP (ps
, session
->internals
.resumed_security_parameters
.session_id
,
837 session
->internals
.resumed_security_parameters
.session_id_size
);
841 resumed_security_parameters
.max_record_send_size
);
844 resumed_security_parameters
.max_record_recv_size
);
846 session
->internals
.resumed_security_parameters
.timestamp
);
849 session
->internals
.resumed_security_parameters
.ecc_curve
);
851 if (timestamp
- session
->internals
.resumed_security_parameters
.timestamp
>
852 session
->internals
.expire_time
853 || session
->internals
.resumed_security_parameters
.timestamp
> timestamp
)
856 return GNUTLS_E_EXPIRED
;
866 * gnutls_session_set_premaster:
867 * @session: is a #gnutls_session_t structure.
868 * @entity: GNUTLS_SERVER or GNUTLS_CLIENT
869 * @version: the TLS protocol version
870 * @kx: the key exchange method
871 * @cipher: the cipher
872 * @mac: the MAC algorithm
873 * @comp: the compression method
874 * @master: the master key to use
875 * @session_id: the session identifier
877 * This function sets the premaster secret in a session. This is
878 * a function intended for exceptional uses. Do not use this
879 * function unless you are implementing a legacy protocol.
880 * Use gnutls_session_set_data() instead.
882 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
883 * an error code is returned.
886 gnutls_session_set_premaster (gnutls_session_t session
, unsigned int entity
,
887 gnutls_protocol_t version
,
888 gnutls_kx_algorithm_t kx
,
889 gnutls_cipher_algorithm_t cipher
,
890 gnutls_mac_algorithm_t mac
,
891 gnutls_compression_method_t comp
,
892 const gnutls_datum_t
* master
,
893 const gnutls_datum_t
* session_id
)
897 memset (&session
->internals
.resumed_security_parameters
, 0,
898 sizeof (session
->internals
.resumed_security_parameters
));
900 session
->internals
.resumed_security_parameters
.entity
= entity
;
901 session
->internals
.resumed_security_parameters
.kx_algorithm
= kx
;
903 ret
= _gnutls_cipher_suite_get_id(kx
, cipher
, mac
, session
->internals
.resumed_security_parameters
.cipher_suite
);
905 return gnutls_assert_val(ret
);
907 session
->internals
.resumed_security_parameters
.compression_method
= comp
;
908 session
->internals
.resumed_security_parameters
.cert_type
= GNUTLS_CRT_UNKNOWN
;
909 session
->internals
.resumed_security_parameters
.version
= version
;
911 if (master
->size
!= GNUTLS_MASTER_SIZE
)
912 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST
);
914 memcpy(session
->internals
.resumed_security_parameters
.master_secret
, master
->data
, master
->size
);
916 if (session_id
->size
> GNUTLS_MAX_SESSION_ID
)
917 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST
);
919 session
->internals
.resumed_security_parameters
.session_id_size
= session_id
->size
;
920 memcpy(session
->internals
.resumed_security_parameters
.session_id
, session_id
->data
, session_id
->size
);
922 session
->internals
.resumed_security_parameters
.max_record_send_size
=
923 session
->internals
.resumed_security_parameters
.max_record_recv_size
= DEFAULT_MAX_RECORD_SIZE
;
925 session
->internals
.resumed_security_parameters
.timestamp
= time(0);
927 session
->internals
.resumed_security_parameters
.ecc_curve
= GNUTLS_ECC_CURVE_INVALID
;
929 session
->internals
.premaster_set
= 1;