Coverage Report

Created: 2023-03-26 07:33

/src/gnutls/lib/ext/signature.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2002-2016 Free Software Foundation, Inc.
3
 * Copyright (C) 2015-2017 Red Hat, Inc.
4
 *
5
 * Author: Nikos Mavrogiannopoulos
6
 *
7
 * This file is part of GnuTLS.
8
 *
9
 * The GnuTLS is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public License
11
 * as published by the Free Software Foundation; either version 2.1 of
12
 * the License, or (at your option) any later version.
13
 *
14
 * This library is distributed in the hope that it will be useful, but
15
 * WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public License
20
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
21
 *
22
 */
23
24
/* This file contains the code for the Signature Algorithms TLS extension.
25
 * This extension is currently gnutls specific.
26
 */
27
28
#include "gnutls_int.h"
29
#include "errors.h"
30
#include "num.h"
31
#include <gnutls/gnutls.h>
32
#include <ext/signature.h>
33
#include <state.h>
34
#include <num.h>
35
#include <algorithms.h>
36
#include <abstract_int.h>
37
38
/*
39
 * Some (all SChannel) clients fail to send proper SigAlgs due to Micro$oft crazyness.
40
 * Patch the extension for them.
41
 */
42
#ifdef ENABLE_GOST
43
# define GOST_SIG_FIXUP_SCHANNEL
44
#endif
45
46
static int _gnutls_signature_algorithm_recv_params(gnutls_session_t
47
               session,
48
               const uint8_t * data,
49
               size_t data_size);
50
static int _gnutls_signature_algorithm_send_params(gnutls_session_t
51
               session,
52
               gnutls_buffer_st * extdata);
53
static void signature_algorithms_deinit_data(gnutls_ext_priv_data_t priv);
54
static int signature_algorithms_pack(gnutls_ext_priv_data_t epriv,
55
             gnutls_buffer_st * ps);
56
static int signature_algorithms_unpack(gnutls_buffer_st * ps,
57
               gnutls_ext_priv_data_t * _priv);
58
59
const hello_ext_entry_st ext_mod_sig = {
60
  .name = "Signature Algorithms",
61
  .tls_id = 13,
62
  .gid = GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
63
  .validity =
64
      GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS |
65
      GNUTLS_EXT_FLAG_CLIENT_HELLO,
66
  .client_parse_point = GNUTLS_EXT_TLS,
67
  .server_parse_point = GNUTLS_EXT_TLS,
68
  .recv_func = _gnutls_signature_algorithm_recv_params,
69
  .send_func = _gnutls_signature_algorithm_send_params,
70
  .pack_func = signature_algorithms_pack,
71
  .unpack_func = signature_algorithms_unpack,
72
  .deinit_func = signature_algorithms_deinit_data,
73
  .cannot_be_overriden = 1
74
};
75
76
typedef struct {
77
  /* TLS 1.2 signature algorithms */
78
  gnutls_sign_algorithm_t sign_algorithms[MAX_ALGOS];
79
  uint16_t sign_algorithms_size;
80
} sig_ext_st;
81
82
/* generates a SignatureAndHashAlgorithm structure with length as prefix
83
 * by using the setup priorities.
84
 */
85
int
86
_gnutls_sign_algorithm_write_params(gnutls_session_t session,
87
            gnutls_buffer_st * extdata)
88
0
{
89
0
  uint8_t *p;
90
0
  unsigned int len, i;
91
0
  const sign_algorithm_st *aid, *prev = NULL;
92
0
  uint8_t buffer[MAX_ALGOS * 2];
93
94
0
  p = buffer;
95
0
  len = 0;
96
97
  /* This generates a list of TLS signature algorithms. It has
98
   * limited duplicate detection, and does not add twice the same
99
   * AID */
100
101
0
  for (i = 0; i < session->internals.priorities->sigalg.size; i++) {
102
0
    aid = &session->internals.priorities->sigalg.entry[i]->aid;
103
104
0
    if (HAVE_UNKNOWN_SIGAID(aid))
105
0
      continue;
106
107
0
    if (prev && prev->id[0] == aid->id[0]
108
0
        && prev->id[1] == aid->id[1])
109
0
      continue;
110
111
    /* Ignore non-GOST sign types for CertReq */
112
0
    if (session->security_parameters.cs &&
113
0
        _gnutls_kx_is_vko_gost(session->security_parameters.
114
0
             cs->kx_algorithm)
115
0
        && !_sign_is_gost(session->internals.priorities->
116
0
              sigalg.entry[i]))
117
0
      continue;
118
119
0
    _gnutls_handshake_log
120
0
        ("EXT[%p]: sent signature algo (%d.%d) %s\n", session,
121
0
         (int)aid->id[0], (int)aid->id[1],
122
0
         session->internals.priorities->sigalg.entry[i]->name);
123
124
0
    len += 2;
125
0
    if (unlikely(len >= sizeof(buffer))) {
126
0
      len -= 2;
127
0
      break;
128
0
    }
129
130
0
    *p = aid->id[0];
131
0
    p++;
132
0
    *p = aid->id[1];
133
0
    p++;
134
0
    prev = aid;
135
0
  }
136
137
0
  return _gnutls_buffer_append_data_prefix(extdata, 16, buffer, len);
138
0
}
139
140
/* Parses the Signature Algorithm structure and stores data into
141
 * session->security_parameters.extensions.
142
 */
