Coverage Report

Created: 2026-05-16 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnutls/lib/auth/rsa.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2000-2012 Free Software Foundation, 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
/* This file contains the RSA key exchange part of the certificate
24
 * authentication.
25
 */
26
27
#include "gnutls_int.h"
28
#include "auth.h"
29
#include "errors.h"
30
#include "dh.h"
31
#include "num.h"
32
#include "datum.h"
33
#include "auth/cert.h"
34
#include "pk.h"
35
#include "algorithms.h"
36
#include "global.h"
37
#include "debug.h"
38
#include "tls-sig.h"
39
#include "x509.h"
40
#include "random.h"
41
#include "mpi.h"
42
#include "abstract_int.h"
43
#include "auth/rsa_common.h"
44
45
int _gnutls_gen_rsa_client_kx(gnutls_session_t, gnutls_buffer_st *);
46
static int proc_rsa_client_kx(gnutls_session_t, uint8_t *, size_t);
47
48
const mod_auth_st rsa_auth_struct = {
49
  "RSA",
50
  _gnutls_gen_cert_server_crt,
51
  _gnutls_gen_cert_client_crt,
52
  NULL, /* gen server kx */
53
  _gnutls_gen_rsa_client_kx,
54
  _gnutls_gen_cert_client_crt_vrfy, /* gen client cert vrfy */
55
  _gnutls_gen_cert_server_cert_req, /* server cert request */
56
57
  _gnutls_proc_crt,
58
  _gnutls_proc_crt,
59
  NULL, /* proc server kx */
60
  proc_rsa_client_kx, /* proc client kx */
61
  _gnutls_proc_cert_client_crt_vrfy, /* proc client cert vrfy */
62
  _gnutls_proc_cert_cert_req /* proc server cert request */
63
};
64
65
static int check_key_usage_for_enc(gnutls_session_t session, unsigned key_usage)
66
1.32k
{
67
1.32k
  if (key_usage != 0) {
68
25
    if (!(key_usage & GNUTLS_KEY_KEY_ENCIPHERMENT) &&
69
11
        !(key_usage & GNUTLS_KEY_KEY_AGREEMENT)) {
70
2
      gnutls_assert();
71
2
      if (session->internals.allow_key_usage_violation == 0) {
72
2
        _gnutls_audit_log(
73
2
          session,
74
2
          "Peer's certificate does not allow encryption. Key usage violation detected.\n");
75
2
        return GNUTLS_E_KEY_USAGE_VIOLATION;
76
2
      } else {
77
0
        _gnutls_audit_log(
78
0
          session,
79
0
          "Peer's certificate does not allow encryption. Key usage violation detected (ignored).\n");
80
0
      }
81
2
    }
82
25
  }
83
1.31k
  return 0;
84
1.32k
}
85
86
/* This function reads the RSA parameters from peer's certificate;
87
 *
88
 * IMPORTANT:
89
 * Currently this function gets only called on the client side
90
 * during generation of the client kx msg. This function
91
 * retrieves the RSA params from the peer's certificate. That is in
92
 * this case the server's certificate. As of GNUTLS version 3.6.4 it is
93
 * possible to negotiate different certificate types for client and
94
 * server. Therefore the correct cert type needs to be retrieved to be
95
 * used for the _gnutls_get_auth_info_pcert call. If this
96
 * function is to be called on the server side in the future, extra
97
 * checks need to be build in order to retrieve the correct
98
 * certificate type.
99
 */
100
int _gnutls_get_public_rsa_params(gnutls_session_t session,
101
          gnutls_pk_params_st *params)
