Coverage Report

Created: 2026-08-14 06:46

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