Coverage Report

Created: 2025-11-16 07:49

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
0
#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
0
{
48
0
  int ret;
49
0
  const version_entry_st *ver = get_version(session);
50
0
  gnutls_buffer_st buf;
51
0
  uint8_t prefix[PREFIX_SIZE];
52
0
  unsigned key_usage = 0;
53
0
  gnutls_datum_t p;
54
55
0
  _gnutls_handshake_log(
56
0
    "HSK[%p]: verifying TLS 1.3 handshake data using %s\n", session,
57
0
    se->name);
58
59
0
  ret = _gnutls_pubkey_compatible_with_sig(session, cert->pubkey, ver,
60
0
             se->id);
61
0
  if (ret < 0)
62
0
    return gnutls_assert_val(ret);
63
64
0
  if (unlikely(sign_supports_cert_pk_algorithm(
65
0
           se, cert->pubkey->params.algo) == 0)) {
66
0
    _gnutls_handshake_log(
67
0
      "HSK[%p]: certificate of %s cannot be combined with %s sig\n",
68
0
      session, gnutls_pk_get_name(cert->pubkey->params.algo),
69
0
      se->name);
70
0
    return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
71
0
  }
72
73
0
  ret = _gnutls_session_sign_algo_enabled(session, se->id);
74
0
  if (ret < 0)
75
0
    return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
76
77
0
  if ((se->flags & GNUTLS_SIGN_FLAG_TLS13_OK) ==
78
0
      0) /* explicitly prohibited */
79
0
    return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
80
81
0
  gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage);
82
83
0
  ret = _gnutls_check_key_usage_for_sig(session, key_usage, 0);
84
0
  if (ret < 0)
85
0
    return gnutls_assert_val(ret);
86
87
0
  _gnutls_audit_new_context_with_data(
88
0
    "name", CRAU_STRING, "tls::verify", "tls::signature_algorithm",
89
0
    CRAU_WORD, se->aid.id[0] << 8 | se->aid.id[1], NULL);
90
91
0
  _gnutls_buffer_init(&buf);
92
93
0
  memset(prefix, 0x20, sizeof(prefix));
94
0
  ret = _gnutls_buffer_append_data(&buf, prefix, sizeof(prefix));
95
0
  if (ret < 0) {
96
0
    gnutls_assert();
97
0
    goto cleanup;
98
0
  }
99
100
0
  ret = _gnutls_buffer_append_data(&buf, context->data, context->size);
101
0
  if (ret < 0) {
102
0
    gnutls_assert();
103
0
    goto cleanup;
104
0
  }
105
106
0
  ret = _gnutls_buffer_append_data(&buf, "\x00", 1);
107
0
  if (ret < 0) {
108
0
    gnutls_assert();
109
0
    goto cleanup;
110
0
  }
111
112
0
  ret = gnutls_hash_fast(
113
0
    MAC_TO_DIG(session->security_parameters.prf->id),
114
0
    session->internals.handshake_hash_buffer.data,
115
0
    session->internals.handshake_hash_buffer_prev_len, prefix);
116
0
  if (ret < 0) {
117
0
    gnutls_assert();
118
0
    goto cleanup;
119
0
  }
120
121
0
  ret = _gnutls_buffer_append_data(
122
0
    &buf, prefix, session->security_parameters.prf->output_size);
123
0
  if (ret < 0) {
124
0
    gnutls_assert();
125
0
    goto cleanup;
126
0
  }
127
128
0
  p.data = buf.data;
129
0
  p.size = buf.length;
130
131
0
  verify_flags |= GNUTLS_VERIFY_RSA_PSS_FIXED_SALT_LENGTH;
132
0
  ret = gnutls_pubkey_verify_data2(cert->pubkey, se->id, verify_flags, &p,
133
0
           signature);
134
0
  if (ret < 0) {
135
0
    gnutls_assert();
136
0
    goto cleanup;
137
0
  }
138
139
0
  ret = 0;
140
0
cleanup:
141
0
  _gnutls_buffer_clear(&buf);
142
0
  gnutls_audit_pop_context();
143
144
0
  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
0
{
153
0
  gnutls_datum_t p;
154
0
  int ret;
155
0
  gnutls_buffer_st buf;
156
0
  uint8_t tmp[MAX_HASH_SIZE];
157
158
0
  if (unlikely(se == NULL ||
159
0
         (se->flags & GNUTLS_SIGN_FLAG_TLS13_OK) == 0))
160
0
    return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
161
162
0
  if (unlikely(sign_supports_priv_pk_algorithm(se, pkey->pk_algorithm) ==
163
0
         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
0
  _gnutls_handshake_log(
168
0
    "HSK[%p]: signing TLS 1.3 handshake data: using %s and PRF: %s\n",
169
0
    session, se->name, session->security_parameters.prf->name);
170
171
0
  _gnutls_audit_new_context_with_data(
172
0
    "name", CRAU_STRING, "tls::sign", "tls::signature_algorithm",
173
0
    CRAU_WORD, se->aid.id[0] << 8 | se->aid.id[1], NULL);
174
175
0
  _gnutls_buffer_init(&buf);
176
177
0
  ret = _gnutls_buffer_resize(&buf, PREFIX_SIZE);
178
0
  if (ret < 0) {
179
0
    gnutls_assert();
180
0
    goto cleanup;
181
0
  }
182
183
0
  memset(buf.data, 0x20, PREFIX_SIZE);
184
0
  buf.length += PREFIX_SIZE;
185
186
0
  ret = _gnutls_buffer_append_data(&buf, context->data, context->size);
187
0
  if (ret < 0) {
188
0
    gnutls_assert();
189
0
    goto cleanup;
190
0
  }
191
192
0
  ret = _gnutls_buffer_append_data(&buf, "\x00", 1);
193
0
  if (ret < 0) {
194
0
    gnutls_assert();
195
0
    goto cleanup;
196
0
  }
197
198
0
  ret = gnutls_hash_fast(MAC_TO_DIG(session->security_parameters.prf->id),
199
0
             session->internals.handshake_hash_buffer.data,
200
0
             session->internals.handshake_hash_buffer.length,
201
0
             tmp);
202
0
  if (ret < 0) {
203
0
    gnutls_assert();
204
0
    goto cleanup;
205
0
  }
206
207
0
  ret = _gnutls_buffer_append_data(
208
0
    &buf, tmp, session->security_parameters.prf->output_size);
209
0
  if (ret < 0) {
210
0
    gnutls_assert();
211
0
    goto cleanup;
212
0
  }
213
214
0
  p.data = buf.data;
215
0
  p.size = buf.length;
216
217
0
  ret = gnutls_privkey_sign_data2(
218
0
    pkey, se->id, GNUTLS_PRIVKEY_FLAG_RSA_PSS_FIXED_SALT_LENGTH, &p,
219
0
    signature);
220
0
  if (ret < 0) {
221
0
    gnutls_assert();
222
0
    goto cleanup;
223
0
  }
224
225
0
  ret = 0;
226
0
cleanup:
227
0
  _gnutls_buffer_clear(&buf);
228
0
  gnutls_audit_pop_context();
229
230
0
  return ret;
231
0
}