Coverage Report

Created: 2024-06-20 06:28

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