Coverage Report

Created: 2025-11-16 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnutls/lib/tls-sig.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2001-2012 Free Software Foundation, Inc.
3
 * Copyright (C) 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
#include "gnutls_int.h"
25
#include "errors.h"
26
#include "x509_b64.h"
27
#include "auth/cert.h"
28
#include "algorithms.h"
29
#include "datum.h"
30
#include "mpi.h"
31
#include "global.h"
32
#include "pk.h"
33
#include "debug.h"
34
#include "buffers.h"
35
#include "tls-sig.h"
36
#include "kx.h"
37
#include <libtasn1.h>
38
#include "ext/signature.h"
39
#include "state.h"
40
#include "x509/common.h"
41
#include "abstract_int.h"
42
#include "audit.h"
43
44
int _gnutls_check_key_usage_for_sig(gnutls_session_t session,
45
            unsigned key_usage, unsigned our_cert)
46
0
{
47
0
  const char *lstr;
48
0
  unsigned allow_key_usage_violation;
49
50
0
  if (our_cert) {
51
0
    lstr = "Local";
52
0
    allow_key_usage_violation =
53
0
      session->internals.priorities
54
0
        ->allow_server_key_usage_violation;
55
0
  } else {
56
0
    lstr = "Peer's";
57
0
    allow_key_usage_violation =
58
0
      session->internals.allow_key_usage_violation;
59
0
  }
60
61
0
  if (key_usage != 0) {
62
0
    if (!(key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE)) {
63
0
      gnutls_assert();
64
0
      if (likely(allow_key_usage_violation == 0)) {
65
0
        _gnutls_audit_log(
66
0
          session,
67
0
          "%s certificate does not allow digital signatures. Key usage violation detected.\n",
68
0
          lstr);
69
0
        return GNUTLS_E_KEY_USAGE_VIOLATION;
70
0
      } else {
71
0
        _gnutls_audit_log(
72
0
          session,
73
0
          "%s certificate does not allow digital signatures. Key usage violation detected (ignored).\n",
74
0
          lstr);
75
0
      }
76
0
    }
77
0
  }
78
0
  return 0;
79
0
}
80
81
/* Generates a signature of all the random data and the parameters.
82
 * Used in *DHE_* ciphersuites for TLS 1.2.
83
 */
84
static int _gnutls_handshake_sign_data12(gnutls_session_t session,
85
           gnutls_pcert_st *cert,
86
           gnutls_privkey_t pkey,
87
           gnutls_datum_t *params,
88
           gnutls_datum_t *signature,
89
           const gnutls_sign_entry_st *se)
90
0
{
91
0
  gnutls_datum_t dconcat;
92
0
  int ret;
93
94
0
  _gnutls_handshake_log(
95
0
    "HSK[%p]: signing TLS 1.2 handshake data: using %s\n", session,
96
0
    se->name);
97
98
0
  if (unlikely(sign_supports_priv_pk_algorithm(se, pkey->pk_algorithm) ==
99
0
         0))
100
0
    return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
101
102
0
  dconcat.size = GNUTLS_RANDOM_SIZE * 2 + params->size;
103
0
  dconcat.data = gnutls_malloc(dconcat.size);
104
0
  if (dconcat.data == NULL)
105
0
    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
106
107
0
  memcpy(dconcat.data, session->security_parameters.client_random,
108
0
         GNUTLS_RANDOM_SIZE);
109
0
  memcpy(dconcat.data + GNUTLS_RANDOM_SIZE,
110
0
         session->security_parameters.server_random, GNUTLS_RANDOM_SIZE);
111
0
  memcpy(dconcat.data + GNUTLS_RANDOM_SIZE * 2, params->data,
112
0
         params->size);
113
114
0
  ret = gnutls_privkey_sign_data2(pkey, se->id, 0, &dconcat, signature);
115
0
  if (ret < 0) {
116
0
    gnutls_assert();
117
0
  }
118
0
  gnutls_free(dconcat.data);
119
120
0
  return ret;
121
0
}
122
123
static int _gnutls_handshake_sign_data10(gnutls_session_t session,
124
           gnutls_pcert_st *cert,
125
           gnutls_privkey_t pkey,
126
           gnutls_datum_t *params,
127
           gnutls_datum_t *signature,
128
           const gnutls_sign_entry_st *se)
