Coverage Report

Created: 2026-03-31 07:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnutls/lib/system/ktls.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2021 Free Software Foundation, Inc.
3
 *
4
 * Author: František Krenželok
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 "config.h"
24
#include "system/ktls.h"
25
26
#ifdef ENABLE_KTLS
27
28
#include <sys/socket.h>
29
#include <netinet/tcp.h>
30
#include <unistd.h>
31
#include <errno.h>
32
#include "record.h"
33
34
#if defined(__FreeBSD__)
35
#include <sys/ktls.h>
36
#include <sys/types.h>
37
#include <netinet/in.h>
38
#include <crypto/cryptodev.h>
39
40
#else
41
#include <linux/tls.h>
42
#include "ext/session_ticket.h"
43
#include <sys/sendfile.h>
44
#include <sys/utsname.h>
45
#endif
46
47
/**
48
 * gnutls_transport_is_ktls_enabled:
49
 * @session: is a #gnutls_session_t type.
50
 *
51
 * Checks if KTLS is now enabled and was properly inicialized.
52
 *
53
 * Returns: %GNUTLS_KTLS_RECV, %GNUTLS_KTLS_SEND, %GNUTLS_KTLS_DUPLEX, otherwise 0
54
 *
55
 * Since: 3.7.3
56
 **/
57
gnutls_transport_ktls_enable_flags_t
58
gnutls_transport_is_ktls_enabled(gnutls_session_t session)
59
{
60
  if (unlikely(!session->internals.initial_negotiation_completed)) {
61
    _gnutls_debug_log("Initial negotiation is not yet complete\n");
62
    gnutls_assert();
63
    return 0;
64
  }
65
66
  return session->internals.ktls_enabled;
67
}
68
69
void _gnutls_ktls_enable(gnutls_session_t session)
70
{
71
#if defined(__FreeBSD__)
72
  session->internals.ktls_enabled |= GNUTLS_KTLS_RECV;
73
  session->internals.ktls_enabled |= GNUTLS_KTLS_SEND;
74
#else
75
  int sockin, sockout;
76
77
  gnutls_transport_get_int2(session, &sockin, &sockout);
78
79
  if (setsockopt(sockin, SOL_TCP, TCP_ULP, "tls", sizeof("tls")) == 0) {
80
    session->internals.ktls_enabled |= GNUTLS_KTLS_RECV;
81
    if (sockin == sockout) {
82
      session->internals.ktls_enabled |= GNUTLS_KTLS_SEND;
83
    }
84
  } else {
85
    _gnutls_record_log(
86
      "kTLS: Unable to set TCP_ULP for read socket: %d\n",
87
      errno);
88
    gnutls_assert();
89
  }
90
91
  if (sockin != sockout) {
92
    if (setsockopt(sockout, SOL_TCP, TCP_ULP, "tls",
93
             sizeof("tls")) == 0) {
94
      session->internals.ktls_enabled |= GNUTLS_KTLS_SEND;
95
    } else {
96
      _gnutls_record_log(
97
        "kTLS: Unable to set TCP_ULP for write socket: %d\n",
98
        errno);
99
      gnutls_assert();
100
    }
101
  }
102
#endif
103
}
104
105
#if defined(__FreeBSD__)
106
107
int _gnutls_ktls_set_keys(gnutls_session_t session,
108
        gnutls_transport_ktls_enable_flags_t in)
