~ubuntu-branches/ubuntu/quantal/gnutls26/quantal-security

« back to all changes in this revision

Viewing changes to lib/gnutls_constate.c

  • Committer: Package Import Robot
  • Author(s): Andreas Metzler
  • Date: 2011-10-01 15:28:13 UTC
  • mfrom: (12.1.20 sid)
  • Revision ID: package-import@ubuntu.com-20111001152813-yygm1c4cxonfxhzy
Tags: 2.12.11-1
* New upstream version.
  + Allow CA importing of 0 certificates to succeed. Closes: #640639
* Add libp11-kit-dev to libgnutls-dev dependencies. (see #643811)
* [20_guiledocstring.diff] guile: Fix docstring extraction with CPP 4.5+.

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
#include <gnutls_num.h>
36
36
#include <gnutls_datum.h>
37
37
#include <gnutls_state.h>
 
38
#include <gnutls_extensions.h>
 
39
#include <gnutls_buffers.h>
38
40
 
39
41
static const char keyexp[] = "key expansion";
40
42
static const int keyexp_length = sizeof (keyexp) - 1;
56
58
 * (session->cipher_specs)
57
59
 */
58
60
static int
59
 
_gnutls_set_keys (gnutls_session_t session, int hash_size, int IV_size,
60
 
                  int key_size, int export_flag)
 
61
_gnutls_set_keys (gnutls_session_t session, record_parameters_st * params,
 
62
                  int hash_size, int IV_size, int key_size, int export_flag)
61
63
{
62
64
  /* FIXME: This function is too long
63
65
   */
68
70
  char buf[65];
69
71
  /* avoid using malloc */
70
72
  opaque key_block[2 * MAX_HASH_SIZE + 2 * MAX_CIPHER_KEY_SIZE +
71
 
                   2 * MAX_CIPHER_BLOCK_SIZE];
 
73
                   2 * MAX_CIPHER_BLOCK_SIZE];
 
74
  record_state_st *client_write, *server_write;
72
75
 
73
 
  if (session->cipher_specs.generated_keys != 0)
74
 
    {
75
 
      /* keys have already been generated.
76
 
       * reset generated_keys and exit normally.
77
 
       */
78
 
      session->cipher_specs.generated_keys = 0;
79
 
      return 0;
80
 
    }
 
76
  client_write =
 
77
    session->security_parameters.entity ==
 
78
    GNUTLS_CLIENT ? &params->write : &params->read;
 
79
  server_write =
 
80
    session->security_parameters.entity ==
 
81
    GNUTLS_SERVER ? &params->write : &params->read;
81
82
 
82
83
  block_size = 2 * hash_size + 2 * key_size;
83
84
  if (export_flag == 0)
84
85
    block_size += 2 * IV_size;
85
86
 
86
87
  memcpy (rnd, session->security_parameters.server_random,
87
 
          GNUTLS_RANDOM_SIZE);
 
88
          GNUTLS_RANDOM_SIZE);
88
89
  memcpy (&rnd[GNUTLS_RANDOM_SIZE],
89
 
          session->security_parameters.client_random, GNUTLS_RANDOM_SIZE);
 
90
          session->security_parameters.client_random, GNUTLS_RANDOM_SIZE);
90
91
 
91
92
  memcpy (rrnd, session->security_parameters.client_random,
92
 
          GNUTLS_RANDOM_SIZE);
 
93
          GNUTLS_RANDOM_SIZE);
93
94
  memcpy (&rrnd[GNUTLS_RANDOM_SIZE],
94
 
          session->security_parameters.server_random, GNUTLS_RANDOM_SIZE);
 
95
          session->security_parameters.server_random, GNUTLS_RANDOM_SIZE);
95
96
 
96
97
  if (session->security_parameters.version == GNUTLS_SSL3)
97
 
    {                           /* SSL 3 */
 
98
    {                           /* SSL 3 */
98
99
      ret =
99
 
        _gnutls_ssl3_generate_random
100
 
        (session->security_parameters.master_secret, GNUTLS_MASTER_SIZE, rnd,
101
 
         2 * GNUTLS_RANDOM_SIZE, block_size, key_block);
 
100
        _gnutls_ssl3_generate_random
 
101
        (session->security_parameters.master_secret, GNUTLS_MASTER_SIZE, rnd,
 
102
         2 * GNUTLS_RANDOM_SIZE, block_size, key_block);
102
103
    }
103
104
  else
104
 
    {                           /* TLS 1.0 */
 
105
    {                           /* TLS 1.0 */
105
106
      ret =
106
 
        _gnutls_PRF (session, session->security_parameters.master_secret,
107
 
                     GNUTLS_MASTER_SIZE, keyexp, keyexp_length,
108
 
                     rnd, 2 * GNUTLS_RANDOM_SIZE, block_size, key_block);
 
107
        _gnutls_PRF (session, session->security_parameters.master_secret,
 
108
                     GNUTLS_MASTER_SIZE, keyexp, keyexp_length,
 
109
                     rnd, 2 * GNUTLS_RANDOM_SIZE, block_size, key_block);
109
110
    }
110
111
 
111
112
  if (ret < 0)
112
 
    {
113
 
      gnutls_assert ();
114
 
      return ret;
115
 
    }
 
113
    return gnutls_assert_val (ret);
116
114
 
117
115
  _gnutls_hard_log ("INT: KEY BLOCK[%d]: %s\n", block_size,
118
 
                    _gnutls_bin2hex (key_block, block_size, buf,
119
 
                                     sizeof (buf)));
120
 
 
121
 
  _gnutls_free_datum (&session->cipher_specs.server_write_mac_secret);
122
 
  _gnutls_free_datum (&session->cipher_specs.client_write_mac_secret);
123
 
  _gnutls_free_datum (&session->cipher_specs.server_write_IV);
124
 
  _gnutls_free_datum (&session->cipher_specs.client_write_IV);
125
 
  _gnutls_free_datum (&session->cipher_specs.server_write_key);
126
 
  _gnutls_free_datum (&session->cipher_specs.client_write_key);
 
116
                    _gnutls_bin2hex (key_block, block_size, buf,
 
117
                                     sizeof (buf), NULL));
127
118
 
128
119
  pos = 0;
129
120
  if (hash_size > 0)
130
121
    {
131
122
 
132
123
      if (_gnutls_sset_datum
133
 
          (&session->cipher_specs.client_write_mac_secret,
134
 
           &key_block[pos], hash_size) < 0)
135
 
        {
136
 
          gnutls_assert ();
137
 
          return GNUTLS_E_MEMORY_ERROR;
138
 
        }
 
124
          (&client_write->mac_secret, &key_block[pos], hash_size) < 0)
 
125
        return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);
 
126
 
139
127
      pos += hash_size;
140
128
 
141
129
      if (_gnutls_sset_datum
142
 
          (&session->cipher_specs.server_write_mac_secret,
143
 
           &key_block[pos], hash_size) < 0)
144
 
        {
145
 
          gnutls_assert ();
146
 
          return GNUTLS_E_MEMORY_ERROR;
147
 
        }
 
130
          (&server_write->mac_secret, &key_block[pos], hash_size) < 0)
 
131
        return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);
 
132
 
148
133
      pos += hash_size;
149
134
    }
150
135
 
156
141
      int client_write_key_size, server_write_key_size;
157
142
 
158
143
      if (export_flag == 0)
159
 
        {
160
 
          client_write_key = &key_block[pos];
161
 
          client_write_key_size = key_size;
162
 
 
163
 
          pos += key_size;
164
 
 
165
 
          server_write_key = &key_block[pos];
166
 
          server_write_key_size = key_size;
167
 
 
168
 
          pos += key_size;
169
 
 
170
 
        }
 
