~ubuntu-branches/ubuntu/oneiric/gnutls26/oneiric

« back to all changes in this revision

Viewing changes to lib/ext_session_ticket.c

  • Committer: Bazaar Package Importer
  • Author(s): Steve Langasek
  • Date: 2011-05-20 13:07:18 UTC
  • mfrom: (12.1.11 sid)
  • Revision ID: james.westby@ubuntu.com-20110520130718-db41dybbanzfvlji
Tags: 2.10.5-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Fix build failure with --no-add-needed.
  - Build for multiarch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2009, 2010 Free Software Foundation, Inc.
 
3
 *
 
4
 * Author: Daiki Ueno
 
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
 
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
 
22
 *
 
23
 */
 
24
 
 
25
#include <gnutls_int.h>
 
26
#include <gnutls_errors.h>
 
27
#include <gnutls_datum.h>
 
28
#include <gnutls_algorithms.h>
 
29
#include <gnutls_handshake.h>
 
30
#include <gnutls_num.h>
 
31
#include <gnutls_constate.h>
 
32
#include <gnutls_session_pack.h>
 
33
#include <random.h>
 
34
#include <ext_session_ticket.h>
 
35
 
 
36
#ifdef ENABLE_SESSION_TICKET
 
37
 
 
38
#define KEY_NAME_SIZE SESSION_TICKET_KEY_NAME_SIZE
 
39
#define KEY_SIZE SESSION_TICKET_KEY_SIZE
 
40
#define IV_SIZE SESSION_TICKET_IV_SIZE
 
41
#define MAC_SECRET_SIZE SESSION_TICKET_MAC_SECRET_SIZE
 
42
 
 
43
#define MAC_SIZE 32
 
44
 
 
45
struct ticket
 
46
{
 
47
  opaque key_name[KEY_NAME_SIZE];
 
48
  opaque IV[IV_SIZE];
 
49
  opaque *encrypted_state;
 
50
  uint16_t encrypted_state_len;
 
51
  opaque mac[MAC_SIZE];
 
52
};
 
53
 
 
54
static int
 
55
digest_ticket (const gnutls_datum_t * key, struct ticket *ticket,
 
56
               opaque * digest)
 
57
{
 
58
  digest_hd_st digest_hd;
 
59
  uint16_t length16;
 
60
  int ret;
 
61
 
 
62
  ret = _gnutls_hmac_init (&digest_hd, GNUTLS_MAC_SHA256, key->data,
 
63
                           key->size);
 
64
  if (ret < 0)
 
65
    {
 
66
      gnutls_assert ();
 
67
      return ret;
 
68
    }
 
69
  _gnutls_hmac (&digest_hd, ticket->key_name, KEY_NAME_SIZE);
 
70
  _gnutls_hmac (&digest_hd, ticket->IV, IV_SIZE);
 
71
  length16 = _gnutls_conv_uint16 (ticket->encrypted_state_len);
 
72
  _gnutls_hmac (&digest_hd, &length16, 2);
 
73
  _gnutls_hmac (&digest_hd, ticket->encrypted_state,
 
74
                ticket->encrypted_state_len);
 
75
  _gnutls_hmac_deinit (&digest_hd, digest);
 
76
 
 
77
  return 0;
 
78
}
 
79
 
 
80
static int
 
81
decrypt_ticket (gnutls_session_t session, struct ticket *ticket)
 
