[Upstream] x509: optimize subject alternative name access
[platform/upstream/gnutls.git] / lib / gnutls_session_pack.c
1 /*
2  * Copyright (C) 2000-2012 Free Software Foundation, Inc.
3  *
4  * Author: Nikos Mavrogiannopoulos
5  *
6  * This file is part of GnuTLS.
7  *
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.
12  *
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.
17  *
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/>
20  *
21  */
22
23 /* Contains functions that are supposed to pack and unpack session data,
24  * before and after they are sent to the database backend.
25  */
26
27 #include <gnutls_int.h>
28 #ifdef ENABLE_SRP
29 #include <auth/srp.h>
30 #endif
31 #ifdef ENABLE_PSK
32 #include <auth/psk.h>
33 #endif
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>
46
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);
51
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);
56
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);
61
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);
66
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);
71
72
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.
76  *
77  * packed_session will contain the session data.
78  *
79  * The data will be in a platform independent format.
80  */
81 int
82 _gnutls_session_pack(gnutls_session_t session,
83                      gnutls_datum_t * packed_session)
84 {
85         int ret;
86         gnutls_buffer_st sb;
87         uint8_t id;
88
89         if (packed_session == NULL) {
90                 gnutls_assert();
91                 return GNUTLS_E_INTERNAL_ERROR;
92         }
93
94         _gnutls_buffer_init(&sb);
95
96
97         id = gnutls_auth_get_type(session);
98
99         BUFFER_APPEND_NUM(&sb, PACKED_SESSION_MAGIC);
100         BUFFER_APPEND_NUM(&sb, session->security_parameters.timestamp);
101         BUFFER_APPEND(&sb, &id, 1);
102
103         switch (id) {
104 #ifdef ENABLE_SRP
105         case GNUTLS_CRD_SRP:
106                 ret = pack_srp_auth_info(session, &sb);
107                 if (ret < 0) {
108                         gnutls_assert();
109                         goto fail;
110                 }
111                 break;
112 #endif
113 #ifdef ENABLE_PSK
114         case GNUTLS_CRD_PSK:
115                 ret = pack_psk_auth_info(session, &sb);
116                 if (ret < 0) {
117                         gnutls_assert();
118                         goto fail;
119                 }
120                 break;
121 #endif
122 #ifdef ENABLE_ANON
123         case GNUTLS_CRD_ANON:
124                 ret = pack_anon_auth_info(session, &sb);
125                 if (ret < 0) {
126                         gnutls_assert();
127                         goto fail;
128                 }
129                 break;
130 #endif
131         case GNUTLS_CRD_CERTIFICATE:
132                 ret = pack_certificate_auth_info(session, &sb);
133                 if (ret < 0) {
134                         gnutls_assert();
135                         goto fail;
136                 }
137                 break;
138         default:
139                 return GNUTLS_E_INTERNAL_ERROR;
140
141         }
142
143         /* Auth_info structures copied. Now copy security_parameters_st. 
144          * packed_session must have allocated space for the security parameters.
145          */
146         ret = pack_security_parameters(session, &sb);
147         if (ret < 0) {
148                 gnutls_assert();
149                 goto fail;
150         }
151
152         ret = _gnutls_ext_pack(session, &sb);
153         if (ret < 0) {
154                 gnutls_assert();
155                 goto fail;
156         }
157
158         return _gnutls_buffer_to_datum(&sb, packed_session);
159
160       fail:
161         _gnutls_buffer_clear(&sb);
162         return ret;
163 }
164
165
166 /* Load session data from a buffer.
167  */
168 int
169 _gnutls_session_unpack(gnutls_session_t session,
170                        const gnutls_datum_t * packed_session)
171 {
172         int ret;
173         gnutls_buffer_st sb;
174         uint32_t magic;
175         uint8_t id;
176
177         _gnutls_buffer_init(&sb);
178
179         if (packed_session == NULL || packed_session->size == 0) {
180                 gnutls_assert();
181                 return GNUTLS_E_INTERNAL_ERROR;
182         }
183
184         ret =
185             _gnutls_buffer_append_data(&sb, packed_session->data,
186                                        packed_session->size);
187         if (ret < 0) {
188                 gnutls_assert();
189                 return ret;
190         }
191
192         if (session->key.auth_info != NULL) {
193                 _gnutls_free_auth_info(session);
194         }
195
196         BUFFER_POP_NUM(&sb, magic);
197         if (magic != PACKED_SESSION_MAGIC) {
198                 ret = gnutls_assert_val(GNUTLS_E_DB_ERROR);
199                 goto error;
200         }
201
202         BUFFER_POP_NUM(&sb,
203                        session->internals.resumed_security_parameters.
204                        timestamp);
205         BUFFER_POP(&sb, &id, 1);
206
207         switch (id) {
208 #ifdef ENABLE_SRP
209         case GNUTLS_CRD_SRP:
210                 ret = unpack_srp_auth_info(session, &sb);
211                 if (ret < 0) {
212                         gnutls_assert();
213                         goto error;
214                 }
215                 break;
216 #endif
217 #ifdef ENABLE_PSK
218         case GNUTLS_CRD_PSK:
219                 ret = unpack_psk_auth_info(session, &sb);
220                 if (ret < 0) {
221                         gnutls_assert();
222                         goto error;
223                 }
224                 break;
225 #endif
226 #ifdef ENABLE_ANON
227         case GNUTLS_CRD_ANON:
228                 ret = unpack_anon_auth_info(session, &sb);
229                 if (ret < 0) {
230                         gnutls_assert();
231                         return ret;
232                 }
233                 break;
234 #endif
235         case GNUTLS_CRD_CERTIFICATE:
236                 ret = unpack_certificate_auth_info(session, &sb);
237                 if (ret < 0) {
238                         gnutls_assert();
239                         goto error;
240                 }
241                 break;
242         default:
243                 gnutls_assert();
244                 ret = GNUTLS_E_INTERNAL_ERROR;
245                 goto error;
246
247         }
248
249         /* Auth_info structures copied. Now copy security_parameters_st. 
250          * packed_session must have allocated space for the security parameters.
251          */
252         ret = unpack_security_parameters(session, &sb);
253         if (ret < 0) {
254                 gnutls_assert();
255                 goto error;
256         }
257
258         ret = _gnutls_ext_unpack(session, &sb);
259         if (ret < 0) {
260                 gnutls_assert();
261                 goto error;
262         }
263
264         ret = 0;
265
266       error:
267         _gnutls_buffer_clear(&sb);
268
269         return ret;
270 }
271
272
273
274 /* Format: 
275  *      1 byte the credentials type
276  *      4 bytes the size of the whole structure
277  *        DH stuff
278  *      2 bytes the size of secret key in bits
279  *      4 bytes the size of the prime
280  *      x bytes 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
285  *        RSA stuff
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
290  *        CERTIFICATES
291  *      4 bytes the length of the certificate list
292  *      4 bytes the size of first certificate
293  *      x bytes the certificate
294  *       and so on...
295  */
296 static int
297 pack_certificate_auth_info(gnutls_session_t session, gnutls_buffer_st * ps)
298 {
299         unsigned int i;
300         int cur_size, ret;
301         cert_auth_info_t info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
302         int size_offset;
303
304         size_offset = ps->length;
305         BUFFER_APPEND_NUM(ps, 0);
306         cur_size = ps->length;
307
308         if (info) {
309
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);
317
318                 BUFFER_APPEND_NUM(ps, info->ncerts);
319
320                 for (i = 0; i < info->ncerts; i++)
321                         BUFFER_APPEND_PFX4(ps,
322                                            info->raw_certificate_list[i].
323                                            data,
324                                            info->raw_certificate_list[i].
325                                            size);
326         }
327
328         /* write the real size */
329         _gnutls_write_uint32(ps->length - cur_size,
330                              ps->data + size_offset);
331
332         return 0;
333 }
334
335
336 /* Upack certificate info.
337  */
338 static int
339 unpack_certificate_auth_info(gnutls_session_t session,
340                              gnutls_buffer_st * ps)
341 {
342         int ret;
343         unsigned int i = 0, j = 0;
344         size_t pack_size;
345         cert_auth_info_t info = NULL;
346
347         BUFFER_POP_NUM(ps, pack_size);
348
349         if (pack_size == 0)
350                 return 0;       /* nothing to be done */
351
352         /* client and server have the same auth_info here
353          */
354         ret =
355             _gnutls_auth_info_set(session, GNUTLS_CRD_CERTIFICATE,
356                                   sizeof(cert_auth_info_st), 1);
357         if (ret < 0) {
358                 gnutls_assert();
359                 return ret;
360         }
361
362         info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
363         if (info == NULL)
364                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
365
366         BUFFER_POP_NUM(ps, info->dh.secret_bits);
367
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);
371
372         BUFFER_POP_NUM(ps, info->ncerts);
373
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) {
378                         gnutls_assert();
379                         ret = GNUTLS_E_MEMORY_ERROR;
380                         goto error;
381                 }
382         }
383
384         for (i = 0; i < info->ncerts; i++) {
385                 BUFFER_POP_DATUM(ps, &info->raw_certificate_list[i]);
386         }
387
388         return 0;
389
390       error:
391         if (info) {
392                 _gnutls_free_datum(&info->dh.prime);
393                 _gnutls_free_datum(&info->dh.generator);
394                 _gnutls_free_datum(&info->dh.public_key);
395
396                 for (j = 0; j < i; j++)
397                         _gnutls_free_datum(&info->raw_certificate_list[j]);
398
399                 gnutls_free(info->raw_certificate_list);
400         }
401
402         return ret;
403
404 }
405
406 #ifdef ENABLE_SRP
407 /* Packs the SRP session authentication data.
408  */
409
410 /* Format: 
411  *      1 byte the credentials type
412  *      4 bytes the size of the SRP username (x)
413  *      x bytes the SRP username
414  */
415 static int
416 pack_srp_auth_info(gnutls_session_t session, gnutls_buffer_st * ps)
417 {
418         srp_server_auth_info_t info = _gnutls_get_auth_info(session, GNUTLS_CRD_SRP);
419         int len, ret;
420         int size_offset;
421         size_t cur_size;
422         const char *username = NULL;
423
424         if (info && info->username) {
425                 username = info->username;
426                 len = strlen(info->username) + 1;       /* include the terminating null */
427         } else
428                 len = 0;
429
430         size_offset = ps->length;
431         BUFFER_APPEND_NUM(ps, 0);
432         cur_size = ps->length;
433
434         BUFFER_APPEND_PFX4(ps, username, len);
435
436         /* write the real size */
437         _gnutls_write_uint32(ps->length - cur_size,
438                              ps->data + size_offset);
439
440         return 0;
441 }
442
443
444 static int
445 unpack_srp_auth_info(gnutls_session_t session, gnutls_buffer_st * ps)
446 {
447         size_t username_size;
448         int ret;
449         srp_server_auth_info_t info;
450
451         BUFFER_POP_NUM(ps, username_size);
452         if (username_size > sizeof(info->username)) {
453                 gnutls_assert();
454                 return GNUTLS_E_INTERNAL_ERROR;
455         }
456
457         ret =
458             _gnutls_auth_info_set(session, GNUTLS_CRD_SRP,
459                                   sizeof(srp_server_auth_info_st), 1);
460         if (ret < 0) {
461                 gnutls_assert();
462                 return ret;
463         }
464
465         info = _gnutls_get_auth_info(session, GNUTLS_CRD_SRP);
466         if (info == NULL)
467                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
468
469         BUFFER_POP(ps, info->username, username_size);
470         if (username_size == 0)
471                 info->username[0] = 0;
472
473         ret = 0;
474
475       error:
476         return ret;
477 }
478 #endif
479
480
481 #ifdef ENABLE_ANON
482 /* Packs the ANON session authentication data.
483  */
484
485 /* Format: 
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
490  *      x bytes 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
495  */
496 static int
497 pack_anon_auth_info(gnutls_session_t session, gnutls_buffer_st * ps)
498 {
499         int cur_size, ret;
500         anon_auth_info_t info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
501         int size_offset;
502
503         size_offset = ps->length;
504         BUFFER_APPEND_NUM(ps, 0);
505         cur_size = ps->length;
506
507         if (info) {
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);
515         }
516
517         /* write the real size */
518         _gnutls_write_uint32(ps->length - cur_size,
519                              ps->data + size_offset);
520
521         return 0;
522 }
523
524
525 static int
526 unpack_anon_auth_info(gnutls_session_t session, gnutls_buffer_st * ps)
527 {
528         int ret;
529         size_t pack_size;
530         anon_auth_info_t info = NULL;
531
532         BUFFER_POP_NUM(ps, pack_size);
533
534         if (pack_size == 0)
535                 return 0;       /* nothing to be done */
536
537         /* client and server have the same auth_info here
538          */
539         ret =
540             _gnutls_auth_info_set(session, GNUTLS_CRD_ANON,
541                                   sizeof(anon_auth_info_st), 1);
542         if (ret < 0) {
543                 gnutls_assert();
544                 return ret;
545         }
546
547         info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
548         if (info == NULL)
549                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
550
551         BUFFER_POP_NUM(ps, info->dh.secret_bits);
552
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);
556
557         return 0;
558
559       error:
560         if (info) {
561                 _gnutls_free_datum(&info->dh.prime);
562                 _gnutls_free_datum(&info->dh.generator);
563                 _gnutls_free_datum(&info->dh.public_key);
564         }
565
566         return ret;
567 }
568 #endif                          /* ANON */
569
570 #ifdef ENABLE_PSK
571 /* Packs the PSK session authentication data.
572  */
573
574 /* Format: 
575  *      1 byte the credentials type
576  *      4 bytes the size of the whole structure
577  *
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
582  *      x bytes 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
587  */
588 static int
589 pack_psk_auth_info(gnutls_session_t session, gnutls_buffer_st * ps)
590 {
591         psk_auth_info_t info;
592         int username_len;
593         int hint_len, ret;
594         int size_offset;
595         size_t cur_size;
596
597         info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
598         if (info == NULL)
599                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
600
601         username_len = strlen(info->username) + 1;      /* include the terminating null */
602         hint_len = strlen(info->hint) + 1;      /* include the terminating null */
603
604         size_offset = ps->length;
605         BUFFER_APPEND_NUM(ps, 0);
606         cur_size = ps->length;
607
608         BUFFER_APPEND_PFX4(ps, info->username, username_len);
609         BUFFER_APPEND_PFX4(ps, info->hint, hint_len);
610
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);
617
618         /* write the real size */
619         _gnutls_write_uint32(ps->length - cur_size,
620                              ps->data + size_offset);
621
622         return 0;
623 }
624
625 static int
626 unpack_psk_auth_info(gnutls_session_t session, gnutls_buffer_st * ps)
627 {
628         size_t username_size, hint_size;
629         int ret;
630         psk_auth_info_t info;
631
632         ret =
633             _gnutls_auth_info_set(session, GNUTLS_CRD_PSK,
634                                   sizeof(psk_auth_info_st), 1);
635         if (ret < 0) {
636                 gnutls_assert();
637                 return ret;
638         }
639
640         info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
641         if (info == NULL)
642                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
643
644         BUFFER_POP_NUM(ps, username_size);
645         if (username_size > sizeof(info->username)) {
646                 gnutls_assert();
647                 return GNUTLS_E_INTERNAL_ERROR;
648         }
649
650         BUFFER_POP(ps, info->username, username_size);
651
652         BUFFER_POP_NUM(ps, hint_size);
653         if (hint_size > sizeof(info->hint)) {
654                 gnutls_assert();
655                 return GNUTLS_E_INTERNAL_ERROR;
656         }
657         BUFFER_POP(ps, info->hint, hint_size);
658
659         BUFFER_POP_NUM(ps, info->dh.secret_bits);
660
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);
664
665         ret = 0;
666
667       error:
668         _gnutls_free_datum(&info->dh.prime);
669         _gnutls_free_datum(&info->dh.generator);
670         _gnutls_free_datum(&info->dh.public_key);
671
672         return ret;
673 }
674 #endif
675
676
677 /* Packs the security parameters.
678  */
679
680 /* Format: 
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
687  *
688  *      1 byte the write cipher algorithm
689  *      1 byte the write mac algorithm
690  *      1 byte the write compression algorithm
691  *
692  *      1 byte the certificate type
693  *      1 byte the protocol version
694  *
695  *      2 bytes the cipher suite
696  *
697  *      48 bytes the master secret
698  *
699  *      32 bytes the client random
700  *      32 bytes the server random
701  *
702  *      1 byte the session ID size
703  *      x bytes the session ID (32 bytes max)
704  *
705  *      4 bytes the new record padding flag
706  *      4 bytes the ECC curve
707  *            -------------------
708  *                MAX: 169 bytes
709  *
710  */
711 static int
712 pack_security_parameters(gnutls_session_t session, gnutls_buffer_st * ps)
713 {
714
715         int ret;
716         int size_offset;
717         size_t cur_size;
718         record_parameters_st *params;
719
720         if (session->security_parameters.epoch_read
721             != session->security_parameters.epoch_write) {
722                 gnutls_assert();
723                 return GNUTLS_E_INVALID_REQUEST;
724         }
725
726         ret = _gnutls_epoch_get(session, EPOCH_READ_CURRENT, &params);
727         if (ret < 0) {
728                 gnutls_assert();
729                 return ret;
730         }
731
732         /* move after the auth info stuff.
733          */
734         size_offset = ps->length;
735         BUFFER_APPEND_NUM(ps, 0);
736         cur_size = ps->length;
737
738
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);
746
747         BUFFER_APPEND(ps, session->security_parameters.master_secret,
748                       GNUTLS_MASTER_SIZE);
749         BUFFER_APPEND(ps, session->security_parameters.client_random,
750                       GNUTLS_RANDOM_SIZE);
751         BUFFER_APPEND(ps, session->security_parameters.server_random,
752                       GNUTLS_RANDOM_SIZE);
753
754         BUFFER_APPEND(ps, &session->security_parameters.session_id_size,
755                       1);
756         BUFFER_APPEND(ps, session->security_parameters.session_id,
757                       session->security_parameters.session_id_size);
758
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);
766
767         BUFFER_APPEND_NUM(ps,
768                           session->security_parameters.server_sign_algo);
769         BUFFER_APPEND_NUM(ps,
770                           session->security_parameters.client_sign_algo);
771
772         _gnutls_write_uint32(ps->length - cur_size,
773                              ps->data + size_offset);
774
775         return 0;
776 }
777
778 static int
779 unpack_security_parameters(gnutls_session_t session, gnutls_buffer_st * ps)
780 {
781         size_t pack_size;
782         int ret;
783         unsigned version;
784         time_t timestamp;
785
786         BUFFER_POP_NUM(ps, pack_size);
787
788         if (pack_size == 0)
789                 return GNUTLS_E_INVALID_REQUEST;
790
791         timestamp =
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 =
796             timestamp;
797
798         timestamp = gnutls_time(0);
799
800         BUFFER_POP_NUM(ps,
801                        session->internals.resumed_security_parameters.
802                        entity);
803         BUFFER_POP_NUM(ps,
804                        session->internals.resumed_security_parameters.
805                        kx_algorithm);
806         BUFFER_POP(ps,
807                    session->internals.resumed_security_parameters.
808                    cipher_suite, 2);
809         BUFFER_POP_NUM(ps,
810                        session->internals.resumed_security_parameters.
811                        compression_method);
812         BUFFER_POP_NUM(ps,
813                        session->internals.resumed_security_parameters.
814                        cert_type);
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 ==
819             NULL)
820                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
821
822         BUFFER_POP(ps,
823                    session->internals.resumed_security_parameters.
824                    master_secret, GNUTLS_MASTER_SIZE);
825
826         BUFFER_POP(ps,
827                    session->internals.resumed_security_parameters.
828                    client_random, GNUTLS_RANDOM_SIZE);
829         BUFFER_POP(ps,
830                    session->internals.resumed_security_parameters.
831                    server_random, GNUTLS_RANDOM_SIZE);
832         BUFFER_POP(ps,
833                    &session->internals.resumed_security_parameters.
834                    session_id_size, 1);
835
836         BUFFER_POP(ps,
837                    session->internals.resumed_security_parameters.
838                    session_id,
839                    session->internals.resumed_security_parameters.
840                    session_id_size);
841
842         BUFFER_POP_NUM(ps,
843                        session->internals.resumed_security_parameters.
844                        max_record_send_size);
845         BUFFER_POP_NUM(ps,
846                        session->internals.resumed_security_parameters.
847                        max_record_recv_size);
848
849         BUFFER_POP_NUM(ps,
850                        session->internals.resumed_security_parameters.
851                        ecc_curve);
852         BUFFER_POP_NUM(ps,
853                        session->internals.resumed_security_parameters.
854                        server_sign_algo);
855         BUFFER_POP_NUM(ps,
856                        session->internals.resumed_security_parameters.
857                        client_sign_algo);
858
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);
864         }
865
866         if (timestamp -
867             session->internals.resumed_security_parameters.timestamp >
868             session->internals.expire_time
869             || session->internals.resumed_security_parameters.timestamp >
870             timestamp) {
871                 gnutls_assert();
872                 return GNUTLS_E_EXPIRED;
873         }
874
875         ret = 0;
876
877       error:
878         return ret;
879 }
880
881 /**
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
892  *
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.
897  *
898  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
899  *   an error code is returned.
900  **/
901 int
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)
910 {
911         int ret;
912
913         memset(&session->internals.resumed_security_parameters, 0,
914                sizeof(session->internals.resumed_security_parameters));
915
916         session->internals.resumed_security_parameters.entity = entity;
917         session->internals.resumed_security_parameters.kx_algorithm = kx;
918
919         ret =
920             _gnutls_cipher_suite_get_id(kx, cipher, mac,
921                                         session->internals.
922                                         resumed_security_parameters.
923                                         cipher_suite);
924         if (ret < 0)
925                 return gnutls_assert_val(ret);
926
927         session->internals.resumed_security_parameters.compression_method =
928             comp;
929         session->internals.resumed_security_parameters.cert_type =
930             DEFAULT_CERT_TYPE;
931         session->internals.resumed_security_parameters.pversion =
932             version_to_entry(version);
933
934         if (session->internals.resumed_security_parameters.pversion ==
935             NULL)
936                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
937
938         if (master->size != GNUTLS_MASTER_SIZE)
939                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
940
941         memcpy(session->internals.resumed_security_parameters.
942                master_secret, master->data, master->size);
943
944         if (session_id->size > GNUTLS_MAX_SESSION_ID)
945                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
946
947         session->internals.resumed_security_parameters.session_id_size =
948             session_id->size;
949         memcpy(session->internals.resumed_security_parameters.session_id,
950                session_id->data, session_id->size);
951
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;
956
957         session->internals.resumed_security_parameters.timestamp =
958             gnutls_time(0);
959
960         session->internals.resumed_security_parameters.ecc_curve =
961             GNUTLS_ECC_CURVE_INVALID;
962
963         session->internals.premaster_set = 1;
964
965         return 0;
966 }