144
        {
 
145
          client_write_key = &key_block[pos];
 
146
          client_write_key_size = key_size;
 
147
 
 
148
          pos += key_size;
 
149
 
 
150
          server_write_key = &key_block[pos];
 
151
          server_write_key_size = key_size;
 
152
 
 
153
          pos += key_size;
 
154
 
 
155
        }
171
156
      else
172
 
        {                       /* export */
173
 
          client_write_key = key1;
174
 
          server_write_key = key2;
175
 
 
176
 
          /* generate the final keys */
177
 
 
178
 
          if (session->security_parameters.version == GNUTLS_SSL3)
179
 
            {                   /* SSL 3 */
180
 
              ret =
181
 
                _gnutls_ssl3_hash_md5 (&key_block[pos],
182
 
                                       key_size, rrnd,
183
 
                                       2 * GNUTLS_RANDOM_SIZE,
184
 
                                       EXPORT_FINAL_KEY_SIZE,
185
 
                                       client_write_key);
186
 
 
187
 
            }
188
 
          else
189
 
            {                   /* TLS 1.0 */
190
 
              ret =
191
 
                _gnutls_PRF (session, &key_block[pos], key_size,
192
 
                             cliwrite, cliwrite_length,
193
 
                             rrnd,
194
 
                             2 * GNUTLS_RANDOM_SIZE,
195
 
                             EXPORT_FINAL_KEY_SIZE, client_write_key);
196
 
            }
197
 
 
198
 
          if (ret < 0)
199
 
            {
200
 
              gnutls_assert ();
201
 
              return ret;
202
 
            }
203
 
 
204
 
          client_write_key_size = EXPORT_FINAL_KEY_SIZE;
205
 
          pos += key_size;
206
 
 
207
 
          if (session->security_parameters.version == GNUTLS_SSL3)
208
 
            {                   /* SSL 3 */
209
 
              ret =
210
 
                _gnutls_ssl3_hash_md5 (&key_block[pos], key_size,
211
 
                                       rnd, 2 * GNUTLS_RANDOM_SIZE,
212
 
                                       EXPORT_FINAL_KEY_SIZE,
213
 
                                       server_write_key);
214
 
            }
215
 
          else
216
 
            {                   /* TLS 1.0 */
217
 
              ret =
218
 
                _gnutls_PRF (session, &key_block[pos], key_size,
219
 
                             servwrite, servwrite_length,
220
 
                             rrnd, 2 * GNUTLS_RANDOM_SIZE,
221
 
                             EXPORT_FINAL_KEY_SIZE, server_write_key);
222
 
            }
223
 
 
224
 
          if (ret < 0)
225
 
            {
226
 
              gnutls_assert ();
227
 
              return ret;
228
 
            }
229
 
 
230
 
          server_write_key_size = EXPORT_FINAL_KEY_SIZE;
231
 
          pos += key_size;
232
 
        }
 
157
        {                       /* export */
 
158
          client_write_key = key1;
 
159
          server_write_key = key2;
 
160
 
 
161
          /* generate the final keys */
 
162
 
 
163
          if (session->security_parameters.version == GNUTLS_SSL3)
 
164
            {                   /* SSL 3 */
 
165
              ret =
 
166
                _gnutls_ssl3_hash_md5 (&key_block[pos],
 
167
                                       key_size, rrnd,
 
168
                                       2 * GNUTLS_RANDOM_SIZE,
 
169
                                       EXPORT_FINAL_KEY_SIZE,
 
170
                                       client_write_key);
 
171
 
 
172
            }
 
173
          else
 
174
            {                   /* TLS 1.0 */
 
175
              ret =
 
176
                _gnutls_PRF (session, &key_block[pos], key_size,
 
177
                             cliwrite, cliwrite_length,
 
178
                             rrnd,
 
179
                             2 * GNUTLS_RANDOM_SIZE,
 
180
                             EXPORT_FINAL_KEY_SIZE, client_write_key);
 
181
            }
 
182
 
 
183
          if (ret < 0)
 
184
            return gnutls_assert_val (ret);
 
185
 
 
186
          client_write_key_size = EXPORT_FINAL_KEY_SIZE;
 
187
          pos += key_size;
 
188
 
 
189
          if (session->security_parameters.version == GNUTLS_SSL3)
 
190
            {                   /* SSL 3 */
 
191
              ret =
 
192
                _gnutls_ssl3_hash_md5 (&key_block[pos], key_size,
 
193
                                       rnd, 2 * GNUTLS_RANDOM_SIZE,
 
194
                                       EXPORT_FINAL_KEY_SIZE,
 
195
                                       server_write_key);
 
196
            }
 
197
          else
 
198
            {                   /* TLS 1.0 */
 
199
              ret =
 
200
                _gnutls_PRF (session, &key_block[pos], key_size,
 
201
                             servwrite, servwrite_length,
 
202
                             rrnd, 2 * GNUTLS_RANDOM_SIZE,
 
203
                             EXPORT_FINAL_KEY_SIZE, server_write_key);
 
204
            }
 
205
 
 
206
          if (ret < 0)
 
207
            return gnutls_assert_val (ret);
 
208
 
 
209
          server_write_key_size = EXPORT_FINAL_KEY_SIZE;
 
210
          pos += key_size;
 
211
        }
233
212
 
234
213
      if (_gnutls_sset_datum
235
 
          (&session->cipher_specs.client_write_key,
236
 
           client_write_key, client_write_key_size) < 0)
237
 
        {
238
 
          gnutls_assert ();
239
 
          return GNUTLS_E_MEMORY_ERROR;
240
 
        }
 
214
          (&client_write->key, client_write_key, client_write_key_size) < 0)
 
215
        return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);
 
216
 
241
217
      _gnutls_hard_log ("INT: CLIENT WRITE KEY [%d]: %s\n",
242
 
                        client_write_key_size,
243
 
                        _gnutls_bin2hex (client_write_key,
244
 
                                         client_write_key_size, buf,
245
 
                                         sizeof (buf)));
 
218
                        client_write_key_size,
 
219
                        _gnutls_bin2hex (client_write_key,
 
220
                                         client_write_key_size, buf,
 
221
                                         sizeof (buf), NULL));
246
222
 
247
223
      if (_gnutls_sset_datum
248
 
          (&session->cipher_specs.server_write_key,
249
 
           server_write_key, server_write_key_size) < 0)
250
 
        {
251
 
          gnutls_assert ();
252
 
          return GNUTLS_E_MEMORY_ERROR;
253
 
        }
 
224
          (&server_write->key, server_write_key, server_write_key_size) < 0)
 
225
        return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);
254
226
 
255
227
      _gnutls_hard_log ("INT: SERVER WRITE KEY [%d]: %s\n",
256
 
                        server_write_key_size,
257
 
                        _gnutls_bin2hex (server_write_key,
258
 
                                         server_write_key_size, buf,
259
 
                                         sizeof (buf)));
 
228
                        server_write_key_size,
 
229
                        _gnutls_bin2hex (server_write_key,
 
230
                                         server_write_key_size, buf,
 
231
                                         sizeof (buf), NULL));
260
232
 
261
233
    }
262
234
 
266
238
  if (IV_size > 0 && export_flag == 0)
267
239
    {
268
240
      if (_gnutls_sset_datum
269
 
          (&session->cipher_specs.client_write_IV, &key_block[pos],
270
 
           IV_size) < 0)
271
 
        {
272
 
          gnutls_assert ();
273
 
          return GNUTLS_E_MEMORY_ERROR;
274
 
        }
 
241
          (&client_write->IV, &key_block[pos], IV_size) < 0)
 