129
0
{
130
0
  gnutls_datum_t dconcat;
131
0
  int ret;
132
0
  digest_hd_st td_sha;
133
0
  uint8_t concat[MAX_SIG_SIZE];
134
0
  const mac_entry_st *me;
135
0
  gnutls_pk_algorithm_t pk_algo;
136
137
0
  pk_algo = gnutls_privkey_get_pk_algorithm(pkey, NULL);
138
0
  if (pk_algo == GNUTLS_PK_RSA)
139
0
    me = hash_to_entry(GNUTLS_DIG_MD5_SHA1);
140
0
  else
141
0
    me = hash_to_entry(se->hash);
142
0
  if (me == NULL)
143
0
    return gnutls_assert_val(GNUTLS_E_UNKNOWN_HASH_ALGORITHM);
144
145
0
  if (unlikely(sign_supports_priv_pk_algorithm(se, pk_algo) == 0))
146
0
    return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
147
148
0
  _gnutls_handshake_log("HSK[%p]: signing handshake data: using %s\n",
149
0
            session, se->name);
150
151
0
  ret = _gnutls_hash_init(&td_sha, me);
152
0
  if (ret < 0) {
153
0
    gnutls_assert();
154
0
    return ret;
155
0
  }
156
157
0
  _gnutls_hash(&td_sha, session->security_parameters.client_random,
158
0
         GNUTLS_RANDOM_SIZE);
159
0
  _gnutls_hash(&td_sha, session->security_parameters.server_random,
160
0
         GNUTLS_RANDOM_SIZE);
161
0
  _gnutls_hash(&td_sha, params->data, params->size);
162
163
0
  _gnutls_hash_deinit(&td_sha, concat);
164
165
0
  dconcat.data = concat;
166
0
  dconcat.size = _gnutls_hash_get_algo_len(me);
167
168
0
  ret = gnutls_privkey_sign_hash(pkey, MAC_TO_DIG(me->id),
169
0
               GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA,
170
0
               &dconcat, signature);
171
0
  if (ret < 0) {
172
0
    gnutls_assert();
173
0
  }
174
175
0
  return ret;
176
0
}
177
178
/* Generates a signature of all the random data and the parameters.
179
 * Used in DHE_* ciphersuites.
180
 */
181
int _gnutls_handshake_sign_data(gnutls_session_t session, gnutls_pcert_st *cert,
182
        gnutls_privkey_t pkey, gnutls_datum_t *params,
183
        gnutls_datum_t *signature,
184
        gnutls_sign_algorithm_t *sign_algo)
185
0
{
186
0
  const version_entry_st *ver = get_version(session);
187
0
  unsigned key_usage = 0;
188
0
  const gnutls_sign_entry_st *se;
189
0
  int ret;
190
191
0
  *sign_algo = session->security_parameters.server_sign_algo;
192
0
  if (*sign_algo == GNUTLS_SIGN_UNKNOWN) {
193
0
    gnutls_assert();
194
0
    return GNUTLS_E_UNWANTED_ALGORITHM;
195
0
  }
196
197
0
  gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage);
198
199
0
  ret = _gnutls_check_key_usage_for_sig(session, key_usage, 1);
200
0
  if (ret < 0)
201
0
    return gnutls_assert_val(ret);
202
203
0
  se = _gnutls_sign_to_entry(*sign_algo);
204
205
0
  _gnutls_audit_new_context_with_data(
206
0
    "name", CRAU_STRING, "tls::sign", "tls::signature_algorithm",
207
0
    CRAU_WORD, se->aid.id[0] << 8 | se->aid.id[1], NULL);
208
209
0
  if (_gnutls_version_has_selectable_sighash(ver))
210
0
    ret = _gnutls_handshake_sign_data12(session, cert, pkey, params,
211
0
                signature, se);
212
0
  else
213
0
    ret = _gnutls_handshake_sign_data10(session, cert, pkey, params,
214
0
                signature, se);
215
216
0
  gnutls_audit_pop_context();
217
0
  return ret;
218
0
}
219
220
/* Generates a signature of all the random data and the parameters.
221
 * Used in DHE_* ciphersuites.
222
 */
223
static int _gnutls_handshake_verify_data10(gnutls_session_t session,
224
             unsigned verify_flags,
225
             gnutls_pcert_st *cert,
226
             const gnutls_datum_t *params,
227
             gnutls_datum_t *signature,
228
             gnutls_sign_algorithm_t sign_algo)
229
0
{
230
0
  gnutls_datum_t dconcat;
231
0
  int ret;
232
0
  digest_hd_st td_sha;
233
0
  uint8_t concat[MAX_SIG_SIZE];
234
0
  gnutls_digest_algorithm_t hash_algo;
235
0
  const mac_entry_st *me;
236
0
  gnutls_pk_algorithm_t pk_algo;
237
0
  const gnutls_sign_entry_st *se;
238
239
0
  pk_algo = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);
