Coverage Report

Created: 2023-03-26 08:33

/src/gnutls/lib/secrets.c
Line
Count
Source (jump to first uncovered line)
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
/* TLS 1.3 secret key derivation handling.
24
 */
25
26
#include <config.h>
27
#include "crypto-api.h"
28
#include "fips.h"
29
#include "gnutls_int.h"
30
#include "secrets.h"
31
32
/* HKDF-Extract(0,0) or HKDF-Extract(0, PSK) */
33
int _tls13_init_secret(gnutls_session_t session, const uint8_t * psk,
34
           size_t psk_size)
35
0
{
36
0
  session->key.proto.tls13.temp_secret_size =
37
0
      session->security_parameters.prf->output_size;
38
39
0
  return _tls13_init_secret2(session->security_parameters.prf,
40
0
           psk, psk_size,
41
0
           session->key.proto.tls13.temp_secret);
42
0
}
43
44
int _tls13_init_secret2(const mac_entry_st * prf,
45
      const uint8_t * psk, size_t psk_size, void *out)
46
0
{
47
0
  char buf[128];
48
49
0
  if (unlikely(prf == NULL))
50
0
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
51
52
  /* when no PSK, use the zero-value */
53
0
  if (psk == NULL) {
54
0
    psk_size = prf->output_size;
55
0
    if (unlikely(psk_size >= sizeof(buf)))
56
0
      return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
57
58
0
    memset(buf, 0, psk_size);
59
0
    psk = (uint8_t *) buf;
60
0
  }
61
62
0
  return gnutls_hmac_fast(prf->id, "", 0, psk, psk_size, out);
63
0
}
64
65
/* HKDF-Extract(Prev-Secret, key) */
66
int _tls13_update_secret(gnutls_session_t session, const uint8_t * key,
67
       size_t key_size)
68
0
{
69
0
  gnutls_datum_t _key;
70
0
  gnutls_datum_t salt;
71
0
  int ret;
72
73
0
  _key.data = (void *)key;
74
0
  _key.size = key_size;
75
0
  salt.data = (void *)session->key.proto.tls13.temp_secret;
76
0
  salt.size = session->key.proto.tls13.temp_secret_size;
77
78
0
  ret = _gnutls_hkdf_extract(session->security_parameters.prf->id,
79
0
           &_key, &salt,
80
0
           session->key.proto.tls13.temp_secret);
81
0
  if (ret < 0)
82
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
83
0
  else
84
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
85
86
0
  return ret;
87
0
}
88
89
/* Derive-Secret(Secret, Label, Messages) */
90
int _tls13_derive_secret2(const mac_entry_st * prf,
91
        const char *label, unsigned label_size,
92
        const uint8_t * tbh, size_t tbh_size,
93
        const uint8_t secret[MAX_HASH_SIZE], void *out)
94
0
{
95
0
  uint8_t digest[MAX_HASH_SIZE];
96
0
  int ret;
97
0
  unsigned digest_size;
98
99
0
  if (unlikely(prf == NULL))
100
0
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
101
0
  if (unlikely(label_size >= sizeof(digest)))
102
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
103
104
0
  digest_size = prf->output_size;
105
0
  ret = gnutls_hash_fast((gnutls_digest_algorithm_t) prf->id,
106
0
             tbh, tbh_size, digest);
107
0
  if (ret < 0)
108
0
    return gnutls_assert_val(ret);
109
110
0
  return _tls13_expand_secret2(prf, label, label_size, digest,
111
0
             digest_size, secret, digest_size, out);
112
0
}
113
114
/* Derive-Secret(Secret, Label, Messages) */
115
int _tls13_derive_secret(gnutls_session_t session,
116
       const char *label, unsigned label_size,
117
       const uint8_t * tbh, size_t tbh_size,
118
       const uint8_t secret[MAX_HASH_SIZE], void *out)
119
0
{
120
0
  if (unlikely(session->security_parameters.prf == NULL))
121
0
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
122
123
0
  return _tls13_derive_secret2(session->security_parameters.prf, label,
124
0
             label_size, tbh, tbh_size, secret, out);
125
0
}
126
127
/* HKDF-Expand-Label(Secret, Label, HashValue, Length) */
128
int _tls13_expand_secret2(const mac_entry_st * prf,
129
        const char *label, unsigned label_size,
130
        const uint8_t * msg, size_t msg_size,
131
        const uint8_t secret[MAX_HASH_SIZE],
132
        unsigned out_size, void *out)
133
0
{
134
0
  uint8_t tmp[256] = "tls13 ";
135
0
  gnutls_buffer_st str;
136
0
  gnutls_datum_t key;
137
0
  gnutls_datum_t info;
138
0
  int ret;
139
140
0
  if (unlikely(label_size >= sizeof(tmp) - 6))
141
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
142
143
0
  _gnutls_buffer_init(&str);
144
145
0
  ret = _gnutls_buffer_append_prefix(&str, 16, out_size);
146
0
  if (ret < 0) {
147
0
    gnutls_assert();
148
0
    goto cleanup;
149
0
  }
150
151
0
  memcpy(&tmp[6], label, label_size);
152
0
  ret = _gnutls_buffer_append_data_prefix(&str, 8, tmp, label_size + 6);
153
0
  if (ret < 0) {
154
0
    gnutls_assert();
155
0
    goto cleanup;
156
0
  }
157
158
0
  ret = _gnutls_buffer_append_data_prefix(&str, 8, msg, msg_size);
159
0
  if (ret < 0) {
160
0
    gnutls_assert();
161
0
    goto cleanup;
162
0
  }
163
164
0
  key.data = (void *)secret;
165
0
  key.size = _gnutls_mac_get_algo_len(mac_to_entry(prf->id));
166
0
  info.data = str.data;
167
0
  info.size = str.length;
168
169
0
  ret = _gnutls_hkdf_expand(prf->id, &key, &info, out, out_size);
170
0
  if (ret < 0) {
171
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
172
0
    gnutls_assert();
173
0
    goto cleanup;
174
0
  } else {
175
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
176
0
  }
177
178
#if 0
179
  _gnutls_hard_log("INT: hkdf label: %d,%s\n",
180
       out_size,
181
       _gnutls_bin2hex(str.data, str.length,
182
           (char *)tmp, sizeof(tmp), NULL));
183
  _gnutls_hard_log("INT: secret expanded for '%.*s': %d,%s\n",
184
       (int)label_size, label, out_size,
185
       _gnutls_bin2hex(out, out_size,
186
           (char *)tmp, sizeof(tmp), NULL));
187
#endif
188
189
0
  ret = 0;
190
0
 cleanup:
191
0
  _gnutls_buffer_clear(&str);
192
0
  return ret;
193
0
}
194
195
int _tls13_expand_secret(gnutls_session_t session,
196
       const char *label, unsigned label_size,
197
       const uint8_t * msg, size_t msg_size,
198
       const uint8_t secret[MAX_HASH_SIZE],
199
       unsigned out_size, void *out)
200
0
{
201
0
  if (unlikely(session->security_parameters.prf == NULL))
202
0
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
203
204
0
  return _tls13_expand_secret2(session->security_parameters.prf,
205
0
             label, label_size,
206
0
             msg, msg_size, secret, out_size, out);
207
0
}