109
{
110
  gnutls_cipher_algorithm_t cipher = gnutls_cipher_get(session);
111
  gnutls_datum_t mac_key;
112
  gnutls_datum_t iv;
113
  gnutls_datum_t cipher_key;
114
  unsigned char seq_number[12];
115
  int sockin, sockout;
116
  int ret;
117
118
  gnutls_transport_get_int2(session, &sockin, &sockout);
119
  /* check whether or not cipher suite supports ktls
120
   */
121
  int version = gnutls_protocol_get_version(session);
122
  if ((version != GNUTLS_TLS1_3 && version != GNUTLS_TLS1_2) ||
123
      (cipher != GNUTLS_CIPHER_AES_128_GCM &&
124
       cipher != GNUTLS_CIPHER_AES_256_GCM &&
125
       cipher != GNUTLS_CIPHER_CHACHA20_POLY1305)) {
126
    return GNUTLS_E_UNIMPLEMENTED_FEATURE;
127
  }
128
129
  ret = gnutls_record_get_state(session, 1, &mac_key, &iv, &cipher_key,
130
              seq_number);
131
  if (ret < 0) {
132
    return ret;
133
  }
134
135
  in &= session->internals.ktls_enabled;
136
137
  if (in & GNUTLS_KTLS_RECV) {
138
    struct tls_enable crypto_info;
139
    memset(&crypto_info, 0, sizeof(crypto_info));
140
    switch (cipher) {
141
    case GNUTLS_CIPHER_AES_128_GCM: {
142
      crypto_info.cipher_algorithm = CRYPTO_AES_NIST_GCM_16;
143
      assert(cipher_key.size == AES_128_GMAC_KEY_LEN);
144
145
      if (version == GNUTLS_TLS1_2) {
146
        crypto_info.tls_vmajor = TLS_MAJOR_VER_ONE;
147
        crypto_info.tls_vminor = TLS_MINOR_VER_TWO;
148
        crypto_info.iv =
149
          gnutls_malloc(TLS_AEAD_GCM_LEN);
150
        if (!crypto_info.iv) {
151
          gnutls_assert();
152
          return GNUTLS_E_MEMORY_ERROR;
153
        }
154
        crypto_info.iv_len = TLS_AEAD_GCM_LEN;
155
        memcpy(crypto_info.iv, seq_number,
156
               TLS_AEAD_GCM_LEN);
157
      } else {
158
        crypto_info.tls_vmajor = TLS_MAJOR_VER_ONE;
159
        crypto_info.tls_vminor = TLS_MINOR_VER_THREE;
160
        assert(iv.size == TLS_1_3_GCM_IV_LEN);
161
162
        crypto_info.iv =
163
          gnutls_malloc(TLS_1_3_GCM_IV_LEN);
164
        if (!crypto_info.iv) {
165
          gnutls_assert();
166
          return GNUTLS_E_MEMORY_ERROR;
167
        }
168
        crypto_info.iv_len = TLS_1_3_GCM_IV_LEN;
169
        memcpy(crypto_info.iv, iv.data,
170
               TLS_1_3_GCM_IV_LEN);
171
      }
172
173
      memcpy(crypto_info.rec_seq, seq_number, 8);
174
175
      crypto_info.cipher_key_len = AES_128_GMAC_KEY_LEN;
176
      crypto_info.cipher_key =
177
        gnutls_malloc(AES_128_GMAC_KEY_LEN);
178
      if (!crypto_info.cipher_key) {
179
        gnutls_assert();
180
        return GNUTLS_E_MEMORY_ERROR;
181
      }
182
      memcpy(crypto_info.cipher_key, cipher_key.data,
183
             AES_128_GMAC_KEY_LEN);
184
185
      if (setsockopt(sockin, IPPROTO_TCP, TCP_RXTLS_ENABLE,
186
               &crypto_info, sizeof(crypto_info))) {
187
        session->internals.ktls_enabled &=
188
          ~GNUTLS_KTLS_RECV;
189
        return gnutls_assert_val(
190
          GNUTLS_E_INTERNAL_ERROR);
191
      }
192
    } break;
193
    case GNUTLS_CIPHER_AES_256_GCM: {
194
      crypto_info.cipher_algorithm = CRYPTO_AES_NIST_GCM_16;
195
      assert(cipher_key.size == AES_256_GMAC_KEY_LEN);
196
197
      if (version == GNUTLS_TLS1_2) {
198
        crypto_info.tls_vmajor = TLS_MAJOR_VER_ONE;
199
        crypto_info.tls_vminor = TLS_MINOR_VER_TWO;
200
        crypto_info.iv =
201
          gnutls_malloc(TLS_AEAD_GCM_LEN);
202
        if (!crypto_info.iv) {
203
          gnutls_assert();
204
          return GNUTLS_E_MEMORY_ERROR;
205
        }
206
        crypto_info.iv_len = TLS_AEAD_GCM_LEN;
207
        memcpy(crypto_info.iv, seq_number,
208
               TLS_AEAD_GCM_LEN);
209
      } else {
210
        crypto_info.tls_vmajor = TLS_MAJOR_VER_ONE;
211
        crypto_info.tls_vminor = TLS_MINOR_VER_THREE;
212
        assert(iv.size == TLS_1_3_GCM_IV_LEN);
213
214
        crypto_info.iv =
215
          gnutls_malloc(TLS_1_3_GCM_IV_LEN);
216
        if (!crypto_info.iv) {
217
          gnutls_assert();
218
          return GNUTLS_E_MEMORY_ERROR;
219
        }
220
        crypto_info.iv_len = TLS_1_3_GCM_IV_LEN;
221
        memcpy(crypto_info.iv, iv.data,
222
               TLS_1_3_GCM_IV_LEN);
223
      }
224
225
      memcpy(crypto_info.rec_seq, seq_number, 8);
226
227
      crypto_info.cipher_key_len = AES_256_GMAC_KEY_LEN;
228
      crypto_info.cipher_key =
229
        gnutls_malloc(AES_256_GMAC_KEY_LEN);
230
      if (!crypto_info.cipher_key) {
231
        gnutls_assert();
232
        return GNUTLS_E_MEMORY_ERROR;
233
      }
234
      memcpy(crypto_info.cipher_key, cipher_key.data,
235
             AES_256_GMAC_KEY_LEN);
236
237
      if (setsockopt(sockin, IPPROTO_TCP, TCP_RXTLS_ENABLE,
238
               &crypto_info, sizeof(crypto_info))) {
239
        session->internals.ktls_enabled &=
240
          ~GNUTLS_KTLS_RECV;
241
        return gnutls_assert_val(
242
          GNUTLS_E_INTERNAL_ERROR);
243
      }
244
245
    } break;
246
    case GNUTLS_CIPHER_CHACHA20_POLY1305: {
247
      crypto_info.cipher_algorithm = CRYPTO_CHACHA20_POLY1305;
248
      assert(cipher_key.size == POLY1305_KEY_LEN);
249
250
      if (version == GNUTLS_TLS1_2) {
251
        crypto_info.tls_vmajor = TLS_MAJOR_VER_ONE;
252
        crypto_info.tls_vminor = TLS_MINOR_VER_TWO;
253
      } else {
254
        crypto_info.tls_vmajor = TLS_MAJOR_VER_ONE;
255
        crypto_info.tls_vminor = TLS_MINOR_VER_THREE;
256
      }
257
258
      assert(iv.size == CHACHA20_POLY1305_IV_LEN);
259
      crypto_info.iv =
260
        gnutls_malloc(CHACHA20_POLY1305_IV_LEN);
261
      if (!crypto_info.iv) {
262
        gnutls_assert();
263
        return GNUTLS_E_MEMORY_ERROR;
264
      }
265
      crypto_info.iv_len = TLS_CHACHA20_IV_LEN;
266
      memcpy(crypto_info.iv, iv.data, TLS_CHACHA20_IV_LEN);
267
268
      memcpy(crypto_info.rec_seq, seq_number, 8);
269
270
      crypto_info.cipher_key_len = POLY1305_KEY_LEN;
271
      crypto_info.cipher_key =
272
        gnutls_malloc(POLY1305_KEY_LEN);
273
      if (!crypto_info.cipher_key) {
274
        gnutls_assert();
275
        return GNUTLS_E_MEMORY_ERROR;
276
      }
277
      memcpy(crypto_info.cipher_key, cipher_key.data,
278
             POLY1305_KEY_LEN);
279
280
      if (setsockopt(sockin, IPPROTO_TCP, TCP_RXTLS_ENABLE,
281
               &crypto_info, sizeof(crypto_info))) {
282
        session->internals.ktls_enabled &=
283
          ~GNUTLS_KTLS_RECV;
284
        return gnutls_assert_val(
285
          GNUTLS_E_INTERNAL_ERROR);
286
      }
287
288
    } break;
289
    default:
290
      assert(0);
291
    }
292
  }
293
294
  ret = gnutls_record_get_state(session, 0, &mac_key, &iv, &cipher_key,
295
              seq_number);
296
  if (ret < 0) {
297
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
298
  }
299
300
  if (in & GNUTLS_KTLS_SEND) {
301
    struct tls_enable crypto_info;
302
    memset(&crypto_info, 0, sizeof(crypto_info));
303
    switch (cipher) {
304
    case GNUTLS_CIPHER_AES_128_GCM: {
305
      crypto_info.cipher_algorithm = CRYPTO_AES_NIST_GCM_16;
306
      assert(cipher_key.size == AES_128_GMAC_KEY_LEN);
307
308
      if (version == GNUTLS_TLS1_2) {
309
        crypto_info.tls_vmajor = TLS_MAJOR_VER_ONE;
310
        crypto_info.tls_vminor = TLS_MINOR_VER_TWO;
311
        crypto_info.iv =
312
          gnutls_malloc(TLS_AEAD_GCM_LEN);
313
        if (!crypto_info.iv) {
314
          gnutls_assert();
315
          return GNUTLS_E_MEMORY_ERROR;
316
        }
317
        crypto_info.iv_len = TLS_AEAD_GCM_LEN;
318
        memcpy(crypto_info.iv, seq_number,
319
               TLS_AEAD_GCM_LEN);
320
      } else {
321
        crypto_info.tls_vmajor = TLS_MAJOR_VER_ONE;
322
        crypto_info.tls_vminor = TLS_MINOR_VER_THREE;
323
        assert(iv.size == TLS_1_3_GCM_IV_LEN);
324
325
        crypto_info.iv =
326
          gnutls_malloc(TLS_1_3_GCM_IV_LEN);
327
        if (!crypto_info.iv) {
328
          gnutls_assert();
329
          return GNUTLS_E_MEMORY_ERROR;
330
        }
331
        crypto_info.iv_len = TLS_1_3_GCM_IV_LEN;
332
        memcpy(crypto_info.iv, iv.data,
333
               TLS_1_3_GCM_IV_LEN);
334
      }
335
336
      memcpy(crypto_info.rec_seq, seq_number, 8);
337
338
      crypto_info.cipher_key_len = AES_128_GMAC_KEY_LEN;
339
      crypto_info.cipher_key =
340
        gnutls_malloc(AES_128_GMAC_KEY_LEN);
341
      if (!crypto_info.cipher_key) {
342
        gnutls_assert();
343
        return GNUTLS_E_MEMORY_ERROR;
344
      }
345
      memcpy(crypto_info.cipher_key, cipher_key.data,
346
             AES_128_GMAC_KEY_LEN);
347
348
      if (setsockopt(sockin, IPPROTO_TCP, TCP_TXTLS_ENABLE,
349
               &crypto_info, sizeof(crypto_info))) {
350
        session->internals.ktls_enabled &=
351
          ~GNUTLS_KTLS_SEND;
352
        return gnutls_assert_val(
353
          GNUTLS_E_INTERNAL_ERROR);
354
      }
355
    } break;
356
    case GNUTLS_CIPHER_AES_256_GCM: {
357
      crypto_info.cipher_algorithm = CRYPTO_AES_NIST_GCM_16;
358
      assert(cipher_key.size == AES_256_GMAC_KEY_LEN);
359
360
      if (version == GNUTLS_TLS1_2) {
361
        crypto_info.tls_vmajor = TLS_MAJOR_VER_ONE;
362
        crypto_info.tls_vminor = TLS_MINOR_VER_TWO;
363
        crypto_info.iv =
364
          gnutls_malloc(TLS_AEAD_GCM_LEN);
365
        if (!crypto_info.iv) {
366
          gnutls_assert();
367
          return GNUTLS_E_MEMORY_ERROR;
368
        }
369
        crypto_info.iv_len = TLS_AEAD_GCM_LEN;
370
        memcpy(crypto_info.iv, seq_number,
371
               TLS_AEAD_GCM_LEN);
372
      } else {
373
        crypto_info.tls_vmajor = TLS_MAJOR_VER_ONE;
374
        crypto_info.tls_vminor = TLS_MINOR_VER_THREE;
375
        assert(iv.size == TLS_1_3_GCM_IV_LEN);
376
377
        crypto_info.iv =
378
          gnutls_malloc(TLS_1_3_GCM_IV_LEN);
379
        if (!crypto_info.iv) {
380
          gnutls_assert();
381
          return GNUTLS_E_MEMORY_ERROR;
382
        }
383
        crypto_info.iv_len = TLS_1_3_GCM_IV_LEN;
384
        memcpy(crypto_info.iv, iv.data,
385
               TLS_1_3_GCM_IV_LEN);
386
      }
387
388
      memcpy(crypto_info.rec_seq, seq_number, 8);
389
390
      crypto_info.cipher_key_len = AES_256_GMAC_KEY_LEN;
391
      crypto_info.cipher_key =
392
        gnutls_malloc(AES_256_GMAC_KEY_LEN);
393
      if (!crypto_info.cipher_key) {
394
        gnutls_assert();
395
        return GNUTLS_E_MEMORY_ERROR;
396
      }
397
      memcpy(crypto_info.cipher_key, cipher_key.data,
398
             AES_256_GMAC_KEY_LEN);
399
400
      if (setsockopt(sockin, IPPROTO_TCP, TCP_TXTLS_ENABLE,
401
               &crypto_info, sizeof(crypto_info))) {
402
        session->internals.ktls_enabled &=
403
          ~GNUTLS_KTLS_SEND;
404
        return gnutls_assert_val(
405
          GNUTLS_E_INTERNAL_ERROR);
406
      }
407
408
    } break;
409
    case GNUTLS_CIPHER_CHACHA20_POLY1305: {
410
      crypto_info.cipher_algorithm = CRYPTO_CHACHA20_POLY1305;
411
      assert(cipher_key.size == POLY1305_KEY_LEN);
412
413
      if (version == GNUTLS_TLS1_2) {
414
        crypto_info.tls_vmajor = TLS_MAJOR_VER_ONE;
415
        crypto_info.tls_vminor = TLS_MINOR_VER_TWO;
416
      } else {
417
        crypto_info.tls_vmajor = TLS_MAJOR_VER_ONE;
418
        crypto_info.tls_vminor = TLS_MINOR_VER_THREE;
419
      }
420
421
      assert(iv.size == CHACHA20_POLY1305_IV_LEN);
422
      crypto_info.iv =
423
        gnutls_malloc(CHACHA20_POLY1305_IV_LEN);
424
      if (!crypto_info.iv) {
425
        gnutls_assert();
426
        return GNUTLS_E_MEMORY_ERROR;
427
      }
428
      crypto_info.iv_len = TLS_CHACHA20_IV_LEN;
429
      memcpy(crypto_info.iv, iv.data, TLS_CHACHA20_IV_LEN);
430
431
      memcpy(crypto_info.rec_seq, seq_number, 8);
432
433
      crypto_info.cipher_key_len = POLY1305_KEY_LEN;
434
      crypto_info.cipher_key =
435
        gnutls_malloc(POLY1305_KEY_LEN);
436
      if (!crypto_info.cipher_key) {
437
        gnutls_assert();
438
        return GNUTLS_E_MEMORY_ERROR;
439
      }
440
      memcpy(crypto_info.cipher_key, cipher_key.data,
441
             POLY1305_KEY_LEN);
442
443
      if (setsockopt(sockin, IPPROTO_TCP, TCP_TXTLS_ENABLE,
444
               &crypto_info, sizeof(crypto_info))) {
445
        session->internals.ktls_enabled &=
446
          ~GNUTLS_KTLS_SEND;
447
        return gnutls_assert_val(
448
          GNUTLS_E_INTERNAL_ERROR);
449
      }
450
451
    } break;
452
    default:
453
      assert(0);
454
    }
455
456
    // set callback for sending handshake messages
457
    gnutls_handshake_set_read_function(
458
      session, _gnutls_ktls_send_handshake_msg);
459
460
    // set callback for sending alert messages
461
    gnutls_alert_set_read_function(session,
462
                 _gnutls_ktls_send_alert_msg);
463
  }
464
465
  return in;
466
}
467
#else
468
469
int _gnutls_ktls_set_keys(gnutls_session_t session,
470
        gnutls_transport_ktls_enable_flags_t in)
