~ubuntu-branches/ubuntu/trusty/gnutls26/trusty

« back to all changes in this revision

Viewing changes to lib/ext_signature.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
* 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:
1
1
/*
2
 
 * Copyright (C) 2002, 2003, 2004, 2005, 2009, 2010 Free Software
 
2
 * Copyright (C) 2002,2003,2004,2005,2009,2010,2011 Free Software
3
3
 * Foundation, Inc.
4
4
 *
5
5
 * Author: Nikos Mavrogiannopoulos
34
34
#include <gnutls_state.h>
35
35
#include <gnutls_num.h>
36
36
#include <gnutls_algorithms.h>
 
37
#include <x509/common.h> /* dsa_q_to_hash */
 
38
#include <gnutls_cert.h>
 
39
 
 
40
static int _gnutls_signature_algorithm_recv_params (gnutls_session_t session,
 
41
                                                    const opaque * data,
 
42
                                                    size_t data_size);
 
43
static int _gnutls_signature_algorithm_send_params (gnutls_session_t session,
 
44
                                                    opaque * data, size_t);
 
45
static void signature_algorithms_deinit_data (extension_priv_data_t priv);
 
46
static int signature_algorithms_pack (extension_priv_data_t epriv,
 
47
                                      gnutls_buffer_st * ps);
 
48
static int signature_algorithms_unpack (gnutls_buffer_st * ps,
 
49
                                        extension_priv_data_t * _priv);
 
50
 
 
51
extension_entry_st ext_mod_sig = {
 
52
  .name = "SIGNATURE ALGORITHMS",
 
53
  .type = GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
 
54
  .parse_type = GNUTLS_EXT_TLS,
 
55
 
 
56
  .recv_func = _gnutls_signature_algorithm_recv_params,
 
57
  .send_func = _gnutls_signature_algorithm_send_params,
 
58
  .pack_func = signature_algorithms_pack,
 
59
  .unpack_func = signature_algorithms_unpack,
 
60
  .deinit_func = signature_algorithms_deinit_data,
 
61
};
 
62
 
 
63
typedef struct
 
64
{
 
65
  /* TLS 1.2 signature algorithms */
 
66
  gnutls_sign_algorithm_t sign_algorithms[MAX_SIGNATURE_ALGORITHMS];
 
67
  uint16_t sign_algorithms_size;
 
68
} sig_ext_st;
37
69
 
38
70
/* generates a SignatureAndHashAlgorithm structure with length as prefix
39
71
 * by using the setup priorities.
40
72
 */
41
73
int
42
74
_gnutls_sign_algorithm_write_params (gnutls_session_t session, opaque * data,
43
 
                                     size_t max_data_size)
 
75
                                     size_t max_data_size)
44
76
{
45
 
  opaque *p = data;
46
 
  int len, i, j;
47
 
  sign_algorithm_st aid;
 
77
  opaque *p = data, *len_p;
 
78
  int len, i, j, hash;
 
79
  const sign_algorithm_st *aid;
48
80
 
49
 
  len = session->internals.priorities.sign_algo.algorithms * 2;
50
 
  if (max_data_size < len + 2)
 
81
  if (max_data_size < (session->internals.priorities.sign_algo.algorithms*2) + 2)
51
82
    {
52
83
      gnutls_assert ();
53
84
      return GNUTLS_E_SHORT_MEMORY_BUFFER;
54
85
    }
55
86
 
56
 
  _gnutls_write_uint16 (len, p);
 
87
  len = 0;
 
88
  len_p = p;
 
89
 
57
90
  p += 2;
58
91
 
59
 
  for (i = j = 0; i < len; i += 2, j++)
 
92
  for (i = j = 0; j < session->internals.priorities.sign_algo.algorithms; i += 2, j++)
60
93
    {
 
94
      /* In gnutls we keep a state of SHA1 and SHA256 and thus cannot
 
95
       * use anything else.
 
96
       */
 
97
      hash = _gnutls_sign_get_hash_algorithm(session->internals.priorities.sign_algo.priority[j]);
 
98
      if (hash != GNUTLS_DIG_SHA1 && hash != GNUTLS_DIG_SHA256)
 
99
        continue;
 
100
      
61
101
      aid =
62
 
        _gnutls_sign_to_tls_aid (session->internals.priorities.
63
 
                                 sign_algo.priority[j]);
64
 
      *p = aid.hash_algorithm;
65
 
      p++;
66
 
      *p = aid.sign_algorithm;
67
 
      p++;
 
102
        _gnutls_sign_to_tls_aid (session->internals.priorities.
 
103
                                 sign_algo.priority[j]);
68
104
 
 
105
      if (aid == NULL)
 
106
        continue;
 
107
        
 
108
       _gnutls_debug_log ("EXT[SIGA]: sent signature algo (%d.%d) %s\n", aid->hash_algorithm, 
 
109
         aid->sign_algorithm, gnutls_sign_get_name(session->internals.priorities.sign_algo.priority[j]));
 
110
      *p = aid->hash_algorithm;
 
111
      p++;
 
112
      *p = aid->sign_algorithm;
 
113
      p++;
 
114
      len+=2;
69
115
    }
 
116
 
 
117
  _gnutls_write_uint16 (len, len_p);
 
118
 
70
119
  return len + 2;
71
120
}
72
121
 
 
122
 
