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.14 Code Coverage Lines: 87 120 72.5 %
Date: 2020-10-30 04:50:48 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          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        5748 : int _gnutls13_recv_certificate_verify(gnutls_session_t session)
      44             : {
      45        5748 :         int ret;
      46        5748 :         gnutls_buffer_st buf;
      47        5748 :         const gnutls_sign_entry_st *se;
      48        5748 :         gnutls_datum_t sig_data;
      49        5748 :         gnutls_certificate_credentials_t cred;
      50        5748 :         unsigned vflags;
      51        5748 :         gnutls_pcert_st peer_cert;
      52        5748 :         cert_auth_info_t info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
      53        5748 :         bool server = 0;
      54        5748 :         gnutls_certificate_type_t cert_type;
      55             : 
      56        5748 :         memset(&peer_cert, 0, sizeof(peer_cert));
      57             : 
      58             :         /* this message is only expected if we have received
      59             :          * a certificate message */
      60        5748 :         if (!(session->internals.hsk_flags & HSK_CRT_VRFY_EXPECTED))
      61             :                 return 0;
      62             : 
      63         572 :         if (session->security_parameters.entity == GNUTLS_SERVER)
      64          77 :                 server = 1;
      65             : 
      66         572 :         cred = (gnutls_certificate_credentials_t)
      67         572 :                 _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE);
      68         572 :         if (unlikely(cred == NULL))
      69           0 :                 return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
      70         572 :         if (unlikely(info == NULL))
      71           0 :                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
      72             : 
      73         572 :         ret = _gnutls_recv_handshake(session, GNUTLS_HANDSHAKE_CERTIFICATE_VERIFY, 0, &buf);
      74         572 :         if (ret < 0)
      75           4 :                 return gnutls_assert_val(ret);
      76             : 
      77         568 :         _gnutls_handshake_log("HSK[%p]: Parsing certificate verify\n", session);
      78             : 
      79         568 :         if (buf.length < 2) {
      80           0 :                 gnutls_assert();
      81           0 :                 ret = GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
      82           0 :                 goto cleanup;
      83             :         }
      84             : 
      85         568 :         se = _gnutls_tls_aid_to_sign_entry(buf.data[0], buf.data[1], get_version(session));
      86         568 :         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_RECEIVED_ILLEGAL_PARAMETER);
      89           0 :                 goto cleanup;
      90             :         }
      91             : 
      92         568 :         if (server)
      93          77 :                 gnutls_sign_algorithm_set_client(session, se->id);
      94             :         else
      95         491 :                 gnutls_sign_algorithm_set_server(session, se->id);
      96             : 
      97         568 :         buf.data+=2;
      98         568 :         buf.length-=2;
      99             : 
     100             :         /* we check during verification whether the algorithm is enabled */
     101             : 
     102         568 :         ret = _gnutls_buffer_pop_datum_prefix16(&buf, &sig_data);
     103         568 :         if (ret < 0) {
     104           0 :                 gnutls_assert();
     105           0 :                 goto cleanup;
     106             :         }
     107             : 
     108         568 :         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         568 :         cert_type = get_certificate_type(session, GNUTLS_CTYPE_PEERS);
     117             : 
     118             :         /* Verify the signature */
     119         568 :         ret = _gnutls_get_auth_info_pcert(&peer_cert, cert_type, info);
     120         568 :         if (ret < 0) {
     121           0 :                 gnutls_assert();
     122           0 :                 goto cleanup;
     123             :         }
     124             : 
     125         568 :         vflags = cred->verify_flags | session->internals.additional_verify_flags;
     126             : 
     127        1059 :         ret = _gnutls13_handshake_verify_data(session, vflags, &peer_cert,
     128             :                                               server?(&cli_ctx):(&srv_ctx),
     129             :                                               &sig_data, se);
     130         568 :         if (ret < 0) {
     131           2 :                 gnutls_assert();
     132           2 :                 goto cleanup;
     133             :         }
     134             : 
     135         566 :         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         568 :  cleanup:
     143         568 :         gnutls_pcert_deinit(&peer_cert);
     144         568 :         _gnutls_buffer_clear(&buf);
     145         568 :         return ret;
     146             : }
     147             : 
     148        5775 : int _gnutls13_send_certificate_verify(gnutls_session_t session, unsigned again)
     149             : {
     150        5775 :         int ret;
     151        5775 :         gnutls_pcert_st *apr_cert_list;
     152        5775 :         gnutls_privkey_t apr_pkey;
     153        5775 :         int apr_cert_list_length;
     154        5775 :         mbuffer_st *bufel = NULL;
     155        5775 :         gnutls_buffer_st buf;
     156        5775 :         gnutls_datum_t sig = {NULL, 0};
     157        5775 :         gnutls_sign_algorithm_t algo;
     158        5775 :         const gnutls_sign_entry_st *se;
     159        5775 :         bool server = 0;
     160             : 
     161        5775 :         if (again == 0) {
     162        5775 :                 if (!session->internals.initial_negotiation_completed &&
     163        5773 :                     session->internals.hsk_flags & HSK_PSK_SELECTED)
     164             :                         return 0;
     165             : 
     166        4184 :                 if (session->security_parameters.entity == GNUTLS_SERVER &&
     167        3713 :                     session->internals.resumed)
     168             :                         return 0;
     169             : 
     170        4184 :                 if (session->security_parameters.entity == GNUTLS_SERVER)
     171        3713 :                         server = 1;
     172             : 
     173        4184 :                 ret = _gnutls_get_selected_cert(session, &apr_cert_list,
     174             :                                                 &apr_cert_list_length, &apr_pkey);
     175        4184 :                 if (ret < 0)
     176           0 :                         return gnutls_assert_val(ret);
     177             : 
     178        4184 :                 if (apr_cert_list_length == 0) {
     179         424 :                         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        3760 :                 if (server) {
     191        3713 :                         algo = _gnutls_session_get_sign_algo(session, &apr_cert_list[0], apr_pkey, 0, GNUTLS_KX_UNKNOWN);
     192        3713 :                         if (algo == GNUTLS_SIGN_UNKNOWN)
     193           0 :                                 return gnutls_assert_val(GNUTLS_E_INCOMPATIBLE_SIG_WITH_KEY);
     194             : 
     195        3713 :                         gnutls_sign_algorithm_set_server(session, algo);
     196             :                 } else {
     197             :                         /* for client, signature algorithm is already
     198             :                          * determined from Certificate Request */
     199          47 :                         algo = gnutls_sign_algorithm_get_client(session);
     200          47 :                         if (unlikely(algo == GNUTLS_SIGN_UNKNOWN))
     201           0 :                                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
     202             :                 }
     203             : 
     204        3760 :                 se = _gnutls_sign_to_entry(algo);
     205             : 
     206        3807 :                 ret = _gnutls13_handshake_sign_data(session, &apr_cert_list[0], apr_pkey,
     207             :                                                     server?(&srv_ctx):(&cli_ctx),
     208             :                                                     &sig, se);
     209        3760 :                 if (ret < 0)
     210           0 :                         return gnutls_assert_val(ret);
     211             : 
     212        7520 :                 ret = _gnutls_buffer_init_handshake_mbuffer(&buf);
     213        3760 :                 if (ret < 0) {
     214           0 :                         gnutls_assert();
     215           0 :                         goto cleanup;
     216             :                 }
     217             : 
     218        3760 :                 ret = _gnutls_buffer_append_data(&buf, se->aid.id, 2);
     219        3760 :                 if (ret < 0) {
     220           0 :                         gnutls_assert();
     221           0 :                         goto cleanup;
     222             :                 }
     223             : 
     224        3760 :                 ret = _gnutls_buffer_append_data_prefix(&buf, 16, sig.data, sig.size);
     225        3760 :                 if (ret < 0) {
     226           0 :                         gnutls_assert();
     227           0 :                         goto cleanup;
     228             :                 }
     229             : 
     230        3760 :                 bufel = _gnutls_buffer_to_mbuffer(&buf);
     231             : 
     232        3760 :                 gnutls_free(sig.data);
     233             :         }
     234             : 
     235        3760 :         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.14