82
{
 
83
  cipher_hd_st cipher_hd;
 
84
  gnutls_datum_t key, IV, mac_secret, state;
 
85
  opaque final[32];
 
86
  time_t timestamp = time (0);
 
87
  int ret;
 
88
 
 
89
  /* Check the integrity of ticket using HMAC-SHA-256. */
 
90
  mac_secret.data = (void *)
 
91
    session->internals.session_ticket_key->mac_secret;
 
92
  mac_secret.size = MAC_SECRET_SIZE;
 
93
  ret = digest_ticket (&mac_secret, ticket, final);
 
94
  if (ret < 0)
 
95
    {
 
96
      gnutls_assert ();
 
97
      return ret;
 
98
    }
 
99
 
 
100
  if (memcmp (ticket->mac, final, MAC_SIZE))
 
101
    {
 
102
      gnutls_assert ();
 
103
      return GNUTLS_E_DECRYPTION_FAILED;
 
104
    }
 
105
 
 
106
  /* Decrypt encrypted_state using 128-bit AES in CBC mode. */
 
107
  key.data = (void *) session->internals.session_ticket_key->key;
 
108
  key.size = KEY_SIZE;
 
109
  IV.data = ticket->IV;
 
110
  IV.size = IV_SIZE;
 
111
  ret =
 
112
    _gnutls_cipher_init (&cipher_hd, GNUTLS_CIPHER_AES_128_CBC, &key, &IV);
 
113
  if (ret < 0)
 
114
    {
 
115
      gnutls_assert ();
 
116
      return ret;
 
117
    }
 
118
  ret = _gnutls_cipher_decrypt (&cipher_hd, ticket->encrypted_state,
 
119
                                ticket->encrypted_state_len);
 
120
  _gnutls_cipher_deinit (&cipher_hd);
 
121
  if (ret < 0)
 
122
    {
 
123
      gnutls_assert ();
 
124
      return ret;
 
125
    }
 
126
 
 
127
  /* Unpack security parameters. */
 
128
  state.data = ticket->encrypted_state;
 
129
  state.size = ticket->encrypted_state_len;
 
130
  ret = _gnutls_session_unpack (session, &state);
 
131
  if (ret < 0)
 
132
    {
 
133
      gnutls_assert ();
 
134
      return ret;
 
135
    }
 
136
 
 
137
  if (timestamp - session->internals.resumed_security_parameters.timestamp >
 
138
      session->internals.expire_time
 
139
      || session->internals.resumed_security_parameters.timestamp > timestamp)
 
140
    {
 
141
      gnutls_assert ();
 
142
      return GNUTLS_E_EXPIRED;
 
143
    }
 
144
 
 
145
  session->internals.resumed = RESUME_TRUE;
 
146
 
 
147
  return 0;
 
148
}
 
149
 
 
150
static int
 
151
encrypt_ticket (gnutls_session_t session, struct ticket *ticket)
 
152
{
 
153
  cipher_hd_st cipher_hd;
 
154
  gnutls_datum_t key, IV, mac_secret, state, encrypted_state;
 
155
  int blocksize;
 
156
  int ret;
 
157
 
 
158
  /* Pack security parameters. */
 
159
  ret = _gnutls_session_pack (session, &state);
 
160
  if (ret < 0)
 
161
    {
 
162
      gnutls_assert ();
 
163
      return ret;
 
164
    }
 
165
  blocksize = gnutls_cipher_get_block_size (GNUTLS_CIPHER_AES_128_CBC);
 
166
  encrypted_state.size =
 
167
    ((state.size + blocksize - 1) / blocksize) * blocksize;
 
168
  encrypted_state.data = gnutls_malloc (encrypted_state.size);
 
169
  if (!encrypted_state.data)
 
170
    {
 
171
      gnutls_assert ();
 
172
      _gnutls_free_datum (&state);
 
173
      return GNUTLS_E_MEMORY_ERROR;
 
174
    }
 
175
  memset (encrypted_state.data, 0, encrypted_state.size);
 
176
  memcpy (encrypted_state.data, state.data, state.size);
 
177
  _gnutls_free_datum (&state);
 
178
 
 
179
  /* Encrypt state using 128-bit AES in CBC mode. */
 
180
  key.data = (void *) session->internals.session_ticket_key->key;
 
181
  key.size = KEY_SIZE;
 
182
  IV.data = session->internals.session_ticket_IV;
 
183
  IV.size = IV_SIZE;
 
184
  ret =
 
185
    _gnutls_cipher_init (&cipher_hd, GNUTLS_CIPHER_AES_128_CBC, &key, &IV);
 
186
  if (ret < 0)
 
187
    {
 
188
      gnutls_assert ();
 
189
      _gnutls_free_datum (&encrypted_state);
 
190
      return ret;
 
191
    }
 
192
 
 
193
  ret = _gnutls_cipher_encrypt (&cipher_hd, encrypted_state.data,
 
194
                                encrypted_state.size);
 
195
  _gnutls_cipher_deinit (&cipher_hd);
 
196
  if (ret < 0)
 
197
    {
 
198
      gnutls_assert ();
 
199
      _gnutls_free_datum (&encrypted_state);
 
200
      return ret;
 
201
    }
 
202
 
 
203
  /* Fill the ticket structure to compute MAC. */
 
204
  memcpy (ticket->key_name,
 
205
          session->internals.session_ticket_key->key_name, KEY_NAME_SIZE);
 
206
  memcpy (ticket->IV, IV.data, IV.size);
 
207
  ticket->encrypted_state_len = encrypted_state.size;
 
208
  ticket->encrypted_state = encrypted_state.data;
 
209
 
 
210
  mac_secret.data =
 
211
    (void *) session->internals.session_ticket_key->mac_secret;
 
212
  mac_secret.size = MAC_SECRET_SIZE;
 
213
  ret = digest_ticket (&mac_secret, ticket, ticket->mac);
 
214
  if (ret < 0)
 
215
    {
 
216
      gnutls_assert ();
 
217
      _gnutls_free_datum (&encrypted_state);
 
218
      return ret;
 
219
    }
 
220
 
 
221
  return 0;
 
222
}
 