471
{
472
  gnutls_cipher_algorithm_t cipher = gnutls_cipher_get(session);
473
  int version = gnutls_protocol_get_version(session);
474
  struct utsname utsname;
475
  char *endptr;
476
  long major, minor;
477
  gnutls_datum_t mac_key;
478
  gnutls_datum_t iv;
479
  gnutls_datum_t cipher_key;
480
  unsigned char seq_number[12];
481
  int sockin, sockout;
482
  int ret;
483
484
  ret = uname(&utsname);
485
  if (unlikely(ret < 0)) {
486
    return GNUTLS_E_INTERNAL_ERROR;
487
  }
488
489
  if (strcmp(utsname.sysname, "Linux") != 0) {
490
    return GNUTLS_E_INTERNAL_ERROR;
491
  }
492
493
  major = strtol(utsname.release, &endptr, 10);
494
  if (major < 0 || major == LONG_MAX || *endptr != '.') {
495
    return GNUTLS_E_INTERNAL_ERROR;
496
  }
497
  minor = strtol(endptr + 1, &endptr, 10);
498
  if (minor < 0 || minor == LONG_MAX || *endptr != '.') {
499
    return GNUTLS_E_INTERNAL_ERROR;
500
  }
501
502
  _gnutls_debug_log("Linux kernel version %lu.%lu has been detected\n",
503
        major, minor);
504
505
  /* setsockopt(SOL_TLS, TLS_RX) support added in 5.10 */
506
  if (major < 5 || (major == 5 && minor < 10)) {
507
    return GNUTLS_E_UNIMPLEMENTED_FEATURE;
508
  }
509
510
  if (major < 6 || (major == 6 && minor < 14)) {
511
    _gnutls_debug_log("Linux kernel version %lu.%lu doesn't yet "
512
          "support kTLS keyupdate, this will result in "
513
          "invalidation of the current session after a "
514
          "key-update is performed\n",
515
          major, minor);
516
  }
517
518
  /* check whether or not cipher suite supports ktls
519
   */
520
  switch (cipher) {
521
  case GNUTLS_CIPHER_AES_128_GCM:
522
  case GNUTLS_CIPHER_AES_256_GCM:
523
    break;
524
  case GNUTLS_CIPHER_AES_128_CCM:
525
  case GNUTLS_CIPHER_CHACHA20_POLY1305:
526
    /* AES-128-CCM and CHACHA20-POLY1305 can only be set
527
     * using setsockopt since 5.11.
528
     */
529
    if (major < 5 || (major == 5 && minor < 11)) {
530
      return GNUTLS_E_UNIMPLEMENTED_FEATURE;
531
    }
532
    break;
533
  default:
534
    return GNUTLS_E_UNIMPLEMENTED_FEATURE;
535
  }
536
537
  if (version < GNUTLS_TLS1_2) {
538
    return GNUTLS_E_UNIMPLEMENTED_FEATURE;
539
  }
540
541
  gnutls_transport_get_int2(session, &sockin, &sockout);
542
543
  ret = gnutls_record_get_state(session, 1, &mac_key, &iv, &cipher_key,
544
              seq_number);
545
  if (ret < 0) {
546
    return ret;
547
  }
548
549
  in &= session->internals.ktls_enabled;
550
551
  if (in & GNUTLS_KTLS_RECV) {
552
    switch (cipher) {
553
    case GNUTLS_CIPHER_AES_128_GCM: {
554
      struct tls12_crypto_info_aes_gcm_128 crypto_info;
555
      memset(&crypto_info, 0, sizeof(crypto_info));
556
557
      crypto_info.info.cipher_type = TLS_CIPHER_AES_GCM_128;
558
      assert(cipher_key.size ==
559
             TLS_CIPHER_AES_GCM_128_KEY_SIZE);
560
561
      /* for TLS 1.2 IV is generated in kernel */
562
      if (version == GNUTLS_TLS1_2) {
563
        crypto_info.info.version = TLS_1_2_VERSION;
564
        memcpy(crypto_info.iv, seq_number,
565
               TLS_CIPHER_AES_GCM_128_IV_SIZE);
566
      } else {
567
        crypto_info.info.version = TLS_1_3_VERSION;
568
        assert(iv.size ==
569
               TLS_CIPHER_AES_GCM_128_SALT_SIZE +
570
                 TLS_CIPHER_AES_GCM_128_IV_SIZE);
571
572
        memcpy(crypto_info.iv,
573
               iv.data +
574
                 TLS_CIPHER_AES_GCM_128_SALT_SIZE,
575
               TLS_CIPHER_AES_GCM_128_IV_SIZE);
576
      }
577
578
      memcpy(crypto_info.salt, iv.data,
579
             TLS_CIPHER_AES_GCM_128_SALT_SIZE);
580
      memcpy(crypto_info.rec_seq, seq_number,
581
             TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);
582
      memcpy(crypto_info.key, cipher_key.data,
583
             TLS_CIPHER_AES_GCM_128_KEY_SIZE);
584
585
      if (setsockopt(sockin, SOL_TLS, TLS_RX, &crypto_info,
586
               sizeof(crypto_info))) {
587
        session->internals.ktls_enabled &=
588
          ~GNUTLS_KTLS_RECV;
589
        return gnutls_assert_val(
590
          GNUTLS_E_INTERNAL_ERROR);
591
      }
592
    } break;
593
    case GNUTLS_CIPHER_AES_256_GCM: {
594
      struct tls12_crypto_info_aes_gcm_256 crypto_info;
595
      memset(&crypto_info, 0, sizeof(crypto_info));
596
597
      crypto_info.info.cipher_type = TLS_CIPHER_AES_GCM_256;
598
      assert(cipher_key.size ==
599
             TLS_CIPHER_AES_GCM_256_KEY_SIZE);
600
601
      /* for TLS 1.2 IV is generated in kernel */
602
      if (version == GNUTLS_TLS1_2) {
603
        crypto_info.info.version = TLS_1_2_VERSION;
604
        memcpy(crypto_info.iv, seq_number,
605
               TLS_CIPHER_AES_GCM_256_IV_SIZE);
606
      } else {
607
        crypto_info.info.version = TLS_1_3_VERSION;
608
        assert(iv.size ==
609
               TLS_CIPHER_AES_GCM_256_SALT_SIZE +
610
                 TLS_CIPHER_AES_GCM_256_IV_SIZE);
611
612
        memcpy(crypto_info.iv,
613
               iv.data +
614
                 TLS_CIPHER_AES_GCM_256_SALT_SIZE,
615
               TLS_CIPHER_AES_GCM_256_IV_SIZE);
616
      }
617
618
      memcpy(crypto_info.salt, iv.data,
619
             TLS_CIPHER_AES_GCM_256_SALT_SIZE);
620
      memcpy(crypto_info.rec_seq, seq_number,
621
             TLS_CIPHER_AES_GCM_256_REC_SEQ_SIZE);
622
      memcpy(crypto_info.key, cipher_key.data,
623
             TLS_CIPHER_AES_GCM_256_KEY_SIZE);
624
625
      if (setsockopt(sockin, SOL_TLS, TLS_RX, &crypto_info,
626
               sizeof(crypto_info))) {
627
        session->internals.ktls_enabled &=
628
          ~GNUTLS_KTLS_RECV;
629
        return gnutls_assert_val(
630
          GNUTLS_E_INTERNAL_ERROR);
631
      }
632
    } break;
633
    case GNUTLS_CIPHER_AES_128_CCM: {
634
      struct tls12_crypto_info_aes_ccm_128 crypto_info;
635
      memset(&crypto_info, 0, sizeof(crypto_info));
636
637
      crypto_info.info.cipher_type = TLS_CIPHER_AES_CCM_128;
638
      assert(cipher_key.size ==
639
             TLS_CIPHER_AES_CCM_128_KEY_SIZE);
640
641
      /* for TLS 1.2 IV is generated in kernel */
642
      if (version == GNUTLS_TLS1_2) {
643
        crypto_info.info.version = TLS_1_2_VERSION;
644
        memcpy(crypto_info.iv, seq_number,
645
               TLS_CIPHER_AES_CCM_128_IV_SIZE);
646
      } else {
647
        crypto_info.info.version = TLS_1_3_VERSION;
648
        assert(iv.size ==
649
               TLS_CIPHER_AES_CCM_128_SALT_SIZE +
650
                 TLS_CIPHER_AES_CCM_128_IV_SIZE);
651
652
        memcpy(crypto_info.iv,
653
               iv.data +
654
                 TLS_CIPHER_AES_CCM_128_SALT_SIZE,
655
               TLS_CIPHER_AES_CCM_128_IV_SIZE);
656
      }
657
658
      memcpy(crypto_info.salt, iv.data,
659
             TLS_CIPHER_AES_CCM_128_SALT_SIZE);
660
      memcpy(crypto_info.rec_seq, seq_number,
661
             TLS_CIPHER_AES_CCM_128_REC_SEQ_SIZE);
662
      memcpy(crypto_info.key, cipher_key.data,
663
             TLS_CIPHER_AES_CCM_128_KEY_SIZE);
664
665
      if (setsockopt(sockin, SOL_TLS, TLS_RX, &crypto_info,
666
               sizeof(crypto_info))) {
667
        session->internals.ktls_enabled &=
668
          ~GNUTLS_KTLS_RECV;
669
        return gnutls_assert_val(
670
          GNUTLS_E_INTERNAL_ERROR);
671
      }
672
    } break;
673
    case GNUTLS_CIPHER_CHACHA20_POLY1305: {
674
      struct tls12_crypto_info_chacha20_poly1305 crypto_info;
675
      memset(&crypto_info, 0, sizeof(crypto_info));
676
677
      crypto_info.info.cipher_type =
678
        TLS_CIPHER_CHACHA20_POLY1305;
679
      assert(cipher_key.size ==
680
             TLS_CIPHER_CHACHA20_POLY1305_KEY_SIZE);
681
682
      if (version == GNUTLS_TLS1_2)
683
        crypto_info.info.version = TLS_1_2_VERSION;
684
      else
685
        crypto_info.info.version = TLS_1_3_VERSION;
686
      /* TLS_CIPHER_CHACHA20_POLY1305_SALT_SIZE is 0 */
687
      assert(iv.size == TLS_CIPHER_CHACHA20_POLY1305_IV_SIZE);
688
      memcpy(crypto_info.iv, iv.data,
689
             TLS_CIPHER_CHACHA20_POLY1305_IV_SIZE);
690
691
      memcpy(crypto_info.rec_seq, seq_number,
692
             TLS_CIPHER_CHACHA20_POLY1305_REC_SEQ_SIZE);
693
      memcpy(crypto_info.key, cipher_key.data,
694
             TLS_CIPHER_CHACHA20_POLY1305_KEY_SIZE);
695
696
      if (setsockopt(sockin, SOL_TLS, TLS_RX, &crypto_info,
697
               sizeof(crypto_info))) {
698
        session->internals.ktls_enabled &=
699
          ~GNUTLS_KTLS_RECV;
700
        return gnutls_assert_val(
701
          GNUTLS_E_INTERNAL_ERROR);
702
      }
703
    } break;
704
    default:
705
      assert(0);
706
    }
707
  }
708
709
  ret = gnutls_record_get_state(session, 0, &mac_key, &iv, &cipher_key,
710
              seq_number);
711
  if (ret < 0) {
712
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
713
  }
714
715
  if (in & GNUTLS_KTLS_SEND) {
716
    switch (cipher) {
717
    case GNUTLS_CIPHER_AES_128_GCM: {
718
      struct tls12_crypto_info_aes_gcm_128 crypto_info;
719
      memset(&crypto_info, 0, sizeof(crypto_info));
720
721
      crypto_info.info.cipher_type = TLS_CIPHER_AES_GCM_128;
722
723
      assert(cipher_key.size ==
724
             TLS_CIPHER_AES_GCM_128_KEY_SIZE);
725
726
      /* for TLS 1.2 IV is generated in kernel */
727
      if (version == GNUTLS_TLS1_2) {
728
        crypto_info.info.version = TLS_1_2_VERSION;
729
        memcpy(crypto_info.iv, seq_number,
730
               TLS_CIPHER_AES_GCM_128_IV_SIZE);
731
      } else {
732
        crypto_info.info.version = TLS_1_3_VERSION;
733
        assert(iv.size ==
734
               TLS_CIPHER_AES_GCM_128_SALT_SIZE +
735
                 TLS_CIPHER_AES_GCM_128_IV_SIZE);
736
737
        memcpy(crypto_info.iv,
738
               iv.data +
739
                 TLS_CIPHER_AES_GCM_128_SALT_SIZE,
740
               TLS_CIPHER_AES_GCM_128_IV_SIZE);
741
      }
742
743
      memcpy(crypto_info.salt, iv.data,
744
             TLS_CIPHER_AES_GCM_128_SALT_SIZE);
745
      memcpy(crypto_info.rec_seq, seq_number,
746
             TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);
747
      memcpy(crypto_info.key, cipher_key.data,
748
             TLS_CIPHER_AES_GCM_128_KEY_SIZE);
749
750
      if (setsockopt(sockout, SOL_TLS, TLS_TX, &crypto_info,
751
               sizeof(crypto_info))) {
752
        session->internals.ktls_enabled &=
753
          ~GNUTLS_KTLS_SEND;
754
        return gnutls_assert_val(
755
          GNUTLS_E_INTERNAL_ERROR);
756
      }
757
    } break;
758
    case GNUTLS_CIPHER_AES_256_GCM: {
759
      struct tls12_crypto_info_aes_gcm_256 crypto_info;
760
      memset(&crypto_info, 0, sizeof(crypto_info));
761
762
      crypto_info.info.cipher_type = TLS_CIPHER_AES_GCM_256;
763
      assert(cipher_key.size ==
764
             TLS_CIPHER_AES_GCM_256_KEY_SIZE);
765
766
      /* for TLS 1.2 IV is generated in kernel */
767
      if (version == GNUTLS_TLS1_2) {
768
        crypto_info.info.version = TLS_1_2_VERSION;
769
        memcpy(crypto_info.iv, seq_number,
770
               TLS_CIPHER_AES_GCM_256_IV_SIZE);
771
      } else {
772
        crypto_info.info.version = TLS_1_3_VERSION;
773
        assert(iv.size ==
774
               TLS_CIPHER_AES_GCM_256_SALT_SIZE +
775
                 TLS_CIPHER_AES_GCM_256_IV_SIZE);
776
777
        memcpy(crypto_info.iv,
778
               iv.data +
779
                 TLS_CIPHER_AES_GCM_256_SALT_SIZE,
780
               TLS_CIPHER_AES_GCM_256_IV_SIZE);
781
      }
782
783
      memcpy(crypto_info.salt, iv.data,
784
             TLS_CIPHER_AES_GCM_256_SALT_SIZE);
785
      memcpy(crypto_info.rec_seq, seq_number,
786
             TLS_CIPHER_AES_GCM_256_REC_SEQ_SIZE);
787
      memcpy(crypto_info.key, cipher_key.data,
788
             TLS_CIPHER_AES_GCM_256_KEY_SIZE);
789
790
      if (setsockopt(sockout, SOL_TLS, TLS_TX, &crypto_info,
791
               sizeof(crypto_info))) {
792
        session->internals.ktls_enabled &=
793
          ~GNUTLS_KTLS_SEND;
794
        return gnutls_assert_val(
795
          GNUTLS_E_INTERNAL_ERROR);
796
      }
797
    } break;
798
    case GNUTLS_CIPHER_AES_128_CCM: {
799
      struct tls12_crypto_info_aes_ccm_128 crypto_info;
800
      memset(&crypto_info, 0, sizeof(crypto_info));
801
802
      crypto_info.info.cipher_type = TLS_CIPHER_AES_CCM_128;
803
      assert(cipher_key.size ==
804
             TLS_CIPHER_AES_CCM_128_KEY_SIZE);
805
806
      /* for TLS 1.2 IV is generated in kernel */
807
      if (version == GNUTLS_TLS1_2) {
808
        crypto_info.info.version = TLS_1_2_VERSION;
809
        memcpy(crypto_info.iv, seq_number,
810
               TLS_CIPHER_AES_CCM_128_IV_SIZE);
811
      } else {
812
        crypto_info.info.version = TLS_1_3_VERSION;
813
        assert(iv.size ==
814
               TLS_CIPHER_AES_CCM_128_SALT_SIZE +
815
                 TLS_CIPHER_AES_CCM_128_IV_SIZE);
816
817
        memcpy(crypto_info.iv,
818
               iv.data +
819
                 TLS_CIPHER_AES_CCM_128_SALT_SIZE,
820
               TLS_CIPHER_AES_CCM_128_IV_SIZE);
821
      }
822
823
      memcpy(crypto_info.salt, iv.data,
824
             TLS_CIPHER_AES_CCM_128_SALT_SIZE);
825
      memcpy(crypto_info.rec_seq, seq_number,
826
             TLS_CIPHER_AES_CCM_128_REC_SEQ_SIZE);
827
      memcpy(crypto_info.key, cipher_key.data,
828
             TLS_CIPHER_AES_CCM_128_KEY_SIZE);
829
830
      if (setsockopt(sockout, SOL_TLS, TLS_TX, &crypto_info,
831
               sizeof(crypto_info))) {
832
        session->internals.ktls_enabled &=
833
          ~GNUTLS_KTLS_SEND;
834
        return gnutls_assert_val(
835
          GNUTLS_E_INTERNAL_ERROR);
836
      }
837
    } break;
838
    case GNUTLS_CIPHER_CHACHA20_POLY1305: {
839
      struct tls12_crypto_info_chacha20_poly1305 crypto_info;
840
      memset(&crypto_info, 0, sizeof(crypto_info));
841
842
      crypto_info.info.cipher_type =
843
        TLS_CIPHER_CHACHA20_POLY1305;
844
      assert(cipher_key.size ==
845
             TLS_CIPHER_CHACHA20_POLY1305_KEY_SIZE);
846
847
      if (version == GNUTLS_TLS1_2)
848
        crypto_info.info.version = TLS_1_2_VERSION;
849
      else
850
        crypto_info.info.version = TLS_1_3_VERSION;
851
      /* TLS_CIPHER_CHACHA20_POLY1305_SALT_SIZE is 0 */
852
      assert(iv.size == TLS_CIPHER_CHACHA20_POLY1305_IV_SIZE);
853
      memcpy(crypto_info.iv, iv.data,
854
             TLS_CIPHER_CHACHA20_POLY1305_IV_SIZE);
855
856
      memcpy(crypto_info.rec_seq, seq_number,
857
             TLS_CIPHER_CHACHA20_POLY1305_REC_SEQ_SIZE);
858
      memcpy(crypto_info.key, cipher_key.data,
859
             TLS_CIPHER_CHACHA20_POLY1305_KEY_SIZE);
860
861
      if (setsockopt(sockout, SOL_TLS, TLS_TX, &crypto_info,
862
               sizeof(crypto_info))) {
863
        session->internals.ktls_enabled &=
864
          ~GNUTLS_KTLS_SEND;
865
        return gnutls_assert_val(
866
          GNUTLS_E_INTERNAL_ERROR);
867
      }
868
    } break;
869
    default:
870
      assert(0);
871
    }
872
873
    // set callback for sending handshake messages
874
    gnutls_handshake_set_read_function(
875
      session, _gnutls_ktls_send_handshake_msg);
876
877
    // set callback for sending alert messages
878
    gnutls_alert_set_read_function(session,
879
                 _gnutls_ktls_send_alert_msg);
880
  }
881
882
  return in;
883
}
884
#endif
885
886
ssize_t _gnutls_ktls_send_file(gnutls_session_t session, int fd, off_t *offset,
887
             size_t count)