240
0
  if (pk_algo == GNUTLS_PK_RSA) {
241
0
    hash_algo = GNUTLS_DIG_MD5_SHA1;
242
0
    verify_flags |= GNUTLS_PUBKEY_VERIFY_FLAG_TLS1_RSA;
243
0
  } else {
244
0
    hash_algo = GNUTLS_DIG_SHA1;
245
0
    if (sign_algo == GNUTLS_SIGN_UNKNOWN) {
246
0
      sign_algo = gnutls_pk_to_sign(pk_algo, hash_algo);
247
0
    }
248
0
  }
249
250
0
  me = hash_to_entry(hash_algo);
251
252
0
  ret = _gnutls_hash_init(&td_sha, me);
253
0
  if (ret < 0) {
254
0
    gnutls_assert();
255
0
    return ret;
256
0
  }
257
258
0
  _gnutls_hash(&td_sha, session->security_parameters.client_random,
259
0
         GNUTLS_RANDOM_SIZE);
260
0
  _gnutls_hash(&td_sha, session->security_parameters.server_random,
261
0
         GNUTLS_RANDOM_SIZE);
262
0
  _gnutls_hash(&td_sha, params->data, params->size);
263
264
0
  _gnutls_hash_deinit(&td_sha, concat);
265
266
0
  dconcat.data = concat;
267
0
  dconcat.size = _gnutls_hash_get_algo_len(me);
268
269
0
  se = _gnutls_sign_to_entry(sign_algo);
270
0
  if (se) {
271
0
    _gnutls_audit_data("tls::signature_algorithm", CRAU_WORD,
272
0
           se->aid.id[0] << 8 | se->aid.id[1], NULL);
273
0
  }
274
275
0
  ret = gnutls_pubkey_verify_hash2(cert->pubkey, sign_algo,
276
0
           GNUTLS_VERIFY_ALLOW_SIGN_WITH_SHA1 |
277
0
             verify_flags,
278
0
           &dconcat, signature);
279
0
  if (ret < 0)
280
0
    return gnutls_assert_val(ret);
281
282
0
  return ret;
283
0
}
284
285
static int _gnutls_handshake_verify_data12(gnutls_session_t session,
286
             unsigned verify_flags,
287
             gnutls_pcert_st *cert,
288
             const gnutls_datum_t *params,
289
             gnutls_datum_t *signature,
290
             gnutls_sign_algorithm_t sign_algo)
291
0
{
292
0
  gnutls_datum_t dconcat;
293
0
  int ret;
294
0
  const version_entry_st *ver = get_version(session);
295
0
  const gnutls_sign_entry_st *se = _gnutls_sign_to_entry(sign_algo);
296
297
0
  if (unlikely(se == NULL))
298
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
299
300
0
  _gnutls_handshake_log(
301
0
    "HSK[%p]: verify TLS 1.2 handshake data: using %s\n", session,
302
0
    se->name);
303
304
0
  ret = _gnutls_pubkey_compatible_with_sig(session, cert->pubkey, ver,
305
0
             sign_algo);
306
0
  if (ret < 0)
307
0
    return gnutls_assert_val(ret);
308
309
0
  if (unlikely(sign_supports_cert_pk_algorithm(
310
0
           se, cert->pubkey->params.algo) == 0)) {
311
0
    _gnutls_handshake_log(
312
0
      "HSK[%p]: certificate of %s cannot be combined with %s sig\n",
313
0
      session, gnutls_pk_get_name(cert->pubkey->params.algo),
314
0
      se->name);
315
0
    return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
316
0
  }
317
318
0
  ret = _gnutls_session_sign_algo_enabled(session, sign_algo);
319
0
  if (ret < 0)
320
0
    return gnutls_assert_val(ret);
321
322
0
  dconcat.size = GNUTLS_RANDOM_SIZE * 2 + params->size;
323
0
  dconcat.data = gnutls_malloc(dconcat.size);
324
0
  if (dconcat.data == NULL)
325
0
    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
326
327
0
  memcpy(dconcat.data, session->security_parameters.client_random,
328
0
         GNUTLS_RANDOM_SIZE);
329
0
  memcpy(dconcat.data + GNUTLS_RANDOM_SIZE,
330
0
         session->security_parameters.server_random, GNUTLS_RANDOM_SIZE);
331
0
  memcpy(dconcat.data + GNUTLS_RANDOM_SIZE * 2, params->data,
332
0
         params->size);
333
334
0
  _gnutls_audit_data("tls::signature_algorithm", CRAU_WORD,
335
0
         se->aid.id[0] << 8 | se->aid.id[1], NULL);
336
337
0
  ret = gnutls_pubkey_verify_data2(cert->pubkey, sign_algo, verify_flags,
338
0
           &dconcat, signature);
339
0
  if (ret < 0)
340
0
    gnutls_assert();
341
342
0
  gnutls_free(dconcat.data);
343
344
0
  return ret;
345
0
}
346
347
int _gnutls_handshake_verify_data(gnutls_session_t session,
348
          unsigned verify_flags, gnutls_pcert_st *cert,
349
          const gnutls_datum_t *params,
350
          gnutls_datum_t *signature,
351
          gnutls_sign_algorithm_t sign_algo)
