Coverage Report

Created: 2023-03-26 07:33

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