Pack/unpack psk identity hint too.
[gnutls.git] / lib / gnutls_session_pack.c
blobf3b1255f746cd2f5276f462126c9f7345956cdd2
1 /*
2 * Copyright (C) 2000, 2004, 2005, 2007, 2008 Free Software Foundation
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GNUTLS.
8 * The GNUTLS library 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
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21 * USA
25 /* Contains functions that are supposed to pack and unpack session data,
26 * before and after they are sent to the database backend.
29 #include <gnutls_int.h>
30 #ifdef ENABLE_SRP
31 # include <auth_srp.h>
32 #endif
33 #ifdef ENABLE_PSK
34 # include <auth_psk.h>
35 #endif
36 #include <auth_anon.h>
37 #include <auth_cert.h>
38 #include <gnutls_errors.h>
39 #include <gnutls_auth_int.h>
40 #include <gnutls_session_pack.h>
41 #include <gnutls_datum.h>
42 #include <gnutls_num.h>
44 #define PACK_HEADER_SIZE 1
45 #define MAX_SEC_PARAMS 7+MAX_SRP_USERNAME+MAX_SERVER_NAME_EXTENSIONS*(3+MAX_SERVER_NAME_SIZE)+165
46 static int pack_certificate_auth_info (gnutls_session_t,
47 gnutls_datum_t * packed_session);
48 static int unpack_certificate_auth_info (gnutls_session_t,
49 const gnutls_datum_t *
50 packed_session);
52 static int unpack_srp_auth_info (gnutls_session_t session,
53 const gnutls_datum_t * packed_session);
54 static int pack_srp_auth_info (gnutls_session_t session,
55 gnutls_datum_t * packed_session);
57 static int unpack_psk_auth_info (gnutls_session_t session,
58 const gnutls_datum_t * packed_session);
59 static int pack_psk_auth_info (gnutls_session_t session,
60 gnutls_datum_t * packed_session);
62 static int unpack_anon_auth_info (gnutls_session_t session,
63 const gnutls_datum_t * packed_session);
64 static int pack_anon_auth_info (gnutls_session_t session,
65 gnutls_datum_t * packed_session);
67 static int unpack_security_parameters (gnutls_session_t session,
68 const gnutls_datum_t * packed_session);
69 static int pack_security_parameters (gnutls_session_t session,
70 gnutls_datum_t * 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.
81 int
82 _gnutls_session_pack (gnutls_session_t session,
83 gnutls_datum_t * packed_session)
85 int ret;
87 if (packed_session == NULL)
89 gnutls_assert ();
90 return GNUTLS_E_INTERNAL_ERROR;
94 switch (gnutls_auth_get_type (session))
96 #ifdef ENABLE_SRP
97 case GNUTLS_CRD_SRP:
98 ret = pack_srp_auth_info (session, packed_session);
99 if (ret < 0)
101 gnutls_assert ();
102 return ret;
104 break;
105 #endif
106 #ifdef ENABLE_PSK
107 case GNUTLS_CRD_PSK:
108 ret = pack_psk_auth_info (session, packed_session);
109 if (ret < 0)
111 gnutls_assert ();
112 return ret;
114 break;
115 #endif
116 #ifdef ENABLE_ANON
117 case GNUTLS_CRD_ANON:
118 ret = pack_anon_auth_info (session, packed_session);
119 if (ret < 0)
121 gnutls_assert ();
122 return ret;
124 break;
125 #endif
126 case GNUTLS_CRD_CERTIFICATE:
127 ret = pack_certificate_auth_info (session, packed_session);
128 if (ret < 0)
130 gnutls_assert ();
131 return ret;
133 break;
134 default:
135 return GNUTLS_E_INTERNAL_ERROR;
139 /* Auth_info structures copied. Now copy security_parameters_st.
140 * packed_session must have allocated space for the security parameters.
142 ret = pack_security_parameters (session, packed_session);
143 if (ret < 0)
145 gnutls_assert ();
146 _gnutls_free_datum (packed_session);
147 return ret;
150 return 0;
154 /* Load session data from a buffer.
157 _gnutls_session_unpack (gnutls_session_t session,
158 const gnutls_datum_t * packed_session)
160 int ret;
162 if (packed_session == NULL || packed_session->size == 0)
164 gnutls_assert ();
165 return GNUTLS_E_INTERNAL_ERROR;
168 if (_gnutls_get_auth_info(session) != NULL)
170 _gnutls_free_auth_info (session);
173 switch (packed_session->data[0])
175 #ifdef ENABLE_SRP
176 case GNUTLS_CRD_SRP:
177 ret = unpack_srp_auth_info (session, packed_session);
178 if (ret < 0)
180 gnutls_assert ();
181 return ret;
183 break;
184 #endif
185 #ifdef ENABLE_PSK
186 case GNUTLS_CRD_PSK:
187 ret = unpack_psk_auth_info (session, packed_session);
188 if (ret < 0)
190 gnutls_assert ();
191 return ret;
193 break;
194 #endif
195 #ifdef ENABLE_ANON
196 case GNUTLS_CRD_ANON:
197 ret = unpack_anon_auth_info (session, packed_session);
198 if (ret < 0)
200 gnutls_assert ();
201 return ret;
203 break;
204 #endif
205 case GNUTLS_CRD_CERTIFICATE:
206 ret = unpack_certificate_auth_info (session, packed_session);
207 if (ret < 0)
209 gnutls_assert ();
210 return ret;
212 break;
213 default:
214 gnutls_assert ();
215 return GNUTLS_E_INTERNAL_ERROR;
219 /* Auth_info structures copied. Now copy security_parameters_st.
220 * packed_session must have allocated space for the security parameters.
222 ret = unpack_security_parameters (session, packed_session);
223 if (ret < 0)
225 gnutls_assert ();
226 return ret;
229 return 0;
233 /* Format:
234 * 1 byte the credentials type
235 * 4 bytes the size of the whole structure
236 * DH stuff
237 * 2 bytes the size of secret key in bits
238 * 4 bytes the size of the prime
239 * x bytes the prime
240 * 4 bytes the size of the generator
241 * x bytes the generator
242 * 4 bytes the size of the public key
243 * x bytes the public key
244 * RSA stuff
245 * 4 bytes the size of the modulus
246 * x bytes the modulus
247 * 4 bytes the size of the exponent
248 * x bytes the exponent
249 * CERTIFICATES
250 * 4 bytes the length of the certificate list
251 * 4 bytes the size of first certificate
252 * x bytes the certificate
253 * and so on...
255 static int
256 pack_certificate_auth_info (gnutls_session_t session,
257 gnutls_datum_t * packed_session)
259 unsigned int pos = 0, i;
260 int cert_size, pack_size;
261 cert_auth_info_t info = _gnutls_get_auth_info (session);
263 if (info)
265 cert_size = 4;
267 for (i = 0; i < info->ncerts; i++)
268 cert_size += 4 + info->raw_certificate_list[i].size;
270 pack_size = 2 + 4 + info->dh.prime.size +
271 4 + info->dh.generator.size + 4 + info->dh.public_key.size +
272 4 + info->rsa_export.modulus.size +
273 4 + info->rsa_export.exponent.size + cert_size;
275 else
276 pack_size = 0;
278 packed_session->size = PACK_HEADER_SIZE + pack_size + sizeof (uint32_t);
280 /* calculate the size and allocate the data.
282 packed_session->data =
283 gnutls_malloc (packed_session->size + MAX_SEC_PARAMS);
285 if (packed_session->data == NULL)
287 gnutls_assert ();
288 return GNUTLS_E_MEMORY_ERROR;
291 packed_session->data[0] = GNUTLS_CRD_CERTIFICATE;
292 _gnutls_write_uint32 (pack_size, &packed_session->data[PACK_HEADER_SIZE]);
293 pos += 4 + PACK_HEADER_SIZE;
296 if (pack_size > 0)
299 _gnutls_write_uint16 (info->dh.secret_bits, &packed_session->data[pos]);
300 pos += 2;
302 _gnutls_write_datum32 (&packed_session->data[pos], info->dh.prime);
303 pos += 4 + info->dh.prime.size;
304 _gnutls_write_datum32 (&packed_session->data[pos], info->dh.generator);
305 pos += 4 + info->dh.generator.size;
306 _gnutls_write_datum32 (&packed_session->data[pos], info->dh.public_key);
307 pos += 4 + info->dh.public_key.size;
309 _gnutls_write_datum32 (&packed_session->data[pos],
310 info->rsa_export.modulus);
311 pos += 4 + info->rsa_export.modulus.size;
312 _gnutls_write_datum32 (&packed_session->data[pos],
313 info->rsa_export.exponent);
314 pos += 4 + info->rsa_export.exponent.size;
316 _gnutls_write_uint32 (info->ncerts, &packed_session->data[pos]);
317 pos += 4;
319 for (i = 0; i < info->ncerts; i++)
321 _gnutls_write_datum32 (&packed_session->data[pos],
322 info->raw_certificate_list[i]);
323 pos += sizeof (uint32_t) + info->raw_certificate_list[i].size;
327 return 0;
331 /* Upack certificate info.
333 static int
334 unpack_certificate_auth_info (gnutls_session_t session,
335 const gnutls_datum_t * packed_session)
337 int pos = 0, size, ret;
338 unsigned int i = 0, j;
339 size_t pack_size;
340 cert_auth_info_t info;
342 if (packed_session->data[0] != GNUTLS_CRD_CERTIFICATE)
344 gnutls_assert ();
345 return GNUTLS_E_INVALID_REQUEST;
348 pack_size = _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]);
349 pos += PACK_HEADER_SIZE + 4;
351 if (pack_size == 0)
352 return 0; /* nothing to be done */
354 /* a simple check for integrity */
355 if (pack_size + PACK_HEADER_SIZE + 4 > packed_session->size)
357 gnutls_assert ();
358 return GNUTLS_E_INVALID_REQUEST;
361 /* client and server have the same auth_info here
363 ret =
364 _gnutls_auth_info_set (session, GNUTLS_CRD_CERTIFICATE,
365 sizeof (cert_auth_info_st), 1);
366 if (ret < 0)
368 gnutls_assert ();
369 return ret;
372 info = _gnutls_get_auth_info (session);
373 if (info == NULL)
375 gnutls_assert ();
376 return GNUTLS_E_INTERNAL_ERROR;
379 info->dh.secret_bits = _gnutls_read_uint16 (&packed_session->data[pos]);
380 pos += 2;
382 size = _gnutls_read_uint32 (&packed_session->data[pos]);
383 pos += 4;
384 ret = _gnutls_set_datum (&info->dh.prime, &packed_session->data[pos], size);
385 if (ret < 0)
387 gnutls_assert ();
388 goto error;
390 pos += size;
392 size = _gnutls_read_uint32 (&packed_session->data[pos]);
393 pos += 4;
394 ret =
395 _gnutls_set_datum (&info->dh.generator, &packed_session->data[pos], size);
396 if (ret < 0)
398 gnutls_assert ();
399 goto error;
401 pos += size;
403 size = _gnutls_read_uint32 (&packed_session->data[pos]);
404 pos += 4;
405 ret =
406 _gnutls_set_datum (&info->dh.public_key, &packed_session->data[pos],
407 size);
408 if (ret < 0)
410 gnutls_assert ();
411 goto error;
413 pos += size;
415 size = _gnutls_read_uint32 (&packed_session->data[pos]);
416 pos += 4;
417 ret =
418 _gnutls_set_datum (&info->rsa_export.modulus,
419 &packed_session->data[pos], size);
420 if (ret < 0)
422 gnutls_assert ();
423 goto error;
425 pos += size;
427 size = _gnutls_read_uint32 (&packed_session->data[pos]);
428 pos += 4;
429 ret =
430 _gnutls_set_datum (&info->rsa_export.exponent,
431 &packed_session->data[pos], size);
432 if (ret < 0)
434 gnutls_assert ();
435 goto error;
437 pos += size;
439 info->ncerts = _gnutls_read_uint32 (&packed_session->data[pos]);
440 pos += 4;
442 if (info->ncerts > 0)
444 info->raw_certificate_list =
445 gnutls_calloc (1, sizeof (gnutls_datum_t) * info->ncerts);
446 if (info->raw_certificate_list == NULL)
448 gnutls_assert ();
449 ret = GNUTLS_E_MEMORY_ERROR;
450 goto error;
454 for (i = 0; i < info->ncerts; i++)
456 size = _gnutls_read_uint32 (&packed_session->data[pos]);
457 pos += sizeof (uint32_t);
459 ret =
460 _gnutls_set_datum (&info->raw_certificate_list[i],
461 &packed_session->data[pos], size);
462 pos += size;
464 if (ret < 0)
466 gnutls_assert ();
467 goto error;
472 return 0;
474 error:
475 _gnutls_free_datum (&info->dh.prime);
476 _gnutls_free_datum (&info->dh.generator);
477 _gnutls_free_datum (&info->dh.public_key);
479 _gnutls_free_datum (&info->rsa_export.modulus);
480 _gnutls_free_datum (&info->rsa_export.exponent);
482 for (j = 0; j < i; j++)
483 _gnutls_free_datum (&info->raw_certificate_list[j]);
485 gnutls_free (info->raw_certificate_list);
487 return ret;
491 #ifdef ENABLE_SRP
492 /* Packs the SRP session authentication data.
495 /* Format:
496 * 1 byte the credentials type
497 * 4 bytes the size of the SRP username (x)
498 * x bytes the SRP username
500 static int
501 pack_srp_auth_info (gnutls_session_t session, gnutls_datum_t * packed_session)
503 srp_server_auth_info_t info = _gnutls_get_auth_info (session);
504 int pack_size;
506 if (info && info->username)
507 pack_size = strlen (info->username) + 1; /* include the terminating null */
508 else
509 pack_size = 0;
511 packed_session->size = PACK_HEADER_SIZE + pack_size + sizeof (uint32_t);
513 /* calculate the size and allocate the data.
515 packed_session->data =
516 gnutls_malloc (packed_session->size + MAX_SEC_PARAMS);
518 if (packed_session->data == NULL)
520 gnutls_assert ();
521 return GNUTLS_E_MEMORY_ERROR;
524 packed_session->data[0] = GNUTLS_CRD_SRP;
525 _gnutls_write_uint32 (pack_size, &packed_session->data[PACK_HEADER_SIZE]);
527 if (pack_size > 0)
528 memcpy (&packed_session->data[PACK_HEADER_SIZE + sizeof (uint32_t)],
529 info->username, pack_size + 1);
531 return 0;
535 static int
536 unpack_srp_auth_info (gnutls_session_t session,
537 const gnutls_datum_t * packed_session)
539 size_t username_size;
540 int ret;
541 srp_server_auth_info_t info;
543 if (packed_session->data[0] != GNUTLS_CRD_SRP)
545 gnutls_assert ();
546 return GNUTLS_E_INVALID_REQUEST;
549 username_size =
550 _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]);
552 if (username_size == 0)
553 return 0; /* nothing to be done */
555 /* a simple check for integrity */
556 if (username_size + 4 + PACK_HEADER_SIZE > packed_session->size)
558 gnutls_assert ();
559 return GNUTLS_E_INVALID_REQUEST;
562 ret =
563 _gnutls_auth_info_set (session, GNUTLS_CRD_SRP,
564 sizeof (srp_server_auth_info_st), 1);
565 if (ret < 0)
567 gnutls_assert ();
568 return ret;
571 info = _gnutls_get_auth_info (session);
572 if (info == NULL)
574 gnutls_assert ();
575 return GNUTLS_E_INTERNAL_ERROR;
578 memcpy (info->username,
579 &packed_session->data[PACK_HEADER_SIZE + sizeof (uint32_t)],
580 username_size);
582 return 0;
584 #endif
587 #ifdef ENABLE_ANON
588 /* Packs the ANON session authentication data.
591 /* Format:
592 * 1 byte the credentials type
593 * 4 bytes the size of the whole structure
594 * 2 bytes the size of secret key in bits
595 * 4 bytes the size of the prime
596 * x bytes the prime
597 * 4 bytes the size of the generator
598 * x bytes the generator
599 * 4 bytes the size of the public key
600 * x bytes the public key
602 static int
603 pack_anon_auth_info (gnutls_session_t session, gnutls_datum_t * packed_session)
605 anon_auth_info_t info = _gnutls_get_auth_info (session);
606 int pos = 0;
607 size_t pack_size;
609 if (info)
610 pack_size = 2 + 4 * 3 + info->dh.prime.size +
611 info->dh.generator.size + info->dh.public_key.size;
612 else
613 pack_size = 0;
615 packed_session->size = PACK_HEADER_SIZE + pack_size + sizeof (uint32_t);
617 /* calculate the size and allocate the data.
619 packed_session->data =
620 gnutls_malloc (packed_session->size + MAX_SEC_PARAMS);
622 if (packed_session->data == NULL)
624 gnutls_assert ();
625 return GNUTLS_E_MEMORY_ERROR;
628 packed_session->data[0] = GNUTLS_CRD_ANON;
629 _gnutls_write_uint32 (pack_size, &packed_session->data[PACK_HEADER_SIZE]);
630 pos += 4 + PACK_HEADER_SIZE;
632 if (pack_size > 0)
634 _gnutls_write_uint16 (info->dh.secret_bits, &packed_session->data[pos]);
635 pos += 2;
637 _gnutls_write_datum32 (&packed_session->data[pos], info->dh.prime);
638 pos += 4 + info->dh.prime.size;
639 _gnutls_write_datum32 (&packed_session->data[pos], info->dh.generator);
640 pos += 4 + info->dh.generator.size;
641 _gnutls_write_datum32 (&packed_session->data[pos], info->dh.public_key);
642 pos += 4 + info->dh.public_key.size;
646 return 0;
650 static int
651 unpack_anon_auth_info (gnutls_session_t session,
652 const gnutls_datum_t * packed_session)
654 size_t pack_size;
655 int pos = 0, size, ret;
656 anon_auth_info_t info;
658 if (packed_session->data[0] != GNUTLS_CRD_ANON)
660 gnutls_assert ();
661 return GNUTLS_E_INVALID_REQUEST;
664 pack_size = _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]);
665 pos += PACK_HEADER_SIZE + 4;
668 if (pack_size == 0)
669 return 0; /* nothing to be done */
671 /* a simple check for integrity */
672 if (pack_size + PACK_HEADER_SIZE + 4 > packed_session->size)
674 gnutls_assert ();
675 return GNUTLS_E_INVALID_REQUEST;
678 /* client and serer have the same auth_info here
680 ret =
681 _gnutls_auth_info_set (session, GNUTLS_CRD_ANON,
682 sizeof (anon_auth_info_st), 1);
683 if (ret < 0)
685 gnutls_assert ();
686 return ret;
689 info = _gnutls_get_auth_info (session);
690 if (info == NULL)
692 gnutls_assert ();
693 return GNUTLS_E_INTERNAL_ERROR;
696 info->dh.secret_bits = _gnutls_read_uint16 (&packed_session->data[pos]);
697 pos += 2;
699 size = _gnutls_read_uint32 (&packed_session->data[pos]);
700 pos += 4;
701 ret = _gnutls_set_datum (&info->dh.prime, &packed_session->data[pos], size);
702 if (ret < 0)
704 gnutls_assert ();
705 goto error;
707 pos += size;
709 size = _gnutls_read_uint32 (&packed_session->data[pos]);
710 pos += 4;
711 ret =
712 _gnutls_set_datum (&info->dh.generator, &packed_session->data[pos], size);
713 if (ret < 0)
715 gnutls_assert ();
716 goto error;
718 pos += size;
720 size = _gnutls_read_uint32 (&packed_session->data[pos]);
721 pos += 4;
722 ret =
723 _gnutls_set_datum (&info->dh.public_key, &packed_session->data[pos],
724 size);
725 if (ret < 0)
727 gnutls_assert ();
728 goto error;
730 pos += size;
732 return 0;
734 error:
735 _gnutls_free_datum (&info->dh.prime);
736 _gnutls_free_datum (&info->dh.generator);
737 _gnutls_free_datum (&info->dh.public_key);
738 return ret;
740 #endif /* ANON */
742 #ifdef ENABLE_PSK
743 /* Packs the PSK session authentication data.
746 /* Format:
747 * 1 byte the credentials type
748 * 4 bytes the size of the whole structure
749 * 4 bytes the size of the PSK username (x)
750 * x bytes the PSK username
751 * 2 bytes the size of secret key in bits
752 * 4 bytes the size of the prime
753 * x bytes the prime
754 * 4 bytes the size of the generator
755 * x bytes the generator
756 * 4 bytes the size of the public key
757 * x bytes the public key
759 static int
760 pack_psk_auth_info (gnutls_session_t session, gnutls_datum_t * packed_session)
762 psk_auth_info_t info;
763 int pack_size, username_size = 0, hint_size = 0, pos;
765 info = _gnutls_get_auth_info (session);
767 if (info)
769 username_size = strlen (info->username) + 1; /* include the terminating null */
770 hint_size = strlen (info->hint) + 1; /* include the terminating null */
771 pack_size = username_size + hint_size +
772 2 + 4 * 3 + info->dh.prime.size + info->dh.generator.size +
773 info->dh.public_key.size;
775 else
776 pack_size = 0;
778 packed_session->size = PACK_HEADER_SIZE + pack_size + sizeof (uint32_t);
780 /* calculate the size and allocate the data.
782 packed_session->data =
783 gnutls_malloc (packed_session->size + MAX_SEC_PARAMS);
785 if (packed_session->data == NULL)
787 gnutls_assert ();
788 return GNUTLS_E_MEMORY_ERROR;
791 pos = 0;
793 packed_session->data[pos] = GNUTLS_CRD_PSK;
794 pos++;
796 _gnutls_write_uint32 (pack_size, &packed_session->data[pos]);
797 pos += 4;
800 if (pack_size > 0)
802 _gnutls_write_uint32 (username_size, &packed_session->data[pos]);
803 pos += 4;
805 memcpy (&packed_session->data[pos], info->username, username_size);
806 pos += username_size;
808 _gnutls_write_uint32 (hint_size, &packed_session->data[pos]);
809 pos += 4;
811 memcpy (&packed_session->data[pos], info->hint, hint_size);
812 pos += hint_size;
814 _gnutls_write_uint16 (info->dh.secret_bits, &packed_session->data[pos]);
815 pos += 2;
817 _gnutls_write_datum32 (&packed_session->data[pos], info->dh.prime);
818 pos += 4 + info->dh.prime.size;
819 _gnutls_write_datum32 (&packed_session->data[pos], info->dh.generator);
820 pos += 4 + info->dh.generator.size;
821 _gnutls_write_datum32 (&packed_session->data[pos], info->dh.public_key);
822 pos += 4 + info->dh.public_key.size;
826 return 0;
829 static int
830 unpack_psk_auth_info (gnutls_session_t session,
831 const gnutls_datum_t * packed_session)
833 size_t username_size, hint_size;
834 size_t pack_size;
835 int pos = 0, size, ret;
836 psk_auth_info_t info;
838 if (packed_session->data[0] != GNUTLS_CRD_PSK)
840 gnutls_assert ();
841 return GNUTLS_E_INVALID_REQUEST;
844 pack_size = _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]);
845 pos += PACK_HEADER_SIZE + 4;
848 if (pack_size == 0)
849 return 0; /* nothing to be done */
851 /* a simple check for integrity */
852 if (pack_size + PACK_HEADER_SIZE + 4 > packed_session->size)
854 gnutls_assert ();
855 return GNUTLS_E_INVALID_REQUEST;
858 /* client and serer have the same auth_info here
860 ret =
861 _gnutls_auth_info_set (session, GNUTLS_CRD_PSK,
862 sizeof (psk_auth_info_st), 1);
863 if (ret < 0)
865 gnutls_assert ();
866 return ret;
869 info = _gnutls_get_auth_info (session);
870 if (info == NULL)
872 gnutls_assert ();
873 return GNUTLS_E_INTERNAL_ERROR;
876 username_size = _gnutls_read_uint32 (&packed_session->data[pos]);
877 pos += 4;
879 memcpy (info->username, &packed_session->data[pos], username_size);
880 pos += username_size;
882 hint_size = _gnutls_read_uint32 (&packed_session->data[pos]);
883 pos += 4;
885 memcpy (info->hint, &packed_session->data[pos], hint_size);
886 pos += hint_size;
888 info->dh.secret_bits = _gnutls_read_uint16 (&packed_session->data[pos]);
889 pos += 2;
891 size = _gnutls_read_uint32 (&packed_session->data[pos]);
892 pos += 4;
893 ret = _gnutls_set_datum (&info->dh.prime, &packed_session->data[pos], size);
894 if (ret < 0)
896 gnutls_assert ();
897 goto error;
899 pos += size;
901 size = _gnutls_read_uint32 (&packed_session->data[pos]);
902 pos += 4;
903 ret =
904 _gnutls_set_datum (&info->dh.generator, &packed_session->data[pos], size);
905 if (ret < 0)
907 gnutls_assert ();
908 goto error;
910 pos += size;
912 size = _gnutls_read_uint32 (&packed_session->data[pos]);
913 pos += 4;
914 ret =
915 _gnutls_set_datum (&info->dh.public_key, &packed_session->data[pos],
916 size);
917 if (ret < 0)
919 gnutls_assert ();
920 goto error;
922 pos += size;
924 return 0;
926 error:
927 _gnutls_free_datum (&info->dh.prime);
928 _gnutls_free_datum (&info->dh.generator);
929 _gnutls_free_datum (&info->dh.public_key);
930 return ret;
932 #endif
935 /* Packs the security parameters.
938 /* Format:
939 * 4 bytes the total security data size
940 * 1 byte the entity type (client/server)
941 * 1 byte the key exchange algorithm used
942 * 1 byte the read cipher algorithm
943 * 1 byte the read mac algorithm
944 * 1 byte the read compression algorithm
946 * 1 byte the write cipher algorithm
947 * 1 byte the write mac algorithm
948 * 1 byte the write compression algorithm
950 * 1 byte the certificate type
951 * 1 byte the protocol version
953 * 2 bytes the cipher suite
955 * 48 bytes the master secret
957 * 32 bytes the client random
958 * 32 bytes the server random
960 * 1 byte the session ID size
961 * x bytes the session ID (32 bytes max)
963 * 4 bytes a timestamp
964 * -------------------
965 * MAX: 165 bytes
967 * EXTENSIONS:
968 * 2 bytes the record send size
969 * 2 bytes the record recv size
971 * 1 byte the SRP username size
972 * x bytes the SRP username (MAX_SRP_USERNAME)
974 * 2 bytes the number of server name extensions (up to MAX_SERVER_NAME_EXTENSIONS)
975 * 1 byte the first name type
976 * 2 bytes the size of the first name
977 * x bytes the first name (MAX_SERVER_NAME_SIZE)
978 * and so on...
980 * --------------------
981 * MAX: 7+MAX_SRP_USERNAME+MAX_SERVER_NAME_EXTENSIONS*(3+MAX_SERVER_NAME_SIZE)
983 static int
984 pack_security_parameters (gnutls_session_t session,
985 gnutls_datum_t * packed_session)
987 int pos = 0;
988 size_t len, init, i;
990 /* move after the auth info stuff.
992 init =
993 _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]) + 4 +
994 PACK_HEADER_SIZE;
996 pos = init + 4; /* make some space to write later the size */
998 packed_session->data[pos++] = session->security_parameters.entity;
999 packed_session->data[pos++] = session->security_parameters.kx_algorithm;
1000 packed_session->data[pos++] =
1001 session->security_parameters.read_bulk_cipher_algorithm;
1002 packed_session->data[pos++] =
1003 session->security_parameters.read_mac_algorithm;
1004 packed_session->data[pos++] =
1005 session->security_parameters.read_compression_algorithm;
1006 packed_session->data[pos++] =
1007 session->security_parameters.write_bulk_cipher_algorithm;
1008 packed_session->data[pos++] =
1009 session->security_parameters.write_mac_algorithm;
1010 packed_session->data[pos++] =
1011 session->security_parameters.write_compression_algorithm;
1012 packed_session->data[pos++] =
1013 session->security_parameters.current_cipher_suite.suite[0];
1014 packed_session->data[pos++] =
1015 session->security_parameters.current_cipher_suite.suite[1];
1017 packed_session->data[pos++] = session->security_parameters.cert_type;
1018 packed_session->data[pos++] = session->security_parameters.version;
1020 memcpy (&packed_session->data[pos],
1021 session->security_parameters.master_secret, TLS_MASTER_SIZE);
1022 pos += TLS_MASTER_SIZE;
1024 memcpy (&packed_session->data[pos],
1025 session->security_parameters.client_random, TLS_RANDOM_SIZE);
1026 pos += TLS_RANDOM_SIZE;
1027 memcpy (&packed_session->data[pos],
1028 session->security_parameters.server_random, TLS_RANDOM_SIZE);
1029 pos += TLS_RANDOM_SIZE;
1031 packed_session->data[pos++] = session->security_parameters.session_id_size;
1032 memcpy (&packed_session->data[pos], session->security_parameters.session_id,
1033 session->security_parameters.session_id_size);
1034 pos += session->security_parameters.session_id_size;
1036 _gnutls_write_uint32 (session->security_parameters.timestamp,
1037 &packed_session->data[pos]);
1038 pos += 4;
1040 /* Extensions */
1041 _gnutls_write_uint16 (session->security_parameters.max_record_send_size,
1042 &packed_session->data[pos]);
1043 pos += 2;
1045 _gnutls_write_uint16 (session->security_parameters.max_record_recv_size,
1046 &packed_session->data[pos]);
1047 pos += 2;
1049 /* SRP */
1050 len =
1051 strlen ((char *) session->security_parameters.extensions.srp_username);
1052 packed_session->data[pos++] = len;
1053 memcpy (&packed_session->data[pos],
1054 session->security_parameters.extensions.srp_username, len);
1055 pos += len;
1057 _gnutls_write_uint16 (session->security_parameters.extensions.
1058 server_names_size, &packed_session->data[pos]);
1059 pos += 2;
1061 for (i = 0; i < session->security_parameters.extensions.server_names_size;
1062 i++)
1064 packed_session->data[pos++] =
1065 session->security_parameters.extensions.server_names[i].type;
1066 _gnutls_write_uint16 (session->security_parameters.extensions.
1067 server_names[i].name_length,
1068 &packed_session->data[pos]);
1069 pos += 2;
1071 memcpy (&packed_session->data[pos],
1072 session->security_parameters.extensions.server_names[i].name,
1073 session->security_parameters.extensions.server_names[i].
1074 name_length);
1075 pos +=
1076 session->security_parameters.extensions.server_names[i].name_length;
1079 /* write the total size */
1080 _gnutls_write_uint32 (pos - init - 4, &packed_session->data[init]);
1081 packed_session->size += pos - init;
1083 return 0;
1087 static int
1088 unpack_security_parameters (gnutls_session_t session,
1089 const gnutls_datum_t * packed_session)
1091 size_t pack_size, init, i;
1092 int pos = 0, len;
1093 time_t timestamp = time (0);
1096 /* skip the auth info stuff */
1097 init =
1098 _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]) + 4 +
1099 PACK_HEADER_SIZE;
1101 pos = init;
1103 pack_size = _gnutls_read_uint32 (&packed_session->data[pos]);
1104 pos += 4;
1107 if (pack_size == 0)
1108 return GNUTLS_E_INVALID_REQUEST;
1110 /* a simple check for integrity */
1111 if (pack_size > MAX_SEC_PARAMS)
1113 gnutls_assert ();
1114 return GNUTLS_E_INVALID_REQUEST;
1117 session->internals.resumed_security_parameters.entity =
1118 packed_session->data[pos++];
1119 session->internals.resumed_security_parameters.kx_algorithm =
1120 packed_session->data[pos++];
1121 session->internals.resumed_security_parameters.read_bulk_cipher_algorithm =
1122 packed_session->data[pos++];
1123 session->internals.resumed_security_parameters.read_mac_algorithm =
1124 packed_session->data[pos++];
1125 session->internals.resumed_security_parameters.read_compression_algorithm =
1126 packed_session->data[pos++];
1127 session->internals.resumed_security_parameters.write_bulk_cipher_algorithm =
1128 packed_session->data[pos++];
1129 session->internals.resumed_security_parameters.write_mac_algorithm =
1130 packed_session->data[pos++];
1131 session->internals.resumed_security_parameters.write_compression_algorithm =
1132 packed_session->data[pos++];
1133 session->internals.resumed_security_parameters.current_cipher_suite.
1134 suite[0] = packed_session->data[pos++];
1135 session->internals.resumed_security_parameters.current_cipher_suite.
1136 suite[1] = packed_session->data[pos++];
1138 session->internals.resumed_security_parameters.cert_type =
1139 packed_session->data[pos++];
1140 session->internals.resumed_security_parameters.version =
1141 packed_session->data[pos++];
1143 memcpy (session->internals.resumed_security_parameters.master_secret,
1144 &packed_session->data[pos], TLS_MASTER_SIZE);
1145 pos += TLS_MASTER_SIZE;
1147 memcpy (session->internals.resumed_security_parameters.client_random,
1148 &packed_session->data[pos], TLS_RANDOM_SIZE);
1149 pos += TLS_RANDOM_SIZE;
1150 memcpy (session->internals.resumed_security_parameters.server_random,
1151 &packed_session->data[pos], TLS_RANDOM_SIZE);
1152 pos += TLS_RANDOM_SIZE;
1154 session->internals.resumed_security_parameters.session_id_size =
1155 packed_session->data[pos++];
1156 memcpy (session->internals.resumed_security_parameters.session_id,
1157 &packed_session->data[pos],
1158 session->internals.resumed_security_parameters.session_id_size);
1159 pos += session->internals.resumed_security_parameters.session_id_size;
1161 session->internals.resumed_security_parameters.timestamp =
1162 _gnutls_read_uint32 (&packed_session->data[pos]);
1163 pos += 4;
1165 if (timestamp - session->internals.resumed_security_parameters.timestamp >
1166 session->internals.expire_time
1167 || session->internals.resumed_security_parameters.timestamp > timestamp)
1169 gnutls_assert ();
1170 return GNUTLS_E_EXPIRED;
1173 /* Extensions */
1174 session->internals.resumed_security_parameters.max_record_send_size =
1175 _gnutls_read_uint16 (&packed_session->data[pos]);
1176 pos += 2;
1178 session->internals.resumed_security_parameters.max_record_recv_size =
1179 _gnutls_read_uint16 (&packed_session->data[pos]);
1180 pos += 2;
1183 /* SRP */
1184 len = packed_session->data[pos++]; /* srp username length */
1185 memcpy (session->internals.resumed_security_parameters.extensions.
1186 srp_username, &packed_session->data[pos], len);
1187 session->internals.resumed_security_parameters.extensions.
1188 srp_username[len] = 0;
1189 pos += len;
1191 session->internals.resumed_security_parameters.extensions.
1192 server_names_size = _gnutls_read_uint16 (&packed_session->data[pos]);
1193 pos += 2;
1194 for (i = 0;
1196 session->internals.resumed_security_parameters.extensions.
1197 server_names_size; i++)
1199 session->internals.resumed_security_parameters.extensions.
1200 server_names[i].type = packed_session->data[pos++];
1201 session->internals.resumed_security_parameters.extensions.
1202 server_names[i].name_length =
1203 _gnutls_read_uint16 (&packed_session->data[pos]);
1204 pos += 2;
1206 memcpy (session->internals.resumed_security_parameters.extensions.
1207 server_names[i].name, &packed_session->data[pos],
1208 session->internals.resumed_security_parameters.extensions.
1209 server_names[i].name_length);
1210 pos +=
1211 session->internals.resumed_security_parameters.extensions.
1212 server_names[i].name_length;
1214 return 0;