352
0
{
353
0
  unsigned key_usage;
354
0
  int ret;
355
0
  const version_entry_st *ver = get_version(session);
356
357
0
  if (cert == NULL) {
358
0
    gnutls_assert();
359
0
    return GNUTLS_E_CERTIFICATE_ERROR;
360
0
  }
361
362
0
  gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage);
363
364
0
  ret = _gnutls_check_key_usage_for_sig(session, key_usage, 0);
365
0
  if (ret < 0)
366
0
    return gnutls_assert_val(ret);
367
368
0
  gnutls_sign_algorithm_set_server(session, sign_algo);
369
370
0
  _gnutls_audit_new_context_with_data("name", CRAU_STRING, "tls::verify",
371
0
              NULL);
372
373
0
  if (_gnutls_version_has_selectable_sighash(ver))
374
0
    ret = _gnutls_handshake_verify_data12(session, verify_flags,
375
0
                  cert, params, signature,
376
0
                  sign_algo);
377
0
  else
378
0
    ret = _gnutls_handshake_verify_data10(session, verify_flags,
379
0
                  cert, params, signature,
380
0
                  sign_algo);
381
382
0
  gnutls_audit_pop_context();
383
0
  return ret;
384
0
}
385
386
/* Client certificate verify calculations
387
 */
388
389
static void _gnutls_reverse_datum(gnutls_datum_t *d)
390
0
{
391
0
  unsigned i;
392
393
0
  for (i = 0; i < d->size / 2; i++) {
394
0
    uint8_t t = d->data[i];
395
0
    d->data[i] = d->data[d->size - 1 - i];
396
0
    d->data[d->size - 1 - i] = t;
397
0
  }
398
0
}
399
400
static int _gnutls_create_reverse(const gnutls_datum_t *src,
401
          gnutls_datum_t *dst)
402
0
{
403
0
  unsigned int i;
404
405
0
  dst->size = src->size;
406
0
  dst->data = gnutls_malloc(dst->size);
407
0
  if (!dst->data)
408
0
    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
409
410
0
  for (i = 0; i < dst->size; i++)
411
0
    dst->data[i] = src->data[dst->size - 1 - i];
412
413
0
  return 0;
414
0
}
415
416
/* this is _gnutls_handshake_verify_crt_vrfy for TLS 1.2
417
 */
418
static int _gnutls_handshake_verify_crt_vrfy12(
419
  gnutls_session_t session, unsigned verify_flags, gnutls_pcert_st *cert,
420
  gnutls_datum_t *signature, gnutls_sign_algorithm_t sign_algo)
421
0
{
422
0
  int ret;
423
0
  gnutls_datum_t dconcat;
424
0
  const gnutls_sign_entry_st *se = _gnutls_sign_to_entry(sign_algo);
425
0
  gnutls_datum_t sig_rev = { NULL, 0 };
426
427
0
  ret = _gnutls_session_sign_algo_enabled(session, sign_algo);
428
0
  if (ret < 0)
429
0
    return gnutls_assert_val(ret);
430
431
0
  if (unlikely(sign_supports_cert_pk_algorithm(
432
0
           se, cert->pubkey->params.algo) == 0)) {
433
0
    _gnutls_handshake_log(
434
0
      "HSK[%p]: certificate of %s cannot be combined with %s sig\n",
435
0
      session, gnutls_pk_get_name(cert->pubkey->params.algo),
436
0
      se->name);
437
0
    return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
438
0
  }
439
440
0
  if (se->flags & GNUTLS_SIGN_FLAG_CRT_VRFY_REVERSE) {
441
0
    ret = _gnutls_create_reverse(signature, &sig_rev);
442
0
    if (ret < 0)
443
0
      return gnutls_assert_val(ret);
444
0
  }
445
446
0
  dconcat.data = session->internals.handshake_hash_buffer.data;
447
0
  dconcat.size = session->internals.handshake_hash_buffer_prev_len;
448
449
0
  _gnutls_audit_data("tls::signature_algorithm", CRAU_WORD,
450
0
         se->aid.id[0] << 8 | se->aid.id[1], NULL);
451
452
  /* Here we intentionally enable flag GNUTLS_VERIFY_ALLOW_BROKEN
453
   * because we have checked whether the currently used signature
454
   * algorithm is allowed in the session. */
455
0
  ret = gnutls_pubkey_verify_data2(
456
0
    cert->pubkey, sign_algo,
457
0
    verify_flags | GNUTLS_VERIFY_ALLOW_BROKEN, &dconcat,
458
0
    sig_rev.data ? &sig_rev : signature);
459
0
  _gnutls_free_datum(&sig_rev);
460
0
  if (ret < 0)
461
0
    gnutls_assert();
462
463
0
  return ret;
464
0
}
465
466
/* Verifies a SSL 3.0 signature (like the one in the client certificate
467
 * verify message).
468
 */