223
 
 
224
int
 
225
_gnutls_session_ticket_recv_params (gnutls_session_t session,
 
226
                                    const opaque * data, size_t _data_size)
 
227
{
 
228
  ssize_t data_size = _data_size;
 
229
 
 
230
  if (!session->internals.session_ticket_enable)
 
231
    return 0;
 
232
 
 
233
  if (session->security_parameters.entity == GNUTLS_SERVER)
 
234
    {
 
235
      struct ticket ticket;
 
236
      const opaque *encrypted_state;
 
237
      int ret;
 
238
 
 
239
      /* The client requested a new session ticket. */
 
240
      if (data_size == 0)
 
241
        {
 
242
          session->internals.session_ticket_renew = 1;
 
243
          return 0;
 
244
        }
 
245
 
 
246
      DECR_LEN (data_size, KEY_NAME_SIZE);
 
247
      memcpy (ticket.key_name, data, KEY_NAME_SIZE);
 
248
      data += KEY_NAME_SIZE;
 
249
 
 
250
      /* If the key name of the ticket does not match the one that we
 
251
         hold, issue a new ticket. */
 
252
      if (memcmp (ticket.key_name,
 
253
                  session->internals.session_ticket_key->key_name,
 
254
                  KEY_NAME_SIZE))
 
255
        {
 
256
          session->internals.session_ticket_renew = 1;
 
257
          return 0;
 
258
        }
 
259
 
 
260
      DECR_LEN (data_size, IV_SIZE);
 
261
      memcpy (ticket.IV, data, IV_SIZE);
 
262
      data += IV_SIZE;
 
263
 
 
264
      DECR_LEN (data_size, 2);
 
265
      ticket.encrypted_state_len = _gnutls_read_uint16 (data);
 
266
      data += 2;
 
267
 
 
268
      encrypted_state = data;
 
269
 
 
270
      DECR_LEN (data_size, ticket.encrypted_state_len);
 
271
      data += ticket.encrypted_state_len;
 
272
 
 
273
      DECR_LEN (data_size, MAC_SIZE);
 
274
      memcpy (ticket.mac, data, MAC_SIZE);
 
275
 
 
276
      ticket.encrypted_state = gnutls_malloc (ticket.encrypted_state_len);
 
277
      if (!ticket.encrypted_state)
 
278
        {
 
279
          gnutls_assert ();
 
280
          return GNUTLS_E_MEMORY_ERROR;
 
281
        }
 
282
      memcpy (ticket.encrypted_state, encrypted_state,
 
283
              ticket.encrypted_state_len);
 
284
 
 
285
      ret = decrypt_ticket (session, &ticket);
 
286
      gnutls_free (ticket.encrypted_state);
 
287
      if (ret < 0)
 
288
        {
 
289
          session->internals.session_ticket_renew = 1;
 
290
          return 0;
 
291
        }
 
292
    }
 
293
  else
 
294
    {
 
295
      if (data_size == 0)
 
296
        {
 
297
          session->internals.session_ticket_renew = 1;
 
298
          return 0;
 
299
        }
 
300
    }
 
301
 
 
302
  return 0;
 
303
}
 
304
 
 
305
/* returns a positive number if we send the extension data, zero if we
 
306
   do not want to send it, and a negative number on failure.
 
307
 */
 