888
{
889
  ssize_t ret;
890
  int sockin, sockout;
891
892
  assert(session != NULL);
893
#if defined(__FreeBSD__)
894
  off_t sbytes = 0;
895
  assert(offset != NULL);
896
#endif
897
898
  gnutls_transport_get_int2(session, &sockin, &sockout);
899
#if defined(__FreeBSD__)
900
  ret = sendfile(fd, sockout, *offset, count, NULL, &sbytes, 0);
901
#else
902
  ret = sendfile(sockout, fd, offset, count);
903
#endif
904
  if (ret == -1) {
905
    switch (errno) {
906
    case EINTR:
907
      return GNUTLS_E_INTERRUPTED;
908
    case EAGAIN:
909
      return GNUTLS_E_AGAIN;
910
    default:
911
      return GNUTLS_E_PUSH_ERROR;
912
    }
913
  }
914
#if defined(__FreeBSD__)
915
  *offset += sbytes; /* follow linux sendfile behavior */
916
  return sbytes;
917
#else
918
  return ret;
919
#endif
920
}
921
922
int _gnutls_ktls_send_control_msg(gnutls_session_t session,
923
          unsigned char record_type, const void *data,
924
          size_t data_size)
925
{
926
  const char *buf = data;
927
  ssize_t ret;
928
  int sockin, sockout;
929
  size_t data_to_send = data_size;
930
931
  assert(session != NULL);
932
933
  gnutls_transport_get_int2(session, &sockin, &sockout);
934
935
  while (data_to_send > 0) {
936
    char cmsg[CMSG_SPACE(sizeof(unsigned char))];
937
    struct msghdr msg = { 0 };
938
    struct iovec msg_iov; /* Vector of data to send/receive into. */
939
    struct cmsghdr *hdr;
940
941
    msg.msg_control = cmsg;
942
    msg.msg_controllen = sizeof cmsg;
943
944
    hdr = CMSG_FIRSTHDR(&msg);
945
#if defined(__FreeBSD__)
946
    hdr->cmsg_level = IPPROTO_TCP;
947
#else
948
    hdr->cmsg_level = SOL_TLS;
949
#endif
950
    hdr->cmsg_type = TLS_SET_RECORD_TYPE;
951
    hdr->cmsg_len = CMSG_LEN(sizeof(unsigned char));
952
953
    // construct record header
954
    *CMSG_DATA(hdr) = record_type;
955
    msg.msg_controllen = hdr->cmsg_len;
956
957
    msg_iov.iov_base = (void *)buf;
958
    msg_iov.iov_len = data_to_send;
959
960
    msg.msg_iov = &msg_iov;
961
    msg.msg_iovlen = 1;
962
963
    ret = sendmsg(sockout, &msg, MSG_DONTWAIT);
964
965
    if (ret == -1) {
966
      switch (errno) {
967
      case EINTR:
968
        if (data_to_send < data_size) {
969
          return data_size - data_to_send;
970
        } else {
971
          return GNUTLS_E_INTERRUPTED;
972
        }
973
      case EAGAIN:
974
        if (data_to_send < data_size) {
975
          return data_size - data_to_send;
976
        } else {
977
          return GNUTLS_E_AGAIN;
978
        }
979
      default:
980
        return GNUTLS_E_PUSH_ERROR;
981
      }
982
    }
983
984
    buf += ret;
985
    data_to_send -= ret;
986
  }
987
988
  return data_size;
989
}
990
991
int _gnutls_ktls_send_handshake_msg(gnutls_session_t session,
992
            gnutls_record_encryption_level_t level,
993
            gnutls_handshake_description_t htype,
994
            const void *data, size_t data_size)
