Coverage Report

Created: 2026-08-14 07:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnutls/lib/ext/etm.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2014 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
/* This file contains the code for the Max Record Size TLS extension.
24
 */
25
26
#include "gnutls_int.h"
27
#include "errors.h"
28
#include "num.h"
29
#include "hello_ext.h"
30
#include "ext/etm.h"
31
32
static int _gnutls_ext_etm_recv_params(gnutls_session_t session,
33
               const uint8_t *data, size_t data_size);
34
static int _gnutls_ext_etm_send_params(gnutls_session_t session,
35
               gnutls_buffer_st *extdata);
36
37
const hello_ext_entry_st ext_mod_etm = {
38
  .name = "Encrypt-then-MAC",
39
  .tls_id = 22,
40
  .gid = GNUTLS_EXTENSION_ETM,
41
  .client_parse_point = GNUTLS_EXT_MANDATORY,
42
  .server_parse_point = GNUTLS_EXT_MANDATORY,
43
  .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS |
44
        GNUTLS_EXT_FLAG_CLIENT_HELLO |
45
        GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
46
  .recv_func = _gnutls_ext_etm_recv_params,
47
  .send_func = _gnutls_ext_etm_send_params,
48
  .pack_func = NULL,
49
  .unpack_func = NULL,
50
  .deinit_func = NULL,
51
  .cannot_be_overriden = 1
52
};
53
54
/* 
55
 * In case of a server: if an EXT_MASTER_SECRET extension type is received then it
56
 * sets a flag into the session security parameters.
57
 *
58
 */
59
static int _gnutls_ext_etm_recv_params(gnutls_session_t session,
60
               const uint8_t *data, size_t data_size)
61
0
{
62
0
  if (data_size != 0) {
63
0
    return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
64
0
  }
65
66
0
  if (session->security_parameters.entity == GNUTLS_SERVER) {
67
0
    gnutls_ext_priv_data_t epriv;
68
69
0
    if (session->internals.no_etm != 0)
70
0
      return 0;
71
72
0
    epriv = (void *)(intptr_t)1;
73
0
    _gnutls_hello_ext_set_priv(session, GNUTLS_EXTENSION_ETM,
74
0
             epriv);
75
76
    /* don't decide now, decide on send */
77
0
    return 0;
78
0
  } else { /* client */
79
0
    const gnutls_cipher_suite_entry_st *e =
80
0
      session->security_parameters.cs;
81
0
    if (e != NULL) {
82
0
      const cipher_entry_st *c;
83
0
      c = cipher_to_entry(e->block_algorithm);
84
0
      if (c == NULL || (c->type == CIPHER_AEAD ||
85
0
            c->type == CIPHER_STREAM))
86
0
        return 0;
87
88
0
      session->security_parameters.etm = 1;
89
0
    }
90
0
  }
91
92
0
  return 0;
93
0
}
94
95
/* returns data_size or a negative number on failure
96
 */
97
static int _gnutls_ext_etm_send_params(gnutls_session_t session,
98
               gnutls_buffer_st *extdata)
99
0
{
100
0
  if (session->internals.no_etm != 0)
101
0
    return 0;
102
103
  /* this function sends the client extension data */
104
0
  if (session->security_parameters.entity == GNUTLS_CLIENT) {
105
0
    if (session->internals.priorities->have_cbc != 0)
106
0
      return GNUTLS_E_INT_RET_0;
107
0
    else
108
0
      return 0;
109
0
  } else { /* server side */
110
0
    const gnutls_cipher_suite_entry_st *e;
111
0
    const cipher_entry_st *c;
112
0
    int ret;
113
0
    gnutls_ext_priv_data_t epriv;
114
115
0
    e = session->security_parameters.cs;
116
0
    if (e != NULL) {
117
0
      c = cipher_to_entry(e->block_algorithm);
118
0
      if (c == NULL || (c->type == CIPHER_AEAD ||
119
0
            c->type == CIPHER_STREAM))
120
0
        return 0;
121
122
0
      ret = _gnutls_hello_ext_get_priv(
123
0
        session, GNUTLS_EXTENSION_ETM, &epriv);
124
0
      if (ret < 0 || ((intptr_t)epriv) == 0)
125
0
        return 0;
126
127
0
      session->security_parameters.etm = 1;
128
0
      return GNUTLS_E_INT_RET_0;
129
0
    }
130
0
  }
131
132
0
  return 0;
133
0
}
134
135
/**
136
 * gnutls_session_etm_status:
137
 * @session: is a #gnutls_session_t type.
138
 *
139
 * Get the status of the encrypt-then-mac extension negotiation.
140
 * This is in accordance to rfc7366
141
 *
142
 * Returns: Non-zero if the negotiation was successful or zero otherwise.
143
 **/
144
unsigned gnutls_session_etm_status(gnutls_session_t session)
145
0
{
146
0
  return session->security_parameters.etm;
147
0
}