73
123
/* Parses the Signature Algorithm structure and stores data into
74
124
 * session->security_parameters.extensions.
75
125
 */
76
126
int
77
127
_gnutls_sign_algorithm_parse_data (gnutls_session_t session,
78
 
                                   const opaque * data, size_t data_size)
 
128
                                   const opaque * data, size_t data_size)
79
129
{
80
130
  int sig, i;
 
131
  sig_ext_st *priv;
 
132
  extension_priv_data_t epriv;
81
133
 
82
 
  session->security_parameters.extensions.sign_algorithms_size = 0;
 
134
  priv = gnutls_calloc (1, sizeof (*priv));
 
135
  if (priv == NULL)
 
136
    {
 
137
      gnutls_assert ();
 
138
      return GNUTLS_E_MEMORY_ERROR;
 
139
    }
83
140
 
84
141
  for (i = 0; i < data_size; i += 2)
85
142
    {
89
146
      aid.sign_algorithm = data[i + 1];
90
147
 
91
148
      sig = _gnutls_tls_aid_to_sign (&aid);
 
149
 
 
150
       _gnutls_debug_log ("EXT[SIGA]: rcvd signature algo (%d.%d) %s\n", aid.hash_algorithm, 
 
151
         aid.sign_algorithm, gnutls_sign_get_name(sig));
 
152
 
92
153
      if (sig != GNUTLS_SIGN_UNKNOWN)
93
 
        {
94
 
          session->security_parameters.extensions.sign_algorithms[session->
95
 
                                                                  security_parameters.
96
 
                                                                  extensions.sign_algorithms_size++]
97
 
            = sig;
98
 
          if (session->security_parameters.extensions.sign_algorithms_size ==
99
 
              MAX_SIGNATURE_ALGORITHMS)
100
 
            break;
101
 
        }
 
154
        {
 
155
          priv->sign_algorithms[priv->sign_algorithms_size++] = sig;
 
156
          if (priv->sign_algorithms_size == MAX_SIGNATURE_ALGORITHMS)
 
157
            break;
 
158
        }
102
159
    }
103
160
 
 
161
  epriv.ptr = priv;
 
162
  _gnutls_ext_set_session_data (session,
 
163
                                GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS, epriv);
 
164
 
104
165
  return 0;
105
166
}
106
167
 
113
174
 * then it is an error;
114
175
 */
115
176
 
116
 
int
 
177
static int
117
178
_gnutls_signature_algorithm_recv_params (gnutls_session_t session,
118
 
                                         const opaque * data,
119
 
                                         size_t _data_size)
 
179
                                         const opaque * data,
 
180
                                         size_t _data_size)
120
181
{
121
182
  ssize_t data_size = _data_size;
122
183
  int ret;
136
197
      /* SERVER SIDE - we must check if the sent cert type is the right one
137
198
       */
138
199
      if (data_size > 2)
139
 
        {
140
 
          uint16_t len;
141
 
 
142
 
 
143
 
          DECR_LEN (data_size, 2);
144
 
          len = _gnutls_read_uint16 (data);
145
 
          DECR_LEN (data_size, len);
146
 
 
147
 
          ret = _gnutls_sign_algorithm_parse_data (session, data + 2, len);
148
 
          if (ret < 0)
149
 
            {
150
 
              gnutls_assert ();
151
 
              return ret;
152
 
            }
153
 
        }
 
200
        {
 
201
          uint16_t len;
 
202
 
 
203
          DECR_LEN (data_size, 2);
 
204
          len = _gnutls_read_uint16 (data);
 
205
          DECR_LEN (data_size, len);
 
206
 
 
207
          ret = _gnutls_sign_algorithm_parse_data (session, data + 2, len);
 
208
          if (ret < 0)
 
209
            {
 
210
              gnutls_assert ();
 
211
              return ret;
 
212
            }
 
213
        }
154
214
    }