469
#ifdef ENABLE_SSL3
470
static int _gnutls_handshake_verify_crt_vrfy3(gnutls_session_t session,
471
                unsigned verify_flags,
472
                gnutls_pcert_st *cert,
473
                gnutls_datum_t *signature,
474
                gnutls_sign_algorithm_t sign_algo)
475
{
476
  int ret;
477
  uint8_t concat[MAX_SIG_SIZE];
478
  digest_hd_st td_sha;
479
  gnutls_datum_t dconcat;
480
  gnutls_pk_algorithm_t pk =
481
    gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);
482
  const gnutls_sign_entry_st *se;
483
484
  ret = _gnutls_generate_master(session, 1);
485
  if (ret < 0) {
486
    return gnutls_assert_val(ret);
487
  }
488
489
  dconcat.data = concat;
490
  dconcat.size = 0;
491
492
  if (pk == GNUTLS_PK_RSA) {
493
    digest_hd_st td_md5;
494
495
    ret = _gnutls_hash_init(&td_md5, hash_to_entry(GNUTLS_DIG_MD5));
496
    if (ret < 0)
497
      return gnutls_assert_val(ret);
498
499
    _gnutls_hash(&td_md5,
500
           session->internals.handshake_hash_buffer.data,
501
           session->internals.handshake_hash_buffer_prev_len);
502
503
    ret = _gnutls_mac_deinit_ssl3_handshake(
504
      &td_md5, concat,
505
      session->security_parameters.master_secret,
506
      GNUTLS_MASTER_SIZE);
507
    if (ret < 0)
508
      return gnutls_assert_val(ret);
509
510
    verify_flags |= GNUTLS_PUBKEY_VERIFY_FLAG_TLS1_RSA;
511
    dconcat.size = 16;
512
  }
513
514
  ret = _gnutls_hash_init(&td_sha, hash_to_entry(GNUTLS_DIG_SHA1));
515
  if (ret < 0) {
516
    gnutls_assert();
517
    return GNUTLS_E_HASH_FAILED;
518
  }
519
520
  _gnutls_hash(&td_sha, session->internals.handshake_hash_buffer.data,
521
         session->internals.handshake_hash_buffer_prev_len);
522
523
  ret = _gnutls_mac_deinit_ssl3_handshake(
524
    &td_sha, dconcat.data + dconcat.size,
525
    session->security_parameters.master_secret, GNUTLS_MASTER_SIZE);
526
  if (ret < 0) {
527
    return gnutls_assert_val(ret);
528
  }
529
530
  dconcat.size += 20;
531
532
  se = _gnutls_sign_to_entry(sign_algo);
533
  if (se) {
534
    _gnutls_audit_data("tls::signature_algorithm", CRAU_WORD,
535
           se->aid.id[0] << 8 | se->aid.id[1], NULL);
536
  }
537
538
  ret = gnutls_pubkey_verify_hash2(cert->pubkey, GNUTLS_SIGN_UNKNOWN,
539
           GNUTLS_VERIFY_ALLOW_SIGN_WITH_SHA1 |
540
             verify_flags,
541
           &dconcat, signature);
542
  if (ret < 0)
543
    return gnutls_assert_val(ret);
544
545
  return ret;
546
}
547
#endif
548
549
static int _gnutls_handshake_verify_crt_vrfy10(
550
  gnutls_session_t session, unsigned verify_flags, gnutls_pcert_st *cert,
551
  gnutls_datum_t *signature, gnutls_sign_algorithm_t sign_algo)