143
int
144
_gnutls_sign_algorithm_parse_data(gnutls_session_t session,
145
          const uint8_t * data, size_t data_size)
146
0
{
147
0
  unsigned int sig, i;
148
0
  sig_ext_st *priv;
149
0
  gnutls_ext_priv_data_t epriv;
150
0
  const version_entry_st *ver = get_version(session);
151
152
0
  if (data_size == 0 || data_size % 2 != 0)
153
0
    return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
154
155
0
  if (ver == NULL) { /* assume TLS 1.2 semantics */
156
0
    ver = version_to_entry(GNUTLS_TLS1_2);
157
0
    if (unlikely(ver == NULL)) {
158
0
      return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
159
0
    }
160
0
  }
161
162
0
  priv = gnutls_calloc(1, sizeof(*priv));
163
0
  if (priv == NULL) {
164
0
    gnutls_assert();
165
0
    return GNUTLS_E_MEMORY_ERROR;
166
0
  }
167
168
0
  for (i = 0; i < data_size; i += 2) {
169
0
    uint8_t id[2];
170
171
0
    id[0] = data[i];
172
0
    id[1] = data[i + 1];
173
174
0
    sig = _gnutls_tls_aid_to_sign(id[0], id[1], ver);
175
176
0
    _gnutls_handshake_log
177
0
        ("EXT[%p]: rcvd signature algo (%d.%d) %s\n", session,
178
0
         (int)id[0], (int)id[1], gnutls_sign_get_name(sig));
179
180
0
    if (sig != GNUTLS_SIGN_UNKNOWN) {
181
0
      if (priv->sign_algorithms_size == MAX_ALGOS)
182
0
        break;
183
0
      priv->sign_algorithms[priv->sign_algorithms_size++] =
184
0
          sig;
185
0
    }
186
0
  }
187
188
0
  epriv = priv;
189
0
  _gnutls_hello_ext_set_priv(session,
190
0
           GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
191
0
           epriv);
192
193
0
  return 0;
194
0
}
195
196
/*
197
 * In case of a server: if a SIGNATURE_ALGORITHMS extension type is
198
 * received then it stores into the session security parameters the
199
 * new value.
200
 *
201
 * In case of a client: If a signature_algorithms have been specified
202
 * then it is an error;
203
 */
204
205
static int
206
_gnutls_signature_algorithm_recv_params(gnutls_session_t session,
207
          const uint8_t * data, size_t data_size)