242
        return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);
 
243
 
275
244
      pos += IV_size;
276
245
 
277
246
      if (_gnutls_sset_datum
278
 
          (&session->cipher_specs.server_write_IV, &key_block[pos],
279
 
           IV_size) < 0)
280
 
        {
281
 
          gnutls_assert ();
282
 
          return GNUTLS_E_MEMORY_ERROR;
283
 
        }
 
247
          (&server_write->IV, &key_block[pos], IV_size) < 0)
 
248
        return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);
 
249
 
284
250
      pos += IV_size;
285
251
 
286
252
    }
289
255
      opaque iv_block[MAX_CIPHER_BLOCK_SIZE * 2];
290
256
 
291
257
      if (session->security_parameters.version == GNUTLS_SSL3)
292
 
        {                       /* SSL 3 */
293
 
          ret = _gnutls_ssl3_hash_md5 ("", 0,
294
 
                                       rrnd, GNUTLS_RANDOM_SIZE * 2,
295
 
                                       IV_size, iv_block);
296
 
 
297
 
          if (ret < 0)
298
 
            {
299
 
              gnutls_assert ();
300
 
              return ret;
301
 
            }
302
 
 
303
 
          ret = _gnutls_ssl3_hash_md5 ("", 0, rnd,
304
 
                                       GNUTLS_RANDOM_SIZE * 2,
305
 
                                       IV_size, &iv_block[IV_size]);
306
 
 
307
 
        }
 
258
        {                       /* SSL 3 */
 
259
          ret = _gnutls_ssl3_hash_md5 ("", 0,
 
260
                                       rrnd, GNUTLS_RANDOM_SIZE * 2,
 
261
                                       IV_size, iv_block);
 
262
 
 
263
          if (ret < 0)
 
264
            return gnutls_assert_val (ret);
 
265
 
 
266
 
 
267
          ret = _gnutls_ssl3_hash_md5 ("", 0, rnd,
 
268
                                       GNUTLS_RANDOM_SIZE * 2,
 
269
                                       IV_size, &iv_block[IV_size]);
 
270
 
 
271
        }
308
272
      else
309
 
        {                       /* TLS 1.0 */
310
 
          ret = _gnutls_PRF (session, "", 0,
311
 
                             ivblock, ivblock_length, rrnd,
312
 
                             2 * GNUTLS_RANDOM_SIZE, IV_size * 2, iv_block);
313
 
        }
 
273
        {                       /* TLS 1.0 */
 
274
          ret = _gnutls_PRF (session, "", 0,
 
275
                             ivblock, ivblock_length, rrnd,
 
276
                             2 * GNUTLS_RANDOM_SIZE, IV_size * 2, iv_block);
 
277
        }
314
278
 
315
279
      if (ret < 0)
316
 
        {
317
 
          gnutls_assert ();
318
 
          return ret;
319
 
        }
320
 
 
321
 
      if (_gnutls_sset_datum
322
 
          (&session->cipher_specs.client_write_IV, iv_block, IV_size) < 0)
323
 
        {
324
 
          gnutls_assert ();
325
 
          return GNUTLS_E_MEMORY_ERROR;
326
 
        }
327
 
 
328
 
      if (_gnutls_sset_datum
329
 
          (&session->cipher_specs.server_write_IV,
330
 
           &iv_block[IV_size], IV_size) < 0)
331
 
        {
332
 
          gnutls_assert ();
333
 
          return GNUTLS_E_MEMORY_ERROR;
334
 
        }
335
 
    }
336
 
 
337
 
  session->cipher_specs.generated_keys = 1;
338
 
 
339
 
  return 0;
340
 
}
341
 
 
342
 
static int
343
 
_gnutls_set_read_keys (gnutls_session_t session)
344
 
{
345
 
  int hash_size;
346
 
  int IV_size;
347
 
  int key_size, export_flag;
348
 
  gnutls_cipher_algorithm_t algo;
349
 
  gnutls_mac_algorithm_t mac_algo;
350
 
 
351
 
  mac_algo = session->security_parameters.read_mac_algorithm;
352
 
  algo = session->security_parameters.read_bulk_cipher_algorithm;
353
 
 
354
 
  hash_size = _gnutls_hash_get_algo_len (mac_algo);
355
 
  IV_size = _gnutls_cipher_get_iv_size (algo);
356
 
  key_size = gnutls_cipher_get_key_size (algo);
357
 
  export_flag = _gnutls_cipher_get_export_flag (algo);
358
 
 
359
 
  return _gnutls_set_keys (session, hash_size, IV_size, key_size,
360
 
                           export_flag);
361
 
}
362
 
 
363
 
static int
364
 
_gnutls_set_write_keys (gnutls_session_t session)
365
 
{
366
 
  int hash_size;
367
 
  int IV_size;
368
 
  int key_size, export_flag;
369
 
  gnutls_cipher_algorithm_t algo;
370
 
  gnutls_mac_algorithm_t mac_algo;
371
 
 
372
 
  mac_algo = session->security_parameters.write_mac_algorithm;
373
 
  algo = session->security_parameters.write_bulk_cipher_algorithm;
374
 
 
375
 
  hash_size = _gnutls_hash_get_algo_len (mac_algo);
376
 
  IV_size = _gnutls_cipher_get_iv_size (algo);
377
 
  key_size = gnutls_cipher_get_key_size (algo);
378
 
  export_flag = _gnutls_cipher_get_export_flag (algo);
379
 
 
380
 
  return _gnutls_set_keys (session, hash_size, IV_size, key_size,
381
 
                           export_flag);
382
 
}
383
 
 
384
 
#define CPY_EXTENSIONS \
385
 
        gnutls_free(dst->extensions.session_ticket); \
386
 
        gnutls_free(dst->extensions.oprfi_client); \
387
 
        gnutls_free(dst->extensions.oprfi_server); \
388
 
        memcpy(&dst->extensions.server_names, &src->extensions, sizeof(src->extensions)); \
389
 
        memset(&src->extensions, 0, sizeof(src->extensions))    /* avoid duplicate free's */
 
280
        return gnutls_assert_val (ret);
 
281
 
 
282
      if (_gnutls_sset_datum (&client_write->IV, iv_block, IV_size) < 0)
 
283
        return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);
 
284
 
 
285
      if (_gnutls_sset_datum
 
286
          (&server_write->IV, &iv_block[IV_size], IV_size) < 0)
 
287
        return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);
 
288
    }
 
289
 
 
290
  return 0;
 
291
}
 
292
 
 
293
static int
 
294
_gnutls_init_record_state (record_parameters_st * params, int read,
 
295
                           record_state_st * state)
 
296
{
 
297
  int ret;
 
298
 
 
299
  ret = _gnutls_cipher_init (&state->cipher_state,
 
300
                             params->cipher_algorithm,
 
301
                             &state->key, &state->IV);
 
302
  if (ret < 0 && params->cipher_algorithm != GNUTLS_CIPHER_NULL)
 
303
    return gnutls_assert_val (ret);
 
304
 
 
305
  state->compression_state =
 
306
    _gnutls_comp_init (params->compression_algorithm, read);
 
307
 
 
308
  if (state->compression_state == GNUTLS_COMP_FAILED)
 
309
    return gnutls_assert_val (GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM);
 
310
 
 
311
  return 0;
 
312
}
 
313
 
 
314
int
 
315
_gnutls_epoch_set_cipher_suite (gnutls_session_t session,
 
316
                                int epoch_rel, cipher_suite_st * suite)
 
