Coverage Report

Created: 2025-03-18 06:55

/src/gnutls/lib/auth/cert.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
/* The certificate authentication functions which are needed in the handshake,
25
 * and are common to RSA and DHE key exchange, are in this file.
26
 */
27
28
#include "gnutls_int.h"
29
#include "auth.h"
30
#include "errors.h"
31
#include "auth/cert.h"
32
#include "dh.h"
33
#include "num.h"
34
#include "libtasn1.h"
35
#include "datum.h"
36
#include "ext/signature.h"
37
#include "pk.h"
38
#include "algorithms.h"
39
#include "global.h"
40
#include "record.h"
41
#include "tls-sig.h"
42
#include "state.h"
43
#include "pk.h"
44
#include "x509.h"
45
#include "x509/verify-high.h"
46
#include <gnutls/abstract.h>
47
#include "abstract_int.h"
48
#include "debug.h"
49
50
static void selected_certs_set(gnutls_session_t session, gnutls_pcert_st *certs,
51
             int ncerts, gnutls_ocsp_data_st *ocsp,
52
             unsigned nocsp, gnutls_privkey_t key,
53
             int need_free,
54
             gnutls_status_request_ocsp_func ocsp_func,
55
             void *ocsp_func_ptr);
56
57
0
#define MAX_CLIENT_SIGN_ALGOS 5
58
#define CERTTYPE_SIZE (MAX_CLIENT_SIGN_ALGOS + 1)
59
typedef enum CertificateSigType {
60
  RSA_SIGN = 1,
61
  DSA_SIGN = 2,
62
  ECDSA_SIGN = 64,
63
#ifdef ENABLE_GOST
64
  GOSTR34102012_256_SIGN = 67,
65
  GOSTR34102012_512_SIGN = 68
66
#endif
67
} CertificateSigType;
68
69
enum CertificateSigTypeFlags {
70
  RSA_SIGN_FLAG = 1,
71
  DSA_SIGN_FLAG = 1 << 1,
72
  ECDSA_SIGN_FLAG = 1 << 2,
73
#ifdef ENABLE_GOST
74
  GOSTR34102012_256_SIGN_FLAG = 1 << 3,
75
  GOSTR34102012_512_SIGN_FLAG = 1 << 4
76
#endif
77
};
78
79
/* Moves data from an internal certificate struct (gnutls_pcert_st) to
80
 * another internal certificate struct (cert_auth_info_t), and deinitializes
81
 * the former.
82
 */
83
int _gnutls_pcert_to_auth_info(cert_auth_info_t info, gnutls_pcert_st *certs,
84
             size_t ncerts)
85
0
{
86
0
  size_t i, j;
87
88
0
  if (info->raw_certificate_list != NULL) {
89
0
    for (j = 0; j < info->ncerts; j++)
90
0
      _gnutls_free_datum(&info->raw_certificate_list[j]);
91
0
    gnutls_free(info->raw_certificate_list);
92
0
  }
93
94
0
  if (ncerts == 0) {
95
0
    info->raw_certificate_list = NULL;
96
0
    info->ncerts = 0;
97
0
    return 0;
98
0
  }
99
100
0
  info->raw_certificate_list =
101
0
    gnutls_calloc(ncerts, sizeof(gnutls_datum_t));
102
0
  if (info->raw_certificate_list == NULL) {
103
0
    gnutls_assert();
104
0
    return GNUTLS_E_MEMORY_ERROR;
105
0
  }
106
107
0
  info->cert_type = certs[0].type;
108
0
  info->ncerts = ncerts;
109
110
0
  for (i = 0; i < ncerts; i++) {
111
0
    info->raw_certificate_list[i].data = certs[i].cert.data;
112
0
    info->raw_certificate_list[i].size = certs[i].cert.size;
113
0
    certs[i].cert.data = NULL;
114
0
    gnutls_pcert_deinit(&certs[i]);
115
0
  }
116
0
  gnutls_free(certs);
117
118
0
  return 0;
119
0
}
120
121
/* returns 0 if the algo_to-check exists in the pk_algos list,
122
 * -1 otherwise.
123
 */
124
inline static int check_pk_algo_in_list(const gnutls_pk_algorithm_t *pk_algos,
125
          int pk_algos_length,
126
          gnutls_pk_algorithm_t algo_to_check)
127
0
{
128
0
  int i;
129
0
  for (i = 0; i < pk_algos_length; i++) {
130
0
    if (algo_to_check == pk_algos[i]) {
131
0
      return 0;
132
0
    }
133
0
  }
134
0
  return -1;
135
0
}
136
137
/* Returns the issuer's Distinguished name in odn, of the certificate
138
 * specified in cert.
139
 */
140
static int cert_get_issuer_dn(gnutls_pcert_st *cert, gnutls_datum_t *odn)
141
0
{
142
0
  asn1_node dn;
143
0
  int len, result;
144
0
  int start, end;
145
146
0
  if ((result = asn1_create_element(_gnutls_get_pkix(),
147
0
            "PKIX1.Certificate", &dn)) !=
148
0
      ASN1_SUCCESS) {
149
0
    gnutls_assert();
150
0
    return _gnutls_asn2err(result);
151
0
  }
152
153
0
  result = asn1_der_decoding(&dn, cert->cert.data, cert->cert.size, NULL);
154
0
  if (result != ASN1_SUCCESS) {
155
    /* couldn't decode DER */
156
0
    gnutls_assert();
157
0
    asn1_delete_structure(&dn);
158
0
    return _gnutls_asn2err(result);
159
0
  }
160
161
0
  result = asn1_der_decoding_startEnd(dn, cert->cert.data,
162
0
              cert->cert.size,
163
0
              "tbsCertificate.issuer", &start,
164
0
              &end);
165
166
0
  if (result != ASN1_SUCCESS) {
167
    /* couldn't decode DER */
168
0
    gnutls_assert();
169
0
    asn1_delete_structure(&dn);
170
0
    return _gnutls_asn2err(result);
171
0
  }
172
0
  asn1_delete_structure(&dn);
173
174
0
  len = end - start + 1;
175
176
0
  odn->size = len;
177
0
  odn->data = &cert->cert.data[start];
178
179
0
  return 0;
180
0
}
181
182
/* Locates the most appropriate x509 certificate using the
183
 * given DN. If indx == -1 then no certificate was found.
184
 *
185
 * That is to guess which certificate to use, based on the
186
 * CAs and sign algorithms supported by the peer server.
187
 */
188
static int find_x509_client_cert(gnutls_session_t session,
189
         const gnutls_certificate_credentials_t cred,
190
         const uint8_t *_data, size_t _data_size,
191
         const gnutls_pk_algorithm_t *pk_algos,
192
         int pk_algos_length, int *indx)
193
0
{
194
0
  unsigned size;
195
0
  gnutls_datum_t odn = { NULL, 0 }, asked_dn;
196
0
  const uint8_t *data = _data;
197
0
  ssize_t data_size = _data_size;
198
0
  unsigned i, j;
199
0
  int result, cert_pk;
200
0
  unsigned key_usage;
201
202
0
  *indx = -1;
203
204
  /* If peer doesn't send any issuers and we have a single certificate
205
   * then send that one.
206
   */
207
0
  if (cred->ncerts == 1 &&
208
0
      (data_size == 0 ||
209
0
       (session->internals.flags & GNUTLS_FORCE_CLIENT_CERT))) {
210
0
    if (cred->certs[0].cert_list[0].type == GNUTLS_CRT_X509) {
211
0
      key_usage = get_key_usage(
212
0
        session, cred->certs[0].cert_list[0].pubkey);
213
214
      /* For client certificates we require signatures */
215
0
      result = _gnutls_check_key_usage_for_sig(session,
216
0
                 key_usage, 1);
217
0
      if (result < 0) {
218
0
        _gnutls_debug_log(
219
0
          "Client certificate is not suitable for signing\n");
220
0
        return gnutls_assert_val(result);
221
0
      }
222
223
0
      *indx = 0;
224
0
      return 0;
225
0
    }
226
0
  }
227
228
0
  do {
229
0
    DECR_LENGTH_RET(data_size, 2, 0);
230
0
    size = _gnutls_read_uint16(data);
231
0
    DECR_LENGTH_RET(data_size, size, 0);
232
0
    data += 2;
233
234
0
    asked_dn.data = (void *)data;
235
0
    asked_dn.size = size;
236
0
    _gnutls_dn_log("Peer requested CA", &asked_dn);
237
238
0
    for (i = 0; i < cred->ncerts; i++) {
239
0
      for (j = 0; j < cred->certs[i].cert_list_length; j++) {
240
0
        if ((result = cert_get_issuer_dn(
241
0
               &cred->certs[i].cert_list[j],
242
0
               &odn)) < 0) {
243
0
          gnutls_assert();
244
0
          return result;
245
0
        }
246
247
0
        if (odn.size == 0 || odn.size != asked_dn.size)
248
0
          continue;
249
250
0
        key_usage = get_key_usage(
251
0
          session,
252
0
          cred->certs[i].cert_list[0].pubkey);
253
254
        /* For client certificates we require signatures */
255
0
        if (_gnutls_check_key_usage_for_sig(
256
0
              session, key_usage, 1) < 0) {
257
0
          _gnutls_debug_log(
258
0
            "Client certificate is not suitable for signing\n");
259
0
          continue;
260
0
        }
261
262
        /* If the DN matches and
263
         * the *_SIGN algorithm matches
264
         * the cert is our cert!
265
         */
266
0
        cert_pk = gnutls_pubkey_get_pk_algorithm(
267
0
          cred->certs[i].cert_list[0].pubkey,
268
0
          NULL);
269
270
0
        if ((memcmp(odn.data, asked_dn.data,
271
0
              asked_dn.size) == 0) &&
272
0
            (check_pk_algo_in_list(pk_algos,
273
0
                 pk_algos_length,
274
0
                 cert_pk) == 0)) {
275
0
          *indx = i;
276
0
          break;
277
0
        }
278
0
      }
279
0
      if (*indx != -1)
280
0
        break;
281
0
    }
282
283
0
    if (*indx != -1)
284
0
      break;
285
286
    /* move to next record */
287
0
    data += size;
288
0
  } while (1);
289
290
0
  return 0;
291
0
}
292
293
/* Locates the first raw public-key.
294
 * Currently it only makes sense to associate one raw pubkey per session.
295
 * Associating more raw pubkeys with a session has no use because we
296
 * don't know how to select the correct one.
297
 */
