Coverage Report

Created: 2023-03-26 07:33

/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,
29
           const uint8_t * data, size_t data_size,
30
           unsigned int mac_data, 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],
76
       content_type_t type,
77
       uint64_t sequence,
78
       const uint8_t * data, size_t data_size, size_t tag_size)
79
0
{
80
0
  int ret;
81
0
  const version_entry_st *ver = get_version(session);
82
0
  unsigned int tmp_pad_failed = 0;
83
0
  unsigned int pad_failed = 0;
84
0
  unsigned int pad, i, length;
85
0
  const uint8_t *tag_ptr = NULL;
86
0
  unsigned preamble_size;
87
0
  uint8_t tag[MAX_HASH_SIZE];
88
#ifdef ENABLE_SSL3
89
  unsigned blocksize = _gnutls_cipher_get_block_size(params->cipher);
90
#endif
91
92
0
  pad = data[data_size - 1];  /* pad */
93
94
  /* Check the padding bytes (TLS 1.x).
95
   * Note that we access all 256 bytes of ciphertext for padding check
96
   * because there is a timing channel in that memory access (in certain CPUs).
97
   */
98
#ifdef ENABLE_SSL3
99
  if (ver->id == GNUTLS_SSL3) {
100
    if (pad >= blocksize)
101
      pad_failed = 1;
102
  } else
103
#endif
104
0
  {
105
0
    for (i = 2; i <= MIN(256, data_size); i++) {
106
0
      tmp_pad_failed |= (data[data_size - i] != pad);
107
0
      pad_failed |= ((i <= (1 + pad)) & (tmp_pad_failed));
108
0
    }
109
0
  }
110
111
0
  if (unlikely
112
0
      (pad_failed != 0 || (1 + pad > ((int)data_size - tag_size)))) {
113
    /* We do not fail here. We check below for the
114
     * the pad_failed. If zero means success.
115
     */
116
0
    pad_failed = 1;
117
0
    pad = 0;
118
0
  }
119
120
0
  length = data_size - tag_size - pad - 1;
121
0
  tag_ptr = &data[length];
122
123
  /* Pass the type, version, length and plain through
124
   * MAC.
125
   */
126
0
  preamble_size =
127
0
      _gnutls_make_preamble(sequence, type, length, ver, preamble);
128
129
0
  ret =
130
0
      _gnutls_auth_cipher_add_auth(&params->read.ctx.tls12, preamble,
131
0
           preamble_size);
132
0
  if (unlikely(ret < 0))
133
0
    return gnutls_assert_val(ret);
134
135
0
  ret =
136
0
      _gnutls_auth_cipher_add_auth(&params->read.ctx.tls12, data, length);
137
0
  if (unlikely(ret < 0))
138
0
    return gnutls_assert_val(ret);
139
140
0
  ret = _gnutls_auth_cipher_tag(&params->read.ctx.tls12, tag, tag_size);
141
0
  if (unlikely(ret < 0))
142
0
    return gnutls_assert_val(ret);
143
144
0
  if (unlikely
145
0
      (gnutls_memcmp(tag, tag_ptr, tag_size) != 0 || pad_failed != 0)) {
146
    /* HMAC was not the same. */
147
0
    dummy_wait(params, data, data_size,
148
0
         length + preamble_size,
149
0
         preamble_size + data_size - tag_size - 1);
150
151
0
    return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
152
0
  }
153
154
0
  return length;
155
0
}