155
215
 
156
216
  return 0;
158
218
 
159
219
/* returns data_size or a negative number on failure
160
220
 */
161
 
int
 
221
static int
162
222
_gnutls_signature_algorithm_send_params (gnutls_session_t session,
163
 
                                         opaque * data, size_t data_size)
 
223
                                         opaque * data, size_t data_size)
164
224
{
165
225
  int ret;
166
226
  gnutls_protocol_t ver = gnutls_protocol_get_version (session);
170
230
      && _gnutls_version_has_selectable_sighash (ver))
171
231
    {
172
232
      if (session->internals.priorities.sign_algo.algorithms > 0)
173
 
        {
174
 
          ret =
175
 
            _gnutls_sign_algorithm_write_params (session, data, data_size);
176
 
          if (ret < 0)
177
 
            {
178
 
              gnutls_assert ();
179
 
              return ret;
180
 
            }
181
 
          return ret;
182
 
        }
 
233
        {
 
234
          ret =
 
235
            _gnutls_sign_algorithm_write_params (session, data, data_size);
 
236
          if (ret < 0)
 
237
            {
 
238
              gnutls_assert ();
 
239
              return ret;
 
240
            }
 
241
          return ret;
 
242
        }
183
243
    }
184
244
 
185
245
  /* if we are here it means we don't send the extension */
186
246
  return 0;
187
247
}
188
248
 
 
249
int cert_compatible_with_sig(gnutls_cert* cert, gnutls_protocol_t ver, 
 
250
  gnutls_sign_algorithm_t sign)
 
251
{
 
252
unsigned int hash_len;
 
253
 
 
254
  if (cert->subject_pk_algorithm == GNUTLS_PK_DSA)
 
255
    { /* override */
 
256
      int hash_algo = _gnutls_dsa_q_to_hash (cert->params[1], &hash_len);
 
257
 
 
258
      /* DSA keys over 1024 bits cannot be used with TLS 1.x, x<2 */
 
259
      if (!_gnutls_version_has_selectable_sighash (ver))
 
260
        {
 
261
          if (hash_algo != GNUTLS_DIG_SHA1)
 
262
            return gnutls_assert_val(GNUTLS_E_INCOMPAT_DSA_KEY_WITH_TLS_PROTOCOL);
 
263
        }
 
264
      else
 
265
        {
 
266
          if (_gnutls_hash_get_algo_len(_gnutls_sign_get_hash_algorithm(sign)) < hash_len)
 
267
            return GNUTLS_E_UNWANTED_ALGORITHM;
 
268
        }
 
269
        
 
270
    }
 
271
 
 
272
  return 0;
 
273
}
 
274
 
189
275
/* Returns a requested by the peer signature algorithm that
190
276
 * matches the given public key algorithm. Index can be increased
191
277
 * to return the second choice etc.
192
278
 */
193
279
gnutls_sign_algorithm_t
194
 
_gnutls_session_get_sign_algo (gnutls_session_t session,
195
 
                               gnutls_pk_algorithm_t pk,
196
 
                               gnutls_digest_algorithm_t * hash)
 