317
{
 
318
  gnutls_cipher_algorithm_t cipher_algo;
 
319
  gnutls_mac_algorithm_t mac_algo;
 
320
  record_parameters_st *params;
 
321
  int ret;
 
322
 
 
323
  ret = _gnutls_epoch_get (session, epoch_rel, &params);
 
324
  if (ret < 0)
 
325
    return gnutls_assert_val (ret);
 
326
 
 
327
  if (params->initialized
 
328
      || params->cipher_algorithm != GNUTLS_CIPHER_UNKNOWN
 
329
      || params->mac_algorithm != GNUTLS_MAC_UNKNOWN)
 
330
    return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR);
 
331
 
 
332
  cipher_algo = _gnutls_cipher_suite_get_cipher_algo (suite);
 
333
  mac_algo = _gnutls_cipher_suite_get_mac_algo (suite);
 
334
 
 
335
  if (_gnutls_cipher_is_ok (cipher_algo) != 0
 
336
      || _gnutls_mac_is_ok (mac_algo) != 0)
 
337
    return gnutls_assert_val (GNUTLS_E_UNWANTED_ALGORITHM);
 
338
 
 
339
  params->cipher_algorithm = cipher_algo;
 
340
  params->mac_algorithm = mac_algo;
 
341
 
 
342
  return 0;
 
343
}
 
344
 
 
345
int
 
346
_gnutls_epoch_set_compression (gnutls_session_t session,
 
347
                               int epoch_rel,
 
348
                               gnutls_compression_method_t comp_algo)
 
349
{
 
350
  record_parameters_st *params;
 
351
  int ret;
 
352
 
 
353
  ret = _gnutls_epoch_get (session, epoch_rel, &params);
 
354
  if (ret < 0)
 
355
    return gnutls_assert_val (ret);
 
356
 
 
357
  if (params->initialized
 
358
      || params->compression_algorithm != GNUTLS_COMP_UNKNOWN)
 
359
    return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR);
 
360
 
 
361
  if (_gnutls_compression_is_ok (comp_algo) != 0)
 
362
    return gnutls_assert_val (GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM);
 
363
 
 
364
  params->compression_algorithm = comp_algo;
 
365
 
 
366
  return 0;
 
367
}
 
368
 
 
369
void
 
370
_gnutls_epoch_set_null_algos (gnutls_session_t session,
 
371
                              record_parameters_st * params)
 
372
{
 
373
  /* This is only called on startup. We are extra paranoid about this
 
374
     because it may cause unencrypted application data to go out on
 
375
     the wire. */
 
376
  if (params->initialized || params->epoch != 0)
 
377
    {
 
378
      gnutls_assert ();
 
379
      return;
 
380
    }
 
381
 
 
382
  params->cipher_algorithm = GNUTLS_CIPHER_NULL;
 
383
  params->mac_algorithm = GNUTLS_MAC_NULL;
 
384
  params->compression_algorithm = GNUTLS_COMP_NULL;
 
385
  params->initialized = 1;
 
386
}
 
387
 
 
388
int
 
389
_gnutls_epoch_set_keys (gnutls_session_t session, uint16_t epoch)
 
390
{
 
391
  int hash_size;
 
392
  int IV_size;
 
393
  int key_size, export_flag;
 
394
  gnutls_cipher_algorithm_t cipher_algo;
 
395
  gnutls_mac_algorithm_t mac_algo;
 
396
  gnutls_compression_method_t comp_algo;
 
397
  record_parameters_st *params;
 
398
  int ret;
 
399
 
 
400
  ret = _gnutls_epoch_get (session, epoch, &params);
 
401
  if (ret < 0)
 
402
    return gnutls_assert_val (ret);
 
403
 
 
404
  if (params->initialized)
 
405
    return 0;
 
406
 
 
407
  _gnutls_record_log
 
408
    ("REC[%p]: Initializing epoch #%u\n", session, params->epoch);
 
409
 
 
410
  cipher_algo = params->cipher_algorithm;
 
411
  mac_algo = params->mac_algorithm;
 
412
  comp_algo = params->compression_algorithm;
 
413
 
 
414
  if (_gnutls_cipher_is_ok (cipher_algo) != 0
 
415
      || _gnutls_mac_is_ok (mac_algo) != 0)
 
416
    return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR);
 
417
 
 
418
  if (_gnutls_compression_is_ok (comp_algo) != 0)
 
419
    return gnutls_assert_val (GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM);
 
420
 
 
421
  IV_size = _gnutls_cipher_get_iv_size (cipher_algo);
 
422
  key_size = gnutls_cipher_get_key_size (cipher_algo);
 
423
  export_flag = _gnutls_cipher_get_export_flag (cipher_algo);
 
424
  hash_size = _gnutls_hash_get_algo_len (mac_algo);
 
425
 
 
426
  ret = _gnutls_set_keys
 
427
    (session, params, hash_size, IV_size, key_size, export_flag);
 
428
  if (ret < 0)
 
429
    return gnutls_assert_val (ret);
 
430
 
 
431
  ret = _gnutls_init_record_state (params, 1, &params->read);
 
432
  if (ret < 0)
 
433
    return gnutls_assert_val (ret);
 
434
 
 
435
  ret = _gnutls_init_record_state (params, 0, &params->write);
 
436
  if (ret < 0)
 
437
    return gnutls_assert_val (ret);
 
438
 
 
439
  _gnutls_record_log ("REC[%p]: Epoch #%u ready\n", session, params->epoch);
 
440
 
 
441
  params->initialized = 1;
 
442
  return 0;
 
443
}
 
444
 
390
445
 
391
446
#define CPY_COMMON dst->entity = src->entity; \
392
447
        dst->kx_algorithm = src->kx_algorithm; \
400
455
        dst->timestamp = src->timestamp; \
401
456
        dst->max_record_recv_size = src->max_record_recv_size; \
402
457
        dst->max_record_send_size = src->max_record_send_size; \
403
 
        dst->version = src->version; \
404
 
        memcpy( &dst->inner_secret, &src->inner_secret, GNUTLS_MASTER_SIZE)
405
 
 
406
 
static void
407
 
_gnutls_cpy_read_security_parameters (security_parameters_st *
408
 
                                      dst, security_parameters_st * src)
409
 
{
410
 
  CPY_COMMON;
411
 
 
412
 
  dst->read_bulk_cipher_algorithm = src->read_bulk_cipher_algorithm;
413
 
  dst->read_mac_algorithm = src->read_mac_algorithm;
414
 
  dst->read_compression_algorithm = src->read_compression_algorithm;
415
 
}
416
 
 
417
 
static void
418
 
_gnutls_cpy_write_security_parameters (security_parameters_st *
419
 
                                       dst, security_parameters_st * src)
420
 
{
421
 
  CPY_COMMON;
422
 
  CPY_EXTENSIONS;               /* only do once */
423
 
 
424
 
  dst->write_bulk_cipher_algorithm = src->write_bulk_cipher_algorithm;
425
 
  dst->write_mac_algorithm = src->write_mac_algorithm;
426
 
  dst->write_compression_algorithm = src->write_compression_algorithm;
 
458
        dst->version = src->version
 
459
 
 
460
static void
 
461
_gnutls_set_resumed_parameters (gnutls_session_t session)
 
462
{
 
463
  security_parameters_st *src =
 
464
    &session->internals.resumed_security_parameters;
 
465
  security_parameters_st *dst = &session->security_parameters;
 
466
 
 
467
  CPY_COMMON;
427
468
}
428
469
 
429
470
/* Sets the current connection session to conform with the
440
481
/* Setup the master secret 
441
482
 */
442
483
  if ((ret = _gnutls_generate_master (session, 0)) < 0)
443
 
    {
444
 
      gnutls_assert ();
445
 
      return ret;
446
 
    }
447
 
 
448
 
 
449
 
  return 0;
450
 
}
451
 
 
 