995
{
996
  return _gnutls_ktls_send_control_msg(session, GNUTLS_HANDSHAKE, data,
997
               data_size);
998
}
999
1000
int _gnutls_ktls_send_alert_msg(gnutls_session_t session,
1001
        gnutls_record_encryption_level_t level,
1002
        gnutls_alert_level_t alert_level,
1003
        gnutls_alert_description_t alert_desc)
1004
{
1005
  uint8_t data[2];
1006
  data[0] = (uint8_t)alert_level;
1007
  data[1] = (uint8_t)alert_desc;
1008
  return _gnutls_ktls_send_control_msg(session, GNUTLS_ALERT, data, 2);
1009
}
1010
1011
int _gnutls_ktls_recv_control_msg(gnutls_session_t session,
1012
          unsigned char *record_type, void *data,
1013
          size_t data_size)
1014
{
1015
  char *buf = data;
1016
  ssize_t ret;
1017
  int sockin, sockout;
1018
1019
  char cmsg[CMSG_SPACE(sizeof(unsigned char))];
1020
  struct msghdr msg = { 0 };
1021
  struct iovec msg_iov;
1022
  struct cmsghdr *hdr;
1023
1024
  assert(session != NULL);
1025
1026
  gnutls_transport_get_int2(session, &sockin, &sockout);
1027
1028
  if (session->internals.read_eof != 0) {
1029
    return 0;
1030
  } else if (session->internals.invalid_connection != 0 ||
1031
       session->internals.may_not_read != 0)
1032
    return GNUTLS_E_INVALID_SESSION;
1033
1034
  /* receive message */
1035
  msg.msg_control = cmsg;
1036
  msg.msg_controllen = sizeof cmsg;
1037
1038
  msg_iov.iov_base = buf;
1039
  msg_iov.iov_len = data_size;
1040
1041
  msg.msg_iov = &msg_iov;
1042
  msg.msg_iovlen = 1;
1043
1044
  ret = recvmsg(sockin, &msg, MSG_DONTWAIT);
1045
1046
  if (ret == -1) {
1047
    switch (errno) {
1048
    case EAGAIN:
1049
      return GNUTLS_E_AGAIN;
1050
    case EINVAL:
1051
      return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
1052
    case EMSGSIZE:
1053
      return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
1054
    case EBADMSG:
1055
      return GNUTLS_E_DECRYPTION_FAILED;
1056
    default:
1057
      return GNUTLS_E_PULL_ERROR;
1058
    }
1059
  } else if (unlikely(ret == -EKEYEXPIRED)) {
1060
    /* This will be received until a keyupdate is performed on the
1061
       scoket. */
1062
    _gnutls_debug_log("kTLS: socket(recv) has not yet received "
1063
          "updated keys\n");
1064
    gnutls_assert();
1065
    return GNUTLS_E_AGAIN;
1066
  }
1067
1068
  /* connection closed */
1069
  if (ret == 0)
1070
    return 0;
1071
1072
  /* get record type from header */
1073
  hdr = CMSG_FIRSTHDR(&msg);
1074
  if (hdr == NULL) {
1075
    return GNUTLS_E_PULL_ERROR;
1076
  }
1077
#if defined(__FreeBSD__)
1078
  if (hdr->cmsg_level == IPPROTO_TCP && hdr->cmsg_type == TLS_GET_RECORD)
1079
#else
1080
  if (hdr->cmsg_level == SOL_TLS && hdr->cmsg_type == TLS_GET_RECORD_TYPE)
1081
#endif
1082
    *record_type = *(unsigned char *)CMSG_DATA(hdr);
1083
  else
1084
    *record_type = GNUTLS_APPLICATION_DATA;
1085
1086
  return ret;
1087
}
1088
1089
int _gnutls_ktls_recv_int(gnutls_session_t session, content_type_t type,
1090
        void *data, size_t data_size)
