Coverage Report

Created: 2025-03-18 06:55

/src/gnutls/lib/cipher-cbc.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2000-2013 Free Software Foundation, Inc.
3
 * Copyright (C) 2013 Nikos Mavrogiannopoulos
4
 * Copyright (C) 2017-2018 Red Hat, Inc.
5
 *
6
 * Author: Nikos Mavrogiannopoulos
7
 *
8
 * This file is part of GnuTLS.
9
 *
10
 * The GnuTLS is free software; you can redistribute it and/or
11
 * modify it under the terms of the GNU Lesser General Public License
12
 * as published by the Free Software Foundation; either version 2.1 of
13
 * the License, or (at your option) any later version.
14
 *
15
 * This library is distributed in the hope that it will be useful, but
16
 * WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18
 * Lesser General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Lesser General Public License
21
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
22
 *
23
 */
24
25
#include "gnutls_int.h"
26
#include "cipher.h"
27
28
static void dummy_wait(record_parameters_st *params, const uint8_t *data,
29
           size_t data_size, unsigned int mac_data,
30
           unsigned int max_mac_data)
31
0
{
32
  /* this hack is only needed on CBC ciphers when Encrypt-then-MAC mode
33
   * is not supported by the peer. */
34
0
  unsigned v;
35
0
  unsigned int tag_size =
36
0
    _gnutls_auth_cipher_tag_len(&params->read.ctx.tls12);
37
0
  unsigned hash_block = _gnutls_mac_block_size(params->mac);
38
39
  /* force additional hash compression function evaluations to prevent timing
40
   * attacks that distinguish between wrong-mac + correct pad, from wrong-mac + incorrect pad.
41
   */
42
43
0
  if (params->mac && params->mac->id == GNUTLS_MAC_SHA384)
44
    /* v = 1 for the hash function padding + 16 for message length */
45
0
    v = 17;
46
0
  else /* v = 1 for the hash function padding + 8 for message length */
47
0
    v = 9;
48
49
0
  if (hash_block > 0) {
50
0
    int max_blocks =
51
0
      (max_mac_data + v + hash_block - 1) / hash_block;
52
0
    int hashed_blocks =
53
0
      (mac_data + v + hash_block - 1) / hash_block;
54
0
    unsigned to_hash;
55
56
0
    max_blocks -= hashed_blocks;
57
0
    if (max_blocks < 1)
58
0
      return;
59
60
0
    to_hash = max_blocks * hash_block;
61
0
    if ((unsigned)to_hash + 1 + tag_size < data_size) {
62
0
      _gnutls_auth_cipher_add_auth(
63
0
        &params->read.ctx.tls12,
64
0
        data + data_size - tag_size - to_hash - 1,
65
0
        to_hash);
66
0
    }
67
0
  }
68
0
}
69
70
/* Verifies the CBC HMAC. That's a special case as it tries to avoid
71
 * any leaks which could make CBC ciphersuites without EtM usable as an
72
 * oracle to attacks.
73
 */
74
int cbc_mac_verify(gnutls_session_t session, record_parameters_st *params,
75
       uint8_t preamble[MAX_PREAMBLE_SIZE], content_type_t type,
76
       uint64_t sequence, const uint8_t *data, size_t data_size,
77
       size_t tag_size)
78
0
{
79
0
  int ret;
80
0
  const version_entry_st *ver = get_version(session);
81
0
  unsigned int tmp_pad_failed = 0;
82
0
  unsigned int pad_failed = 0;
83
0
  unsigned int pad, i, length;
84
0
  const uint8_t *tag_ptr = NULL;
85
0
  unsigned preamble_size;
86
0
  uint8_t tag[MAX_HASH_SIZE];
87
#ifdef ENABLE_SSL3
88
  unsigned blocksize = _gnutls_cipher_get_block_size(params->cipher);
89
#endif
90
91
0
  pad = data[data_size - 1]; /* pad */
92
93
  /* Check the padding bytes (TLS 1.x).
94
   * Note that we access all 256 bytes of ciphertext for padding check
95
   * because there is a timing channel in that memory access (in certain CPUs).
96
   */
97
#ifdef ENABLE_SSL3
98
  if (ver->id == GNUTLS_SSL3) {
99
    if (pad >= blocksize)
100
      pad_failed = 1;
101
  } else
102
#endif
103
0
  {
104
0
    for (i = 2; i <= MIN(256, data_size); i++) {
105
0
      tmp_pad_failed |= (data[data_size - i] != pad);
106
0
      pad_failed |= ((i <= (1 + pad)) & (tmp_pad_failed));
107
0
    }
108
0
  }
109
110
0
  if (unlikely(pad_failed != 0 ||
111
0
         (1 + pad > ((int)data_size - tag_size)))) {
112
    /* We do not fail here. We check below for the
113
     * the pad_failed. If zero means success.
114
     */
115
0
    pad_failed = 1;
116
0
    pad = 0;
117
0
  }
118
119
0
  length = data_size - tag_size - pad - 1;
120
0
  tag_ptr = &data[length];
121
122
  /* Pass the type, version, length and plain through
123
   * MAC.
124
   */
125
0
  preamble_size =
126
0
    _gnutls_make_preamble(sequence, type, length, ver, preamble);
127
128
0
  ret = _gnutls_auth_cipher_add_auth(&params->read.ctx.tls12, preamble,
129
0
             preamble_size);
130
0
  if (unlikely(ret < 0))
131
0
    return gnutls_assert_val(ret);
132
133
0
  ret = _gnutls_auth_cipher_add_auth(&params->read.ctx.tls12, data,
134
0
             length);
135
0
  if (unlikely(ret < 0))
136
0
    return gnutls_assert_val(ret);
137
138
0
  ret = _gnutls_auth_cipher_tag(&params->read.ctx.tls12, tag, tag_size);
139
0
  if (unlikely(ret < 0))
140
0
    return gnutls_assert_val(ret);
141
142
0
  if (unlikely(gnutls_memcmp(tag, tag_ptr, tag_size) != 0 ||
143
0
         pad_failed != 0)) {
144
    /* HMAC was not the same. */
145
0
    dummy_wait(params, data, data_size, length + preamble_size,
146
0
         preamble_size + data_size - tag_size - 1);
147
148
0
    return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
149
0
  }
150
151
0
  return length;
152
0
}