Coverage Report

Created: 2025-11-16 06:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnutls/lib/tls13-sig.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2017-2019 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 "auth/cert.h"
26
#include "algorithms.h"
27
#include "ext/signature.h"
28
#include "abstract_int.h"
29
#include "tls13-sig.h"
30
#include "tls-sig.h"
31
#include "hash_int.h"
32
#include "audit.h"
33
34
#undef PREFIX_SIZE
35
4.64k
#define PREFIX_SIZE 64
36
#if PREFIX_SIZE < MAX_HASH_SIZE
37
/* we assume later that prefix is sufficient to store hash output */
38
#error Need to modify code
39
#endif
40
41
int _gnutls13_handshake_verify_data(gnutls_session_t session,
42
            unsigned verify_flags,
43
            gnutls_pcert_st *cert,
44
            const gnutls_datum_t *context,
45
            const gnutls_datum_t *signature,
46
            const gnutls_sign_entry_st *se)
47
2.59k
{
48
2.59k
  int ret;
49
2.59k
  const version_entry_st *ver = get_version(session);
50
2.59k
  gnutls_buffer_st buf;
51
2.59k
  uint8_t prefix[PREFIX_SIZE];
52
2.59k
  unsigned key_usage = 0;
53
2.59k
  gnutls_datum_t p;
54
55
2.59k
  _gnutls_handshake_log(
56
2.59k
    "HSK[%p]: verifying TLS 1.3 handshake data using %s\n", session,
57
2.59k
    se->name);
58
59
2.59k
  ret = _gnutls_pubkey_compatible_with_sig(session, cert->pubkey, ver,
60
2.59k
             se->id);
61
2.59k
  if (ret < 0)
62
18
    return gnutls_assert_val(ret);
63
64
2.57k
  if (unlikely(sign_supports_cert_pk_algorithm(
65
2.57k
           se, cert->pubkey->params.algo) == 0)) {
66
9
    _gnutls_handshake_log(
67
9
      "HSK[%p]: certificate of %s cannot be combined with %s sig\n",
68
9
      session, gnutls_pk_get_name(cert->pubkey->params.algo),
69
9
      se->name);
70
9
    return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
71
9
  }
72
73
2.56k
  ret = _gnutls_session_sign_algo_enabled(session, se->id);
74
2.56k
  if (ret < 0)
75
1
    return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
76
77
2.56k
  if ((se->flags & GNUTLS_SIGN_FLAG_TLS13_OK) ==
78
2.56k
      0) /* explicitly prohibited */
79
0
    return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
80
81
2.56k
  gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage);
82
83
2.56k
  ret = _gnutls_check_key_usage_for_sig(session, key_usage, 0);
84
2.56k
  if (ret < 0)
85
1
    return gnutls_assert_val(ret);
86
87
2.56k
  _gnutls_audit_new_context_with_data(
88
2.56k
    "name", CRAU_STRING, "tls::verify", "tls::signature_algorithm",
89
2.56k
    CRAU_WORD, se->aid.id[0] << 8 | se->aid.id[1], NULL);
90
91
2.56k
  _gnutls_buffer_init(&buf);
92
93
2.56k
  memset(prefix, 0x20, sizeof(prefix));
94
2.56k
  ret = _gnutls_buffer_append_data(&buf, prefix, sizeof(prefix));
95
2.56k
  if (ret < 0) {
96
0
    gnutls_assert();
97
0
    goto cleanup;
98
0
  }
99
100
2.56k
  ret = _gnutls_buffer_append_data(&buf, context->data, context->size);
101
2.56k
  if (ret < 0) {
102
0
    gnutls_assert();
103
0
    goto cleanup;
104
0
  }
105
106
2.56k
  ret = _gnutls_buffer_append_data(&buf, "\x00", 1);
107
2.56k
  if (ret < 0) {
108
0
    gnutls_assert();
109
0
    goto cleanup;
110
0
  }
111
112
2.56k
  ret = gnutls_hash_fast(
113
2.56k
    MAC_TO_DIG(session->security_parameters.prf->id),
114
2.56k
    session->internals.handshake_hash_buffer.data,
115
2.56k
    session->internals.handshake_hash_buffer_prev_len, prefix);
116
2.56k
  if (ret < 0) {
117
0
    gnutls_assert();
118
0
    goto cleanup;
119
0
  }
120
121
2.56k
  ret = _gnutls_buffer_append_data(
122
2.56k
    &buf, prefix, session->security_parameters.prf->output_size);
123
2.56k
  if (ret < 0) {
124
0
    gnutls_assert();
125
0
    goto cleanup;
126
0
  }