102
1.32k
{
103
1.32k
  int ret;
104
1.32k
  cert_auth_info_t info;
105
1.32k
  unsigned key_usage;
106
1.32k
  gnutls_pcert_st peer_cert;
107
1.32k
  gnutls_certificate_type_t cert_type;
108
109
1.32k
  assert(!IS_SERVER(session));
110
111
  /* normal non export case */
112
113
1.32k
  info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
114
115
1.32k
  if (info == NULL || info->ncerts == 0) {
116
0
    gnutls_assert();
117
0
    return GNUTLS_E_INTERNAL_ERROR;
118
0
  }
119
  // Get the negotiated server certificate type
120
1.32k
  cert_type = get_certificate_type(session, GNUTLS_CTYPE_SERVER);
121
122
1.32k
  ret = _gnutls_get_auth_info_pcert(&peer_cert, cert_type, info);
123
124
1.32k
  if (ret < 0) {
125
0
    gnutls_assert();
126
0
    return ret;
127
0
  }
128
129
1.32k
  gnutls_pubkey_get_key_usage(peer_cert.pubkey, &key_usage);
130
131
1.32k
  ret = check_key_usage_for_enc(session, key_usage);
132
1.32k
  if (ret < 0) {
133
2
    gnutls_assert();
134
2
    goto cleanup2;
135
2
  }
136
137
1.31k
  gnutls_pk_params_init(params);
138
139
1.31k
  ret = _gnutls_pubkey_get_mpis(peer_cert.pubkey, params);
140
1.31k
  if (ret < 0) {
141
0
    ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
142
0
    goto cleanup2;
143
0
  }
144
145
1.31k
  gnutls_pcert_deinit(&peer_cert);
146
1.31k
  return 0;
147
148
2
cleanup2:
149
2
  gnutls_pcert_deinit(&peer_cert);
150
151
2
  return ret;
152
1.31k
}
153
154
static int proc_rsa_client_kx(gnutls_session_t session, uint8_t *data,
155
            size_t _data_size)
156
100
{
157
100
  gnutls_datum_t ciphertext;
158
100
  int ret, dsize;
159
100
  ssize_t data_size = _data_size;
160
100
  volatile uint8_t ver_maj, ver_min;
161
100
  unsigned int key_bits;
162
163
#ifdef ENABLE_SSL3
164
  if (get_num_version(session) == GNUTLS_SSL3) {
165
    /* SSL 3.0 
166
     */
167
    ciphertext.data = data;
168
    ciphertext.size = data_size;
169
  } else
170
#endif
171
100
  {
172
    /* TLS 1.0+
173
     */
174
100
    DECR_LEN(data_size, 2);
175
98
    ciphertext.data = &data[2];
176
98
    dsize = _gnutls_read_uint16(data);
177
178
98
    if (dsize != data_size) {
179
12
      gnutls_assert();
180
12
      return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
181
12
    }
182
86
    ciphertext.size = dsize;
183
86
  }
184
0
  gnutls_privkey_get_pk_algorithm(session->internals.selected_key,
185
86
          &key_bits);
186
86
  if (ciphertext.size != (key_bits + 7) / 8)
187
72
    return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
188
189
14
  ver_maj = _gnutls_get_adv_version_major(session);
190
14
  ver_min = _gnutls_get_adv_version_minor(session);
191
192
14
  session->key.key.data = gnutls_malloc(GNUTLS_MASTER_SIZE);
193
14
  if (session->key.key.data == NULL) {
194
0
    gnutls_assert();
195
0
    return GNUTLS_E_MEMORY_ERROR;
196
0
  }
197
14
  session->key.key.size = GNUTLS_MASTER_SIZE;
198
199
  /* Fallback value when decryption fails. Needs to be unpredictable. */
200
14
  ret = gnutls_rnd(GNUTLS_RND_NONCE, session->key.key.data,
201
14
       GNUTLS_MASTER_SIZE);
202
14
  if (ret < 0) {
203
0
    gnutls_free(session->key.key.data);
204
0
    session->key.key.size = 0;
205
0
    gnutls_assert();
206
0
    return ret;
207
0
  }
208
209
14
  gnutls_privkey_decrypt_data2(session->internals.selected_key, 0,
210
14
             &ciphertext, session->key.key.data,
211
14
             session->key.key.size);
212
  /* After this point, any conditional on failure that cause differences
213
   * in execution may create a timing or cache access pattern side
214
   * channel that can be used as an oracle, so tread carefully */
215
216
  /* Error handling logic:
217
   * In case decryption fails then don't inform the peer. Just use the
218
   * random key previously generated. (in order to avoid attack against
219
   * pkcs-1 formatting).
220
   *
221
   * If we get version mismatches no error is returned either. We
222
   * proceed normally. This is to defend against the attack described
223
   * in the paper "Attacking RSA-based sessions in SSL/TLS" by
224
   * Vlastimil Klima, Ondej Pokorny and Tomas Rosa.
225
   */
226
227
  /* This is here to avoid the version check attack
228
   * discussed above.
229
   */
230
14
  session->key.key.data[0] = ver_maj;
231
14
  session->key.key.data[1] = ver_min;
232
233
14
  return 0;
234
14
}
235
236
/* return RSA(random) using the peers public key 
237
 */