1091
{
1092
  unsigned char record_type;
1093
  int ret;
1094
1095
  ret = _gnutls_ktls_recv_control_msg(session, &record_type, data,
1096
              data_size);
1097
1098
  if (ret > 0) {
1099
    switch (record_type) {
1100
    case GNUTLS_CHANGE_CIPHER_SPEC:
1101
      return gnutls_assert_val(
1102
        GNUTLS_E_UNIMPLEMENTED_FEATURE);
1103
      break;
1104
    case GNUTLS_ALERT:
1105
      if (ret < 2) {
1106
        return gnutls_assert_val(
1107
          GNUTLS_E_UNEXPECTED_PACKET);
1108
      }
1109
1110
      uint8_t level = ((uint8_t *)data)[0];
1111
      uint8_t desc = ((uint8_t *)data)[1];
1112
1113
      _gnutls_record_log(
1114
        "REC[%p]: Alert[%d|%d] - %s - was received\n",
1115
        session, level, desc,
1116
        gnutls_alert_get_name((int)desc));
1117
1118
      session->internals.last_alert = desc;
1119
1120
      /* if close notify is received and
1121
       * the alert is not fatal
1122
       */
1123
      if (desc == GNUTLS_A_CLOSE_NOTIFY &&
1124
          level != GNUTLS_AL_FATAL) {
1125
        /* If we have been expecting for an alert do
1126
         */
1127
        session->internals.read_eof = 1;
1128
        return 0;
1129
      }
1130
      /* if the alert is FATAL or WARNING
1131
       * return the appropriate message
1132
       */
1133
      gnutls_assert();
1134
      if (level == GNUTLS_AL_FATAL) {
1135
        session->internals.resumable = false;
1136
        session->internals.invalid_connection = 1;
1137
        return gnutls_assert_val(
1138
          GNUTLS_E_FATAL_ALERT_RECEIVED);
1139
      }
1140
1141
      ret = GNUTLS_E_WARNING_ALERT_RECEIVED;
1142
      session_invalidate(session);
1143
      break;
1144
    case GNUTLS_HANDSHAKE:
1145
      ret = gnutls_handshake_write(
1146
        session, GNUTLS_ENCRYPTION_LEVEL_APPLICATION,
1147
        data, ret);
1148
1149
      if (ret < 0)
1150
        return gnutls_assert_val(ret);
1151
1152
      if (type != record_type)
1153
        return GNUTLS_E_AGAIN;
1154
      break;
1155
    case GNUTLS_APPLICATION_DATA:
1156
      if (type != record_type)
1157
        ret = GNUTLS_E_GOT_APPLICATION_DATA;
1158
      break;
1159
    case GNUTLS_HEARTBEAT:
1160
      break;
1161
    default:
1162
      gnutls_assert();
1163
      return GNUTLS_E_UNEXPECTED_PACKET;
1164
    }
1165
  }
1166
  return ret;
1167
}
1168
#else //ENABLE_KTLS
1169
gnutls_transport_ktls_enable_flags_t
1170
gnutls_transport_is_ktls_enabled(gnutls_session_t session)
1171
0
{
1172
0
  return 0;
1173
0
}
1174
1175
void _gnutls_ktls_enable(gnutls_session_t session)
1176
0
{
1177
0
}
1178
1179
int _gnutls_ktls_set_keys(gnutls_session_t sessioni,
1180
        gnutls_transport_ktls_enable_flags_t in)
1181
0
{
1182
0
  return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
1183
0
}
1184
1185
ssize_t _gnutls_ktls_send_file(gnutls_session_t session, int fd, off_t *offset,
1186
             size_t count)
1187
0
{
1188
0
  return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
1189
0
}
1190
1191
int _gnutls_ktls_send_control_msg(gnutls_session_t session,
1192
          unsigned char record_type, const void *data,
1193
          size_t data_size)
1194
0
{
1195
0
  return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
1196
0
}
1197
1198
int _gnutls_ktls_send_handshake_msg(gnutls_session_t session,
1199
            gnutls_record_encryption_level_t level,
1200
            gnutls_handshake_description_t htype,
1201
            const void *data, size_t data_size)
1202
0
{
1203
0
  (void)level;
1204
0
  return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
1205
0
}
1206
1207
int _gnutls_ktls_recv_int(gnutls_session_t session, content_type_t type,
1208
        void *data, size_t data_size)
1209
0
{
1210
0
  return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
1211
0
}
1212
1213
#endif //ENABLE_KTLS