127
128
2.56k
  p.data = buf.data;
129
2.56k
  p.size = buf.length;
130
131
2.56k
  verify_flags |= GNUTLS_VERIFY_RSA_PSS_FIXED_SALT_LENGTH;
132
2.56k
  ret = gnutls_pubkey_verify_data2(cert->pubkey, se->id, verify_flags, &p,
133
2.56k
           signature);
134
2.56k
  if (ret < 0) {
135
2.56k
    gnutls_assert();
136
2.56k
    goto cleanup;
137
2.56k
  }
138
139
0
  ret = 0;
140
2.56k
cleanup:
141
2.56k
  _gnutls_buffer_clear(&buf);
142
2.56k
  gnutls_audit_pop_context();
143
144
2.56k
  return ret;
145
0
}
146
147
int _gnutls13_handshake_sign_data(gnutls_session_t session,
148
          gnutls_pcert_st *cert, gnutls_privkey_t pkey,
149
          const gnutls_datum_t *context,
150
          gnutls_datum_t *signature,
151
          const gnutls_sign_entry_st *se)
152
1.54k
{
153
1.54k
  gnutls_datum_t p;
154
1.54k
  int ret;
155
1.54k
  gnutls_buffer_st buf;
156
1.54k
  uint8_t tmp[MAX_HASH_SIZE];
157
158
1.54k
  if (unlikely(se == NULL ||
159
1.54k
         (se->flags & GNUTLS_SIGN_FLAG_TLS13_OK) == 0))
160
0
    return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
161
162
1.54k
  if (unlikely(sign_supports_priv_pk_algorithm(se, pkey->pk_algorithm) ==
163
1.54k
         0))
164
0
    return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
165
166
  /* when we reach here we know we have a signing certificate */
167
1.54k
  _gnutls_handshake_log(
168
1.54k
    "HSK[%p]: signing TLS 1.3 handshake data: using %s and PRF: %s\n",
169
1.54k
    session, se->name, session->security_parameters.prf->name);
170
171
1.54k
  _gnutls_audit_new_context_with_data(
172
1.54k
    "name", CRAU_STRING, "tls::sign", "tls::signature_algorithm",
173
1.54k
    CRAU_WORD, se->aid.id[0] << 8 | se->aid.id[1], NULL);
174
175
1.54k
  _gnutls_buffer_init(&buf);
176
177
1.54k
  ret = _gnutls_buffer_resize(&buf, PREFIX_SIZE);
178
1.54k
  if (ret < 0) {
179
0
    gnutls_assert();
180
0
    goto cleanup;
181
0
  }
182
183
1.54k
  memset(buf.data, 0x20, PREFIX_SIZE);
184
1.54k
  buf.length += PREFIX_SIZE;
185
186
1.54k
  ret = _gnutls_buffer_append_data(&buf, context->data, context->size);
187
1.54k
  if (ret < 0) {
188
0
    gnutls_assert();
189
0
    goto cleanup;
190
0
  }
191
192
1.54k
  ret = _gnutls_buffer_append_data(&buf, "\x00", 1);
193
1.54k
  if (ret < 0) {
194
0
    gnutls_assert();
195
0
    goto cleanup;
196
0
  }
197
198
1.54k
  ret = gnutls_hash_fast(MAC_TO_DIG(session->security_parameters.prf->id),
199
1.54k
             session->internals.handshake_hash_buffer.data,
200
1.54k
             session->internals.handshake_hash_buffer.length,
201
1.54k
             tmp);
202
1.54k
  if (ret < 0) {
203
0
    gnutls_assert();
204
0
    goto cleanup;
205
0
  }
206
207
1.54k
  ret = _gnutls_buffer_append_data(
208
1.54k
    &buf, tmp, session->security_parameters.prf->output_size);
209
1.54k
  if (ret < 0) {
210
0
    gnutls_assert();
211
0
    goto cleanup;
212
0
  }
213
214
1.54k
  p.data = buf.data;
215
1.54k
  p.size = buf.length;
216
217
1.54k
  ret = gnutls_privkey_sign_data2(
218
1.54k
    pkey, se->id, GNUTLS_PRIVKEY_FLAG_RSA_PSS_FIXED_SALT_LENGTH, &p,
219
1.54k
    signature);
220
1.54k
  if (ret < 0) {
221
0
    gnutls_assert();
222
0
    goto cleanup;
223
0
  }
224
225
1.54k
  ret = 0;
226
1.54k
cleanup:
227
1.54k
  _gnutls_buffer_clear(&buf);
228
1.54k
  gnutls_audit_pop_context();
229
230
1.54k
  return ret;
231
1.54k
}