238
int _gnutls_gen_rsa_client_kx(gnutls_session_t session, gnutls_buffer_st *data)
239
1.32k
{
240
1.32k
  cert_auth_info_t auth = session->key.auth_info;
241
1.32k
  gnutls_datum_t sdata; /* data to send */
242
1.32k
  gnutls_pk_params_st params;
243
1.32k
  int ret;
244
245
1.32k
  if (auth == NULL) {
246
    /* this shouldn't have happened. The proc_certificate
247
     * function should have detected that.
248
     */
249
0
    gnutls_assert();
250
0
    return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
251
0
  }
252
253
1.32k
  session->key.key.size = GNUTLS_MASTER_SIZE;
254
1.32k
  session->key.key.data = gnutls_malloc(session->key.key.size);
255
256
1.32k
  if (session->key.key.data == NULL) {
257
0
    gnutls_assert();
258
0
    return GNUTLS_E_MEMORY_ERROR;
259
0
  }
260
261
1.32k
  ret = gnutls_rnd(GNUTLS_RND_RANDOM, session->key.key.data,
262
1.32k
       session->key.key.size);
263
1.32k
  if (ret < 0) {
264
0
    gnutls_assert();
265
0
    return ret;
266
0
  }
267
268
1.32k
  if (session->internals.rsa_pms_version[0] == 0) {
269
1.32k
    session->key.key.data[0] =
270
1.32k
      _gnutls_get_adv_version_major(session);
271
1.32k
    session->key.key.data[1] =
272
1.32k
      _gnutls_get_adv_version_minor(session);
273
1.32k
  } else { /* use the version provided */
274
0
    session->key.key.data[0] =
275
0
      session->internals.rsa_pms_version[0];
276
0
    session->key.key.data[1] =
277
0
      session->internals.rsa_pms_version[1];
278
0
  }
279
280
  /* move RSA parameters to key (session).
281
   */
282
1.32k
  if ((ret = _gnutls_get_public_rsa_params(session, &params)) < 0) {
283
2
    gnutls_assert();
284
2
    return ret;
285
2
  }
286
287
1.31k
  ret = _gnutls_pk_encrypt(GNUTLS_PK_RSA, &sdata, &session->key.key,
288
1.31k
         &params, &params.spki);
289
290
1.31k
  gnutls_pk_params_release(&params);
291
292
1.31k
  if (ret < 0)
293
20
    return gnutls_assert_val(ret);
294
295
#ifdef ENABLE_SSL3
296
  if (get_num_version(session) == GNUTLS_SSL3) {
297
    /* SSL 3.0 */
298
    ret = _gnutls_buffer_append_data(data, sdata.data, sdata.size);
299
300
    _gnutls_free_datum(&sdata);
301
    return ret;
302
  } else
303
#endif
304
1.29k
  { /* TLS 1.x */
305
1.29k
    ret = _gnutls_buffer_append_data_prefix(data, 16, sdata.data,
306
1.29k
              sdata.size);
307
308
1.29k
    _gnutls_free_datum(&sdata);
309
1.29k
    return ret;
310
1.31k
  }
311
1.31k
}