LCOV - code coverage report
Current view: top level - builds/gnutls/coverage/gnutls-git/lib/auth - cert.c (source / functions) Hit Total Coverage
Test: GnuTLS-3.6.14 Code Coverage Lines: 747 873 85.6 %
Date: 2020-10-30 04:50:48 Functions: 28 28 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14