2 * Copyright (C) 2000, 2004, 2005, 2007, 2008, 2009, 2010 Free Software
5 * Author: Nikos Mavrogiannopoulos
7 * This file is part of GnuTLS.
9 * The GnuTLS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
26 /* Contains functions that are supposed to pack and unpack session data,
27 * before and after they are sent to the database backend.
30 #include <gnutls_int.h>
37 #include <auth_anon.h>
38 #include <auth_cert.h>
39 #include <gnutls_errors.h>
40 #include <gnutls_auth.h>
41 #include <gnutls_session_pack.h>
42 #include <gnutls_datum.h>
43 #include <gnutls_num.h>
44 #include <gnutls_extensions.h>
45 #include <gnutls_constate.h>
47 static int pack_certificate_auth_info (gnutls_session_t
,
48 gnutls_buffer_st
* packed_session
);
49 static int unpack_certificate_auth_info (gnutls_session_t
,
50 gnutls_buffer_st
* packed_session
);
52 static int unpack_srp_auth_info (gnutls_session_t session
,
53 gnutls_buffer_st
* packed_session
);
54 static int pack_srp_auth_info (gnutls_session_t session
,
55 gnutls_buffer_st
* packed_session
);
57 static int unpack_psk_auth_info (gnutls_session_t session
,
58 gnutls_buffer_st
* packed_session
);
59 static int pack_psk_auth_info (gnutls_session_t session
,
60 gnutls_buffer_st
* packed_session
);
62 static int unpack_anon_auth_info (gnutls_session_t session
,
63 gnutls_buffer_st
* packed_session
);
64 static int pack_anon_auth_info (gnutls_session_t session
,
65 gnutls_buffer_st
* packed_session
);
67 static int unpack_security_parameters (gnutls_session_t session
,
68 gnutls_buffer_st
* packed_session
);
69 static int pack_security_parameters (gnutls_session_t session
,
70 gnutls_buffer_st
* packed_session
);
73 /* Since auth_info structures contain malloced data, this function
74 * is required in order to pack these structures in a vector in
75 * order to store them to the DB.
77 * packed_session will contain the session data.
79 * The data will be in a platform independent format.
82 _gnutls_session_pack (gnutls_session_t session
,
83 gnutls_datum_t
* packed_session
)
89 if (packed_session
== NULL
)
92 return GNUTLS_E_INTERNAL_ERROR
;
95 _gnutls_buffer_init (&sb
);
97 id
= gnutls_auth_get_type (session
);
98 BUFFER_APPEND (&sb
, &id
, 1);
104 ret
= pack_srp_auth_info (session
, &sb
);
114 ret
= pack_psk_auth_info (session
, &sb
);
123 case GNUTLS_CRD_ANON
:
124 ret
= pack_anon_auth_info (session
, &sb
);
132 case GNUTLS_CRD_CERTIFICATE
:
133 ret
= pack_certificate_auth_info (session
, &sb
);
141 return GNUTLS_E_INTERNAL_ERROR
;
145 /* Auth_info structures copied. Now copy security_parameters_st.
146 * packed_session must have allocated space for the security parameters.
148 ret
= pack_security_parameters (session
, &sb
);
152 _gnutls_buffer_clear (&sb
);
156 ret
= _gnutls_ext_pack (session
, &sb
);
160 _gnutls_buffer_clear (&sb
);
164 ret
= _gnutls_buffer_to_datum (&sb
, packed_session
);
170 /* Load session data from a buffer.
173 _gnutls_session_unpack (gnutls_session_t session
,
174 const gnutls_datum_t
* packed_session
)
180 _gnutls_buffer_init (&sb
);
182 if (packed_session
== NULL
|| packed_session
->size
== 0)
185 return GNUTLS_E_INTERNAL_ERROR
;
189 _gnutls_buffer_append_data (&sb
, packed_session
->data
,
190 packed_session
->size
);
197 if (_gnutls_get_auth_info (session
) != NULL
)
199 _gnutls_free_auth_info (session
);
202 BUFFER_POP (&sb
, &id
, 1);
208 ret
= unpack_srp_auth_info (session
, &sb
);
218 ret
= unpack_psk_auth_info (session
, &sb
);
227 case GNUTLS_CRD_ANON
:
228 ret
= unpack_anon_auth_info (session
, &sb
);
236 case GNUTLS_CRD_CERTIFICATE
:
237 ret
= unpack_certificate_auth_info (session
, &sb
);
246 ret
= GNUTLS_E_INTERNAL_ERROR
;
251 /* Auth_info structures copied. Now copy security_parameters_st.
252 * packed_session must have allocated space for the security parameters.
254 ret
= unpack_security_parameters (session
, &sb
);
261 ret
= _gnutls_ext_unpack (session
, &sb
);
271 _gnutls_buffer_clear (&sb
);
279 * 1 byte the credentials type
280 * 4 bytes the size of the whole structure
282 * 2 bytes the size of secret key in bits
283 * 4 bytes the size of the prime
285 * 4 bytes the size of the generator
286 * x bytes the generator
287 * 4 bytes the size of the public key
288 * x bytes the public key
290 * 4 bytes the size of the modulus
291 * x bytes the modulus
292 * 4 bytes the size of the exponent
293 * x bytes the exponent
295 * 4 bytes the length of the certificate list
296 * 4 bytes the size of first certificate
297 * x bytes the certificate
301 pack_certificate_auth_info (gnutls_session_t session
, gnutls_buffer_st
* ps
)
305 cert_auth_info_t info
= _gnutls_get_auth_info (session
);
308 size_offset
= ps
->length
;
309 BUFFER_APPEND_NUM (ps
, 0);
310 cur_size
= ps
->length
;
315 BUFFER_APPEND_NUM (ps
, info
->dh
.secret_bits
);
316 BUFFER_APPEND_PFX (ps
, info
->dh
.prime
.data
, info
->dh
.prime
.size
);
317 BUFFER_APPEND_PFX (ps
, info
->dh
.generator
.data
,
318 info
->dh
.generator
.size
);
319 BUFFER_APPEND_PFX (ps
, info
->dh
.public_key
.data
,
320 info
->dh
.public_key
.size
);
321 BUFFER_APPEND_PFX (ps
, info
->rsa_export
.modulus
.data
,
322 info
->rsa_export
.modulus
.size
);
323 BUFFER_APPEND_PFX (ps
, info
->rsa_export
.exponent
.data
,
324 info
->rsa_export
.exponent
.size
);
326 BUFFER_APPEND_NUM (ps
, info
->ncerts
);
328 for (i
= 0; i
< info
->ncerts
; i
++)
329 BUFFER_APPEND_PFX (ps
, info
->raw_certificate_list
[i
].data
,
330 info
->raw_certificate_list
[i
].size
);
333 /* write the real size */
334 _gnutls_write_uint32 (ps
->length
- cur_size
, ps
->data
+ size_offset
);
340 /* Upack certificate info.
343 unpack_certificate_auth_info (gnutls_session_t session
, gnutls_buffer_st
* ps
)
346 unsigned int i
= 0, j
= 0;
348 cert_auth_info_t info
= NULL
;
350 BUFFER_POP_NUM (ps
, pack_size
);
353 return 0; /* nothing to be done */
355 /* client and server have the same auth_info here
358 _gnutls_auth_info_set (session
, GNUTLS_CRD_CERTIFICATE
,
359 sizeof (cert_auth_info_st
), 1);
366 info
= _gnutls_get_auth_info (session
);
370 return GNUTLS_E_INTERNAL_ERROR
;
373 BUFFER_POP_NUM (ps
, info
->dh
.secret_bits
);
375 BUFFER_POP_DATUM (ps
, &info
->dh
.prime
);
376 BUFFER_POP_DATUM (ps
, &info
->dh
.generator
);
377 BUFFER_POP_DATUM (ps
, &info
->dh
.public_key
);
378 BUFFER_POP_DATUM (ps
, &info
->rsa_export
.modulus
);
379 BUFFER_POP_DATUM (ps
, &info
->rsa_export
.exponent
);
381 BUFFER_POP_NUM (ps
, info
->ncerts
);
383 if (info
->ncerts
> 0)
385 info
->raw_certificate_list
=
386 gnutls_calloc (info
->ncerts
, sizeof (gnutls_datum_t
));
387 if (info
->raw_certificate_list
== NULL
)
390 ret
= GNUTLS_E_MEMORY_ERROR
;
395 for (i
= 0; i
< info
->ncerts
; i
++)
397 BUFFER_POP_DATUM (ps
, &info
->raw_certificate_list
[i
]);
405 _gnutls_free_datum (&info
->dh
.prime
);
406 _gnutls_free_datum (&info
->dh
.generator
);
407 _gnutls_free_datum (&info
->dh
.public_key
);
409 _gnutls_free_datum (&info
->rsa_export
.modulus
);
410 _gnutls_free_datum (&info
->rsa_export
.exponent
);
412 for (j
= 0; j
< i
; j
++)
413 _gnutls_free_datum (&info
->raw_certificate_list
[j
]);
415 gnutls_free (info
->raw_certificate_list
);
423 /* Packs the SRP session authentication data.
427 * 1 byte the credentials type
428 * 4 bytes the size of the SRP username (x)
429 * x bytes the SRP username
432 pack_srp_auth_info (gnutls_session_t session
, gnutls_buffer_st
* ps
)
434 srp_server_auth_info_t info
= _gnutls_get_auth_info (session
);
439 if (info
&& info
->username
)
440 len
= strlen (info
->username
) + 1; /* include the terminating null */
444 size_offset
= ps
->length
;
445 BUFFER_APPEND_NUM (ps
, 0);
446 cur_size
= ps
->length
;
448 BUFFER_APPEND_PFX (ps
, info
->username
, len
);
450 /* write the real size */
451 _gnutls_write_uint32 (ps
->length
- cur_size
, ps
->data
+ size_offset
);
458 unpack_srp_auth_info (gnutls_session_t session
, gnutls_buffer_st
* ps
)
460 size_t username_size
;
462 srp_server_auth_info_t info
;
464 BUFFER_POP_NUM (ps
, username_size
);
465 if (username_size
> sizeof (info
->username
))
468 return GNUTLS_E_INTERNAL_ERROR
;
473 _gnutls_auth_info_set (session
, GNUTLS_CRD_SRP
,
474 sizeof (srp_server_auth_info_st
), 1);
481 info
= _gnutls_get_auth_info (session
);
485 return GNUTLS_E_INTERNAL_ERROR
;
488 BUFFER_POP (ps
, info
->username
, username_size
);
499 /* Packs the ANON session authentication data.
503 * 1 byte the credentials type
504 * 4 bytes the size of the whole structure
505 * 2 bytes the size of secret key in bits
506 * 4 bytes the size of the prime
508 * 4 bytes the size of the generator
509 * x bytes the generator
510 * 4 bytes the size of the public key
511 * x bytes the public key
514 pack_anon_auth_info (gnutls_session_t session
, gnutls_buffer_st
* ps
)
517 anon_auth_info_t info
= _gnutls_get_auth_info (session
);
520 size_offset
= ps
->length
;
521 BUFFER_APPEND_NUM (ps
, 0);
522 cur_size
= ps
->length
;
526 BUFFER_APPEND_NUM (ps
, info
->dh
.secret_bits
);
527 BUFFER_APPEND_PFX (ps
, info
->dh
.prime
.data
, info
->dh
.prime
.size
);
528 BUFFER_APPEND_PFX (ps
, info
->dh
.generator
.data
,
529 info
->dh
.generator
.size
);
530 BUFFER_APPEND_PFX (ps
, info
->dh
.public_key
.data
,
531 info
->dh
.public_key
.size
);
534 /* write the real size */
535 _gnutls_write_uint32 (ps
->length
- cur_size
, ps
->data
+ size_offset
);
542 unpack_anon_auth_info (gnutls_session_t session
, gnutls_buffer_st
* ps
)
546 anon_auth_info_t info
= NULL
;
548 BUFFER_POP_NUM (ps
, pack_size
);
551 return 0; /* nothing to be done */
553 /* client and server have the same auth_info here
556 _gnutls_auth_info_set (session
, GNUTLS_CRD_ANON
,
557 sizeof (anon_auth_info_st
), 1);
564 info
= _gnutls_get_auth_info (session
);
568 return GNUTLS_E_INTERNAL_ERROR
;
571 BUFFER_POP_NUM (ps
, info
->dh
.secret_bits
);
573 BUFFER_POP_DATUM (ps
, &info
->dh
.prime
);
574 BUFFER_POP_DATUM (ps
, &info
->dh
.generator
);
575 BUFFER_POP_DATUM (ps
, &info
->dh
.public_key
);
582 _gnutls_free_datum (&info
->dh
.prime
);
583 _gnutls_free_datum (&info
->dh
.generator
);
584 _gnutls_free_datum (&info
->dh
.public_key
);
592 /* Packs the PSK session authentication data.
596 * 1 byte the credentials type
597 * 4 bytes the size of the whole structure
599 * 4 bytes the size of the PSK username (x)
600 * x bytes the PSK username
601 * 2 bytes the size of secret key in bits
602 * 4 bytes the size of the prime
604 * 4 bytes the size of the generator
605 * x bytes the generator
606 * 4 bytes the size of the public key
607 * x bytes the public key
610 pack_psk_auth_info (gnutls_session_t session
, gnutls_buffer_st
* ps
)
612 psk_auth_info_t info
;
618 info
= _gnutls_get_auth_info (session
);
620 if (info
&& info
->username
)
621 username_len
= strlen (info
->username
) + 1; /* include the terminating null */
625 if (info
&& info
->hint
)
626 hint_len
= strlen (info
->hint
) + 1; /* include the terminating null */
630 size_offset
= ps
->length
;
631 BUFFER_APPEND_NUM (ps
, 0);
632 cur_size
= ps
->length
;
634 BUFFER_APPEND_PFX (ps
, info
->username
, username_len
);
635 BUFFER_APPEND_PFX (ps
, info
->hint
, hint_len
);
637 BUFFER_APPEND_NUM (ps
, info
->dh
.secret_bits
);
638 BUFFER_APPEND_PFX (ps
, info
->dh
.prime
.data
, info
->dh
.prime
.size
);
639 BUFFER_APPEND_PFX (ps
, info
->dh
.generator
.data
, info
->dh
.generator
.size
);
640 BUFFER_APPEND_PFX (ps
, info
->dh
.public_key
.data
, info
->dh
.public_key
.size
);
642 /* write the real size */
643 _gnutls_write_uint32 (ps
->length
- cur_size
, ps
->data
+ size_offset
);
649 unpack_psk_auth_info (gnutls_session_t session
, gnutls_buffer_st
* ps
)
651 size_t username_size
, hint_size
;
653 psk_auth_info_t info
;
656 _gnutls_auth_info_set (session
, GNUTLS_CRD_PSK
,
657 sizeof (psk_auth_info_st
), 1);
664 info
= _gnutls_get_auth_info (session
);
668 return GNUTLS_E_INTERNAL_ERROR
;
671 BUFFER_POP_NUM (ps
, username_size
);
672 if (username_size
> sizeof (info
->username
))
675 return GNUTLS_E_INTERNAL_ERROR
;
678 BUFFER_POP (ps
, info
->username
, username_size
);
680 BUFFER_POP_NUM (ps
, hint_size
);
681 if (hint_size
> sizeof (info
->hint
))
684 return GNUTLS_E_INTERNAL_ERROR
;
686 BUFFER_POP (ps
, info
->hint
, hint_size
);
688 BUFFER_POP_NUM (ps
, info
->dh
.secret_bits
);
690 BUFFER_POP_DATUM (ps
, &info
->dh
.prime
);
691 BUFFER_POP_DATUM (ps
, &info
->dh
.generator
);
692 BUFFER_POP_DATUM (ps
, &info
->dh
.public_key
);
697 _gnutls_free_datum (&info
->dh
.prime
);
698 _gnutls_free_datum (&info
->dh
.generator
);
699 _gnutls_free_datum (&info
->dh
.public_key
);
706 /* Packs the security parameters.
710 * 4 bytes the total security data size
711 * 1 byte the entity type (client/server)
712 * 1 byte the key exchange algorithm used
713 * 1 byte the read cipher algorithm
714 * 1 byte the read mac algorithm
715 * 1 byte the read compression algorithm
717 * 1 byte the write cipher algorithm
718 * 1 byte the write mac algorithm
719 * 1 byte the write compression algorithm
721 * 1 byte the certificate type
722 * 1 byte the protocol version
724 * 2 bytes the cipher suite
726 * 48 bytes the master secret
728 * 32 bytes the client random
729 * 32 bytes the server random
731 * 1 byte the session ID size
732 * x bytes the session ID (32 bytes max)
734 * 4 bytes a timestamp
735 * -------------------
740 pack_security_parameters (gnutls_session_t session
, gnutls_buffer_st
* ps
)
746 record_parameters_st
*params
;
748 if (session
->security_parameters
.epoch_read
749 != session
->security_parameters
.epoch_write
)
752 return GNUTLS_E_INVALID_REQUEST
;
755 ret
= _gnutls_epoch_get (session
, EPOCH_READ_CURRENT
, ¶ms
);
762 /* move after the auth info stuff.
764 size_offset
= ps
->length
;
765 BUFFER_APPEND_NUM (ps
, 0);
766 cur_size
= ps
->length
;
769 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.entity
);
770 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.kx_algorithm
);
772 &session
->security_parameters
.current_cipher_suite
.suite
[0],
775 &session
->security_parameters
.current_cipher_suite
.suite
[1],
777 BUFFER_APPEND_NUM (ps
, params
->compression_algorithm
);
778 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.cert_type
);
779 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.version
);
781 BUFFER_APPEND (ps
, session
->security_parameters
.master_secret
,
783 BUFFER_APPEND (ps
, session
->security_parameters
.client_random
,
785 BUFFER_APPEND (ps
, session
->security_parameters
.server_random
,
788 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.session_id_size
);
789 BUFFER_APPEND (ps
, session
->security_parameters
.session_id
,
790 session
->security_parameters
.session_id_size
);
792 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.max_record_send_size
);
793 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.max_record_recv_size
);
794 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.timestamp
);
796 _gnutls_write_uint32 (ps
->length
- cur_size
, ps
->data
+ size_offset
);
802 unpack_security_parameters (gnutls_session_t session
, gnutls_buffer_st
* ps
)
806 time_t timestamp
= time (0);
808 BUFFER_POP_NUM (ps
, pack_size
);
811 return GNUTLS_E_INVALID_REQUEST
;
813 memset (&session
->internals
.resumed_security_parameters
, 0,
814 sizeof (session
->internals
.resumed_security_parameters
));
816 BUFFER_POP_NUM (ps
, session
->internals
.resumed_security_parameters
.entity
);
818 session
->internals
.resumed_security_parameters
.kx_algorithm
);
821 resumed_security_parameters
.current_cipher_suite
.suite
[0], 1);
823 &session
->internals
.resumed_security_parameters
.
824 current_cipher_suite
.suite
[1], 1);
825 BUFFER_POP_NUM (ps
, session
->internals
.resumed_compression_method
);
826 BUFFER_POP_NUM (ps
, session
->internals
.resumed_security_parameters
.cert_type
);
827 BUFFER_POP_NUM (ps
, session
->internals
.resumed_security_parameters
.version
);
830 &session
->internals
.resumed_security_parameters
.master_secret
,
834 &session
->internals
.resumed_security_parameters
.client_random
,
837 &session
->internals
.resumed_security_parameters
.server_random
,
841 resumed_security_parameters
.session_id_size
);
843 BUFFER_POP (ps
, &session
->internals
.resumed_security_parameters
.session_id
,
844 session
->internals
.resumed_security_parameters
.session_id_size
);
848 resumed_security_parameters
.max_record_send_size
);
851 resumed_security_parameters
.max_record_recv_size
);
853 session
->internals
.resumed_security_parameters
.timestamp
);
855 if (timestamp
- session
->internals
.resumed_security_parameters
.timestamp
>
856 session
->internals
.expire_time
857 || session
->internals
.resumed_security_parameters
.timestamp
> timestamp
)
860 return GNUTLS_E_EXPIRED
;