298
static int find_rawpk_client_cert(gnutls_session_t session,
299
          const gnutls_certificate_credentials_t cred,
300
          const gnutls_pk_algorithm_t *pk_algos,
301
          int pk_algos_length, int *indx)
302
0
{
303
0
  unsigned i;
304
0
  int ret;
305
0
  gnutls_pk_algorithm_t pk;
306
307
0
  *indx = -1;
308
309
0
  for (i = 0; i < cred->ncerts; i++) {
310
    /* We know that our list length will be 1, therefore we can
311
     * ignore the rest.
312
     */
313
0
    if (cred->certs[i].cert_list_length == 1 &&
314
0
        cred->certs[i].cert_list[0].type == GNUTLS_CRT_RAWPK) {
315
0
      pk = gnutls_pubkey_get_pk_algorithm(
316
0
        cred->certs[i].cert_list[0].pubkey, NULL);
317
318
      /* For client certificates we require signatures */
319
0
      ret = _gnutls_check_key_usage_for_sig(
320
0
        session,
321
0
        get_key_usage(
322
0
          session,
323
0
          cred->certs[i].cert_list[0].pubkey),
324
0
        1);
325
0
      if (ret < 0) {
326
        /* we return an error instead of skipping so that the user is notified about
327
         * the key incompatibility */
328
0
        _gnutls_debug_log(
329
0
          "Client certificate is not suitable for signing\n");
330
0
        return gnutls_assert_val(ret);
331
0
      }
332
333
      /* Check whether the public-key algorithm of our credential is in
334
       * the list with supported public-key algorithms and whether the
335
       * cert type matches. */
336
0
      if ((check_pk_algo_in_list(pk_algos, pk_algos_length,
337
0
               pk) == 0)) {
338
        // We found a compatible credential
339
0
        *indx = i;
340
0
        break;
341
0
      }
342
0
    }
343
0
  }
344
345
0
  return 0;
346
0
}
347
348
/* Returns the number of issuers in the server's
349
 * certificate request packet.
350
 */
351
static int get_issuers_num(gnutls_session_t session, const uint8_t *data,
352
         ssize_t data_size)