552
0
{
553
0
  int ret;
554
0
  uint8_t concat[MAX_SIG_SIZE];
555
0
  digest_hd_st td_sha;
556
0
  gnutls_datum_t dconcat;
557
0
  gnutls_pk_algorithm_t pk_algo;
558
0
  const mac_entry_st *me;
559
0
  const gnutls_sign_entry_st *se;
560
561
  /* TLS 1.0 and TLS 1.1 */
562
0
  pk_algo = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);
563
0
  if (pk_algo == GNUTLS_PK_RSA) {
564
0
    me = hash_to_entry(GNUTLS_DIG_MD5_SHA1);
565
0
    verify_flags |= GNUTLS_PUBKEY_VERIFY_FLAG_TLS1_RSA;
566
0
    sign_algo = GNUTLS_SIGN_UNKNOWN;
567
0
  } else {
568
0
    me = hash_to_entry(GNUTLS_DIG_SHA1);
569
0
    sign_algo = gnutls_pk_to_sign(pk_algo, GNUTLS_DIG_SHA1);
570
0
  }
571
0
  ret = _gnutls_hash_init(&td_sha, me);
572
0
  if (ret < 0) {
573
0
    gnutls_assert();
574
0
    return ret;
575
0
  }
576
577
0
  _gnutls_hash(&td_sha, session->internals.handshake_hash_buffer.data,
578
0
         session->internals.handshake_hash_buffer_prev_len);
579
580
0
  _gnutls_hash_deinit(&td_sha, concat);
581
582
0
  dconcat.data = concat;
583
0
  dconcat.size = _gnutls_hash_get_algo_len(me);
584
585
0
  se = _gnutls_sign_to_entry(sign_algo);
586
0
  if (se) {
587
0
    _gnutls_audit_data("tls::signature_algorithm", CRAU_WORD,
588
0
           se->aid.id[0] << 8 | se->aid.id[1], NULL);
589
0
  }
590
591
0
  ret = gnutls_pubkey_verify_hash2(cert->pubkey, sign_algo,
592
0
           GNUTLS_VERIFY_ALLOW_SIGN_WITH_SHA1 |
593
0
             verify_flags,
594
0
           &dconcat, signature);
595
0
  if (ret < 0)
596
0
    gnutls_assert();
597
598
0
  return ret;
599
0
}
600
601
/* Verifies a TLS signature (like the one in the client certificate
602
 * verify message). 
603
 */
604
int _gnutls_handshake_verify_crt_vrfy(gnutls_session_t session,
605
              unsigned verify_flags,
606
              gnutls_pcert_st *cert,
607
              gnutls_datum_t *signature,
608
              gnutls_sign_algorithm_t sign_algo)
609
0
{
610
0
  int ret;
611
0
  const version_entry_st *ver = get_version(session);
612
0
  unsigned key_usage;
613
614
0
  if (cert == NULL) {
615
0
    gnutls_assert();
616
0
    return GNUTLS_E_CERTIFICATE_ERROR;
617
0
  }
618
619
0
  gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage);
620
621
0
  ret = _gnutls_check_key_usage_for_sig(session, key_usage, 0);
622
0
  if (ret < 0)
623
0
    return gnutls_assert_val(ret);
624
625
0
  _gnutls_handshake_log("HSK[%p]: verify cert vrfy: using %s\n", session,
626
0
            gnutls_sign_algorithm_get_name(sign_algo));
627
628
0
  if (unlikely(ver == NULL))
629
0
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
630
631
0
  gnutls_sign_algorithm_set_client(session, sign_algo);
632
633
0
  _gnutls_audit_new_context_with_data("name", CRAU_STRING, "tls::verify",
634
0
              NULL);
635
636
  /* TLS 1.2 */
637
0
  if (_gnutls_version_has_selectable_sighash(ver))
638
0
    ret = _gnutls_handshake_verify_crt_vrfy12(
639
0
      session, verify_flags, cert, signature, sign_algo);
640
#ifdef ENABLE_SSL3
641
  else if (ver->id == GNUTLS_SSL3)
642
    ret = _gnutls_handshake_verify_crt_vrfy3(
643
      session, verify_flags, cert, signature, sign_algo);
644
#endif
645
0
  else {
646
    /* TLS 1.0 and TLS 1.1 */
647
0
    ret = _gnutls_handshake_verify_crt_vrfy10(
648
0
      session, verify_flags, cert, signature, sign_algo);
649
0
  }
650
651
0
  gnutls_audit_pop_context();
652
0
  return ret;
653
0
}
654
655
/* the same as _gnutls_handshake_sign_crt_vrfy except that it is made for TLS 1.2.
656
 * Returns the used signature algorithm, or a negative error code.
657
 */