280
_gnutls_session_get_sign_algo (gnutls_session_t session, gnutls_cert* cert)
197
281
{
198
282
  unsigned i;
 
283
  int ret;
199
284
  gnutls_protocol_t ver = gnutls_protocol_get_version (session);
200
 
 
201
 
 
202
 
  if (!_gnutls_version_has_selectable_sighash (ver)
203
 
      || session->security_parameters.extensions.sign_algorithms_size == 0)
204
 
    /* none set, allow all */
 
285
  sig_ext_st *priv;
 
286
  extension_priv_data_t epriv;
 
287
 
 
288
  ret =
 
289
    _gnutls_ext_get_session_data (session,
 
290
                                  GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
 
291
                                  &epriv);
 
292
  priv = epriv.ptr;
 
293
 
 
294
  if (ret < 0 || !_gnutls_version_has_selectable_sighash (ver)
 
295
      || priv->sign_algorithms_size == 0)
 
296
    /* none set, allow SHA-1 only */
205
297
    {
206
 
      *hash = GNUTLS_DIG_SHA1;
207
 
      return _gnutls_x509_pk_to_sign (pk, *hash);
 
298
      return _gnutls_x509_pk_to_sign (cert->subject_pk_algorithm, GNUTLS_DIG_SHA1);
208
299
    }
209
300
 
210
 
  for (i = 0;
211
 
       i < session->security_parameters.extensions.sign_algorithms_size; i++)
 
301
  for (i = 0; i < priv->sign_algorithms_size; i++)
212
302
    {
213
 
      if (_gnutls_sign_get_pk_algorithm
214
 
          (session->security_parameters.extensions.sign_algorithms[i]) == pk)
215
 
        {
216
 
          *hash =
217
 
            _gnutls_sign_get_hash_algorithm (session->security_parameters.
218
 
                                             extensions.sign_algorithms[i]);
219
 
          return session->security_parameters.extensions.sign_algorithms[i];
220
 
        }
 
303
      if (_gnutls_sign_get_pk_algorithm (priv->sign_algorithms[i]) == cert->subject_pk_algorithm)
 
304
        {
 
305
          if (cert_compatible_with_sig(cert, ver, priv->sign_algorithms[i]) < 0)
 
306
            continue;
 
307
 
 
308
          return priv->sign_algorithms[i];
 
309
        }
221
310
    }
222
311
 
223
312
  return GNUTLS_SIGN_UNKNOWN;
230
319
 */
231
320
int
232
321
_gnutls_session_sign_algo_requested (gnutls_session_t session,
233
 
                                     gnutls_sign_algorithm_t sig)
 
322
                                     gnutls_sign_algorithm_t sig)
234
323
{
235
324
  unsigned i;
 
325
  int ret, hash;
236
326
  gnutls_protocol_t ver = gnutls_protocol_get_version (session);
237
 
 
238
 
  if (!_gnutls_version_has_selectable_sighash (ver)
239
 
      || session->security_parameters.extensions.sign_algorithms_size == 0)
 
327
  sig_ext_st *priv;
 
328
  extension_priv_data_t epriv;
 
329
 
 
330
  if (!_gnutls_version_has_selectable_sighash (ver))
 
331
    {
 
332
      return 0;
 
333
    }
 
334
 
 
335
  ret =
 
336
    _gnutls_ext_get_session_data (session,
 
337
                                  GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
 
338
                                  &epriv);
 
339
  if (ret < 0)
 
340
    {
 
341
      gnutls_assert ();
 
342
      /* extension not received allow SHA1 and SHA256 */
 
343
      hash = _gnutls_sign_get_hash_algorithm (sig);
 
344
      if (hash == GNUTLS_DIG_SHA1 || hash == GNUTLS_DIG_SHA256)
 
345
        return 0;
 
346
      else
 
347
        return ret;
 
348
    }
 
349
  priv = epriv.ptr;
 
350
 
 
351
  if (priv->sign_algorithms_size == 0)
240
352
    /* none set, allow all */
241
353
    {
242
354
      return 0;
243
355
    }
244
356
 
245
 
  for (i = 0;
246
 
       i < session->security_parameters.extensions.sign_algorithms_size; i++)
 
357
  for (i = 0; i < priv->sign_algorithms_size; i++)
247
358
    {
248
 
      if (session->security_parameters.extensions.sign_algorithms[i] == sig)
249
 
        {
250
 
          return 0;             /* ok */
251
 
        }
 
359
      if (priv->sign_algorithms[i] == sig)
 
360
        {
 
361
          return 0;             /* ok */
 
362
        }
252
363
    }
253
364
 
254
365
  return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
260
371
 */
261
372
int
262
373
_gnutls_session_sign_algo_enabled (gnutls_session_t session,
263
 
                                   gnutls_sign_algorithm_t sig)
 
374
                                   gnutls_sign_algorithm_t sig)
264
375
{
265
376
  unsigned i;
 
377
  int ret;
266
378
  gnutls_protocol_t ver = gnutls_protocol_get_version (session);
 
379
  sig_ext_st *priv;
 
380
  extension_priv_data_t epriv;
 
381
 
 
382
  ret =
 
383
    _gnutls_ext_get_session_data (session,
 
384
                                  GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
 
385
                                  &epriv);
 
386
  if (ret < 0)
 
387
    {
 
388
      gnutls_assert ();
 
389
      return 0;
 
390
    }
 
391
  priv = epriv.ptr;
267
392
 
268
393
  if (!_gnutls_version_has_selectable_sighash (ver)
269
 
      || session->security_parameters.extensions.sign_algorithms_size == 0)
 
394
      || priv->sign_algorithms_size == 0)