484
    return gnutls_assert_val (ret);
 
485
 
 
486
  return 0;
 
487
}
 
488
 
 
489
 
 
490
 
 
491
static int
 
492
_gnutls_check_algos (gnutls_session_t session,
 
493
                     cipher_suite_st * suite,
 
494
                     gnutls_compression_method_t comp_algo)
 
495
{
 
496
  gnutls_cipher_algorithm_t cipher_algo;
 
497
  gnutls_mac_algorithm_t mac_algo;
 
498
 
 
499
  cipher_algo = _gnutls_cipher_suite_get_cipher_algo (suite);
 
500
  mac_algo = _gnutls_cipher_suite_get_mac_algo (suite);
 
501
 
 
502
  if (_gnutls_cipher_is_ok (cipher_algo) != 0)
 
503
    return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR);
 
504
 
 
505
  if (_gnutls_cipher_priority (session, cipher_algo) < 0)
 
506
    return gnutls_assert_val (GNUTLS_E_UNWANTED_ALGORITHM);
 
507
 
 
508
 
 
509
  if (_gnutls_mac_is_ok (mac_algo) != 0)
 
510
    return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR);
 
511
 
 
512
  if (_gnutls_mac_priority (session, mac_algo) < 0)
 
513
    return gnutls_assert_val (GNUTLS_E_UNWANTED_ALGORITHM);
 
514
 
 
515
 
 
516
  if (_gnutls_compression_is_ok (comp_algo) != 0)
 
517
    return gnutls_assert_val (GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM);
 
518
 
 
519
  return 0;
 
520
}
452
521
 
453
522
/* Initializes the read connection session
454
523
 * (read encrypted data)
456
525
int
457
526
_gnutls_read_connection_state_init (gnutls_session_t session)
458
527
{
459
 
  int mac_size;
460
 
  int rc;
461
 
 
462
 
  _gnutls_uint64zero (session->connection_state.read_sequence_number);
463
 
 
464
 
/* Update internals from CipherSuite selected.
465
 
 * If we are resuming just copy the connection session
466
 
 */
 
528
  const uint16_t epoch_next = session->security_parameters.epoch_next;
 
529
  int ret;
 
530
 
 
531
  /* Update internals from CipherSuite selected.
 
532
   * If we are resuming just copy the connection session
 
533
   */
467
534
  if (session->internals.resumed == RESUME_FALSE)
468
535
    {
469
 
      rc = _gnutls_set_read_cipher (session,
470
 
                                    _gnutls_cipher_suite_get_cipher_algo
471
 
                                    (&session->
472
 
                                     security_parameters.current_cipher_suite));
473
 
      if (rc < 0)
474
 
        return rc;
475
 
      rc = _gnutls_set_read_mac (session,
476
 
                                 _gnutls_cipher_suite_get_mac_algo
477
 
                                 (&session->
478
 
                                  security_parameters.current_cipher_suite));
479
 
      if (rc < 0)
480
 
        return rc;
481
 
 
482
 
      rc = _gnutls_set_kx (session,
483
 
                           _gnutls_cipher_suite_get_kx_algo
484
 
                           (&session->
485
 
                            security_parameters.current_cipher_suite));
486
 
      if (rc < 0)
487
 
        return rc;
488
 
 
489
 
      rc = _gnutls_set_read_compression (session,
490
 
                                         session->
491
 
                                         internals.compression_method);
492
 
      if (rc < 0)
493
 
        return rc;
494
 
    }
495
 
  else
496
 
    {                           /* RESUME_TRUE */
497
 
      _gnutls_cpy_read_security_parameters (&session->security_parameters,
498
 
                                            &session->
499
 
                                            internals.resumed_security_parameters);
500
 
    }
501
 
 
502
 
 
503
 
  rc = _gnutls_set_read_keys (session);
504
 
  if (rc < 0)
505
 
    return rc;
 
536
      ret = _gnutls_check_algos (session,
 
537
                                 &session->
 
538
                                 security_parameters.current_cipher_suite,
 
539
                                 session->internals.compression_method);
 
540
      if (ret < 0)
 
541
        return ret;
 
542
 
 
543
      ret = _gnutls_set_kx (session,
 
544
                            _gnutls_cipher_suite_get_kx_algo
 
545
                            (&session->
 
546
                             security_parameters.current_cipher_suite));
 
547
      if (ret < 0)
 
548
        return ret;
 
549
    }
 
550
  else if (session->security_parameters.entity == GNUTLS_CLIENT)
 
551
    _gnutls_set_resumed_parameters (session);
 
552
 
 
553
  ret = _gnutls_epoch_set_keys (session, epoch_next);
 
554
  if (ret < 0)
 
555
    return ret;
506
556
 
507
557
  _gnutls_handshake_log ("HSK[%p]: Cipher Suite: %s\n",
508
 
                         session,
509
 
                         _gnutls_cipher_suite_get_name
510
 
                         (&session->
511
 
                          security_parameters.current_cipher_suite));
512
 
 
513
 
  if (_gnutls_compression_is_ok
514
 
      (session->security_parameters.read_compression_algorithm) != 0)
515
 
    {
516
 
      gnutls_assert ();
517
 
      return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
518
 
    }
519
 
 
520
 
  if (_gnutls_mac_is_ok
521
 
      (session->security_parameters.read_mac_algorithm) != 0)
522
 
    {
523
 
      gnutls_assert ();
524
 
      return GNUTLS_E_INTERNAL_ERROR;
525
 
    }
526
 
 
527
 
  /* Free all the previous keys/ sessions etc.
528
 
   */
529
 
  if (session->connection_state.read_mac_secret.data != NULL)
530
 
    _gnutls_free_datum (&session->connection_state.read_mac_secret);
531
 
 
532
 
  _gnutls_cipher_deinit (&session->connection_state.read_cipher_state);
533
 
 
534
 
  if (session->connection_state.read_compression_state != NULL)
535
 
    _gnutls_comp_deinit (session->connection_state.read_compression_state, 1);
536
 
 
537
 
 
538
 
  mac_size =
539
 
    _gnutls_hash_get_algo_len (session->
540
 
                               security_parameters.read_mac_algorithm);
541
 
 
542
 
  _gnutls_handshake_log
543
 
    ("HSK[%p]: Initializing internal [read] cipher sessions\n", session);
544
 
 
545
 
  switch (session->security_parameters.entity)
