Coverage Report

Created: 2023-03-26 07:33

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