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 2.1 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>
44 #include <gnutls_state.h>
45 #include <gnutls_db.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) {
91 return GNUTLS_E_INTERNAL_ERROR;
94 _gnutls_buffer_init(&sb);
97 id = gnutls_auth_get_type(session);
99 BUFFER_APPEND_NUM(&sb, PACKED_SESSION_MAGIC);
100 BUFFER_APPEND_NUM(&sb, session->security_parameters.timestamp);
101 BUFFER_APPEND(&sb, &id, 1);
106 ret = pack_srp_auth_info(session, &sb);
115 ret = pack_psk_auth_info(session, &sb);
123 case GNUTLS_CRD_ANON:
124 ret = pack_anon_auth_info(session, &sb);
131 case GNUTLS_CRD_CERTIFICATE:
132 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);
152 ret = _gnutls_ext_pack(session, &sb);
158 return _gnutls_buffer_to_datum(&sb, packed_session);
161 _gnutls_buffer_clear(&sb);
166 /* Load session data from a buffer.
169 _gnutls_session_unpack(gnutls_session_t session,
170 const gnutls_datum_t * packed_session)
177 _gnutls_buffer_init(&sb);
179 if (packed_session == NULL || packed_session->size == 0) {
181 return GNUTLS_E_INTERNAL_ERROR;
185 _gnutls_buffer_append_data(&sb, packed_session->data,
186 packed_session->size);
192 if (session->key.auth_info != NULL) {
193 _gnutls_free_auth_info(session);
196 BUFFER_POP_NUM(&sb, magic);
197 if (magic != PACKED_SESSION_MAGIC) {
198 ret = gnutls_assert_val(GNUTLS_E_DB_ERROR);
203 session->internals.resumed_security_parameters.
205 BUFFER_POP(&sb, &id, 1);
210 ret = unpack_srp_auth_info(session, &sb);
219 ret = unpack_psk_auth_info(session, &sb);
227 case GNUTLS_CRD_ANON:
228 ret = unpack_anon_auth_info(session, &sb);
235 case GNUTLS_CRD_CERTIFICATE:
236 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);
258 ret = _gnutls_ext_unpack(session, &sb);
267 _gnutls_buffer_clear(&sb);
275 * 1 byte the credentials type
276 * 4 bytes the size of the whole structure
278 * 2 bytes the size of secret key in bits
279 * 4 bytes the size of the prime
281 * 4 bytes the size of the generator
282 * x bytes the generator
283 * 4 bytes the size of the public key
284 * x bytes the public key
286 * 4 bytes the size of the modulus
287 * x bytes the modulus
288 * 4 bytes the size of the exponent
289 * x bytes the exponent
291 * 4 bytes the length of the certificate list
292 * 4 bytes the size of first certificate
293 * x bytes the certificate
297 pack_certificate_auth_info(gnutls_session_t session, gnutls_buffer_st * ps)
301 cert_auth_info_t info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
304 size_offset = ps->length;
305 BUFFER_APPEND_NUM(ps, 0);
306 cur_size = ps->length;
310 BUFFER_APPEND_NUM(ps, info->dh.secret_bits);
311 BUFFER_APPEND_PFX4(ps, info->dh.prime.data,
312 info->dh.prime.size);
313 BUFFER_APPEND_PFX4(ps, info->dh.generator.data,
314 info->dh.generator.size);
315 BUFFER_APPEND_PFX4(ps, info->dh.public_key.data,
316 info->dh.public_key.size);
318 BUFFER_APPEND_NUM(ps, info->ncerts);
320 for (i = 0; i < info->ncerts; i++)
321 BUFFER_APPEND_PFX4(ps,
322 info->raw_certificate_list[i].
324 info->raw_certificate_list[i].
328 /* write the real size */
329 _gnutls_write_uint32(ps->length - cur_size,
330 ps->data + size_offset);
336 /* Upack certificate info.
339 unpack_certificate_auth_info(gnutls_session_t session,
340 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);
362 info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
364 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
366 BUFFER_POP_NUM(ps, info->dh.secret_bits);
368 BUFFER_POP_DATUM(ps, &info->dh.prime);
369 BUFFER_POP_DATUM(ps, &info->dh.generator);
370 BUFFER_POP_DATUM(ps, &info->dh.public_key);
372 BUFFER_POP_NUM(ps, info->ncerts);
374 if (info->ncerts > 0) {
375 info->raw_certificate_list =
376 gnutls_calloc(info->ncerts, sizeof(gnutls_datum_t));
377 if (info->raw_certificate_list == NULL) {
379 ret = GNUTLS_E_MEMORY_ERROR;
384 for (i = 0; i < info->ncerts; i++) {
385 BUFFER_POP_DATUM(ps, &info->raw_certificate_list[i]);
392 _gnutls_free_datum(&info->dh.prime);
393 _gnutls_free_datum(&info->dh.generator);
394 _gnutls_free_datum(&info->dh.public_key);
396 for (j = 0; j < i; j++)
397 _gnutls_free_datum(&info->raw_certificate_list[j]);
399 gnutls_free(info->raw_certificate_list);
407 /* Packs the SRP session authentication data.
411 * 1 byte the credentials type
412 * 4 bytes the size of the SRP username (x)
413 * x bytes the SRP username
416 pack_srp_auth_info(gnutls_session_t session, gnutls_buffer_st * ps)
418 srp_server_auth_info_t info = _gnutls_get_auth_info(session, GNUTLS_CRD_SRP);
422 const char *username = NULL;
424 if (info && info->username) {
425 username = info->username;
426 len = strlen(info->username) + 1; /* include the terminating null */
430 size_offset = ps->length;
431 BUFFER_APPEND_NUM(ps, 0);
432 cur_size = ps->length;
434 BUFFER_APPEND_PFX4(ps, username, len);
436 /* write the real size */
437 _gnutls_write_uint32(ps->length - cur_size,
438 ps->data + size_offset);
445 unpack_srp_auth_info(gnutls_session_t session, gnutls_buffer_st * ps)
447 size_t username_size;
449 srp_server_auth_info_t info;
451 BUFFER_POP_NUM(ps, username_size);
452 if (username_size > sizeof(info->username)) {
454 return GNUTLS_E_INTERNAL_ERROR;
458 _gnutls_auth_info_set(session, GNUTLS_CRD_SRP,
459 sizeof(srp_server_auth_info_st), 1);
465 info = _gnutls_get_auth_info(session, GNUTLS_CRD_SRP);
467 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
469 BUFFER_POP(ps, info->username, username_size);
470 if (username_size == 0)
471 info->username[0] = 0;
482 /* Packs the ANON session authentication data.
486 * 1 byte the credentials type
487 * 4 bytes the size of the whole structure
488 * 2 bytes the size of secret key in bits
489 * 4 bytes the size of the prime
491 * 4 bytes the size of the generator
492 * x bytes the generator
493 * 4 bytes the size of the public key
494 * x bytes the public key
497 pack_anon_auth_info(gnutls_session_t session, gnutls_buffer_st * ps)
500 anon_auth_info_t info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
503 size_offset = ps->length;
504 BUFFER_APPEND_NUM(ps, 0);
505 cur_size = ps->length;
508 BUFFER_APPEND_NUM(ps, info->dh.secret_bits);
509 BUFFER_APPEND_PFX4(ps, info->dh.prime.data,
510 info->dh.prime.size);
511 BUFFER_APPEND_PFX4(ps, info->dh.generator.data,
512 info->dh.generator.size);
513 BUFFER_APPEND_PFX4(ps, info->dh.public_key.data,
514 info->dh.public_key.size);
517 /* write the real size */
518 _gnutls_write_uint32(ps->length - cur_size,
519 ps->data + size_offset);
526 unpack_anon_auth_info(gnutls_session_t session, gnutls_buffer_st * ps)
530 anon_auth_info_t info = NULL;
532 BUFFER_POP_NUM(ps, pack_size);
535 return 0; /* nothing to be done */
537 /* client and server have the same auth_info here
540 _gnutls_auth_info_set(session, GNUTLS_CRD_ANON,
541 sizeof(anon_auth_info_st), 1);
547 info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
549 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
551 BUFFER_POP_NUM(ps, info->dh.secret_bits);
553 BUFFER_POP_DATUM(ps, &info->dh.prime);
554 BUFFER_POP_DATUM(ps, &info->dh.generator);
555 BUFFER_POP_DATUM(ps, &info->dh.public_key);
561 _gnutls_free_datum(&info->dh.prime);
562 _gnutls_free_datum(&info->dh.generator);
563 _gnutls_free_datum(&info->dh.public_key);
571 /* Packs the PSK session authentication data.
575 * 1 byte the credentials type
576 * 4 bytes the size of the whole structure
578 * 4 bytes the size of the PSK username (x)
579 * x bytes the PSK username
580 * 2 bytes the size of secret key in bits
581 * 4 bytes the size of the prime
583 * 4 bytes the size of the generator
584 * x bytes the generator
585 * 4 bytes the size of the public key
586 * x bytes the public key
589 pack_psk_auth_info(gnutls_session_t session, gnutls_buffer_st * ps)
591 psk_auth_info_t info;
597 info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
599 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
601 username_len = strlen(info->username) + 1; /* include the terminating null */
602 hint_len = strlen(info->hint) + 1; /* include the terminating null */
604 size_offset = ps->length;
605 BUFFER_APPEND_NUM(ps, 0);
606 cur_size = ps->length;
608 BUFFER_APPEND_PFX4(ps, info->username, username_len);
609 BUFFER_APPEND_PFX4(ps, info->hint, hint_len);
611 BUFFER_APPEND_NUM(ps, info->dh.secret_bits);
612 BUFFER_APPEND_PFX4(ps, info->dh.prime.data, info->dh.prime.size);
613 BUFFER_APPEND_PFX4(ps, info->dh.generator.data,
614 info->dh.generator.size);
615 BUFFER_APPEND_PFX4(ps, info->dh.public_key.data,
616 info->dh.public_key.size);
618 /* write the real size */
619 _gnutls_write_uint32(ps->length - cur_size,
620 ps->data + size_offset);
626 unpack_psk_auth_info(gnutls_session_t session, gnutls_buffer_st * ps)
628 size_t username_size, hint_size;
630 psk_auth_info_t info;
633 _gnutls_auth_info_set(session, GNUTLS_CRD_PSK,
634 sizeof(psk_auth_info_st), 1);
640 info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
642 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
644 BUFFER_POP_NUM(ps, username_size);
645 if (username_size > sizeof(info->username)) {
647 return GNUTLS_E_INTERNAL_ERROR;
650 BUFFER_POP(ps, info->username, username_size);
652 BUFFER_POP_NUM(ps, hint_size);
653 if (hint_size > sizeof(info->hint)) {
655 return GNUTLS_E_INTERNAL_ERROR;
657 BUFFER_POP(ps, info->hint, hint_size);
659 BUFFER_POP_NUM(ps, info->dh.secret_bits);
661 BUFFER_POP_DATUM(ps, &info->dh.prime);
662 BUFFER_POP_DATUM(ps, &info->dh.generator);
663 BUFFER_POP_DATUM(ps, &info->dh.public_key);
668 _gnutls_free_datum(&info->dh.prime);
669 _gnutls_free_datum(&info->dh.generator);
670 _gnutls_free_datum(&info->dh.public_key);
677 /* Packs the security parameters.
681 * 4 bytes the total security data size
682 * 1 byte the entity type (client/server)
683 * 1 byte the key exchange algorithm used
684 * 1 byte the read cipher algorithm
685 * 1 byte the read mac algorithm
686 * 1 byte the read compression algorithm
688 * 1 byte the write cipher algorithm
689 * 1 byte the write mac algorithm
690 * 1 byte the write compression algorithm
692 * 1 byte the certificate type
693 * 1 byte the protocol version
695 * 2 bytes the cipher suite
697 * 48 bytes the master secret
699 * 32 bytes the client random
700 * 32 bytes the server random
702 * 1 byte the session ID size
703 * x bytes the session ID (32 bytes max)
705 * 4 bytes the new record padding flag
706 * 4 bytes the ECC curve
707 * -------------------
712 pack_security_parameters(gnutls_session_t session, gnutls_buffer_st * ps)
718 record_parameters_st *params;
720 if (session->security_parameters.epoch_read
721 != session->security_parameters.epoch_write) {
723 return GNUTLS_E_INVALID_REQUEST;
726 ret = _gnutls_epoch_get(session, EPOCH_READ_CURRENT, ¶ms);
732 /* move after the auth info stuff.
734 size_offset = ps->length;
735 BUFFER_APPEND_NUM(ps, 0);
736 cur_size = ps->length;
739 BUFFER_APPEND_NUM(ps, session->security_parameters.entity);
740 BUFFER_APPEND_NUM(ps, session->security_parameters.kx_algorithm);
741 BUFFER_APPEND(ps, session->security_parameters.cipher_suite, 2);
742 BUFFER_APPEND_NUM(ps,
743 session->security_parameters.compression_method);
744 BUFFER_APPEND_NUM(ps, session->security_parameters.cert_type);
745 BUFFER_APPEND_NUM(ps, session->security_parameters.pversion->id);
747 BUFFER_APPEND(ps, session->security_parameters.master_secret,
749 BUFFER_APPEND(ps, session->security_parameters.client_random,
751 BUFFER_APPEND(ps, session->security_parameters.server_random,
754 BUFFER_APPEND(ps, &session->security_parameters.session_id_size,
756 BUFFER_APPEND(ps, session->security_parameters.session_id,
757 session->security_parameters.session_id_size);
759 BUFFER_APPEND_NUM(ps,
760 session->security_parameters.
761 max_record_send_size);
762 BUFFER_APPEND_NUM(ps,
763 session->security_parameters.
764 max_record_recv_size);
765 BUFFER_APPEND_NUM(ps, session->security_parameters.ecc_curve);
767 BUFFER_APPEND_NUM(ps,
768 session->security_parameters.server_sign_algo);
769 BUFFER_APPEND_NUM(ps,
770 session->security_parameters.client_sign_algo);
772 _gnutls_write_uint32(ps->length - cur_size,
773 ps->data + size_offset);
779 unpack_security_parameters(gnutls_session_t session, gnutls_buffer_st * ps)
786 BUFFER_POP_NUM(ps, pack_size);
789 return GNUTLS_E_INVALID_REQUEST;
792 session->internals.resumed_security_parameters.timestamp;
793 memset(&session->internals.resumed_security_parameters, 0,
794 sizeof(session->internals.resumed_security_parameters));
795 session->internals.resumed_security_parameters.timestamp =
798 timestamp = gnutls_time(0);
801 session->internals.resumed_security_parameters.
804 session->internals.resumed_security_parameters.
807 session->internals.resumed_security_parameters.
810 session->internals.resumed_security_parameters.
813 session->internals.resumed_security_parameters.
815 BUFFER_POP_NUM(ps, version);
816 session->internals.resumed_security_parameters.pversion =
817 version_to_entry(version);
818 if (session->internals.resumed_security_parameters.pversion ==
820 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
823 session->internals.resumed_security_parameters.
824 master_secret, GNUTLS_MASTER_SIZE);
827 session->internals.resumed_security_parameters.
828 client_random, GNUTLS_RANDOM_SIZE);
830 session->internals.resumed_security_parameters.
831 server_random, GNUTLS_RANDOM_SIZE);
833 &session->internals.resumed_security_parameters.
837 session->internals.resumed_security_parameters.
839 session->internals.resumed_security_parameters.
843 session->internals.resumed_security_parameters.
844 max_record_send_size);
846 session->internals.resumed_security_parameters.
847 max_record_recv_size);
850 session->internals.resumed_security_parameters.
853 session->internals.resumed_security_parameters.
856 session->internals.resumed_security_parameters.
859 if (session->internals.resumed_security_parameters.
860 max_record_recv_size == 0
861 || session->internals.resumed_security_parameters.
862 max_record_send_size == 0) {
863 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
867 session->internals.resumed_security_parameters.timestamp >
868 session->internals.expire_time
869 || session->internals.resumed_security_parameters.timestamp >
872 return GNUTLS_E_EXPIRED;
882 * gnutls_session_set_premaster:
883 * @session: is a #gnutls_session_t structure.
884 * @entity: GNUTLS_SERVER or GNUTLS_CLIENT
885 * @version: the TLS protocol version
886 * @kx: the key exchange method
887 * @cipher: the cipher
888 * @mac: the MAC algorithm
889 * @comp: the compression method
890 * @master: the master key to use
891 * @session_id: the session identifier
893 * This function sets the premaster secret in a session. This is
894 * a function intended for exceptional uses. Do not use this
895 * function unless you are implementing a legacy protocol.
896 * Use gnutls_session_set_data() instead.
898 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
899 * an error code is returned.
902 gnutls_session_set_premaster(gnutls_session_t session, unsigned int entity,
903 gnutls_protocol_t version,
904 gnutls_kx_algorithm_t kx,
905 gnutls_cipher_algorithm_t cipher,
906 gnutls_mac_algorithm_t mac,
907 gnutls_compression_method_t comp,
908 const gnutls_datum_t * master,
909 const gnutls_datum_t * session_id)
913 memset(&session->internals.resumed_security_parameters, 0,
914 sizeof(session->internals.resumed_security_parameters));
916 session->internals.resumed_security_parameters.entity = entity;
917 session->internals.resumed_security_parameters.kx_algorithm = kx;
920 _gnutls_cipher_suite_get_id(kx, cipher, mac,
922 resumed_security_parameters.
925 return gnutls_assert_val(ret);
927 session->internals.resumed_security_parameters.compression_method =
929 session->internals.resumed_security_parameters.cert_type =
931 session->internals.resumed_security_parameters.pversion =
932 version_to_entry(version);
934 if (session->internals.resumed_security_parameters.pversion ==
936 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
938 if (master->size != GNUTLS_MASTER_SIZE)
939 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
941 memcpy(session->internals.resumed_security_parameters.
942 master_secret, master->data, master->size);
944 if (session_id->size > GNUTLS_MAX_SESSION_ID)
945 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
947 session->internals.resumed_security_parameters.session_id_size =
949 memcpy(session->internals.resumed_security_parameters.session_id,
950 session_id->data, session_id->size);
952 session->internals.resumed_security_parameters.
953 max_record_send_size =
954 session->internals.resumed_security_parameters.
955 max_record_recv_size = DEFAULT_MAX_RECORD_SIZE;
957 session->internals.resumed_security_parameters.timestamp =
960 session->internals.resumed_security_parameters.ecc_curve =
961 GNUTLS_ECC_CURVE_INVALID;
963 session->internals.premaster_set = 1;