Coverage Report

Created: 2025-03-18 06:55

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