546
 
    {
547
 
    case GNUTLS_SERVER:
548
 
      /* initialize cipher session
549
 
       */
550
 
      rc = _gnutls_cipher_init (&session->connection_state.read_cipher_state,
551
 
                                session->security_parameters.
552
 
                                read_bulk_cipher_algorithm,
553
 
                                &session->cipher_specs.client_write_key,
554
 
                                &session->cipher_specs.client_write_IV);
555
 
      if (rc < 0
556
 
          && session->security_parameters.read_bulk_cipher_algorithm !=
557
 
          GNUTLS_CIPHER_NULL)
558
 
        {
559
 
          gnutls_assert ();
560
 
          return rc;
561
 
        }
562
 
 
563
 
      /* copy mac secrets from cipherspecs, to connection
564
 
       * session.
565
 
       */
566
 
      if (mac_size > 0)
567
 
        {
568
 
          if (_gnutls_sset_datum (&session->connection_state.read_mac_secret,
569
 
                                  session->
570
 
                                  cipher_specs.client_write_mac_secret.data,
571
 
                                  session->
572
 
                                  cipher_specs.client_write_mac_secret.size) <
573
 
              0)
574
 
            {
575
 
              gnutls_assert ();
576
 
              return GNUTLS_E_MEMORY_ERROR;
577
 
            }
578
 
 
579
 
        }
580
 
 
581
 
      break;
582
 
 
583
 
    case GNUTLS_CLIENT:
584
 
      rc = _gnutls_cipher_init (&session->connection_state.read_cipher_state,
585
 
                                session->security_parameters.
586
 
                                read_bulk_cipher_algorithm,
587
 
                                &session->cipher_specs.server_write_key,
588
 
                                &session->cipher_specs.server_write_IV);
589
 
 
590
 
      if (rc < 0
591
 
          && session->security_parameters.read_bulk_cipher_algorithm !=
592
 
          GNUTLS_CIPHER_NULL)
593
 
        {
594
 
          gnutls_assert ();
595
 
          return GNUTLS_E_INTERNAL_ERROR;
596
 
        }
597
 
 
598
 
 
599
 
      /* copy mac secret to connection session
600
 
       */
601
 
      if (mac_size > 0)
602
 
        {
603
 
          if (_gnutls_sset_datum (&session->connection_state.read_mac_secret,
604
 
                                  session->
605
 
                                  cipher_specs.server_write_mac_secret.data,
606
 
                                  session->
607
 
                                  cipher_specs.server_write_mac_secret.size) <
608
 
              0)
609
 
            {
610
 
              gnutls_assert ();
611
 
              return GNUTLS_E_MEMORY_ERROR;
612
 
            }
613
 
        }
614
 
 
615
 
      break;
616
 
 
617
 
    default:                    /* this check is useless */
618
 
      gnutls_assert ();
619
 
      return GNUTLS_E_INTERNAL_ERROR;
620
 
    }
621
 
 
622
 
  session->connection_state.read_compression_state =
623
 
    _gnutls_comp_init (session->
624
 
                       security_parameters.read_compression_algorithm, 1);
625
 
 
626
 
  if (session->connection_state.read_compression_state == GNUTLS_COMP_FAILED)
627
 
    {
628
 
      gnutls_assert ();
629
 
      return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
630
 
    }
 
558
                         session,
 
559
                         _gnutls_cipher_suite_get_name
 
560
                         (&session->
 
561
                          security_parameters.current_cipher_suite));
 
562
 
 
563
  session->security_parameters.epoch_read = epoch_next;
 
564
  _gnutls_epoch_gc (session);
631
565
 
632
566
  return 0;
633
567
}
640
574
int
641
575
_gnutls_write_connection_state_init (gnutls_session_t session)
642
576
{
643
 
  int mac_size;
644
 
  int rc;
645
 
 
646
 
  _gnutls_uint64zero (session->connection_state.write_sequence_number);
 
577
  const uint16_t epoch_next = session->security_parameters.epoch_next;
 
578
  int ret;
647
579
 
648
580
/* Update internals from CipherSuite selected.
649
581
 * If we are resuming just copy the connection session
650
582
 */
651
583
  if (session->internals.resumed == RESUME_FALSE)
652
584
    {
653
 
      rc = _gnutls_set_write_cipher (session,
654
 
                                     _gnutls_cipher_suite_get_cipher_algo
655
 
                                     (&session->
656
 
                                      security_parameters.current_cipher_suite));
657
 
      if (rc < 0)
658
 
        return rc;
659
 
      rc = _gnutls_set_write_mac (session,
660
 
                                  _gnutls_cipher_suite_get_mac_algo
661
 
                                  (&session->
662
 
                                   security_parameters.current_cipher_suite));
663
 
      if (rc < 0)
664
 
        return rc;
665
 
 
666
 
      rc = _gnutls_set_kx (session,
667
 
                           _gnutls_cipher_suite_get_kx_algo
668
 
                           (&session->
669
 
                            security_parameters.current_cipher_suite));
670
 
      if (rc < 0)
671
 
        return rc;
672
 
 
673
 
      rc = _gnutls_set_write_compression (session,
674
 
                                          session->
675
 
                                          internals.compression_method);
676
 
      if (rc < 0)
677
 
        return rc;
678
 
    }
679
 
  else
680
 
    {                           /* RESUME_TRUE */
681
 
      _gnutls_cpy_write_security_parameters (&session->security_parameters,
682
 
                                             &session->
683
 
                                             internals.resumed_security_parameters);
684
 
    }
685
 
 
686
 
  rc = _gnutls_set_write_keys (session);
687
 
  if (rc < 0)
688
 
    return rc;
 
585
      ret = _gnutls_check_algos (session,
 
586
                                 &session->
 
587
                                 security_parameters.current_cipher_suite,
 
588
                                 session->internals.compression_method);
 
589
      if (ret < 0)
 
590
        return ret;
 
591
 
 
592
      ret = _gnutls_set_kx (session,
 
593
                            _gnutls_cipher_suite_get_kx_algo
 
594
                            (&session->
 
595
                             security_parameters.current_cipher_suite));
 
596
      if (ret < 0)
 
597
        return ret;
 
598
    }
 
599
  else if (session->security_parameters.entity == GNUTLS_SERVER)
 
600
    _gnutls_set_resumed_parameters (session);
 
601
 
 
602
  ret = _gnutls_epoch_set_keys (session, epoch_next);
 
603
  if (ret < 0)
 
604
    return gnutls_assert_val (ret);
689
605
 
690
606
  _gnutls_handshake_log ("HSK[%p]: Cipher Suite: %s\n", session,
691
 
                         _gnutls_cipher_suite_get_name
692
 
                         (&session->
693
 
                          security_parameters.current_cipher_suite));
694
 
 
695
 
  if (_gnutls_compression_is_ok
696
 
      (session->security_parameters.write_compression_algorithm) != 0)
697
 
    {
698
 
      gnutls_assert ();
699
 
      return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
700
 
    }
701
 
 
702
 
  if (_gnutls_mac_is_ok
703
 
      (session->security_parameters.write_mac_algorithm) != 0)
704
 
    {
705
 
      gnutls_assert ();
706
 
      return GNUTLS_E_INTERNAL_ERROR;
707
 
    }
708
 
 
709
 
 
710
 
 
711
 
  /* Free all the previous keys/ sessions etc.
712
 
   */
713
 
  if (session->connection_state.write_mac_secret.data != NULL)
714
 
    _gnutls_free_datum (&session->connection_state.write_mac_secret);
715
 
 
716
 
  _gnutls_cipher_deinit (&session->connection_state.write_cipher_state);
717
 
 
718
 
  if (session->connection_state.write_compression_state != NULL)
719
 
    _gnutls_comp_deinit (session->connection_state.write_compression_state,
720
 
                         0);
721
 
 
722
 
  mac_size =
723
 
    _gnutls_hash_get_algo_len (session->
724
 
                               security_parameters.write_mac_algorithm);
 
607
                         _gnutls_cipher_suite_get_name
 
608
                         (&session->
 
609
                          security_parameters.current_cipher_suite));
725
610
 
726
611
  _gnutls_handshake_log
727
612
    ("HSK[%p]: Initializing internal [write] cipher sessions\n", session);
728
613
 
729
 
  switch (session->security_parameters.entity)
