LCOV - code coverage report
Current view: top level - builds/gnutls/coverage/gnutls-git/lib/tls13 - certificate_verify.c (source / functions) Hit Total Coverage
Test: GnuTLS-3.6.7 Code Coverage Lines: 86 120 71.7 %
Date: 2019-04-24 03:13:53 Functions: 2 2 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 50 108 46.3 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (C) 2017 Red Hat, Inc.
       3                 :            :  *
       4                 :            :  * Author: Nikos Mavrogiannopoulos
       5                 :            :  *
       6                 :            :  * This file is part of GnuTLS.
       7                 :            :  *
       8                 :            :  * The GnuTLS is free software; you can redistribute it and/or
       9                 :            :  * modify it under the terms of the GNU Lesser General Public License
      10                 :            :  * as published by the Free Software Foundation; either version 2.1 of
      11                 :            :  * the License, or (at your option) any later version.
      12                 :            :  *
      13                 :            :  * This library is distributed in the hope that it will be useful, but
      14                 :            :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      15                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16                 :            :  * Lesser General Public License for more details.
      17                 :            :  *
      18                 :            :  * You should have received a copy of the GNU Lesser General Public License
      19                 :            :  * along with this program.  If not, see <https://www.gnu.org/licenses/>
      20                 :            :  *
      21                 :            :  */
      22                 :            : 
      23                 :            : #include "gnutls_int.h"
      24                 :            : #include "errors.h"
      25                 :            : #include "handshake.h"
      26                 :            : #include "auth/cert.h"
      27                 :            : #include "ext/signature.h"
      28                 :            : #include "algorithms.h"
      29                 :            : #include "tls13-sig.h"
      30                 :            : #include "mbuffers.h"
      31                 :            : #include "tls13/certificate_verify.h"
      32                 :            : 
      33                 :            : #define SRV_CTX "TLS 1.3, server CertificateVerify"
      34                 :            : static const gnutls_datum_t srv_ctx = {
      35                 :            :         (void*)SRV_CTX, sizeof(SRV_CTX)-1
      36                 :            : };
      37                 :            : 
      38                 :            : #define CLI_CTX "TLS 1.3, client CertificateVerify"
      39                 :            : static const gnutls_datum_t cli_ctx = {
      40                 :            :         (void*)CLI_CTX, sizeof(CLI_CTX)-1
      41                 :            : };
      42                 :            : 
      43                 :       2480 : int _gnutls13_recv_certificate_verify(gnutls_session_t session)
      44                 :            : {
      45                 :       2480 :         int ret;
      46                 :       2480 :         gnutls_buffer_st buf;
      47                 :       2480 :         const gnutls_sign_entry_st *se;
      48                 :       2480 :         gnutls_datum_t sig_data;
      49                 :       2480 :         gnutls_certificate_credentials_t cred;
      50                 :       2480 :         unsigned vflags;
      51                 :       2480 :         gnutls_pcert_st peer_cert;
      52         [ +  + ]:       2480 :         cert_auth_info_t info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
      53                 :       2480 :         bool server = 0;
      54                 :       2480 :         gnutls_certificate_type_t cert_type;
      55                 :            : 
      56                 :       2480 :         memset(&peer_cert, 0, sizeof(peer_cert));
      57                 :            : 
      58                 :            :         /* this message is only expected if we have received
      59                 :            :          * a certificate message */
      60         [ +  + ]:       2480 :         if (!(session->internals.hsk_flags & HSK_CRT_VRFY_EXPECTED))
      61                 :            :                 return 0;
      62                 :            : 
      63         [ +  + ]:        451 :         if (session->security_parameters.entity == GNUTLS_SERVER)
      64                 :         65 :                 server = 1;
      65                 :            : 
      66                 :        451 :         cred = (gnutls_certificate_credentials_t)
      67                 :        451 :                 _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE);
      68         [ -  + ]:        451 :         if (unlikely(cred == NULL))
      69         [ #  # ]:          0 :                 return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
      70         [ -  + ]:        451 :         if (unlikely(info == NULL))
      71         [ #  # ]:          0 :                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
      72                 :            : 
      73                 :        451 :         ret = _gnutls_recv_handshake(session, GNUTLS_HANDSHAKE_CERTIFICATE_VERIFY, 0, &buf);
      74         [ -  + ]:        451 :         if (ret < 0)
      75         [ #  # ]:          0 :                 return gnutls_assert_val(ret);
      76                 :            : 
      77         [ -  + ]:        451 :         _gnutls_handshake_log("HSK[%p]: Parsing certificate verify\n", session);
      78                 :            : 
      79         [ -  + ]:        451 :         if (buf.length < 2) {
      80         [ #  # ]:          0 :                 gnutls_assert();
      81                 :          0 :                 ret = GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
      82                 :          0 :                 goto cleanup;
      83                 :            :         }
      84                 :            : 
      85                 :        902 :         se = _gnutls_tls_aid_to_sign_entry(buf.data[0], buf.data[1], get_version(session));
      86         [ -  + ]:        451 :         if (se == NULL) {
      87         [ #  # ]:          0 :                 _gnutls_handshake_log("Found unsupported signature (%d.%d)\n", (int)buf.data[0], (int)buf.data[1]);
      88         [ #  # ]:          0 :                 ret = gnutls_assert_val(GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM);
      89                 :          0 :                 goto cleanup;
      90                 :            :         }
      91                 :            : 
      92         [ +  + ]:        451 :         if (server)
      93                 :         65 :                 gnutls_sign_algorithm_set_client(session, se->id);
      94                 :            :         else
      95                 :        386 :                 gnutls_sign_algorithm_set_server(session, se->id);
      96                 :            : 
      97                 :        451 :         buf.data+=2;
      98                 :        451 :         buf.length-=2;
      99                 :            : 
     100                 :            :         /* we check during verification whether the algorithm is enabled */
     101                 :            : 
     102                 :        451 :         ret = _gnutls_buffer_pop_datum_prefix16(&buf, &sig_data);
     103         [ -  + ]:        451 :         if (ret < 0) {
     104         [ #  # ]:          0 :                 gnutls_assert();
     105                 :          0 :                 goto cleanup;
     106                 :            :         }
     107                 :            : 
     108         [ -  + ]:        451 :         if (sig_data.size == 0) {
     109         [ #  # ]:          0 :                 gnutls_assert();
     110                 :          0 :                 ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
     111                 :          0 :                 goto cleanup;
     112                 :            :         }
     113                 :            : 
     114                 :            :         /* We verify the certificate of the peer. Therefore we need to
     115                 :            :          * retrieve the negotiated certificate type for the peer. */
     116         [ +  + ]:        451 :         cert_type = get_certificate_type(session, GNUTLS_CTYPE_PEERS);
     117                 :            : 
     118                 :            :         /* Verify the signature */
     119                 :        451 :         ret = _gnutls_get_auth_info_pcert(&peer_cert, cert_type, info);
     120         [ -  + ]:        451 :         if (ret < 0) {
     121         [ #  # ]:          0 :                 gnutls_assert();
     122                 :          0 :                 goto cleanup;
     123                 :            :         }
     124                 :            : 
     125                 :        451 :         vflags = cred->verify_flags | session->internals.additional_verify_flags;
     126                 :            : 
     127         [ +  + ]:        837 :         ret = _gnutls13_handshake_verify_data(session, vflags, &peer_cert,
     128                 :            :                                               server?(&cli_ctx):(&srv_ctx),
     129                 :            :                                               &sig_data, se);
     130         [ +  + ]:        451 :         if (ret < 0) {
     131         [ -  + ]:          2 :                 gnutls_assert();
     132                 :          2 :                 goto cleanup;
     133                 :            :         }
     134                 :            : 
     135         [ -  + ]:        449 :         if (buf.length > 0) {
     136         [ #  # ]:          0 :                 gnutls_assert();
     137                 :          0 :                 ret = GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
     138                 :          0 :                 goto cleanup;
     139                 :            :         }
     140                 :            : 
     141                 :            :         ret = 0;
     142                 :        451 :  cleanup:
     143                 :        451 :         gnutls_pcert_deinit(&peer_cert);
     144                 :        451 :         _gnutls_buffer_clear(&buf);
     145                 :        451 :         return ret;
     146                 :            : }
     147                 :            : 
     148                 :       2477 : int _gnutls13_send_certificate_verify(gnutls_session_t session, unsigned again)
     149                 :            : {
     150                 :       2477 :         int ret;
     151                 :       2477 :         gnutls_pcert_st *apr_cert_list;
     152                 :       2477 :         gnutls_privkey_t apr_pkey;
     153                 :       2477 :         int apr_cert_list_length;
     154                 :       2477 :         mbuffer_st *bufel = NULL;
     155                 :       2477 :         gnutls_buffer_st buf;
     156                 :       2477 :         gnutls_datum_t sig = {NULL, 0};
     157                 :       2477 :         gnutls_sign_algorithm_t algo;
     158                 :       2477 :         const gnutls_sign_entry_st *se;
     159                 :       2477 :         bool server = 0;
     160                 :            : 
     161         [ +  - ]:       2477 :         if (again == 0) {
     162         [ +  + ]:       2477 :                 if (!session->internals.initial_negotiation_completed &&
     163         [ +  + ]:       2476 :                     session->internals.hsk_flags & HSK_PSK_SELECTED)
     164                 :            :                         return 0;
     165                 :            : 
     166         [ +  + ]:       2041 :                 if (session->security_parameters.entity == GNUTLS_SERVER &&
     167         [ +  - ]:       1668 :                     session->internals.resumed)
     168                 :            :                         return 0;
     169                 :            : 
     170         [ +  + ]:       2041 :                 if (session->security_parameters.entity == GNUTLS_SERVER)
     171                 :       1668 :                         server = 1;
     172                 :            : 
     173                 :       2041 :                 ret = _gnutls_get_selected_cert(session, &apr_cert_list,
     174                 :            :                                                 &apr_cert_list_length, &apr_pkey);
     175         [ -  + ]:       2041 :                 if (ret < 0)
     176         [ #  # ]:          0 :                         return gnutls_assert_val(ret);
     177                 :            : 
     178         [ +  + ]:       2041 :                 if (apr_cert_list_length == 0) {
     179         [ -  + ]:        332 :                         if (server) {
     180         [ #  # ]:          0 :                                 return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
     181                 :            :                         } else {
     182                 :            :                                 /* for client, this means either we
     183                 :            :                                  * didn't get a cert request or we are
     184                 :            :                                  * declining authentication; in either
     185                 :            :                                  * case we don't send a cert verify */
     186                 :            :                                 return 0;
     187                 :            :                         }
     188                 :            :                 }
     189                 :            : 
     190         [ +  + ]:       1709 :                 if (server) {
     191                 :       1668 :                         algo = _gnutls_session_get_sign_algo(session, &apr_cert_list[0], apr_pkey, 0);
     192         [ -  + ]:       1668 :                         if (algo == GNUTLS_SIGN_UNKNOWN)
     193         [ #  # ]:          0 :                                 return gnutls_assert_val(GNUTLS_E_INCOMPATIBLE_SIG_WITH_KEY);
     194                 :            : 
     195                 :       1668 :                         gnutls_sign_algorithm_set_server(session, algo);
     196                 :            :                 } else {
     197                 :            :                         /* for client, signature algorithm is already
     198                 :            :                          * determined from Certificate Request */
     199                 :         41 :                         algo = gnutls_sign_algorithm_get_client(session);
     200         [ -  + ]:         41 :                         if (unlikely(algo == GNUTLS_SIGN_UNKNOWN))
     201         [ #  # ]:          0 :                                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
     202                 :            :                 }
     203                 :            : 
     204                 :       1709 :                 se = _gnutls_sign_to_entry(algo);
     205                 :            : 
     206         [ +  + ]:       1750 :                 ret = _gnutls13_handshake_sign_data(session, &apr_cert_list[0], apr_pkey,
     207                 :            :                                                     server?(&srv_ctx):(&cli_ctx),
     208                 :            :                                                     &sig, se);
     209         [ -  + ]:       1709 :                 if (ret < 0)
     210         [ #  # ]:          0 :                         return gnutls_assert_val(ret);
     211                 :            : 
     212         [ +  - ]:       3418 :                 ret = _gnutls_buffer_init_handshake_mbuffer(&buf);
     213         [ -  + ]:       1709 :                 if (ret < 0) {
     214         [ #  # ]:          0 :                         gnutls_assert();
     215                 :          0 :                         goto cleanup;
     216                 :            :                 }
     217                 :            : 
     218                 :       1709 :                 ret = _gnutls_buffer_append_data(&buf, se->aid.id, 2);
     219         [ -  + ]:       1709 :                 if (ret < 0) {
     220         [ #  # ]:          0 :                         gnutls_assert();
     221                 :          0 :                         goto cleanup;
     222                 :            :                 }
     223                 :            : 
     224                 :       1709 :                 ret = _gnutls_buffer_append_data_prefix(&buf, 16, sig.data, sig.size);
     225         [ -  + ]:       1709 :                 if (ret < 0) {
     226         [ #  # ]:          0 :                         gnutls_assert();
     227                 :          0 :                         goto cleanup;
     228                 :            :                 }
     229                 :            : 
     230                 :       1709 :                 bufel = _gnutls_buffer_to_mbuffer(&buf);
     231                 :            : 
     232                 :       1709 :                 gnutls_free(sig.data);
     233                 :            :         }
     234                 :            : 
     235                 :       1709 :         return _gnutls_send_handshake(session, bufel, GNUTLS_HANDSHAKE_CERTIFICATE_VERIFY);
     236                 :            : 
     237                 :          0 :  cleanup:
     238                 :          0 :         gnutls_free(sig.data);
     239                 :          0 :         _gnutls_buffer_clear(&buf);
     240                 :          0 :         return ret;
     241                 :            : }

Generated by: LCOV version 1.13