308
int
 
309
_gnutls_session_ticket_send_params (gnutls_session_t session,
 
310
                                    opaque * data, size_t _data_size)
 
311
{
 
312
  ssize_t data_size = _data_size;
 
313
 
 
314
  if (!session->internals.session_ticket_enable)
 
315
    return 0;
 
316
 
 
317
  if (session->security_parameters.entity == GNUTLS_SERVER)
 
318
    {
 
319
      if (session->internals.session_ticket_renew)
 
320
        {
 
321
          return GNUTLS_E_INT_RET_0;
 
322
        }
 
323
    }
 
324
  else
 
325
    {
 
326
      if (session->internals.resumed_security_parameters.
 
327
          extensions.session_ticket_len > 0)
 
328
        {
 
329
          DECR_LENGTH_RET (data_size,
 
330
                           session->internals.
 
331
                           resumed_security_parameters.extensions.
 
332
                           session_ticket_len, GNUTLS_E_SHORT_MEMORY_BUFFER);
 
333
          memcpy (data,
 
334
                  session->internals.resumed_security_parameters.
 
335
                  extensions.session_ticket,
 
336
                  session->internals.resumed_security_parameters.
 
337
                  extensions.session_ticket_len);
 
338
 
 
339
          return session->internals.resumed_security_parameters.extensions.
 
340
            session_ticket_len;
 
341
        }
 
342
      else
 
343
        {
 
344
          return GNUTLS_E_INT_RET_0;
 
345
        }
 
346
    }
 
347
  return 0;
 
348
}
 
349
 
 
350
/**
 
351
 * gnutls_session_ticket_key_generate:
 
352
 * @key: is a pointer to a #gnutls_datum_t which will contain a newly
 
353
 * created key.
 
354
 *
 
355
 * Generate a random key to encrypt security parameters within
 
356
 * SessionTicket.
 
357
 *
 
358
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
 
359
 * error code.
 
360
 *
 
361
 * Since: 2.10.0
 
362
 **/
 
363
int
 
364
gnutls_session_ticket_key_generate (gnutls_datum_t * key)
 
365
{
 
366
  int ret;
 
367
 
 
368
  key->size = sizeof (struct gnutls_session_ticket_key_st);
 
369
  key->data = gnutls_malloc (key->size);
 
370
  if (!key->data)
 
371
    {
 
372
      gnutls_assert ();
 
373
      return GNUTLS_E_MEMORY_ERROR;
 
374
    }
 
375
 
 
376
  ret = _gnutls_rnd (GNUTLS_RND_RANDOM, key->data, key->size);
 
377
  if (ret < 0)
 
378
    {
 
379
      gnutls_assert ();
 
380
      _gnutls_free_datum (key);
 
381
      return ret;
 
382
    }
 
383
 
 
384
  return 0;
 
385
}
 
386
 
 
387
/**
 
388
 * gnutls_session_ticket_enable_client:
 
389
 * @session: is a #gnutls_session_t structure.
 
390
 *
 
391
 * Request that the client should attempt session resumption using
 
392
 * SessionTicket.
 
393
 *
 
394
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
 
395
 * error code.
 
396
 *
 
397
 * Since: 2.10.0
 
398
 **/
 
399
int
 
400
gnutls_session_ticket_enable_client (gnutls_session_t session)
 
401
{
 
402
  if (!session)
 
403
    {
 
404
      gnutls_assert ();
 
405
      return GNUTLS_E_INVALID_REQUEST;
 
406
    }
 
407
 
 
408
  session->internals.session_ticket_enable = 1;
 
409
  return 0;
 
410
}
 
411
 
 
412
/**
 
413
 * gnutls_session_ticket_enable_server:
 
414
 * @session: is a #gnutls_session_t structure.
 
415
 * @key: key to encrypt session parameters.
 
416
 *
 
417
 * Request that the server should attempt session resumption using
 
418
 * SessionTicket.  @key must be initialized with
 
419
 * gnutls_session_ticket_key_generate().
 
420
 *
 
421
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
 
422
 * error code.
 
423
 *
 
424
 * Since: 2.10.0
 
425
 **/
 
426
int
 
427
gnutls_session_ticket_enable_server (gnutls_session_t session,
 
428
                                     const gnutls_datum_t * key)
 