730
 
    {
731
 
    case GNUTLS_SERVER:
732
 
      /* initialize cipher session
733
 
       */
734
 
      rc = _gnutls_cipher_init (&session->connection_state.write_cipher_state,
735
 
                                session->
736
 
                                security_parameters.write_bulk_cipher_algorithm,
737
 
                                &session->cipher_specs.server_write_key,
738
 
                                &session->cipher_specs.server_write_IV);
739
 
 
740
 
      if (rc < 0
741
 
          && session->security_parameters.write_bulk_cipher_algorithm !=
742
 
          GNUTLS_CIPHER_NULL)
743
 
        {
744
 
          gnutls_assert ();
745
 
          return GNUTLS_E_INTERNAL_ERROR;
746
 
        }
747
 
 
748
 
 
749
 
      /* copy mac secrets from cipherspecs, to connection
750
 
       * session.
751
 
       */
752
 
      if (mac_size > 0)
753
 
        {
754
 
          if (_gnutls_sset_datum (&session->connection_state.write_mac_secret,
755
 
                                  session->
756
 
                                  cipher_specs.server_write_mac_secret.data,
757
 
                                  session->
758
 
                                  cipher_specs.server_write_mac_secret.size) <
759
 
              0)
760
 
            {
761
 
              gnutls_assert ();
762
 
              return GNUTLS_E_MEMORY_ERROR;
763
 
            }
764
 
 
765
 
        }
766
 
 
767
 
 
768
 
      break;
769
 
 
770
 
    case GNUTLS_CLIENT:
771
 
      rc = _gnutls_cipher_init (&session->connection_state.write_cipher_state,
772
 
                                session->
773
 
                                security_parameters.write_bulk_cipher_algorithm,
774
 
                                &session->cipher_specs.client_write_key,
775
 
                                &session->cipher_specs.client_write_IV);
776
 
 
777
 
      if (rc < 0
778
 
          && session->security_parameters.write_bulk_cipher_algorithm !=
779
 
          GNUTLS_CIPHER_NULL)
780
 
        {
781
 
          gnutls_assert ();
782
 
          return GNUTLS_E_INTERNAL_ERROR;
783
 
        }
784
 
 
785
 
      /* copy mac secret to connection session
786
 
       */
787
 
      if (mac_size > 0)
788
 
        {
789
 
          if (_gnutls_sset_datum (&session->connection_state.write_mac_secret,
790
 
                                  session->
791
 
                                  cipher_specs.client_write_mac_secret.data,
792
 
                                  session->
793
 
                                  cipher_specs.client_write_mac_secret.size) <
794
 
              0)
795
 
            {
796
 
              gnutls_assert ();
797
 
              return GNUTLS_E_MEMORY_ERROR;
798
 
            }
799
 
        }
800
 
 
801
 
      break;
802
 
 
803
 
    default:
804
 
      gnutls_assert ();
805
 
      return GNUTLS_E_INTERNAL_ERROR;
806
 
    }
807
 
 
808
 
 
809
 
  session->connection_state.write_compression_state =
810
 
    _gnutls_comp_init (session->
811
 
                       security_parameters.write_compression_algorithm, 0);
812
 
 
813
 
  if (session->connection_state.write_compression_state == GNUTLS_COMP_FAILED)
814
 
    {
815
 
      gnutls_assert ();
816
 
      return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
817
 
    }
818
 
 
819
 
  return 0;
820
 
}
821
 
 
822
 
/* Sets the specified cipher into the pending session 
823
 
 */
824
 
int
825
 
_gnutls_set_read_cipher (gnutls_session_t session,
826
 
                         gnutls_cipher_algorithm_t algo)
827
 
{
828
 
 
829
 
  if (_gnutls_cipher_is_ok (algo) == 0)
830
 
    {
831
 
      if (_gnutls_cipher_priority (session, algo) < 0)
832
 
        {
833
 
          gnutls_assert ();
834
 
          return GNUTLS_E_UNWANTED_ALGORITHM;
835
 
        }
836
 
 
837
 
      session->security_parameters.read_bulk_cipher_algorithm = algo;
838
 
 
839
 
    }
840
 
  else
841
 
    {
842
 
      gnutls_assert ();
843
 
      return GNUTLS_E_INTERNAL_ERROR;
844
 
    }
845
 
 
846
 
  return 0;
847
 
 
848
 
}
849
 
 
850
 
int
851
 
_gnutls_set_write_cipher (gnutls_session_t session,
852
 
                          gnutls_cipher_algorithm_t algo)
853
 
{
854
 
 
855
 
  if (_gnutls_cipher_is_ok (algo) == 0)
856
 
    {
857
 
      if (_gnutls_cipher_priority (session, algo) < 0)
858
 
        {
859
 
          gnutls_assert ();
860
 
          return GNUTLS_E_UNWANTED_ALGORITHM;
861
 
        }
862
 
 
863
 
      session->security_parameters.write_bulk_cipher_algorithm = algo;
864
 
 
865
 
    }
866
 
  else
867
 
    {
868
 
      gnutls_assert ();
869
 
      return GNUTLS_E_INTERNAL_ERROR;
870
 
    }
871
 
 
872
 
  return 0;
873
 
 
874
 
}
875
 
 
876
 
 
877
 
/* Sets the specified algorithm into pending compression session 
878
 
 */
879
 
int
880
 
_gnutls_set_read_compression (gnutls_session_t session,
881
 
                              gnutls_compression_method_t algo)
882
 
{
883
 
 
884
 
  if (_gnutls_compression_is_ok (algo) == 0)
885
 
    {
886
 
      session->security_parameters.read_compression_algorithm = algo;
887
 
    }
888
 
  else
889
 
    {
890
 
      gnutls_assert ();
891
 
      return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
892
 
    }
893
 
  return 0;
894
 
 
895
 
}
896
 
 
897
 
int
898
 
_gnutls_set_write_compression (gnutls_session_t session,
899
 
                               gnutls_compression_method_t algo)
900
 
{
901
 
 
902
 
  if (_gnutls_compression_is_ok (algo) == 0)
903
 
    {
904
 
      session->security_parameters.write_compression_algorithm = algo;
905
 
    }
906
 
  else
907
 
    {
908
 
      gnutls_assert ();
909
 
      return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
910
 
    }
911
 
  return 0;
912
 
 
913
 
}
914
 
 
915
 
/* Sets the specified kx algorithm into pending session 
 
614
  session->security_parameters.epoch_write = epoch_next;
 
615
  _gnutls_epoch_gc (session);
 
616
 
 
617
  return 0;
 
618
}
 
619
 
 
620
/* Sets the specified kx algorithm into pending session
916
621
 */
917
622
int
918
623
_gnutls_set_kx (gnutls_session_t session, gnutls_kx_algorithm_t algo)
923
628
      session->security_parameters.kx_algorithm = algo;
924
629
    }
925
630
  else
926
 
    {
927
 
      gnutls_assert ();
928
 
      return GNUTLS_E_INTERNAL_ERROR;
929
 
    }
 
631
    return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR);
 
632
 
930
633
  if (_gnutls_kx_priority (session, algo) < 0)
931
 
    {
932
 
      gnutls_assert ();
933
 
      /* we shouldn't get here */
934
 
      return GNUTLS_E_UNWANTED_ALGORITHM;
935
 
    }
936
 
 
937
 
  return 0;
938
 
 
939
 
}
940
 
 
941
 
/* Sets the specified mac algorithm into pending session */
942
 
int
943
 
_gnutls_set_read_mac (gnutls_session_t session, gnutls_mac_algorithm_t algo)
944
 
{
945
 
 
946
 
  if (_gnutls_mac_is_ok (algo) == 0)
947
 
    {
948
 
      session->security_parameters.read_mac_algorithm = algo;
949
 
    }
950
 
  else
951
 
    {
952
 
      gnutls_assert ();
953
 
      return GNUTLS_E_INTERNAL_ERROR;
954
 
    }
955
 
  if (_gnutls_mac_priority (session, algo) < 0)
956
 
    {
957
 
      gnutls_assert ();
958
 
      return GNUTLS_E_UNWANTED_ALGORITHM;
959
 
    }
960
 
 
961
 
 
962
 
  return 0;
963
 
 
964
 
}
965
 
 
966
 