658
static int _gnutls_handshake_sign_crt_vrfy12(gnutls_session_t session,
659
               gnutls_pcert_st *cert,
660
               gnutls_privkey_t pkey,
661
               gnutls_datum_t *signature)
662
0
{
663
0
  gnutls_datum_t dconcat;
664
0
  gnutls_sign_algorithm_t sign_algo;
665
0
  const gnutls_sign_entry_st *se;
666
0
  int ret;
667
668
0
  sign_algo = _gnutls_session_get_sign_algo(session, cert, pkey, 1,
669
0
              GNUTLS_KX_UNKNOWN);
670
0
  if (sign_algo == GNUTLS_SIGN_UNKNOWN) {
671
0
    gnutls_assert();
672
0
    return GNUTLS_E_UNWANTED_ALGORITHM;
673
0
  }
674
675
0
  se = _gnutls_sign_to_entry(sign_algo);
676
0
  if (se == NULL)
677
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
678
679
0
  _gnutls_audit_data("tls::signature_algorithm", CRAU_WORD,
680
0
         se->aid.id[0] << 8 | se->aid.id[1], NULL);
681
682
0
  gnutls_sign_algorithm_set_client(session, se->id);
683
684
0
  if (unlikely(sign_supports_priv_pk_algorithm(se, pkey->pk_algorithm) ==
685
0
         0))
686
0
    return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
687
688
0
  _gnutls_debug_log("sign handshake cert vrfy: picked %s\n",
689
0
        gnutls_sign_algorithm_get_name(sign_algo));
690
691
0
  dconcat.data = session->internals.handshake_hash_buffer.data;
692
0
  dconcat.size = session->internals.handshake_hash_buffer.length;
693
694
0
  ret = gnutls_privkey_sign_data2(pkey, sign_algo, 0, &dconcat,
695
0
          signature);
696
0
  if (ret < 0) {
697
0
    gnutls_assert();
698
0
    return ret;
699
0
  }
700
701
0
  if (se->flags & GNUTLS_SIGN_FLAG_CRT_VRFY_REVERSE)
702
0
    _gnutls_reverse_datum(signature);
703
704
0
  return sign_algo;
705
0
}
706
707
#ifdef ENABLE_SSL3
708
static int _gnutls_handshake_sign_crt_vrfy3(gnutls_session_t session,
709
              gnutls_pcert_st *cert,
710
              const version_entry_st *ver,
711
              gnutls_privkey_t pkey,
712
              gnutls_datum_t *signature)
713
{
714
  gnutls_datum_t dconcat;
715
  int ret;
716
  uint8_t concat[MAX_SIG_SIZE];
717
  digest_hd_st td_sha;
718
  gnutls_pk_algorithm_t pk = gnutls_privkey_get_pk_algorithm(pkey, NULL);
719
720
  /* ensure 1024 bit DSA keys are used */
721
  ret = _gnutls_pubkey_compatible_with_sig(session, cert->pubkey, ver,
722
             GNUTLS_SIGN_UNKNOWN);
723
  if (ret < 0)
724
    return gnutls_assert_val(ret);
725
726
  ret = _gnutls_generate_master(session, 1);
727
  if (ret < 0) {
728
    gnutls_assert();
729
    return ret;
730
  }
731
732
  dconcat.data = concat;
733
  dconcat.size = 0;
734
735
  if (pk == GNUTLS_PK_RSA) {
736
    digest_hd_st td_md5;
737
    ret = _gnutls_hash_init(&td_md5, hash_to_entry(GNUTLS_DIG_MD5));
738
    if (ret < 0)
739
      return gnutls_assert_val(ret);
740
741
    _gnutls_hash(&td_md5,
742
           session->internals.handshake_hash_buffer.data,
743
           session->internals.handshake_hash_buffer.length);
744
745
    ret = _gnutls_mac_deinit_ssl3_handshake(
746
      &td_md5, dconcat.data,
747
      session->security_parameters.master_secret,
748
      GNUTLS_MASTER_SIZE);
749
    if (ret < 0)
750
      return gnutls_assert_val(ret);
751
752
    dconcat.size = 16;
753
  }
754
755
  ret = _gnutls_hash_init(&td_sha, hash_to_entry(GNUTLS_DIG_SHA1));
756
  if (ret < 0) {
757
    gnutls_assert();
758
    return ret;
759
  }
760
761
  _gnutls_hash(&td_sha, session->internals.handshake_hash_buffer.data,
762
         session->internals.handshake_hash_buffer.length);
763
  ret = _gnutls_mac_deinit_ssl3_handshake(
764
    &td_sha, dconcat.data + dconcat.size,
765
    session->security_parameters.master_secret, GNUTLS_MASTER_SIZE);
766
  if (ret < 0)
767
    return gnutls_assert_val(ret);
768
769
  dconcat.size += 20;
770
771
  ret = gnutls_privkey_sign_hash(pkey, GNUTLS_DIG_SHA1,
772
               GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA,
773
               &dconcat, signature);
774
  if (ret < 0)
775
    return gnutls_assert_val(ret);
776
777
  return ret;
778
}
779
#endif
780
781
static int _gnutls_handshake_sign_crt_vrfy10(gnutls_session_t session,
782
               gnutls_pcert_st *cert,
783
               const version_entry_st *ver,
784
               gnutls_privkey_t pkey,
785
               gnutls_datum_t *signature)