208
0
{
209
0
  int ret;
210
211
0
  if (session->security_parameters.entity == GNUTLS_CLIENT) {
212
    /* nothing for now */
213
0
    gnutls_assert();
214
    /* Although TLS 1.2 mandates that we must not accept reply
215
     * to this message, there are good reasons to just ignore it. Check
216
     * https://www.ietf.org/mail-archive/web/tls/current/msg03880.html
217
     */
218
    /* return GNUTLS_E_UNEXPECTED_PACKET; */
219
0
  } else {
220
    /* SERVER SIDE
221
     */
222
0
    if (data_size >= 2) {
223
0
      uint16_t len;
224
225
0
      DECR_LEN(data_size, 2);
226
0
      len = _gnutls_read_uint16(data);
227
0
      DECR_LEN(data_size, len);
228
229
0
      if (data_size > 0)
230
0
        return
231
0
            gnutls_assert_val
232
0
            (GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
233
234
0
      ret =
235
0
          _gnutls_sign_algorithm_parse_data(session,
236
0
                    data + 2, len);
237
0
      if (ret < 0) {
238
0
        gnutls_assert();
239
0
        return ret;
240
0
      }
241
0
    } else {
242
0
      return
243
0
          gnutls_assert_val
244
0
          (GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
245
0
    }
246
0
  }
247
248
0
  return 0;
249
0
}
250
251
/* returns data_size or a negative number on failure
252
 */
253
static int
254
_gnutls_signature_algorithm_send_params(gnutls_session_t session,
255
          gnutls_buffer_st * extdata)
256
0
{
257
0
  int ret;
258
0
  size_t init_length = extdata->length;
259
0
  const version_entry_st *ver = get_version(session);
260
261
0
  if (unlikely(ver == NULL))
262
0
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
263
264
  /* this function sends the client extension data */
265
0
  if (session->security_parameters.entity == GNUTLS_CLIENT
266
0
      && _gnutls_version_has_selectable_sighash(ver)) {
267
0
    if (session->internals.priorities->sigalg.size > 0) {
268
0
      ret =
269
0
          _gnutls_sign_algorithm_write_params(session,
270
0
                extdata);
271
0
      if (ret < 0)
272
0
        return gnutls_assert_val(ret);
273
274
0
      return extdata->length - init_length;
275
0
    }
276
0
  }
277
278
  /* if we are here it means we don't send the extension */
279
0
  return 0;
280
0
}
281
282
#ifdef GOST_SIG_FIXUP_SCHANNEL
283
static bool is_gost_sig_present(sig_ext_st * priv)
284
0
{
285
0
  unsigned i;
286
0
  const gnutls_sign_entry_st *se;
287
288
0
  for (i = 0; i < priv->sign_algorithms_size; i++) {
289
0
    se = _gnutls_sign_to_entry(priv->sign_algorithms[i]);
290
0
    if (se != NULL && _sign_is_gost(se))
291
0
      return true;
292
0
  }
293
294
0
  return false;
295
0
}
296
#endif
297
298
/* Returns a requested by the peer signature algorithm that
299
 * matches the given certificate's public key algorithm.
300
 *
301
 * When the @client_cert flag is not set, then this function will
302
 * also check whether the signature algorithm is allowed to be
303
 * used in that session. Otherwise GNUTLS_SIGN_UNKNOWN is
304
 * returned.
305
 */
306
gnutls_sign_algorithm_t
307
_gnutls_session_get_sign_algo(gnutls_session_t session,
308
            gnutls_pcert_st * cert,
309
            gnutls_privkey_t privkey,
310
            unsigned client_cert,
311
            gnutls_kx_algorithm_t kx_algorithm)
312
0
{
313
0
  unsigned i;
314
0
  int ret;
315
0
  const version_entry_st *ver = get_version(session);
316
0
  sig_ext_st *priv;
317
0
  gnutls_ext_priv_data_t epriv;
318
0
  unsigned int cert_algo;
319
0
  const gnutls_sign_entry_st *se;
320
321
0
  if (unlikely(ver == NULL))
322
0
    return gnutls_assert_val(GNUTLS_SIGN_UNKNOWN);
323
324
0
  cert_algo = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);
325
326
0
  ret =
327
0
      _gnutls_hello_ext_get_priv(session,
328
0
               GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
329
0
               &epriv);
330
0
  if (ret < 0)
331
0
    priv = NULL;
332
0
  else
333
0
    priv = epriv;
334
335
0
#ifdef GOST_SIG_FIXUP_SCHANNEL
336
  /*
337
   * Some (all SChannel) clients fail to send proper SigAlgs due to Micro$oft crazyness.
338
   * If we are negotiating GOST KX (because we have received GOST
339
   * ciphersuites) and if we have received no GOST SignatureAlgorithms,
340
   * assume that the client could not send them and continue negotiation
341
   * as if correct algorithm was sent.
342
   */
343
0
  if (_gnutls_kx_is_vko_gost(kx_algorithm) &&
344
0
      (!priv ||
345
0
       !is_gost_sig_present(priv) ||
346
0
       !_gnutls_version_has_selectable_sighash(ver))) {
347
0
    gnutls_digest_algorithm_t dig;
348
349
0
    _gnutls_handshake_log
350
0
        ("EXT[%p]: GOST KX, but no GOST SigAlgs received, patching up.",
351
0
         session);
352
353
0
    if (cert_algo == GNUTLS_PK_GOST_01)
354
0
      dig = GNUTLS_DIG_GOSTR_94;
355
0
    else if (cert_algo == GNUTLS_PK_GOST_12_256)
356
0
      dig = GNUTLS_DIG_STREEBOG_256;
357
0
    else if (cert_algo == GNUTLS_PK_GOST_12_512)
358
0
      dig = GNUTLS_DIG_STREEBOG_512;
359
0
    else
360
0
      dig = GNUTLS_DIG_SHA1;
361
362
0
    ret = gnutls_pk_to_sign(cert_algo, dig);
363
364
0
    if (!client_cert
365
0
        && _gnutls_session_sign_algo_enabled(session, ret) < 0)
366
0
      goto fail;
367
0
    return ret;
368
0
  }
369
0
#endif
370
371
0
  if (!priv || !_gnutls_version_has_selectable_sighash(ver)) {
372
    /* none set, allow SHA-1 only */
373
0
    ret = gnutls_pk_to_sign(cert_algo, GNUTLS_DIG_SHA1);
374
375
0
    if (!client_cert
376
0
        && _gnutls_session_sign_algo_enabled(session, ret) < 0)
377
0
      goto fail;
378
0
    return ret;
379
0
  }
380
381
0
  for (i = 0; i < priv->sign_algorithms_size; i++) {
382
0
    se = _gnutls_sign_to_entry(priv->sign_algorithms[i]);
383
0
    if (se == NULL)
384
0
      continue;
385
386
0
    _gnutls_handshake_log("checking cert compat with %s\n",
387
0
              se->name);
388
389
0
    if (_gnutls_privkey_compatible_with_sig
390
0
        (privkey, priv->sign_algorithms[i]) == 0)
391
0
      continue;
392
393
0
    if (sign_supports_cert_pk_algorithm(se, cert_algo) != 0) {
394
0
      if (_gnutls_pubkey_compatible_with_sig
395
0
          (session, cert->pubkey, ver, se->id) < 0)
396
0
        continue;
397
398
0
      if (_gnutls_session_sign_algo_enabled
399
0
          (session, se->id) < 0)
400
0
        continue;
401
402
0
      return se->id;
403
0
    }
404
0
  }
405
406
  /* When having a legacy client certificate which can only be signed
407
   * using algorithms we don't always enable by default (e.g., DSA-SHA1),
408
   * continue and sign with it. */
409
0
  if (client_cert) {
410
0
    _gnutls_audit_log(session,
411
0
          "No shared signature schemes with peer for client certificate (%s). Is the certificate a legacy one?\n",
412
0
          gnutls_pk_get_name(cert_algo));
413
0
  }
414
415
0
 fail:
416
0
  return GNUTLS_SIGN_UNKNOWN;
417
0
}
418
419
/* Check if the given signature algorithm is supported.
420
 * This means that it is enabled by the priority functions,
421
 * and in case of a server a matching certificate exists.
422
 */
423
int
424
_gnutls_session_sign_algo_enabled(gnutls_session_t session,
425
          gnutls_sign_algorithm_t sig)
426
0
{
427
0
  unsigned i;
428
0
  const version_entry_st *ver = get_version(session);
429
430
0
  if (unlikely(ver == NULL))
431
0
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
432
433
0
  if (!_gnutls_version_has_selectable_sighash(ver)) {
434
0
    return 0;
435
0
  }
436
437
0
  if (ver->tls13_sem) {
438
    /* disallow RSA, DSA, and SHA1 */
439
0
    const gnutls_sign_entry_st *se;
440
441
0
    se = _gnutls_sign_to_entry(sig);
442
0
    if (se == NULL || (se->flags & GNUTLS_SIGN_FLAG_TLS13_OK) == 0) {
443
0
      gnutls_assert();
444
0
      goto disallowed;
445
0
    }
446
0
  }
447
448
0
  for (i = 0; i < session->internals.priorities->sigalg.size; i++) {
449
0
    if (session->internals.priorities->sigalg.entry[i]->id == sig) {
450
0
      return 0; /* ok */
451
0
    }
452
0
  }
453
454
0
 disallowed:
455
0
  _gnutls_handshake_log("Signature algorithm %s is not enabled\n",
456
0
            gnutls_sign_algorithm_get_name(sig));
457
0
  return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
458
0
}
459
460
static void signature_algorithms_deinit_data(gnutls_ext_priv_data_t priv)
461
0
{
462
0
  gnutls_free(priv);
463
0
}
464
465
static int
466
signature_algorithms_pack(gnutls_ext_priv_data_t epriv, gnutls_buffer_st * ps)
467
0
{
468
0
  sig_ext_st *priv = epriv;
469
0
  int ret, i;
470
471
0
  BUFFER_APPEND_NUM(ps, priv->sign_algorithms_size);
472
0
  for (i = 0; i < priv->sign_algorithms_size; i++) {
473
0
    BUFFER_APPEND_NUM(ps, priv->sign_algorithms[i]);
474
0
  }
475
0
  return 0;
476
0
}
477
478
static int
479
signature_algorithms_unpack(gnutls_buffer_st * ps,
480
          gnutls_ext_priv_data_t * _priv)
481
0
{
482
0
  sig_ext_st *priv;
483
0
  int i, ret;
484
0
  gnutls_ext_priv_data_t epriv;
485
486
0
  priv = gnutls_calloc(1, sizeof(*priv));
487
0
  if (priv == NULL) {
488
0
    gnutls_assert();
489
0
    return GNUTLS_E_MEMORY_ERROR;
490
0
  }
491
492
0
  BUFFER_POP_NUM(ps, priv->sign_algorithms_size);
493
0
  for (i = 0; i < priv->sign_algorithms_size; i++) {
494
0
    BUFFER_POP_NUM(ps, priv->sign_algorithms[i]);
495
0
  }
496
497
0
  epriv = priv;
498
0
  *_priv = epriv;
499
500
0
  return 0;
501
502
0
 error:
503
0
  gnutls_free(priv);
504
0
  return ret;
505
0
}
506
507
/**
508
 * gnutls_sign_algorithm_get_requested:
509
 * @session: is a #gnutls_session_t type.
510
 * @indx: is an index of the signature algorithm to return
511
 * @algo: the returned certificate type will be stored there
512
 *
513
 * Returns the signature algorithm specified by index that was
514
 * requested by the peer. If the specified index has no data available
515
 * this function returns %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE.  If
516
 * the negotiated TLS version does not support signature algorithms
517
 * then %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned even
518
 * for the first index.  The first index is 0.
519
 *
520
 * This function is useful in the certificate callback functions
521
 * to assist in selecting the correct certificate.
522
 *
523
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
524
 *   an error code is returned.
525
 *
526
 * Since: 2.10.0
527
 **/
528
int
529
gnutls_sign_algorithm_get_requested(gnutls_session_t session,
530
            size_t indx, gnutls_sign_algorithm_t * algo)
531
0
{
532
0
  const version_entry_st *ver = get_version(session);
533
0
  sig_ext_st *priv;
534
0
  gnutls_ext_priv_data_t epriv;
535
0
  int ret;
536
537
0
  if (unlikely(ver == NULL))
538
0
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
539
540
0
  ret =
541
0
      _gnutls_hello_ext_get_priv(session,
542
0
               GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
543
0
               &epriv);
544
0
  if (ret < 0) {
545
0
    gnutls_assert();
546
0
    return ret;
547
0
  }
548
0
  priv = epriv;
549
550
0
  if (!_gnutls_version_has_selectable_sighash(ver)
551
0
      || priv->sign_algorithms_size == 0) {
552
0
    return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
553
0
  }
554
555
0
  if (indx < priv->sign_algorithms_size) {
556
0
    *algo = priv->sign_algorithms[indx];
557
0
    return 0;
558
0
  } else
559
0
    return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
560
0
}
561
562
/**
563
 * gnutls_sign_algorithm_get:
564
 * @session: is a #gnutls_session_t type.
565
 *
566
 * Returns the signature algorithm that is (or will be) used in this
567
 * session by the server to sign data. This function should be
568
 * used only with TLS 1.2 or later.
569
 *
570
 * Returns: The sign algorithm or %GNUTLS_SIGN_UNKNOWN.
571
 *
572
 * Since: 3.1.1
573
 **/
574
int gnutls_sign_algorithm_get(gnutls_session_t session)
575
0
{
576
0
  return session->security_parameters.server_sign_algo;
577
0
}
578
579
/**
580
 * gnutls_sign_algorithm_get_client:
581
 * @session: is a #gnutls_session_t type.
582
 *
583
 * Returns the signature algorithm that is (or will be) used in this
584
 * session by the client to sign data. This function should be
585
 * used only with TLS 1.2 or later.
586
 *
587
 * Returns: The sign algorithm or %GNUTLS_SIGN_UNKNOWN.
588
 *
589
 * Since: 3.1.11
590
 **/
591
int gnutls_sign_algorithm_get_client(gnutls_session_t session)
592
0
{
593
0
  return session->security_parameters.client_sign_algo;
594
0
}