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>
44 static int pack_certificate_auth_info (gnutls_session_t
,
45 gnutls_buffer_st
* packed_session
);
46 static int unpack_certificate_auth_info (gnutls_session_t
,
47 gnutls_buffer_st
* packed_session
);
49 static int unpack_srp_auth_info (gnutls_session_t session
,
50 gnutls_buffer_st
* packed_session
);
51 static int pack_srp_auth_info (gnutls_session_t session
,
52 gnutls_buffer_st
* packed_session
);
54 static int unpack_psk_auth_info (gnutls_session_t session
,
55 gnutls_buffer_st
* packed_session
);
56 static int pack_psk_auth_info (gnutls_session_t session
,
57 gnutls_buffer_st
* packed_session
);
59 static int unpack_anon_auth_info (gnutls_session_t session
,
60 gnutls_buffer_st
* packed_session
);
61 static int pack_anon_auth_info (gnutls_session_t session
,
62 gnutls_buffer_st
* packed_session
);
64 static int unpack_security_parameters (gnutls_session_t session
,
65 gnutls_buffer_st
* packed_session
);
66 static int pack_security_parameters (gnutls_session_t session
,
67 gnutls_buffer_st
* packed_session
);
70 /* Since auth_info structures contain malloced data, this function
71 * is required in order to pack these structures in a vector in
72 * order to store them to the DB.
74 * packed_session will contain the session data.
76 * The data will be in a platform independent format.
79 _gnutls_session_pack (gnutls_session_t session
,
80 gnutls_datum_t
* packed_session
)
86 if (packed_session
== NULL
)
89 return GNUTLS_E_INTERNAL_ERROR
;
92 _gnutls_buffer_init (&sb
);
94 id
= gnutls_auth_get_type (session
);
95 BUFFER_APPEND (&sb
, &id
, 1);
101 ret
= pack_srp_auth_info (session
, &sb
);
111 ret
= pack_psk_auth_info (session
, &sb
);
120 case GNUTLS_CRD_ANON
:
121 ret
= pack_anon_auth_info (session
, &sb
);
129 case GNUTLS_CRD_CERTIFICATE
:
130 ret
= pack_certificate_auth_info (session
, &sb
);
138 return GNUTLS_E_INTERNAL_ERROR
;
142 /* Auth_info structures copied. Now copy security_parameters_st.
143 * packed_session must have allocated space for the security parameters.
145 ret
= pack_security_parameters (session
, &sb
);
149 _gnutls_buffer_clear (&sb
);
153 ret
= _gnutls_ext_pack (session
, &sb
);
157 _gnutls_buffer_clear (&sb
);
161 ret
= _gnutls_buffer_to_datum (&sb
, packed_session
);
167 /* Load session data from a buffer.
170 _gnutls_session_unpack (gnutls_session_t session
,
171 const gnutls_datum_t
* packed_session
)
177 _gnutls_buffer_init (&sb
);
179 if (packed_session
== NULL
|| packed_session
->size
== 0)
182 return GNUTLS_E_INTERNAL_ERROR
;
186 _gnutls_buffer_append_data (&sb
, packed_session
->data
,
187 packed_session
->size
);
194 if (_gnutls_get_auth_info (session
) != NULL
)
196 _gnutls_free_auth_info (session
);
199 BUFFER_POP (&sb
, &id
, 1);
205 ret
= unpack_srp_auth_info (session
, &sb
);
215 ret
= unpack_psk_auth_info (session
, &sb
);
224 case GNUTLS_CRD_ANON
:
225 ret
= unpack_anon_auth_info (session
, &sb
);
233 case GNUTLS_CRD_CERTIFICATE
:
234 ret
= unpack_certificate_auth_info (session
, &sb
);
243 ret
= GNUTLS_E_INTERNAL_ERROR
;
248 /* Auth_info structures copied. Now copy security_parameters_st.
249 * packed_session must have allocated space for the security parameters.
251 ret
= unpack_security_parameters (session
, &sb
);
258 ret
= _gnutls_ext_unpack (session
, &sb
);
268 _gnutls_buffer_clear (&sb
);
276 * 1 byte the credentials type
277 * 4 bytes the size of the whole structure
279 * 2 bytes the size of secret key in bits
280 * 4 bytes the size of the prime
282 * 4 bytes the size of the generator
283 * x bytes the generator
284 * 4 bytes the size of the public key
285 * x bytes the public key
287 * 4 bytes the size of the modulus
288 * x bytes the modulus
289 * 4 bytes the size of the exponent
290 * x bytes the exponent
292 * 4 bytes the length of the certificate list
293 * 4 bytes the size of first certificate
294 * x bytes the certificate
298 pack_certificate_auth_info (gnutls_session_t session
, gnutls_buffer_st
* ps
)
302 cert_auth_info_t info
= _gnutls_get_auth_info (session
);
305 size_offset
= ps
->length
;
306 BUFFER_APPEND_NUM (ps
, 0);
307 cur_size
= ps
->length
;
312 BUFFER_APPEND_NUM (ps
, info
->dh
.secret_bits
);
313 BUFFER_APPEND_PFX (ps
, info
->dh
.prime
.data
, info
->dh
.prime
.size
);
314 BUFFER_APPEND_PFX (ps
, info
->dh
.generator
.data
,
315 info
->dh
.generator
.size
);
316 BUFFER_APPEND_PFX (ps
, info
->dh
.public_key
.data
,
317 info
->dh
.public_key
.size
);
318 BUFFER_APPEND_PFX (ps
, info
->rsa_export
.modulus
.data
,
319 info
->rsa_export
.modulus
.size
);
320 BUFFER_APPEND_PFX (ps
, info
->rsa_export
.exponent
.data
,
321 info
->rsa_export
.exponent
.size
);
323 BUFFER_APPEND_NUM (ps
, info
->ncerts
);
325 for (i
= 0; i
< info
->ncerts
; i
++)
326 BUFFER_APPEND_PFX (ps
, info
->raw_certificate_list
[i
].data
,
327 info
->raw_certificate_list
[i
].size
);
330 /* write the real size */
331 _gnutls_write_uint32 (ps
->length
- cur_size
, ps
->data
+ size_offset
);
337 /* Upack certificate info.
340 unpack_certificate_auth_info (gnutls_session_t session
, gnutls_buffer_st
* ps
)
343 unsigned int i
= 0, j
= 0;
345 cert_auth_info_t info
= NULL
;
347 BUFFER_POP_NUM (ps
, pack_size
);
350 return 0; /* nothing to be done */
352 /* client and server have the same auth_info here
355 _gnutls_auth_info_set (session
, GNUTLS_CRD_CERTIFICATE
,
356 sizeof (cert_auth_info_st
), 1);
363 info
= _gnutls_get_auth_info (session
);
367 return GNUTLS_E_INTERNAL_ERROR
;
370 BUFFER_POP_NUM (ps
, info
->dh
.secret_bits
);
372 BUFFER_POP_DATUM (ps
, &info
->dh
.prime
);
373 BUFFER_POP_DATUM (ps
, &info
->dh
.generator
);
374 BUFFER_POP_DATUM (ps
, &info
->dh
.public_key
);
375 BUFFER_POP_DATUM (ps
, &info
->rsa_export
.modulus
);
376 BUFFER_POP_DATUM (ps
, &info
->rsa_export
.exponent
);
378 BUFFER_POP_NUM (ps
, info
->ncerts
);
380 if (info
->ncerts
> 0)
382 info
->raw_certificate_list
=
383 gnutls_calloc (info
->ncerts
, sizeof (gnutls_datum_t
));
384 if (info
->raw_certificate_list
== NULL
)
387 ret
= GNUTLS_E_MEMORY_ERROR
;
392 for (i
= 0; i
< info
->ncerts
; i
++)
394 BUFFER_POP_DATUM (ps
, &info
->raw_certificate_list
[i
]);
402 _gnutls_free_datum (&info
->dh
.prime
);
403 _gnutls_free_datum (&info
->dh
.generator
);
404 _gnutls_free_datum (&info
->dh
.public_key
);
406 _gnutls_free_datum (&info
->rsa_export
.modulus
);
407 _gnutls_free_datum (&info
->rsa_export
.exponent
);
409 for (j
= 0; j
< i
; j
++)
410 _gnutls_free_datum (&info
->raw_certificate_list
[j
]);
412 gnutls_free (info
->raw_certificate_list
);
420 /* Packs the SRP session authentication data.
424 * 1 byte the credentials type
425 * 4 bytes the size of the SRP username (x)
426 * x bytes the SRP username
429 pack_srp_auth_info (gnutls_session_t session
, gnutls_buffer_st
* ps
)
431 srp_server_auth_info_t info
= _gnutls_get_auth_info (session
);
436 if (info
&& info
->username
)
437 len
= strlen (info
->username
) + 1; /* include the terminating null */
441 size_offset
= ps
->length
;
442 BUFFER_APPEND_NUM (ps
, 0);
443 cur_size
= ps
->length
;
445 BUFFER_APPEND_PFX (ps
, info
->username
, len
);
447 /* write the real size */
448 _gnutls_write_uint32 (ps
->length
- cur_size
, ps
->data
+ size_offset
);
455 unpack_srp_auth_info (gnutls_session_t session
, gnutls_buffer_st
* ps
)
457 size_t username_size
;
459 srp_server_auth_info_t info
;
461 BUFFER_POP_NUM (ps
, username_size
);
462 if (username_size
> sizeof (info
->username
))
465 return GNUTLS_E_INTERNAL_ERROR
;
470 _gnutls_auth_info_set (session
, GNUTLS_CRD_SRP
,
471 sizeof (srp_server_auth_info_st
), 1);
478 info
= _gnutls_get_auth_info (session
);
482 return GNUTLS_E_INTERNAL_ERROR
;
485 BUFFER_POP (ps
, info
->username
, username_size
);
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_PFX (ps
, info
->dh
.prime
.data
, info
->dh
.prime
.size
);
525 BUFFER_APPEND_PFX (ps
, info
->dh
.generator
.data
,
526 info
->dh
.generator
.size
);
527 BUFFER_APPEND_PFX (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
);
565 return GNUTLS_E_INTERNAL_ERROR
;
568 BUFFER_POP_NUM (ps
, info
->dh
.secret_bits
);
570 BUFFER_POP_DATUM (ps
, &info
->dh
.prime
);
571 BUFFER_POP_DATUM (ps
, &info
->dh
.generator
);
572 BUFFER_POP_DATUM (ps
, &info
->dh
.public_key
);
579 _gnutls_free_datum (&info
->dh
.prime
);
580 _gnutls_free_datum (&info
->dh
.generator
);
581 _gnutls_free_datum (&info
->dh
.public_key
);
589 /* Packs the PSK session authentication data.
593 * 1 byte the credentials type
594 * 4 bytes the size of the whole structure
596 * 4 bytes the size of the PSK username (x)
597 * x bytes the PSK username
598 * 2 bytes the size of secret key in bits
599 * 4 bytes the size of the prime
601 * 4 bytes the size of the generator
602 * x bytes the generator
603 * 4 bytes the size of the public key
604 * x bytes the public key
607 pack_psk_auth_info (gnutls_session_t session
, gnutls_buffer_st
* ps
)
609 psk_auth_info_t info
;
615 info
= _gnutls_get_auth_info (session
);
617 if (info
&& info
->username
)
618 username_len
= strlen (info
->username
) + 1; /* include the terminating null */
622 if (info
&& info
->hint
)
623 hint_len
= strlen (info
->hint
) + 1; /* include the terminating null */
627 size_offset
= ps
->length
;
628 BUFFER_APPEND_NUM (ps
, 0);
629 cur_size
= ps
->length
;
631 BUFFER_APPEND_PFX (ps
, info
->username
, username_len
);
632 BUFFER_APPEND_PFX (ps
, info
->hint
, hint_len
);
634 BUFFER_APPEND_NUM (ps
, info
->dh
.secret_bits
);
635 BUFFER_APPEND_PFX (ps
, info
->dh
.prime
.data
, info
->dh
.prime
.size
);
636 BUFFER_APPEND_PFX (ps
, info
->dh
.generator
.data
, info
->dh
.generator
.size
);
637 BUFFER_APPEND_PFX (ps
, info
->dh
.public_key
.data
, info
->dh
.public_key
.size
);
639 /* write the real size */
640 _gnutls_write_uint32 (ps
->length
- cur_size
, ps
->data
+ size_offset
);
646 unpack_psk_auth_info (gnutls_session_t session
, gnutls_buffer_st
* ps
)
648 size_t username_size
, hint_size
;
650 psk_auth_info_t info
;
653 _gnutls_auth_info_set (session
, GNUTLS_CRD_PSK
,
654 sizeof (psk_auth_info_st
), 1);
661 info
= _gnutls_get_auth_info (session
);
665 return GNUTLS_E_INTERNAL_ERROR
;
668 BUFFER_POP_NUM (ps
, username_size
);
669 if (username_size
> sizeof (info
->username
))
672 return GNUTLS_E_INTERNAL_ERROR
;
675 BUFFER_POP (ps
, info
->username
, username_size
);
677 BUFFER_POP_NUM (ps
, hint_size
);
678 if (hint_size
> sizeof (info
->hint
))
681 return GNUTLS_E_INTERNAL_ERROR
;
683 BUFFER_POP (ps
, info
->hint
, hint_size
);
685 BUFFER_POP_NUM (ps
, info
->dh
.secret_bits
);
687 BUFFER_POP_DATUM (ps
, &info
->dh
.prime
);
688 BUFFER_POP_DATUM (ps
, &info
->dh
.generator
);
689 BUFFER_POP_DATUM (ps
, &info
->dh
.public_key
);
694 _gnutls_free_datum (&info
->dh
.prime
);
695 _gnutls_free_datum (&info
->dh
.generator
);
696 _gnutls_free_datum (&info
->dh
.public_key
);
703 /* Packs the security parameters.
707 * 4 bytes the total security data size
708 * 1 byte the entity type (client/server)
709 * 1 byte the key exchange algorithm used
710 * 1 byte the read cipher algorithm
711 * 1 byte the read mac algorithm
712 * 1 byte the read compression algorithm
714 * 1 byte the write cipher algorithm
715 * 1 byte the write mac algorithm
716 * 1 byte the write compression algorithm
718 * 1 byte the certificate type
719 * 1 byte the protocol version
721 * 2 bytes the cipher suite
723 * 48 bytes the master secret
725 * 32 bytes the client random
726 * 32 bytes the server random
728 * 1 byte the session ID size
729 * x bytes the session ID (32 bytes max)
731 * 4 bytes a timestamp
732 * 4 bytes the ECC curve
733 * -------------------
738 pack_security_parameters (gnutls_session_t session
, gnutls_buffer_st
* ps
)
744 record_parameters_st
*params
;
746 if (session
->security_parameters
.epoch_read
747 != session
->security_parameters
.epoch_write
)
750 return GNUTLS_E_INVALID_REQUEST
;
753 ret
= _gnutls_epoch_get (session
, EPOCH_READ_CURRENT
, ¶ms
);
760 /* move after the auth info stuff.
762 size_offset
= ps
->length
;
763 BUFFER_APPEND_NUM (ps
, 0);
764 cur_size
= ps
->length
;
767 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.entity
);
768 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.kx_algorithm
);
770 session
->security_parameters
.cipher_suite
, 2);
771 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.compression_method
);
772 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.cert_type
);
773 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.version
);
775 BUFFER_APPEND (ps
, session
->security_parameters
.master_secret
,
777 BUFFER_APPEND (ps
, session
->security_parameters
.client_random
,
779 BUFFER_APPEND (ps
, session
->security_parameters
.server_random
,
782 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.session_id_size
);
783 BUFFER_APPEND (ps
, session
->security_parameters
.session_id
,
784 session
->security_parameters
.session_id_size
);
786 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.max_record_send_size
);
787 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.max_record_recv_size
);
788 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.timestamp
);
789 BUFFER_APPEND_NUM (ps
, session
->security_parameters
.ecc_curve
);
791 _gnutls_write_uint32 (ps
->length
- cur_size
, ps
->data
+ size_offset
);
797 unpack_security_parameters (gnutls_session_t session
, gnutls_buffer_st
* ps
)
801 time_t timestamp
= gnutls_time (0);
803 BUFFER_POP_NUM (ps
, pack_size
);
806 return GNUTLS_E_INVALID_REQUEST
;
808 memset (&session
->internals
.resumed_security_parameters
, 0,
809 sizeof (session
->internals
.resumed_security_parameters
));
811 BUFFER_POP_NUM (ps
, session
->internals
.resumed_security_parameters
.entity
);
813 session
->internals
.resumed_security_parameters
.kx_algorithm
);
816 resumed_security_parameters
.cipher_suite
, 2);
817 BUFFER_POP_NUM (ps
, session
->internals
.resumed_security_parameters
.compression_method
);
818 BUFFER_POP_NUM (ps
, session
->internals
.resumed_security_parameters
.cert_type
);
819 BUFFER_POP_NUM (ps
, session
->internals
.resumed_security_parameters
.version
);
822 session
->internals
.resumed_security_parameters
.master_secret
,
826 session
->internals
.resumed_security_parameters
.client_random
,
829 session
->internals
.resumed_security_parameters
.server_random
,
833 resumed_security_parameters
.session_id_size
);
835 BUFFER_POP (ps
, session
->internals
.resumed_security_parameters
.session_id
,
836 session
->internals
.resumed_security_parameters
.session_id_size
);
840 resumed_security_parameters
.max_record_send_size
);
843 resumed_security_parameters
.max_record_recv_size
);
845 session
->internals
.resumed_security_parameters
.timestamp
);
848 session
->internals
.resumed_security_parameters
.ecc_curve
);
850 if (timestamp
- session
->internals
.resumed_security_parameters
.timestamp
>
851 session
->internals
.expire_time
852 || session
->internals
.resumed_security_parameters
.timestamp
> timestamp
)
855 return GNUTLS_E_EXPIRED
;