786
0
{
787
0
  gnutls_datum_t dconcat;
788
0
  int ret;
789
0
  uint8_t concat[MAX_SIG_SIZE];
790
0
  digest_hd_st td_sha;
791
0
  gnutls_pk_algorithm_t pk = gnutls_privkey_get_pk_algorithm(pkey, NULL);
792
0
  const mac_entry_st *me;
793
794
  /* ensure 1024 bit DSA keys are used */
795
0
  ret = _gnutls_pubkey_compatible_with_sig(session, cert->pubkey, ver,
796
0
             GNUTLS_SIGN_UNKNOWN);
797
0
  if (ret < 0)
798
0
    return gnutls_assert_val(ret);
799
800
0
  if (pk == GNUTLS_PK_RSA)
801
0
    me = hash_to_entry(GNUTLS_DIG_MD5_SHA1);
802
0
  else
803
0
    me = hash_to_entry(GNUTLS_DIG_SHA1);
804
805
0
  ret = _gnutls_hash_init(&td_sha, me);
806
0
  if (ret < 0) {
807
0
    gnutls_assert();
808
0
    return ret;
809
0
  }
810
811
0
  _gnutls_hash(&td_sha, session->internals.handshake_hash_buffer.data,
812
0
         session->internals.handshake_hash_buffer.length);
813
814
0
  _gnutls_hash_deinit(&td_sha, concat);
815
816
0
  dconcat.data = concat;
817
0
  dconcat.size = _gnutls_hash_get_algo_len(me);
818
819
0
  ret = gnutls_privkey_sign_hash(pkey, MAC_TO_DIG(me->id),
820
0
               GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA,
821
0
               &dconcat, signature);
822
0
  if (ret < 0) {
823
0
    gnutls_assert();
824
0
    return ret;
825
0
  }
826
827
0
  return GNUTLS_SIGN_UNKNOWN;
828
0
}
829
830
/* Generates a signature of all the previous sent packets in the
831
 * handshake procedure.
832
 * 20040227: now it works for SSL 3.0 as well
833
 * 20091031: works for TLS 1.2 too!
834
 *
835
 * For TLS1.x, x<2 returns negative for failure and zero or unspecified for success.
836
 * For TLS1.2 returns the signature algorithm used on success, or a negative error code;
837
 *
838
 * Returns the used signature algorithm, or a negative error code.
839
 */
840
int _gnutls_handshake_sign_crt_vrfy(gnutls_session_t session,
841
            gnutls_pcert_st *cert,
842
            gnutls_privkey_t pkey,
843
            gnutls_datum_t *signature)
844
0
{
845
0
  int ret;
846
0
  const version_entry_st *ver = get_version(session);
847
0
  unsigned key_usage = 0;
848
849
0
  if (unlikely(ver == NULL))
850
0
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
851
852
0
  gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage);
853
854
0
  ret = _gnutls_check_key_usage_for_sig(session, key_usage, 1);
855
0
  if (ret < 0)
856
0
    return gnutls_assert_val(ret);
857
858
0
  _gnutls_audit_new_context_with_data("name", CRAU_STRING, "tls::sign",
859
0
              NULL);
860
861
  /* TLS 1.2 */
862
0
  if (_gnutls_version_has_selectable_sighash(ver))
863
0
    ret = _gnutls_handshake_sign_crt_vrfy12(session, cert, pkey,
864
0
              signature);
865
866
  /* TLS 1.1 or earlier */
867
#ifdef ENABLE_SSL3
868
  else if (ver->id == GNUTLS_SSL3)
869
    ret = _gnutls_handshake_sign_crt_vrfy3(session, cert, ver, pkey,
870
                   signature);
871
#endif
872
0
  else {
873
0
    ret = _gnutls_handshake_sign_crt_vrfy10(session, cert, ver,
874
0
              pkey, signature);
875
0
  }
876
877
0
  gnutls_audit_pop_context();
878
0
  return ret;
879
0
}