429
{
 
430
  int ret;
 
431
 
 
432
  if (!session || !key
 
433
      || key->size != sizeof (struct gnutls_session_ticket_key_st))
 
434
    {
 
435
      gnutls_assert ();
 
436
      return GNUTLS_E_INVALID_REQUEST;
 
437
    }
 
438
 
 
439
  ret = _gnutls_rnd (GNUTLS_RND_RANDOM,
 
440
                     session->internals.session_ticket_IV, IV_SIZE);
 
441
  if (ret < 0)
 
442
    {
 
443
      gnutls_assert ();
 
444
      return ret;
 
445
    }
 
446
 
 
447
  session->internals.session_ticket_key =
 
448
    (struct gnutls_session_ticket_key_st *) key->data;
 
449
  session->internals.session_ticket_enable = 1;
 
450
  return 0;
 
451
}
 
452
 
 
453
int
 
454
_gnutls_send_new_session_ticket (gnutls_session_t session, int again)
 
455
{
 
456
  uint8_t *data = NULL, *p;
 
457
  int data_size = 0;
 
458
  int ret;
 
459
  struct ticket ticket;
 
460
  uint16_t ticket_len;
 
461
  gnutls_cipher_algorithm_t write_bulk_cipher_algorithm;
 
462
  gnutls_mac_algorithm_t write_mac_algorithm;
 
463
  gnutls_compression_method_t write_compression_algorithm;
 
464
 
 
465
#define SAVE_WRITE_SECURITY_PARAMETERS                                  \
 
466
  do                                                                    \
 
467
    {                                                                   \
 
468
      write_bulk_cipher_algorithm =                                     \
 
469
        session->security_parameters.write_bulk_cipher_algorithm;       \
 
470
      write_mac_algorithm =                                             \
 
471
        session->security_parameters.write_mac_algorithm;               \
 
472
      write_compression_algorithm =                                     \
 
473
        session->security_parameters.write_compression_algorithm;       \
 
474
    }                                                                   \
 
475
  while (0)
 
476
 
 
477
#define RESTORE_WRITE_SECURITY_PARAMETERS                               \
 
478
  do                                                                    \
 
479
    {                                                                   \
 
480
      session->security_parameters.write_bulk_cipher_algorithm =        \
 
481
        write_bulk_cipher_algorithm;                                    \
 
482
      session->security_parameters.write_mac_algorithm =                \
 
483
        write_mac_algorithm;                                            \
 
484
      session->security_parameters.write_compression_algorithm =        \
 
485
        write_compression_algorithm;                                    \
 
486
    }                                                                   \
 
487
  while (0)
 
488
 
 
489
  if (again == 0)
 
490
    {
 
491
      /* XXX: Temporarily set write algorithms to be used.
 
492
         _gnutls_write_connection_state_init() does this job, but it also
 
493
         triggers encryption, while NewSessionTicket should not be
 
494
         encrypted in the record layer. */
 
495
      SAVE_WRITE_SECURITY_PARAMETERS;
 
496
      ret = _gnutls_set_write_cipher (session,
 
497
                                      _gnutls_cipher_suite_get_cipher_algo
 
498
                                      (&session->
 
499
                                       security_parameters.current_cipher_suite));
 
500
      if (ret < 0)
 
501
        return ret;
 
502
      ret = _gnutls_set_write_mac (session,
 
503
                                   _gnutls_cipher_suite_get_mac_algo
 
504
                                   (&session->
 
505
                                    security_parameters.current_cipher_suite));
 
506
      if (ret < 0)
 
507
        return ret;
 
508
      ret = _gnutls_set_write_compression (session,
 
509
                                           session->
 
510
                                           internals.compression_method);
 
511
      if (ret < 0)
 
512
        return ret;
 
513
 
 
514
      ret = encrypt_ticket (session, &ticket);
 
515
      RESTORE_WRITE_SECURITY_PARAMETERS;
 
516
      if (ret < 0)
 
517
        {
 
518
          gnutls_assert ();
 
519
          return ret;
 
520
        }
 
521
 
 
522
      ticket_len = KEY_NAME_SIZE + IV_SIZE + 2 + ticket.encrypted_state_len
 
523
        + MAC_SIZE;
 
524
 
 
525
      data = gnutls_malloc (4 + 2 + ticket_len);
 
526
      if (!data)
 
527
        {
 
528
          gnutls_assert ();
 
529
          gnutls_free (ticket.encrypted_state);
 
530
          return GNUTLS_E_MEMORY_ERROR;
 
531
        }
 
532
 
 
533
      p = data;
 
534
      /* FIXME: ticket lifetime is fixed to 10 days, which should be
 
535
         customizable. */
 
536
      _gnutls_write_uint32 (864000, p);
 
537
      p += 4;
 
538
 
 
539
      _gnutls_write_uint16 (ticket_len, p);
 
540
      p += 2;
 
541
 
 
542
      memcpy (p, ticket.key_name, KEY_NAME_SIZE);
 
543
      p += KEY_NAME_SIZE;
 
544
 
 
545
      memcpy (p, ticket.IV, IV_SIZE);
 
546
      p += IV_SIZE;
 
547
 
 
548
      _gnutls_write_uint16 (ticket.encrypted_state_len, p);
 
549
      p += 2;
 
550
 
 
551
      memcpy (p, ticket.encrypted_state, ticket.encrypted_state_len);
 
552
      gnutls_free (ticket.encrypted_state);
 
553
      p += ticket.encrypted_state_len;
 
554
 
 
555
      memcpy (p, ticket.mac, MAC_SIZE);
 
556
      p += MAC_SIZE;
 
557
 
 
558
      data_size = p - data;
 
559
    }
 
560
 
 
561
  ret = _gnutls_send_handshake (session, data_size ? data : NULL, data_size,
 
562
                                GNUTLS_HANDSHAKE_NEW_SESSION_TICKET);
 
563
  gnutls_free (data);
 
564
 
 
565
  return ret;
 
566
}
 