int
967
 
_gnutls_set_write_mac (gnutls_session_t session, gnutls_mac_algorithm_t algo)
968
 
{
969
 
 
970
 
  if (_gnutls_mac_is_ok (algo) == 0)
971
 
    {
972
 
      session->security_parameters.write_mac_algorithm = algo;
973
 
    }
974
 
  else
975
 
    {
976
 
      gnutls_assert ();
977
 
      return GNUTLS_E_INTERNAL_ERROR;
978
 
    }
979
 
  if (_gnutls_mac_priority (session, algo) < 0)
980
 
    {
981
 
      gnutls_assert ();
982
 
      return GNUTLS_E_UNWANTED_ALGORITHM;
983
 
    }
984
 
 
985
 
 
986
 
  return 0;
987
 
 
 
634
    return gnutls_assert_val (GNUTLS_E_UNWANTED_ALGORITHM);
 
635
 
 
636
  return 0;
 
637
}
 
638
 
 
639
static inline int
 
640
epoch_resolve (gnutls_session_t session,
 
641
               unsigned int epoch_rel, uint16_t * epoch_out)
 
642
{
 
643
  switch (epoch_rel)
 
644
    {
 
645
    case EPOCH_READ_CURRENT:
 
646
      *epoch_out = session->security_parameters.epoch_read;
 
647
      return 0;
 
648
 
 
649
    case EPOCH_WRITE_CURRENT:
 
650
      *epoch_out = session->security_parameters.epoch_write;
 
651
      return 0;
 
652
 
 
653
    case EPOCH_NEXT:
 
654
      *epoch_out = session->security_parameters.epoch_next;
 
655
      return 0;
 
656
 
 
657
    default:
 
658
      if (epoch_rel > 0xffffu)
 
659
        return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST);
 
660
 
 
661
      *epoch_out = epoch_rel;
 
662
      return 0;
 
663
    }
 
664
}
 
665
 
 
666
static inline record_parameters_st **
 
667
epoch_get_slot (gnutls_session_t session, uint16_t epoch)
 
668
{
 
669
  uint16_t epoch_index = epoch - session->security_parameters.epoch_min;
 
670
 
 
671
  if (epoch_index >= MAX_EPOCH_INDEX)
 
672
    {
 
673
      gnutls_assert ();
 
674
      return NULL;
 
675
    }
 
676
 
 
677
  /* The slot may still be empty (NULL) */
 
678
  return &session->record_parameters[epoch_index];
 
679
}
 
680
 
 
681
int
 
682
_gnutls_epoch_get (gnutls_session_t session, unsigned int epoch_rel,
 
683
                   record_parameters_st ** params_out)
 
684
{
 
685
  uint16_t epoch;
 
686
  record_parameters_st **params;
 
687
  int ret;
 
688
 
 
689
  ret = epoch_resolve (session, epoch_rel, &epoch);
 
690
  if (ret < 0)
 
691
    return gnutls_assert_val (ret);
 
692
 
 
693
  params = epoch_get_slot (session, epoch);
 
694
  if (params == NULL || *params == NULL)
 
695
    return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST);
 
696
 
 
697
  *params_out = *params;
 
698
 
 
699
  return 0;
 
700
}
 
701
 
 
702
int
 
703
_gnutls_epoch_alloc (gnutls_session_t session, uint16_t epoch,
 
704
                     record_parameters_st ** out)
 
705
{
 
706
  record_parameters_st **slot;
 
707
 
 
708
  _gnutls_record_log ("REC[%p]: Allocating epoch #%u\n", session, epoch);
 
709
 
 
710
  slot = epoch_get_slot (session, epoch);
 
711
 
 
712
  /* If slot out of range or not empty. */
 
713
  if (slot == NULL)
 
714
    return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST);
 
715
 
 
716
  if (*slot != NULL)
 
717
    return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST);
 
718
 
 
719
  *slot = gnutls_calloc (1, sizeof (record_parameters_st));
 
720
  if (*slot == NULL)
 
721
    return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);
 
722
 
 
723
  (*slot)->epoch = epoch;
 
724
  (*slot)->cipher_algorithm = GNUTLS_CIPHER_UNKNOWN;
 
725
  (*slot)->mac_algorithm = GNUTLS_MAC_UNKNOWN;
 
726
  (*slot)->compression_algorithm = GNUTLS_COMP_UNKNOWN;
 
727
 
 
728
  if (out != NULL)
 
729
    *out = *slot;
 
730
 
 
731
  return 0;
 
732
}
 
733
 
 
734
static inline int
 
735
epoch_alive (gnutls_session_t session, record_parameters_st * params)
 
736
{
 
737
  const security_parameters_st *sp = &session->security_parameters;
 
738
 
 
739
  /* DTLS will, in addition, need to check the epoch timeout value. */
 
740
  return (params->epoch == sp->epoch_read
 
741
          || params->epoch == sp->epoch_write
 
742
          || params->epoch == sp->epoch_next);
 
743
}
 
744
 
 
745
void
 
746
_gnutls_epoch_gc (gnutls_session_t session)
 
747
{
 
748
  int i, j;
 
749
  unsigned int min_index = 0;
 
750
 
 
751
  _gnutls_record_log ("REC[%p]: Start of epoch cleanup\n", session);
 
752
 
 
753
  /* Free all dead cipher state */
 
754
  for (i = 0; i < MAX_EPOCH_INDEX; i++)
 
755
    if (session->record_parameters[i] != NULL
 
756
        && !epoch_alive (session, session->record_parameters[i]))
 
757
      {
 
758
        _gnutls_epoch_free (session, session->record_parameters[i]);
 
759
        session->record_parameters[i] = NULL;
 
760
      }
 
761
 
 
762
  /* Look for contiguous NULLs at the start of the array */
 
763
  for (i = 0; i < MAX_EPOCH_INDEX && session->record_parameters[i] == NULL;
 
764
       i++);
 
765
  min_index = i;
 
766
 
 
767
  /* Pick up the slack in the epoch window. */
 
768
  for (i = 0, j = min_index; j < MAX_EPOCH_INDEX; i++, j++)
 
769
    session->record_parameters[i] = session->record_parameters[j];
 
770
 
 
771
  /* Set the new epoch_min */
 
772
  if (session->record_parameters[0] != NULL)
 
773
    session->security_parameters.epoch_min =
 
774
      session->record_parameters[0]->epoch;
 
775
 
 
776
  _gnutls_record_log ("REC[%p]: End of epoch cleanup\n", session);
 
777
}
 
778
 
 
779
static inline void
 
780
free_record_state (record_state_st * state, int read)
 
781
{
 
782
  _gnutls_free_datum (&state->mac_secret);
 
783
  _gnutls_free_datum (&state->IV);
 
784
  _gnutls_free_datum (&state->key);
 
785
 
 
786
  _gnutls_cipher_deinit (&state->cipher_state);
 
787
 
 
788
  if (state->compression_state != NULL)
 
789
    _gnutls_comp_deinit (state->compression_state, read);
 
790
}
 
791
 
 
792
void
 
793
_gnutls_epoch_free (gnutls_session_t session, record_parameters_st * params)
 
794
{
 
795
  _gnutls_record_log ("REC[%p]: Epoch #%u freed\n", session, params->epoch);
 
796
 
 
797
  free_record_state (&params->read, 1);
 
798
  free_record_state (&params->write, 0);
 
799
 
 
800
  gnutls_free (params);
988
801
}