353
0
{
354
0
  int issuers_dn_len = 0;
355
0
  unsigned size;
356
357
  /* Count the number of the given issuers;
358
   * This is used to allocate the issuers_dn without
359
   * using realloc().
360
   */
361
362
0
  if (data_size == 0 || data == NULL)
363
0
    return 0;
364
365
0
  while (data_size > 0) {
366
    /* This works like DECR_LEN()
367
     */
368
0
    DECR_LENGTH_RET(data_size, 2,
369
0
        GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
370
0
    size = _gnutls_read_uint16(data);
371
372
0
    DECR_LENGTH_RET(data_size, size,
373
0
        GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
374
375
0
    data += 2;
376
377
0
    if (size > 0) {
378
0
      issuers_dn_len++;
379
0
      data += size;
380
0
    }
381
0
  }
382
383
0
  return issuers_dn_len;
384
0
}
385
386
/* Returns the issuers in the server's certificate request
387
 * packet.
388
 */
389
static int get_issuers(gnutls_session_t session, gnutls_datum_t *issuers_dn,
390
           int issuers_len, const uint8_t *data, size_t data_size)
391
0
{
392
0
  int i;
393
0
  unsigned size;
394
395
0
  if (get_certificate_type(session, GNUTLS_CTYPE_CLIENT) !=
396
0
      GNUTLS_CRT_X509)
397
0
    return 0;
398
399
  /* put the requested DNs to req_dn, only in case
400
   * of X509 certificates.
401
   */
402
0
  if (issuers_len > 0) {
403
0
    for (i = 0; i < issuers_len; i++) {
404
      /* The checks here for the buffer boundaries
405
       * are not needed since the buffer has been
406
       * parsed above.
407
       */
408
0
      data_size -= 2;
409
410
0
      size = _gnutls_read_uint16(data);
411
412
0
      data += 2;
413
414
0
      issuers_dn[i].data = (void *)data;
415
0
      issuers_dn[i].size = size;
416
417
0
      _gnutls_dn_log("Peer requested CA", &issuers_dn[i]);
418
419
0
      data += size;
420
0
    }
421
0
  }
422
423
0
  return 0;
424
0
}
425
426
/* Calls the client or server certificate get callback.
427
 */
428
static int call_get_cert_callback(gnutls_session_t session,
429
          const gnutls_datum_t *issuers_dn,
430
          int issuers_dn_length,
431
          gnutls_pk_algorithm_t *pk_algos,
432
          int pk_algos_length)
433
0
{
434
0
  gnutls_privkey_t local_key = NULL;
435
0
  int ret = GNUTLS_E_INTERNAL_ERROR;
436
0
  gnutls_certificate_type_t type;
437
0
  gnutls_certificate_credentials_t cred;
438
0
  gnutls_pcert_st *pcert = NULL;
439
0
  gnutls_ocsp_data_st *ocsp = NULL;
440
0
  unsigned int ocsp_length = 0;
441
0
  unsigned int pcert_length = 0;
442
443
0
  cred = (gnutls_certificate_credentials_t)_gnutls_get_cred(
444
0
    session, GNUTLS_CRD_CERTIFICATE);
445
0
  if (cred == NULL) {
446
0
    gnutls_assert();
447
0
    return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
448
0
  }
449
450
  /* Correctly set the certificate type for ourselves */
451
0
  type = get_certificate_type(session, GNUTLS_CTYPE_OURS);
452
453
  /* Check whether a callback is set and call it */
454
0
  if (cred->get_cert_callback3) {
455
0
    struct gnutls_cert_retr_st info;
456
0
    unsigned int flags = 0;
457
458
0
    memset(&info, 0, sizeof(info));
459
0
    info.req_ca_rdn = issuers_dn;
460
0
    info.nreqs = issuers_dn_length;
461
0
    info.pk_algos = pk_algos;
462
0
    info.pk_algos_length = pk_algos_length;
463
0
    info.cred = cred;
464
465
    /* we avoid all allocations and transformations */
466
0
    ret = cred->get_cert_callback3(session, &info, &pcert,
467
0
                 &pcert_length, &ocsp,
468
0
                 &ocsp_length, &local_key,
469
0
                 &flags);
470
0
    if (ret < 0)
471
0
      return gnutls_assert_val(GNUTLS_E_USER_ERROR);
472
473
0
    if (pcert_length > 0 && type != pcert[0].type)
474
0
      return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
475
476
0
    if (pcert_length == 0) {
477
0
      pcert = NULL;
478
0
      local_key = NULL;
479
0
    }
480
481
0
    selected_certs_set(
482
0
      session, pcert, pcert_length, ocsp, ocsp_length,
483
0
      local_key,
484
0
      (flags & GNUTLS_CERT_RETR_DEINIT_ALL) ? 1 : 0,
485
0
      cred->glob_ocsp_func, cred->glob_ocsp_func_ptr);
486
487
0
    return 0;
488
0
  } else {
489
0
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
490
0
  }
491
0
}
492
493
/* Finds the appropriate certificate depending on the cA Distinguished name
494
 * advertised by the server. If none matches then returns 0 and -1 as index.
495
 * In case of an error a negative error code, is returned.
496
 *
497
 * 20020128: added ability to select a certificate depending on the SIGN
498
 * algorithm (only in automatic mode).
499
 */
500
int _gnutls_select_client_cert(gnutls_session_t session, const uint8_t *_data,
501
             size_t _data_size,
502
             gnutls_pk_algorithm_t *pk_algos,
503
             int pk_algos_length)
504
0
{
505
0
  int result;
506
0
  int indx = -1;
507
0
  gnutls_certificate_credentials_t cred;
508
0
  const uint8_t *data = _data;
509
0
  ssize_t data_size = _data_size;
510
0
  int issuers_dn_length;
511
0
  gnutls_datum_t *issuers_dn = NULL;
512
0
  gnutls_certificate_type_t cert_type;
513
514
0
  cred = (gnutls_certificate_credentials_t)_gnutls_get_cred(
515
0
    session, GNUTLS_CRD_CERTIFICATE);
516
0
  if (cred == NULL) {
517
0
    gnutls_assert();
518
0
    return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
519
0
  }
520
521
0
  cert_type = get_certificate_type(session, GNUTLS_CTYPE_CLIENT);
522
523
0
  if (cred->get_cert_callback3 != NULL) {
524
    /* use a callback to get certificate
525
     */
526
0
    if (cert_type == GNUTLS_CRT_X509) {
527
0
      issuers_dn_length =
528
0
        get_issuers_num(session, data, data_size);
529
0
      if (issuers_dn_length < 0) {
530
0
        gnutls_assert();
531
0
        return issuers_dn_length;
532
0
      }
533
534
0
      if (issuers_dn_length > 0) {
535
0
        issuers_dn =
536
0
          gnutls_malloc(sizeof(gnutls_datum_t) *
537
0
                  issuers_dn_length);
538
0
        if (issuers_dn == NULL) {
539
0
          gnutls_assert();
540
0
          return GNUTLS_E_MEMORY_ERROR;
541
0
        }
542
543
0
        result = get_issuers(session, issuers_dn,
544
0
                 issuers_dn_length, data,
545
0
                 data_size);
546
0
        if (result < 0) {
547
0
          gnutls_assert();
548
0
          goto cleanup;
549
0
        }
550
0
      }
551
0
    } else {
552
0
      issuers_dn_length = 0;
553
0
    }
554
555
0
    result = call_get_cert_callback(session, issuers_dn,
556
0
            issuers_dn_length, pk_algos,
557
0
            pk_algos_length);
558
0
    goto cleanup;
559
560
0
  } else {
561
    /* If we have no callbacks, try to guess.
562
     */
563
0
    switch (cert_type) {
564
0
    case GNUTLS_CRT_X509:
565
0
      result = find_x509_client_cert(session, cred, _data,
566
0
                   _data_size, pk_algos,
567
0
                   pk_algos_length, &indx);
568
0
      break;
569
0
    case GNUTLS_CRT_RAWPK:
570
0
      result = find_rawpk_client_cert(session, cred, pk_algos,
571
0
              pk_algos_length, &indx);
572
0
      break;
573
0
    default:
574
0
      result = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
575
0
      break;
576
0
    }
577
578
0
    if (result < 0) {
579
0
      return gnutls_assert_val(result);
580
0
    }
581
582
0
    if (indx >= 0) {
583
0
      selected_certs_set(session,
584
0
             &cred->certs[indx].cert_list[0],
585
0
             cred->certs[indx].cert_list_length,
586
0
             cred->certs[indx].ocsp_data,
587
0
             cred->certs[indx].ocsp_data_length,
588
0
             cred->certs[indx].pkey, 0, NULL,
589
0
             NULL);
590
0
    } else {
591
0
      selected_certs_set(session, NULL, 0, NULL, 0, NULL, 0,
592
0
             NULL, NULL);
593
0
    }
594
595
0
    result = 0;
596
0
  }
597
598
0
cleanup:
599
0
  gnutls_free(issuers_dn);
600
0
  return result;
601
0
}
602
603
/* Generate certificate message
604
 */
605
static int gen_x509_crt(gnutls_session_t session, gnutls_buffer_st *data)
606
0
{
607
0
  int ret, i;
608
0
  gnutls_pcert_st *apr_cert_list;
609
0
  gnutls_privkey_t apr_pkey;
610
0
  int apr_cert_list_length;
611
0
  unsigned init_pos = data->length;
612
613
  /* find the appropriate certificate
614
   */
615
0
  if ((ret = _gnutls_get_selected_cert(session, &apr_cert_list,
616
0
               &apr_cert_list_length,
617
0
               &apr_pkey)) < 0) {
618
0
    gnutls_assert();
619
0
    return ret;
620
0
  }
621
622
0
  ret = 3;
623
0
  for (i = 0; i < apr_cert_list_length; i++) {
624
0
    ret += apr_cert_list[i].cert.size + 3;
625
    /* hold size
626
     * for uint24 */
627
0
  }
628
629
  /* if no certificates were found then send:
630
   * 0B 00 00 03 00 00 00    // Certificate with no certs
631
   * instead of:
632
   * 0B 00 00 00    // empty certificate handshake
633
   *
634
   * ( the above is the whole handshake message, not
635
   * the one produced here )
636
   */
637
638
0
  ret = _gnutls_buffer_append_prefix(data, 24, ret - 3);
639
0
  if (ret < 0)
640
0
    return gnutls_assert_val(ret);
641
642
0
  for (i = 0; i < apr_cert_list_length; i++) {
643
0
    ret = _gnutls_buffer_append_data_prefix(
644
0
      data, 24, apr_cert_list[i].cert.data,
645
0
      apr_cert_list[i].cert.size);
646
0
    if (ret < 0)
647
0
      return gnutls_assert_val(ret);
648
0
  }
649
650
0
  return data->length - init_pos;
651
0
}
652
653
/* Generates a Raw Public Key certificate message that holds only the
654
 * SubjectPublicKeyInfo part of a regular certificate message.
655
 *
656
 * Returns the number of bytes sent or a negative error code.
657
 */
658
int _gnutls_gen_rawpk_crt(gnutls_session_t session, gnutls_buffer_st *data)
659
0
{
660
0
  int ret;
661
0
  gnutls_pcert_st *apr_cert_list;
662
0
  gnutls_privkey_t apr_pkey;
663
0
  int apr_cert_list_length;
664
665
0
  if ((ret = _gnutls_get_selected_cert(session, &apr_cert_list,
666
0
               &apr_cert_list_length,
667
0
               &apr_pkey)) < 0) {
668
0
    return gnutls_assert_val(ret);
669
0
  }
670
671
  /* Since we are transmitting a raw public key with no additional
672
   * certificate credentials attached to it, it doesn't make sense to
673
   * have more than one certificate set (i.e. to have a certificate chain).
674
   */
675
0
  assert(apr_cert_list_length <= 1);
676
677
  /* Write our certificate containing only the SubjectPublicKeyInfo to
678
   * the output buffer. We always have exactly one certificate that
679
   * contains our raw public key. Our message looks like:
680
   * <length++certificate> where
681
   * length = 3 bytes (or 24 bits) and
682
   * certificate = length bytes.
683
   */
684
0
  if (apr_cert_list_length == 0) {
685
0
    ret = _gnutls_buffer_append_prefix(data, 24, 0);
686
0
  } else {
687
0
    ret = _gnutls_buffer_append_data_prefix(
688
0
      data, 24, apr_cert_list[0].cert.data,
689
0
      apr_cert_list[0].cert.size);
690
0
  }
691
692
0
  if (ret < 0)
693
0
    return gnutls_assert_val(ret);
694
695
0
  return data->length;
696
0
}
697
698
int _gnutls_gen_cert_client_crt(gnutls_session_t session,
699
        gnutls_buffer_st *data)
700
0
{
701
0
  gnutls_certificate_type_t cert_type;
702
703
  // Retrieve the (negotiated) certificate type for the client
704
0
  cert_type = get_certificate_type(session, GNUTLS_CTYPE_CLIENT);
705
706
0
  switch (cert_type) {
707
0
  case GNUTLS_CRT_X509:
708
0
    return gen_x509_crt(session, data);
709
0
  case GNUTLS_CRT_RAWPK:
710
0
    return _gnutls_gen_rawpk_crt(session, data);
711
0
  default:
712
0
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
713
0
  }
714
0
}
715
716
int _gnutls_gen_cert_server_crt(gnutls_session_t session,
717
        gnutls_buffer_st *data)
718
0
{
719
0
  gnutls_certificate_type_t cert_type;
720
721
  // Retrieve the (negotiated) certificate type for the server
722
0
  cert_type = get_certificate_type(session, GNUTLS_CTYPE_SERVER);
723
724
0
  switch (cert_type) {
725
0
  case GNUTLS_CRT_X509:
726
0
    return gen_x509_crt(session, data);
727
0
  case GNUTLS_CRT_RAWPK:
728
0
    return _gnutls_gen_rawpk_crt(session, data);
729
0
  default:
730
0
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
731
0
  }
732
0
}
733
734
static int check_pk_compat(gnutls_session_t session, gnutls_pubkey_t pubkey)
735
0
{
736
0
  unsigned cert_pk;
737
0
  unsigned kx;
738
739
0
  if (session->security_parameters.entity != GNUTLS_CLIENT)
740
0
    return 0;
741
742
0
  cert_pk = gnutls_pubkey_get_pk_algorithm(pubkey, NULL);
743
0
  if (cert_pk == GNUTLS_PK_UNKNOWN) {
744
0
    gnutls_assert();
745
0
    return GNUTLS_E_CERTIFICATE_ERROR;
746
0
  }
747
748
0
  kx = session->security_parameters.cs->kx_algorithm;
749
750
0
  if (_gnutls_map_kx_get_cred(kx, 1) == GNUTLS_CRD_CERTIFICATE &&
751
0
      !_gnutls_kx_supports_pk(kx, cert_pk)) {
752
0
    gnutls_assert();
753
0
    return GNUTLS_E_CERTIFICATE_ERROR;
754
0
  }
755
756
0
  return 0;
757
0
}
758
759
/* Process server certificate
760
 */
761
#define CLEAR_CERTS                                      \
762
0
  for (x = 0; x < peer_certificate_list_size; x++) \
763
0
  gnutls_pcert_deinit(&peer_certificate_list[x])
764
static int _gnutls_proc_x509_crt(gnutls_session_t session, uint8_t *data,
765
         size_t data_size)
766
0
{
767
0
  int size, len, ret;
768
0
  uint8_t *p = data;
769
0
  cert_auth_info_t info;
770
0
  gnutls_certificate_credentials_t cred;
771
0
  ssize_t dsize = data_size;
772
0
  int i;
773
0
  gnutls_pcert_st *peer_certificate_list;
774
0
  size_t peer_certificate_list_size = 0, j, x;
775
0
  gnutls_datum_t tmp;
776
777
0
  cred = (gnutls_certificate_credentials_t)_gnutls_get_cred(
778
0
    session, GNUTLS_CRD_CERTIFICATE);
779
0
  if (cred == NULL) {
780
0
    gnutls_assert();
781
0
    return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
782
0
  }
783
784
0
  if ((ret = _gnutls_auth_info_init(session, GNUTLS_CRD_CERTIFICATE,
785
0
            sizeof(cert_auth_info_st), 1)) < 0) {
786
0
    gnutls_assert();
787
0
    return ret;
788
0
  }
789
790
0
  info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
791
0
  if (unlikely(!info)) {
792
0
    gnutls_assert();
793
0
    return ret;
794
0
  }
795
796
0
  if (data == NULL || data_size == 0) {
797
0
    gnutls_assert();
798
    /* no certificate was sent */
799
0
    return GNUTLS_E_NO_CERTIFICATE_FOUND;
800
0
  }
801
802
0
  DECR_LEN(dsize, 3);
803
0
  size = _gnutls_read_uint24(p);
804
0
  p += 3;
805
806
  /* ensure no discrepancy in data */
807
0
  if (size != dsize)
808
0
    return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
809
810
  /* some implementations send 0B 00 00 06 00 00 03 00 00 00
811
   * instead of just 0B 00 00 03 00 00 00 as an empty certificate message.
812
   */
813
0
  if (size == 0 || (size == 3 && memcmp(p, "\x00\x00\x00", 3) == 0)) {
814
0
    gnutls_assert();
815
    /* no certificate was sent */
816
0
    return GNUTLS_E_NO_CERTIFICATE_FOUND;
817
0
  }
818
819
0
  i = dsize;
820
0
  while (i > 0) {
821
0
    DECR_LEN(dsize, 3);
822
0
    len = _gnutls_read_uint24(p);
823
0
    p += 3;
824
0
    DECR_LEN(dsize, len);
825
0
    peer_certificate_list_size++;
826
0
    p += len;
827
0
    i -= len + 3;
828
0
  }
829
830
0
  if (dsize != 0)
831
0
    return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
832
833
0
  if (peer_certificate_list_size == 0) {
834
0
    gnutls_assert();
835
0
    return GNUTLS_E_NO_CERTIFICATE_FOUND;
836
0
  }
837
838
  /* Ok we now allocate the memory to hold the
839
   * certificate list
840
   */
841
842
0
  peer_certificate_list = gnutls_calloc(
843
0
    1, sizeof(gnutls_pcert_st) * (peer_certificate_list_size));
844
0
  if (peer_certificate_list == NULL) {
845
0
    gnutls_assert();
846
0
    return GNUTLS_E_MEMORY_ERROR;
847
0
  }
848
849
0
  p = data + 3;
850
851
  /* Now we start parsing the list (again).
852
   * We don't use DECR_LEN since the list has
853
   * been parsed before.
854
   */
855
856
0
  for (j = 0; j < peer_certificate_list_size; j++) {
857
0
    len = _gnutls_read_uint24(p);
858
0
    p += 3;
859
860
0
    tmp.size = len;
861
0
    tmp.data = p;
862
863
0
    ret = gnutls_pcert_import_x509_raw(&peer_certificate_list[j],
864
0
               &tmp, GNUTLS_X509_FMT_DER,
865
0
               0);
866
0
    if (ret < 0) {
867
0
      gnutls_assert();
868
0
      peer_certificate_list_size = j;
869
0
      ret = GNUTLS_E_CERTIFICATE_ERROR;
870
0
      goto cleanup;
871
0
    }
872
873
0
    p += len;
874
0
  }
875
876
0
  ret = check_pk_compat(session, peer_certificate_list[0].pubkey);
877
0
  if (ret < 0) {
878
0
    gnutls_assert();
879
0
    goto cleanup;
880
0
  }
881
882
0
  ret = _gnutls_pcert_to_auth_info(info, peer_certificate_list,
883
0
           peer_certificate_list_size);
884
0
  if (ret < 0) {
885
0
    gnutls_assert();
886
0
    goto cleanup;
887
0
  }
888
889
0
  return 0;
890
891
0
cleanup:
892
0
  CLEAR_CERTS;
893
0
  gnutls_free(peer_certificate_list);
894
0
  return ret;
895
0
}
896
897
int _gnutls_proc_rawpk_crt(gnutls_session_t session, uint8_t *data,
898
         size_t data_size)
899
0
{
900
0
  int cert_size, ret;
901
0
  cert_auth_info_t info;
902
0
  gnutls_pcert_st *peer_certificate;
903
0
  gnutls_datum_t tmp_cert;
904
905
0
  uint8_t *p = data;
906
0
  ssize_t dsize = data_size;
907
908
  /* We assume data != null and data_size > 0 because
909
   * the caller checks this for us. */
910
911
  /* Read the length of our certificate. We always have exactly
912
   * one certificate that contains our raw public key. Our message
913
   * looks like:
914
   * <length++certificate> where
915
   * length = 3 bytes and
916
   * certificate = length bytes.
917
   */
918
0
  DECR_LEN(dsize, 3);
919
0
  cert_size = _gnutls_read_uint24(p);
920
0
  p += 3;
921
922
  /* Ensure no discrepancy in data */
923
0
  if (cert_size != dsize)
924
0
    return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
925
926
0
  if (cert_size == 0) {
927
    // No certificate was sent. This is not OK.
928
0
    return gnutls_assert_val(GNUTLS_E_NO_CERTIFICATE_FOUND);
929
0
  }
930
931
0
  DECR_LEN_FINAL(dsize, cert_size);
932
933
  /* We are now going to read our certificate and store it into
934
   * the authentication info structure.
935
   */
936
0
  tmp_cert.size = cert_size;
937
0
  tmp_cert.data = p;
938
939
0
  peer_certificate = gnutls_calloc(1, sizeof(*peer_certificate));
940
0
  if (peer_certificate == NULL) {
941
0
    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
942
0
  }
943
  // Import our raw certificate holding only a raw public key into this pcert
944
0
  ret = gnutls_pcert_import_rawpk_raw(peer_certificate, &tmp_cert,
945
0
              GNUTLS_X509_FMT_DER, 0, 0);
946
0
  if (ret < 0) {
947
0
    gnutls_assert();
948
0
    goto cleanup;
949
0
  }
950
  // Check whether the PK algo is compatible with the negotiated KX
951
0
  ret = check_pk_compat(session, peer_certificate->pubkey);
952
0
  if (ret < 0) {
953
0
    gnutls_assert();
954
0
    goto cleanup;
955
0
  }
956
957
0
  ret = _gnutls_auth_info_init(session, GNUTLS_CRD_CERTIFICATE,
958
0
             sizeof(cert_auth_info_st), 1);
959
0
  if (ret < 0) {
960
0
    gnutls_assert();
961
0
    goto cleanup;
962
0
  }
963
964
0
  info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
965
0
  if (unlikely(!info)) {
966
0
    gnutls_assert();
967
0
    goto cleanup;
968
0
  }
969
970
  /* Copy our imported certificate into the auth info structure
971
   * and free our temporary cert storage peer_certificate.
972
   */
973
0
  ret = _gnutls_pcert_to_auth_info(info, peer_certificate, 1);
974
0
  if (ret < 0) {
975
0
    gnutls_assert();
976
0
    goto cleanup;
977
0
  }
978
979
0
  return GNUTLS_E_SUCCESS;
980
981
0
cleanup:
982
0
  if (peer_certificate != NULL) {
983
0
    gnutls_pcert_deinit(peer_certificate);
984
0
    gnutls_free(peer_certificate);
985
0
  }
986
987
0
  return ret;
988
0
}
989
990
int _gnutls_proc_crt(gnutls_session_t session, uint8_t *data, size_t data_size)
991
0
{
992
0
  gnutls_certificate_credentials_t cred;
993
0
  gnutls_certificate_type_t cert_type;
994
995
0
  cred = (gnutls_certificate_credentials_t)_gnutls_get_cred(
996
0
    session, GNUTLS_CRD_CERTIFICATE);
997
0
  if (cred == NULL) {
998
0
    gnutls_assert();
999
0
    return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
1000
0
  }
1001
1002
  /* Determine what certificate type we need to process.
1003
   * We need to process the certificate of the peer. */
1004
0
  cert_type = get_certificate_type(session, GNUTLS_CTYPE_PEERS);
1005
1006
0
  switch (cert_type) {
1007
0
  case GNUTLS_CRT_X509:
1008
0
    return _gnutls_proc_x509_crt(session, data, data_size);
1009
0
  case GNUTLS_CRT_RAWPK:
1010
0
    return _gnutls_proc_rawpk_crt(session, data, data_size);
1011
0
  default:
1012
0
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
1013
0
  }
1014
0
}
1015
1016
/* Checks if we support the given signature algorithm
1017
 * (RSA or DSA). Returns the corresponding gnutls_pk_algorithm_t
1018
 * if true;
1019
 */
1020
inline static int _gnutls_check_supported_sign_algo(CertificateSigType algo)
1021
0
{
1022
0
  switch (algo) {
1023
0
  case RSA_SIGN:
1024
0
    return GNUTLS_PK_RSA;
1025
0
  case DSA_SIGN:
1026
0
    return GNUTLS_PK_DSA;
1027
0
  case ECDSA_SIGN:
1028
0
    return GNUTLS_PK_EC;
1029
0
#ifdef ENABLE_GOST
1030
0
  case GOSTR34102012_256_SIGN:
1031
0
    return GNUTLS_PK_GOST_12_256;
1032
0
  case GOSTR34102012_512_SIGN:
1033
0
    return GNUTLS_PK_GOST_12_512;
1034
0
#endif
1035
0
  }
1036
1037
0
  return -1;
1038
0
}
1039
1040
int _gnutls_proc_cert_cert_req(gnutls_session_t session, uint8_t *data,
1041
             size_t data_size)
1042
0
{
1043
0
  int size, ret;
1044
0
  uint8_t *p;
1045
0
  gnutls_certificate_credentials_t cred;
1046
0
  ssize_t dsize;
1047
0
  int i;
1048
0
  gnutls_pk_algorithm_t pk_algos[MAX_CLIENT_SIGN_ALGOS];
1049
0
  int pk_algos_length;
1050
0
  const version_entry_st *ver = get_version(session);
1051
1052
0
  if (unlikely(ver == NULL))
1053
0
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
1054
1055
0
  cred = (gnutls_certificate_credentials_t)_gnutls_get_cred(
1056
0
    session, GNUTLS_CRD_CERTIFICATE);
1057
0
  if (cred == NULL) {
1058
0
    gnutls_assert();
1059
0
    return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
1060
0
  }
1061
1062
0
  if ((ret = _gnutls_auth_info_init(session, GNUTLS_CRD_CERTIFICATE,
1063
0
            sizeof(cert_auth_info_st), 0)) < 0) {
1064
0
    gnutls_assert();
1065
0
    return ret;
1066
0
  }
1067
1068
0
  p = data;
1069
0
  dsize = data_size;
1070
1071
0
  DECR_LEN(dsize, 1);
1072
0
  size = p[0];
1073
0
  p++;
1074
  /* check if the sign algorithm is supported.
1075
   */
1076
0
  pk_algos_length = 0;
1077
0
  for (i = 0; i < size; i++, p++) {
1078
0
    DECR_LEN(dsize, 1);
1079
0
    if ((ret = _gnutls_check_supported_sign_algo(*p)) > 0) {
1080
0
      if (pk_algos_length < MAX_CLIENT_SIGN_ALGOS) {
1081
0
        pk_algos[pk_algos_length++] = ret;
1082
0
      }
1083
0
    }
1084
0
  }
1085
1086
0
  if (pk_algos_length == 0) {
1087
0
    gnutls_assert();
1088
0
    return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
1089
0
  }
1090
1091
0
  if (_gnutls_version_has_selectable_sighash(ver)) {
1092
    /* read supported hashes */
1093
0
    int hash_num;
1094
0
    DECR_LEN(dsize, 2);
1095
0
    hash_num = _gnutls_read_uint16(p);
1096
0
    p += 2;
1097
0
    DECR_LEN(dsize, hash_num);
1098
1099
0
    ret = _gnutls_sign_algorithm_parse_data(session, p, hash_num);
1100
0
    if (ret < 0) {
1101
0
      gnutls_assert();
1102
0
      return ret;
1103
0
    }
1104
1105
0
    p += hash_num;
1106
0
  }
1107
1108
  /* read the certificate authorities */
1109
0
  DECR_LEN(dsize, 2);
1110
0
  size = _gnutls_read_uint16(p);
1111
0
  p += 2;
1112
1113
0
  DECR_LEN_FINAL(dsize, size);
1114
1115
  /* We should reply with a certificate message,
1116
   * even if we have no certificate to send.
1117
   */
1118
0
  session->internals.hsk_flags |= HSK_CRT_ASKED;
1119
1120
  /* now we ask the user to tell which one
1121
   * he wants to use.
1122
   */
1123
0
  if ((ret = _gnutls_select_client_cert(session, p, size, pk_algos,
1124
0
                pk_algos_length)) < 0) {
1125
0
    gnutls_assert();
1126
0
    return ret;
1127
0
  }
1128
1129
0
  return 0;
1130
0
}
1131
1132
int _gnutls_gen_cert_client_crt_vrfy(gnutls_session_t session,
1133
             gnutls_buffer_st *data)
1134
0
{
1135
0
  int ret;
1136
0
  gnutls_pcert_st *apr_cert_list;
1137
0
  gnutls_privkey_t apr_pkey;
1138
0
  int apr_cert_list_length;
1139
0
  gnutls_datum_t signature = { NULL, 0 };
1140
0
  gnutls_sign_algorithm_t sign_algo;
1141
0
  const version_entry_st *ver = get_version(session);
1142
0
  unsigned init_pos = data->length;
1143
1144
0
  if (unlikely(ver == NULL))
1145
0
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
1146
1147
  /* find the appropriate certificate */
1148
0
  if ((ret = _gnutls_get_selected_cert(session, &apr_cert_list,
1149
0
               &apr_cert_list_length,
1150
0
               &apr_pkey)) < 0) {
1151
0
    gnutls_assert();
1152
0
    return ret;
1153
0
  }
1154
1155
0
  if (apr_cert_list_length > 0) {
1156
0
    if ((ret = _gnutls_handshake_sign_crt_vrfy(
1157
0
           session, &apr_cert_list[0], apr_pkey,
1158
0
           &signature)) < 0) {
1159
0
      gnutls_assert();
1160
0
      return ret;
1161
0
    }
1162
0
    sign_algo = ret;
1163
0
  } else {
1164
0
    return 0;
1165
0
  }
1166
1167
0
  if (_gnutls_version_has_selectable_sighash(ver)) {
1168
0
    const sign_algorithm_st *aid;
1169
0
    uint8_t p[2];
1170
    /* error checking is not needed here since we have used those algorithms */
1171
0
    aid = _gnutls_sign_to_tls_aid(sign_algo);
1172
0
    if (aid == NULL)
1173
0
      return gnutls_assert_val(GNUTLS_E_UNKNOWN_ALGORITHM);
1174
1175
0
    p[0] = aid->id[0];
1176
0
    p[1] = aid->id[1];
1177
0
    ret = _gnutls_buffer_append_data(data, p, 2);
1178
0
    if (ret < 0) {
1179
0
      gnutls_assert();
1180
0
      goto cleanup;
1181
0
    }
1182
0
  }
1183
1184
0
  ret = _gnutls_buffer_append_data_prefix(data, 16, signature.data,
1185
0
            signature.size);
1186
0
  if (ret < 0) {
1187
0
    gnutls_assert();
1188
0
    goto cleanup;
1189
0
  }
1190
1191
0
  ret = data->length - init_pos;
1192
1193
0
cleanup:
1194
0
  _gnutls_free_datum(&signature);
1195
0
  return ret;
1196
0
}
1197
1198
int _gnutls_proc_cert_client_crt_vrfy(gnutls_session_t session, uint8_t *data,
1199
              size_t data_size)
1200
0
{
1201
0
  int size, ret;
1202
0
  ssize_t dsize = data_size;
1203
0
  uint8_t *pdata = data;
1204
0
  gnutls_datum_t sig;
1205
0
  cert_auth_info_t info =
1206
0
    _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
1207
0
  gnutls_pcert_st peer_cert;
1208
0
  gnutls_sign_algorithm_t sign_algo = GNUTLS_SIGN_UNKNOWN;
1209
0
  const version_entry_st *ver = get_version(session);
1210
0
  gnutls_certificate_credentials_t cred;
1211
0
  unsigned vflags;
1212
1213
0
  if (unlikely(info == NULL || info->ncerts == 0 || ver == NULL)) {
1214
0
    gnutls_assert();
1215
    /* we need this in order to get peer's certificate */
1216
0
    return GNUTLS_E_INTERNAL_ERROR;
1217
0
  }
1218
1219
0
  cred = (gnutls_certificate_credentials_t)_gnutls_get_cred(
1220
0
    session, GNUTLS_CRD_CERTIFICATE);
1221
0
  if (cred == NULL) {
1222
0
    gnutls_assert();
1223
0
    return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
1224
0
  }
1225
1226
0
  vflags = cred->verify_flags |
1227
0
     session->internals.additional_verify_flags;
1228
1229
0
  if (_gnutls_version_has_selectable_sighash(ver)) {
1230
0
    DECR_LEN(dsize, 2);
1231
1232
0
    sign_algo = _gnutls_tls_aid_to_sign(pdata[0], pdata[1], ver);
1233
0
    if (sign_algo == GNUTLS_SIGN_UNKNOWN) {
1234
0
      gnutls_assert();
1235
0
      return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
1236
0
    }
1237
0
    pdata += 2;
1238
0
  }
1239
1240
0
  ret = _gnutls_session_sign_algo_enabled(session, sign_algo);
1241
0
  if (ret < 0)
1242
0
    return gnutls_assert_val(
1243
0
      GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM);
1244
1245
0
  DECR_LEN(dsize, 2);
1246
0
  size = _gnutls_read_uint16(pdata);
1247
0
  pdata += 2;
1248
1249
0
  DECR_LEN_FINAL(dsize, size);
1250
1251
0
  sig.data = pdata;
1252
0
  sig.size = size;
1253
1254
0
  ret = _gnutls_get_auth_info_pcert(
1255
0
    &peer_cert, session->security_parameters.client_ctype, info);
1256
1257
0
  if (ret < 0) {
1258
0
    gnutls_assert();
1259
0
    return ret;
1260
0
  }
1261
1262
0
  if ((ret = _gnutls_handshake_verify_crt_vrfy(
1263
0
         session, vflags, &peer_cert, &sig, sign_algo)) < 0) {
1264
0
    gnutls_assert();
1265
0
    gnutls_pcert_deinit(&peer_cert);
1266
0
    return ret;
1267
0
  }
1268
0
  gnutls_pcert_deinit(&peer_cert);
1269
1270
0
  return 0;
1271
0
}
1272
1273
int _gnutls_gen_cert_server_cert_req(gnutls_session_t session,
1274
             gnutls_buffer_st *data)
1275
0
{
1276
0
  gnutls_certificate_credentials_t cred;
1277
0
  int ret, i;
1278
0
  uint8_t tmp_data[CERTTYPE_SIZE];
1279
0
  const version_entry_st *ver = get_version(session);
1280
0
  unsigned init_pos = data->length;
1281
0
  enum CertificateSigTypeFlags flags;
1282
1283
0
  if (unlikely(ver == NULL))
1284
0
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
1285
1286
  /* Now we need to generate the RDN sequence. This is
1287
   * already in the CERTIFICATE_CRED structure, to improve
1288
   * performance.
1289
   */
1290
1291
0
  cred = (gnutls_certificate_credentials_t)_gnutls_get_cred(
1292
0
    session, GNUTLS_CRD_CERTIFICATE);
1293
0
  if (cred == NULL) {
1294
0
    gnutls_assert();
1295
0
    return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
1296
0
  }
1297
1298
0
  if (_gnutls_version_has_selectable_sighash(ver)) {
1299
0
    size_t j;
1300
1301
0
    flags = 0;
1302
0
    for (j = 0; j < session->internals.priorities->sigalg.size;
1303
0
         j++) {
1304
0
      const gnutls_sign_entry_st *se =
1305
0
        session->internals.priorities->sigalg.entry[j];
1306
0
      switch (se->pk) {
1307
0
      case GNUTLS_PK_RSA:
1308
0
      case GNUTLS_PK_RSA_PSS:
1309
0
        flags |= RSA_SIGN_FLAG;
1310
0
        break;
1311
0
      case GNUTLS_PK_DSA:
1312
0
        flags |= DSA_SIGN_FLAG;
1313
0
        break;
1314
0
      case GNUTLS_PK_ECDSA:
1315
0
        flags |= ECDSA_SIGN_FLAG;
1316
0
        break;
1317
0
#ifdef ENABLE_GOST
1318
0
      case GNUTLS_PK_GOST_12_256:
1319
0
        flags |= GOSTR34102012_256_SIGN_FLAG;
1320
0
        break;
1321
0
      case GNUTLS_PK_GOST_12_512:
1322
0
        flags |= GOSTR34102012_512_SIGN_FLAG;
1323
0
        break;
1324
0
#endif
1325
0
      default:
1326
0
        gnutls_assert();
1327
0
        _gnutls_debug_log(
1328
0
          "%s is unsupported for cert request\n",
1329
0
          gnutls_pk_get_name(se->pk));
1330
0
      }
1331
0
    }
1332
1333
0
  } else {
1334
0
#ifdef ENABLE_GOST
1335
0
    if (_gnutls_kx_is_vko_gost(
1336
0
          session->security_parameters.cs->kx_algorithm)) {
1337
0
      flags = GOSTR34102012_256_SIGN_FLAG |
1338
0
        GOSTR34102012_512_SIGN_FLAG;
1339
0
    } else
1340
0
#endif
1341
0
    {
1342
0
      flags = RSA_SIGN_FLAG | DSA_SIGN_FLAG | ECDSA_SIGN_FLAG;
1343
0
    }
1344
0
  }
1345
1346
0
  i = 1;
1347
0
  if (flags & RSA_SIGN_FLAG) {
1348
0
    tmp_data[i++] = RSA_SIGN;
1349
0
  }
1350
0
  if (flags & DSA_SIGN_FLAG) {
1351
0
    tmp_data[i++] = DSA_SIGN;
1352
0
  }
1353
0
  if (flags & ECDSA_SIGN_FLAG) {
1354
0
    tmp_data[i++] = ECDSA_SIGN;
1355
0
  }
1356
0
#ifdef ENABLE_GOST
1357
0
  if (flags & GOSTR34102012_256_SIGN_FLAG) {
1358
0
    tmp_data[i++] = GOSTR34102012_256_SIGN;
1359
0
  }
1360
0
  if (flags & GOSTR34102012_512_SIGN_FLAG) {
1361
0
    tmp_data[i++] = GOSTR34102012_512_SIGN;
1362
0
  }
1363
0
#endif
1364
0
  tmp_data[0] = i - 1;
1365
1366
0
  ret = _gnutls_buffer_append_data(data, tmp_data, i);
1367
0
  if (ret < 0)
1368
0
    return gnutls_assert_val(ret);
1369
1370
0
  if (_gnutls_version_has_selectable_sighash(ver)) {
1371
0
    ret = _gnutls_sign_algorithm_write_params(session, data);
1372
0
    if (ret < 0) {
1373
0
      gnutls_assert();
1374
0
      return ret;
1375
0
    }
1376
0
  }
1377
1378
0
  if (session->security_parameters.client_ctype == GNUTLS_CRT_X509 &&
1379
0
      session->internals.ignore_rdn_sequence == 0) {
1380
0
    ret = _gnutls_buffer_append_data_prefix(
1381
0
      data, 16, cred->tlist->x509_rdn_sequence.data,
1382
0
      cred->tlist->x509_rdn_sequence.size);
1383
0
    if (ret < 0)
1384
0
      return gnutls_assert_val(ret);
1385
0
  } else {
1386
0
    ret = _gnutls_buffer_append_prefix(data, 16, 0);
1387
0
    if (ret < 0)
1388
0
      return gnutls_assert_val(ret);
1389
0
  }
1390
1391
0
  return data->length - init_pos;
1392
0
}
1393
1394
/* This function will return the appropriate certificate to use.
1395
 * Fills in the apr_cert_list, apr_cert_list_length and apr_pkey.
1396
 * The return value is a negative error code on error.
1397
 *
1398
 * It is normal to return 0 with no certificates in client side.
1399
 *
1400
 */
1401
int _gnutls_get_selected_cert(gnutls_session_t session,
1402
            gnutls_pcert_st **apr_cert_list,
1403
            int *apr_cert_list_length,
1404
            gnutls_privkey_t *apr_pkey)
1405
0
{
1406
0
  if (session->security_parameters.entity == GNUTLS_SERVER) {
1407
0
    *apr_cert_list = session->internals.selected_cert_list;
1408
0
    *apr_pkey = session->internals.selected_key;
1409
0
    *apr_cert_list_length =
1410
0
      session->internals.selected_cert_list_length;
1411
1412
0
    if (*apr_cert_list_length == 0 || *apr_cert_list == NULL) {
1413
0
      gnutls_assert();
1414
0
      return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
1415
0
    }
1416
1417
0
  } else { /* CLIENT SIDE */
1418
    /* _gnutls_select_client_cert() must have been called before.
1419
     */
1420
0
    *apr_cert_list = session->internals.selected_cert_list;
1421
0
    *apr_cert_list_length =
1422
0
      session->internals.selected_cert_list_length;
1423
0
    *apr_pkey = session->internals.selected_key;
1424
0
  }
1425
1426
0
  return 0;
1427
0
}
1428
1429
void _gnutls_selected_certs_deinit(gnutls_session_t session)
1430
0
{
1431
0
  if (session->internals.selected_need_free != 0) {
1432
0
    int i;
1433
1434
0
    for (i = 0; i < session->internals.selected_cert_list_length;
1435
0
         i++) {
1436
0
      gnutls_pcert_deinit(
1437
0
        &session->internals.selected_cert_list[i]);
1438
0
    }
1439
0
    gnutls_free(session->internals.selected_cert_list);
1440
1441
0
    for (i = 0; i < session->internals.selected_ocsp_length; i++) {
1442
0
      _gnutls_free_datum(
1443
0
        &session->internals.selected_ocsp[i].response);
1444
0
    }
1445
0
    gnutls_free(session->internals.selected_ocsp);
1446
1447
0
    gnutls_privkey_deinit(session->internals.selected_key);
1448
0
  }
1449
0
  session->internals.selected_ocsp_func = NULL;
1450
1451
0
  session->internals.selected_cert_list = NULL;
1452
0
  session->internals.selected_cert_list_length = 0;
1453
1454
0
  session->internals.selected_key = NULL;
1455
1456
0
  return;
1457
0
}
1458
1459
static void selected_certs_set(gnutls_session_t session, gnutls_pcert_st *certs,
1460
             int ncerts, gnutls_ocsp_data_st *ocsp,
1461
             unsigned nocsp, gnutls_privkey_t key,
1462
             int need_free,
1463
             gnutls_status_request_ocsp_func ocsp_func,
1464
             void *ocsp_func_ptr)
1465
0
{
1466
0
  _gnutls_selected_certs_deinit(session);
1467
1468
0
  session->internals.selected_cert_list = certs;
1469
0
  session->internals.selected_cert_list_length = ncerts;
1470
1471
0
  session->internals.selected_ocsp = ocsp;
1472
0
  session->internals.selected_ocsp_length = nocsp;
1473
1474
0
  session->internals.selected_key = key;
1475
0
  session->internals.selected_need_free = need_free;
1476
1477
0
  session->internals.selected_ocsp_func = ocsp_func;
1478
0
  session->internals.selected_ocsp_func_ptr = ocsp_func_ptr;
1479
0
}
1480
1481
static void get_server_name(gnutls_session_t session, uint8_t *name,
1482
          size_t max_name_size)
1483
0
{
1484
0
  int ret, i;
1485
0
  size_t max_name;
1486
0
  unsigned int type;
1487
1488
0
  ret = 0;
1489
0
  for (i = 0; !(ret < 0); i++) {
1490
0
    max_name = max_name_size;
1491
0
    ret = gnutls_server_name_get(session, name, &max_name, &type,
1492
0
               i);
1493
0
    if (ret >= 0 && type == GNUTLS_NAME_DNS)
1494
0
      return;
1495
0
  }
1496
1497
0
  name[0] = 0;
1498
1499
0
  return;
1500
0
}
1501
1502
/* Checks the compatibility of the pubkey in the certificate with the
1503
 * ciphersuite and selects a signature algorithm (if required by the
1504
 * ciphersuite and TLS version) appropriate for the certificate. If none
1505
 * can be selected returns an error.
1506
 *
1507
 * IMPORTANT
1508
 * Currently this function is only called from _gnutls_select_server_cert,
1509
 * i.e. it is only called at the server. We therefore retrieve the
1510
 * negotiated server certificate type within this function.
1511
 * If, in the future, this routine is called at the client then we
1512
 * need to adapt the implementation accordingly.
1513
 */
1514
static int cert_select_sign_algorithm(gnutls_session_t session,
1515
              gnutls_pcert_st *cert,
1516
              gnutls_privkey_t pkey,
1517
              const gnutls_cipher_suite_entry_st *cs)
1518
0
{
1519
0
  gnutls_pubkey_t pubkey = cert->pubkey;
1520
0
  gnutls_certificate_type_t cert_type = cert->type;
1521
0
  unsigned pk = pubkey->params.algo;
1522
0
  unsigned key_usage;
1523
0
  gnutls_sign_algorithm_t algo;
1524
0
  const version_entry_st *ver = get_version(session);
1525
0
  gnutls_certificate_type_t ctype;
1526
1527
0
  assert(IS_SERVER(session));
1528
1529
  /* Retrieve the server certificate type */
1530
0
  ctype = get_certificate_type(session, GNUTLS_CTYPE_SERVER);
1531
1532
0
  if (ctype != cert_type) {
1533
0
    return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
1534
0
  }
1535
1536
0
  key_usage = get_key_usage(session, pubkey);
1537
1538
  /* In TLS1.3 we support only signatures; ensure the selected key supports them */
1539
0
  if (ver->tls13_sem &&
1540
0
      _gnutls_check_key_usage_for_sig(session, key_usage, 1) < 0)
1541
0
    return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
1542
1543
0
  if (!ver->tls13_sem &&
1544
0
      !_gnutls_kx_supports_pk_usage(cs->kx_algorithm, pk, key_usage)) {
1545
0
    return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
1546
0
  }
1547
1548
0
  if (!ver->tls13_sem &&
1549
0
      _gnutls_kx_encipher_type(cs->kx_algorithm) != CIPHER_SIGN)
1550
0
    return 0;
1551
1552
0
  if (!_gnutls_version_has_selectable_sighash(ver)) {
1553
    /* For SSL3.0 and TLS1.0 we lie as we cannot express md5-sha1 as
1554
     * signature algorithm. */
1555
0
    algo = gnutls_pk_to_sign(cert->pubkey->params.algo,
1556
0
           GNUTLS_DIG_SHA1);
1557
0
    gnutls_sign_algorithm_set_server(session, algo);
1558
0
    return 0;
1559
0
  }
1560
1561
0
  algo = _gnutls_session_get_sign_algo(session, cert, pkey, 0,
1562
0
               cs->kx_algorithm);
1563
0
  if (algo == GNUTLS_SIGN_UNKNOWN)
1564
0
    return gnutls_assert_val(GNUTLS_E_INCOMPATIBLE_SIG_WITH_KEY);
1565
1566
0
  gnutls_sign_algorithm_set_server(session, algo);
1567
0
  _gnutls_handshake_log("Selected signature algorithm: %s\n",
1568
0
            gnutls_sign_algorithm_get_name(algo));
1569
1570
0
  return 0;
1571
0
}
1572
1573
/* finds the most appropriate certificate in the cert list.
1574
 * The 'appropriate' is defined by the user.
1575
 *
1576
 * requested_algo holds the parameters required by the peer (RSA, DSA
1577
 * or -1 for any).
1578
 *
1579
 * Returns 0 on success and a negative error code on error. The
1580
 * selected certificate will be in session->internals.selected_*.
1581
 *
1582
 */
1583
int _gnutls_select_server_cert(gnutls_session_t session,
1584
             const gnutls_cipher_suite_entry_st *cs)
1585
0
{
1586
0
  unsigned i, j;
1587
0
  int idx, ret;
1588
0
  gnutls_certificate_credentials_t cred;
1589
0
  char server_name[MAX_CN];
1590
1591
0
  cred = (gnutls_certificate_credentials_t)_gnutls_get_cred(
1592
0
    session, GNUTLS_CRD_CERTIFICATE);
1593
0
  if (cred == NULL) {
1594
0
    gnutls_assert(); /* we don't need to select a cert */
1595
0
    return 0;
1596
0
  }
1597
1598
  /* When a callback is set, we call it once to get the
1599
   * certificate and then check its compatibility with
1600
   * the ciphersuites.
1601
   */
1602
0
  if (cred->get_cert_callback3) {
1603
0
    if (session->internals.selected_cert_list_length == 0) {
1604
0
      ret = call_get_cert_callback(session, NULL, 0, NULL, 0);
1605
0
      if (ret < 0)
1606
0
        return gnutls_assert_val(ret);
1607
1608
0
      if (session->internals.selected_cert_list_length == 0)
1609
0
        return gnutls_assert_val(
1610
0
          GNUTLS_E_INSUFFICIENT_CREDENTIALS);
1611
1612
0
      if (unlikely(session->internals.selected_cert_list ==
1613
0
             NULL)) {
1614
0
        return gnutls_assert_val(
1615
0
          GNUTLS_E_INTERNAL_ERROR);
1616
0
      }
1617
1618
0
      _gnutls_debug_log(
1619
0
        "Selected (%s) cert\n",
1620
0
        gnutls_pk_get_name(
1621
0
          session->internals.selected_cert_list[0]
1622
0
            .pubkey->params.algo));
1623
0
    }
1624
1625
0
    if (session->internals.selected_key == NULL)
1626
0
      return gnutls_assert_val(
1627
0
        GNUTLS_E_INSUFFICIENT_CREDENTIALS);
1628
1629
0
    ret = cert_select_sign_algorithm(
1630
0
      session, &session->internals.selected_cert_list[0],
1631
0
      session->internals.selected_key, cs);
1632
0
    if (ret < 0)
1633
0
      return gnutls_assert_val(ret);
1634
1635
0
    return 0;
1636
0
  }
1637
1638
  /* Otherwise... we check the compatibility of the ciphersuite
1639
   * with all the certificates available. */
1640
1641
0
  get_server_name(session, (unsigned char *)server_name,
1642
0
      sizeof(server_name));
1643
1644
0
  _gnutls_handshake_log("HSK[%p]: Requested server name: '%s'\n", session,
1645
0
            server_name);
1646
0
  idx = -1; /* default is use no certificate */
1647
1648
  /* find certificates that match the requested server_name
1649
   */
1650
1651
0
  if (server_name[0] != 0) {
1652
0
    for (j = 0; j < cred->ncerts; j++) {
1653
0
      i = cred->sorted_cert_idx[j];
1654
1655
0
      if (cred->certs[i].names != NULL &&
1656
0
          _gnutls_str_array_match(cred->certs[i].names,
1657
0
                server_name) != 0) {
1658
        /* if requested algorithms are also compatible select it */
1659
1660
0
        ret = cert_select_sign_algorithm(
1661
0
          session, &cred->certs[i].cert_list[0],
1662
0
          cred->certs[i].pkey, cs);
1663
0
        if (ret >= 0) {
1664
0
          idx = i;
1665
0
          _gnutls_debug_log(
1666
0
            "Selected (%s) cert based on ciphersuite %x.%x: %s\n",
1667
0
            gnutls_pk_get_name(
1668
0
              cred->certs[i]
1669
0
                .cert_list[0]
1670
0
                .pubkey->params
1671
0
                .algo),
1672
0
            (unsigned)cs->id[0],
1673
0
            (unsigned)cs->id[1], cs->name);
1674
          /* found */
1675
0
          goto finished;
1676
0
        }
1677
0
      }
1678
0
    }
1679
0
  }
1680
1681
  /* no name match */
1682
0
  for (j = 0; j < cred->ncerts; j++) {
1683
0
    i = cred->sorted_cert_idx[j];
1684
1685
0
    _gnutls_handshake_log(
1686
0
      "HSK[%p]: checking compat of %s with certificate[%d] (%s/%s)\n",
1687
0
      session, cs->name, i,
1688
0
      gnutls_pk_get_name(
1689
0
        cred->certs[i].cert_list[0].pubkey->params.algo),
1690
0
      gnutls_certificate_type_get_name(
1691
0
        cred->certs[i].cert_list[0].type));
1692
1693
0
    ret = cert_select_sign_algorithm(session,
1694
0
             &cred->certs[i].cert_list[0],
1695
0
             cred->certs[i].pkey, cs);
1696
0
    if (ret >= 0) {
1697
0
      idx = i;
1698
0
      _gnutls_debug_log(
1699
0
        "Selected (%s) cert based on ciphersuite %x.%x: %s\n",
1700
0
        gnutls_pk_get_name(
1701
0
          cred->certs[i]
1702
0
            .cert_list[0]
1703
0
            .pubkey->params.algo),
1704
0
        (unsigned)cs->id[0], (unsigned)cs->id[1],
1705
0
        cs->name);
1706
      /* found */
1707
0
      goto finished;
1708
0
    }
1709
0
  }
1710
1711
  /* store the certificate pointer for future use, in the handshake.
1712
   * (This will allow not calling this callback again.)
1713
   */
1714
0
finished:
1715
0
  if (idx >= 0) {
1716
0
    gnutls_status_request_ocsp_func ocsp_func = NULL;
1717
0
    void *ocsp_ptr = NULL;
1718
0
    gnutls_ocsp_data_st *ocsp = NULL;
1719
0
    unsigned nocsp = 0;
1720
1721
0
    if (cred->certs[idx].ocsp_data_length > 0) {
1722
0
      ocsp = &cred->certs[idx].ocsp_data[0];
1723
0
      nocsp = cred->certs[idx].ocsp_data_length;
1724
0
    } else if (cred->glob_ocsp_func != NULL) {
1725
0
      ocsp_func = cred->glob_ocsp_func;
1726
0
      ocsp_ptr = cred->glob_ocsp_func_ptr;
1727
0
    } else if (cred->certs[idx].ocsp_func != NULL) {
1728
0
      ocsp_func = cred->certs[idx].ocsp_func;
1729
0
      ocsp_ptr = cred->certs[idx].ocsp_func_ptr;
1730
0
    }
1731
1732
0
    selected_certs_set(session, &cred->certs[idx].cert_list[0],
1733
0
           cred->certs[idx].cert_list_length, ocsp,
1734
0
           nocsp, cred->certs[idx].pkey, 0, ocsp_func,
1735
0
           ocsp_ptr);
1736
0
  } else {
1737
    /* Certificate does not support REQUESTED_ALGO.  */
1738
0
    return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
1739
0
  }
1740
1741
0
  return 0;
1742
0
}
1743
1744
int _gnutls_gen_dhe_signature(gnutls_session_t session, gnutls_buffer_st *data,
1745
            uint8_t *plain, unsigned plain_size)
1746
0
{
1747
0
  gnutls_pcert_st *apr_cert_list;
1748
0
  gnutls_privkey_t apr_pkey;
1749
0
  int apr_cert_list_length;
1750
0
  gnutls_datum_t signature = { NULL, 0 }, ddata;
1751
0
  gnutls_sign_algorithm_t sign_algo;
1752
0
  const version_entry_st *ver = get_version(session);
1753
0
  int ret;
1754
1755
0
  if (unlikely(ver == NULL))
1756
0
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
1757
1758
0
  ddata.data = plain;
1759
0
  ddata.size = plain_size;
1760
1761
  /* find the appropriate certificate */
1762
0
  if ((ret = _gnutls_get_selected_cert(session, &apr_cert_list,
1763
0
               &apr_cert_list_length,
1764
0
               &apr_pkey)) < 0) {
1765
0
    gnutls_assert();
1766
0
    return ret;
1767
0
  }
1768
1769
0
  if (apr_cert_list_length > 0) {
1770
0
    if ((ret = _gnutls_handshake_sign_data(
1771
0
           session, &apr_cert_list[0], apr_pkey, &ddata,
1772
0
           &signature, &sign_algo)) < 0) {
1773
0
      gnutls_assert();
1774
0
      goto cleanup;
1775
0
    }
1776
0
  } else {
1777
0
    gnutls_assert();
1778
0
    ret = 0; /* ANON-DH, do not put a signature - ILLEGAL! */
1779
0
    goto cleanup;
1780
0
  }
1781
1782
0
  if (_gnutls_version_has_selectable_sighash(ver)) {
1783
0
    const sign_algorithm_st *aid;
1784
0
    uint8_t p[2];
1785
1786
0
    if (sign_algo == GNUTLS_SIGN_UNKNOWN) {
1787
0
      ret = GNUTLS_E_UNKNOWN_ALGORITHM;
1788
0
      goto cleanup;
1789
0
    }
1790
1791
0
    aid = _gnutls_sign_to_tls_aid(sign_algo);
1792
0
    if (aid == NULL) {
1793
0
      gnutls_assert();
1794
0
      ret = GNUTLS_E_UNKNOWN_ALGORITHM;
1795
0
      goto cleanup;
1796
0
    }
1797
1798
0
    p[0] = aid->id[0];
1799
0
    p[1] = aid->id[1];
1800
1801
0
    ret = _gnutls_buffer_append_data(data, p, 2);
1802
0
    if (ret < 0) {
1803
0
      gnutls_assert();
1804
0
      goto cleanup;
1805
0
    }
1806
0
  }
1807
1808
0
  ret = _gnutls_buffer_append_data_prefix(data, 16, signature.data,
1809
0
            signature.size);
1810
0
  if (ret < 0) {
1811
0
    gnutls_assert();
1812
0
  }
1813
1814
0
  ret = 0;
1815
1816
0
cleanup:
1817
0
  _gnutls_free_datum(&signature);
1818
0
  return ret;
1819
0
}
1820
1821
int _gnutls_proc_dhe_signature(gnutls_session_t session, uint8_t *data,
1822
             size_t _data_size, gnutls_datum_t *vparams)
1823
0
{
1824
0
  int sigsize;
1825
0
  gnutls_datum_t signature;
1826
0
  int ret;
1827
0
  cert_auth_info_t info =
1828
0
    _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
1829
0
  ssize_t data_size = _data_size;
1830
0
  gnutls_pcert_st peer_cert;
1831
0
  gnutls_sign_algorithm_t sign_algo = GNUTLS_SIGN_UNKNOWN;
1832
0
  const version_entry_st *ver = get_version(session);
1833
0
  gnutls_certificate_credentials_t cred;
1834
0
  unsigned vflags;
1835
0
  gnutls_certificate_type_t cert_type;
1836
1837
0
  if (unlikely(info == NULL || info->ncerts == 0 || ver == NULL)) {
1838
0
    gnutls_assert();
1839
    /* we need this in order to get peer's certificate */
1840
0
    return GNUTLS_E_INTERNAL_ERROR;
1841
0
  }
1842
1843
0
  cred = (gnutls_certificate_credentials_t)_gnutls_get_cred(
1844
0
    session, GNUTLS_CRD_CERTIFICATE);
1845
0
  if (cred == NULL) {
1846
0
    gnutls_assert();
1847
0
    return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
1848
0
  }
1849
1850
0
  vflags = cred->verify_flags |
1851
0
     session->internals.additional_verify_flags;
1852
1853
  /* VERIFY SIGNATURE */
1854
0
  if (_gnutls_version_has_selectable_sighash(ver)) {
1855
0
    uint8_t id[2];
1856
1857
0
    DECR_LEN(data_size, 1);
1858
0
    id[0] = *data++;
1859
0
    DECR_LEN(data_size, 1);
1860
0
    id[1] = *data++;
1861
1862
0
    sign_algo = _gnutls_tls_aid_to_sign(id[0], id[1], ver);
1863
0
    if (sign_algo == GNUTLS_SIGN_UNKNOWN) {
1864
0
      _gnutls_debug_log("unknown signature %d.%d\n",
1865
0
            (int)id[0], (int)id[1]);
1866
0
      gnutls_assert();
1867
0
      return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
1868
0
    }
1869
0
  }
1870
0
  DECR_LEN(data_size, 2);
1871
0
  sigsize = _gnutls_read_uint16(data);
1872
0
  data += 2;
1873
1874
0
  DECR_LEN_FINAL(data_size, sigsize);
1875
0
  signature.data = data;
1876
0
  signature.size = sigsize;
1877
1878
  // Retrieve the negotiated certificate type
1879
0
  cert_type = get_certificate_type(session, GNUTLS_CTYPE_SERVER);
1880
1881
0
  if ((ret = _gnutls_get_auth_info_pcert(&peer_cert, cert_type, info)) <
1882
0
      0) {
1883
0
    gnutls_assert();
1884
0
    return ret;
1885
0
  }
1886
1887
0
  ret = _gnutls_handshake_verify_data(session, vflags, &peer_cert,
1888
0
              vparams, &signature, sign_algo);
1889
1890
0
  gnutls_pcert_deinit(&peer_cert);
1891
0
  if (ret < 0) {
1892
0
    gnutls_assert();
1893
0
    return ret;
1894
0
  }
1895
1896
0
  return 0;
1897
0
}