567
 
 
568
int
 
569
_gnutls_recv_new_session_ticket (gnutls_session_t session)
 
570
{
 
571
  uint8_t *data = NULL, *p;
 
572
  int data_size;
 
573
  uint32_t lifetime_hint;
 
574
  uint16_t ticket_len;
 
575
  int ret;
 
576
 
 
577
  ret = _gnutls_recv_handshake (session, &data, &data_size,
 
578
                                GNUTLS_HANDSHAKE_NEW_SESSION_TICKET,
 
579
                                MANDATORY_PACKET);
 
580
  if (ret < 0)
 
581
    {
 
582
      gnutls_assert ();
 
583
      return ret;
 
584
    }
 
585
 
 
586
  p = data;
 
587
  DECR_LENGTH_COM (data_size, 4, goto error);
 
588
  lifetime_hint = _gnutls_read_uint32 (p);
 
589
  p += 4;
 
590
 
 
591
  DECR_LENGTH_COM (data_size, 2, goto error);
 
592
  ticket_len = _gnutls_read_uint16 (p);
 
593
  p += 2;
 
594
 
 
595
  DECR_LENGTH_COM (data_size, ticket_len, goto error);
 
596
  session->security_parameters.extensions.session_ticket =
 
597
    gnutls_realloc (session->security_parameters.extensions.session_ticket,
 
598
                    ticket_len);
 
599
  if (!session->security_parameters.extensions.session_ticket)
 
600
    {
 
601
      gnutls_assert ();
 
602
      gnutls_free (data);
 
603
      return GNUTLS_E_MEMORY_ERROR;
 
604
    }
 
605
  memcpy (session->security_parameters.extensions.session_ticket,
 
606
          p, ticket_len);
 
607
  gnutls_free (data);
 
608
  session->security_parameters.extensions.session_ticket_len = ticket_len;
 
609
 
 
610
  /* Discard the current session ID.  (RFC5077 3.4) */
 
611
  ret = _gnutls_generate_session_id (session->security_parameters.session_id,
 
612
                                     &session->
 
613
                                     security_parameters.session_id_size);
 
614
  if (ret < 0)
 
615
    {
 
616
      gnutls_assert ();
 
617
      gnutls_free (session->security_parameters.extensions.session_ticket);
 
618
      return GNUTLS_E_INTERNAL_ERROR;
 
619
    }
 
620
  return 0;
 
621
 
 
622
error:
 
623
  gnutls_free (data);
 
624
  return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
 
625
}
 
626
 
 
627
#endif