270
395
    /* none set, allow all */
271
396
    {
272
397
      return 0;
275
400
  for (i = 0; i < session->internals.priorities.sign_algo.algorithms; i++)
276
401
    {
277
402
      if (session->internals.priorities.sign_algo.priority[i] == sig)
278
 
        {
279
 
          return 0;             /* ok */
280
 
        }
 
403
        {
 
404
          return 0;             /* ok */
 
405
        }
281
406
    }
282
407
 
283
408
  return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
284
409
}
285
410
 
 
411
static void
 
412
signature_algorithms_deinit_data (extension_priv_data_t priv)
 
413
{
 
414
  gnutls_free (priv.ptr);
 
415
}
 
416
 
 
417
static int
 
418
signature_algorithms_pack (extension_priv_data_t epriv, gnutls_buffer_st * ps)
 
419
{
 
420
  sig_ext_st *priv = epriv.ptr;
 
421
  int ret, i;
 
422
 
 
423
  BUFFER_APPEND_NUM (ps, priv->sign_algorithms_size);
 
424
  for (i = 0; i < priv->sign_algorithms_size; i++)
 
425
    {
 
426
      BUFFER_APPEND_NUM (ps, priv->sign_algorithms[i]);
 
427
    }
 
428
  return 0;
 
429
}
 
430
 
 
431
static int
 
432
signature_algorithms_unpack (gnutls_buffer_st * ps,
 
433
                             extension_priv_data_t * _priv)
 
434
{
 
435
  sig_ext_st *priv;
 
436
  int i, ret;
 
437
  extension_priv_data_t epriv;
 
438
 
 
439
  priv = gnutls_calloc (1, sizeof (*priv));
 
440
  if (priv == NULL)
 
441
    {
 
442
      gnutls_assert ();
 
443
      return GNUTLS_E_MEMORY_ERROR;
 
444
    }
 
445
 
 
446
  BUFFER_POP_NUM (ps, priv->sign_algorithms_size);
 
447
  for (i = 0; i < priv->sign_algorithms_size; i++)
 
448
    {
 
449
      BUFFER_POP_NUM (ps, priv->sign_algorithms[i]);
 
450
    }
 
451
 
 
452
  epriv.ptr = priv;
 
453
  *_priv = epriv;
 
454
 
 
455
  return 0;
 
456
 
 
457
error:
 
458
  gnutls_free (priv);
 
459
  return ret;
 
460
}
 
461
 
 
462
 
 
463
 
286
464
/**
287
465
 * gnutls_sign_algorithm_get_requested:
288
466
 * @session: is a #gnutls_session_t structure.
306
484
 **/
307
485
int
308
486
gnutls_sign_algorithm_get_requested (gnutls_session_t session,
309
 
                                     size_t indx,
310
 
                                     gnutls_sign_algorithm_t * algo)
 
487
                                     size_t indx,
 
488
                                     gnutls_sign_algorithm_t * algo)
311
489
{
312
490
  gnutls_protocol_t ver = gnutls_protocol_get_version (session);
 
491
  sig_ext_st *priv;
 
492
  extension_priv_data_t epriv;
 
493
  int ret;
 
494
 
 
495
  ret =
 
496
    _gnutls_ext_get_session_data (session,
 
497
                                  GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
 
498
                                  &epriv);
 
499
  if (ret < 0)
 
500
    {
 
501
      gnutls_assert ();
 
502
      return ret;
 
503
    }
 
504
  priv = epriv.ptr;
313
505
 
314
506
  if (!_gnutls_version_has_selectable_sighash (ver)
315
 
      || session->security_parameters.extensions.sign_algorithms_size == 0)
 
507
      || priv->sign_algorithms_size == 0)
316
508
    {
317
509
      return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
318
510
    }
319
511
 
320
 
  if (indx < session->security_parameters.extensions.sign_algorithms_size)
 
512
  if (indx < priv->sign_algorithms_size)
321
513
    {
322
 
      *algo = session->security_parameters.extensions.sign_algorithms[indx];
 
514
      *algo = priv->sign_algorithms[indx];
323
515
      return 0;
324
516
    }
325
517
  else