Coverage Report

Created: 2025-07-23 07:16

/src/gnutls/lib/system/ktls.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2021 Free Software Foundation, Inc.
3
 *
4
 * Author: Fratniš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
      /* for TLS 1.2 IV is generated in kernel */
683
      if (version == GNUTLS_TLS1_2) {
684
        crypto_info.info.version = TLS_1_2_VERSION;
685
        memcpy(crypto_info.iv, seq_number,
686
               TLS_CIPHER_CHACHA20_POLY1305_IV_SIZE);
687
      } else {
688
        crypto_info.info.version = TLS_1_3_VERSION;
689
        assert(iv.size ==
690
               TLS_CIPHER_CHACHA20_POLY1305_SALT_SIZE +
691
                 TLS_CIPHER_CHACHA20_POLY1305_IV_SIZE);
692
693
        memcpy(crypto_info.iv,
694
               iv.data +
695
                 TLS_CIPHER_CHACHA20_POLY1305_SALT_SIZE,
696
               TLS_CIPHER_CHACHA20_POLY1305_IV_SIZE);
697
      }
698
699
      memcpy(crypto_info.salt, iv.data,
700
             TLS_CIPHER_CHACHA20_POLY1305_SALT_SIZE);
701
      memcpy(crypto_info.rec_seq, seq_number,
702
             TLS_CIPHER_CHACHA20_POLY1305_REC_SEQ_SIZE);
703
      memcpy(crypto_info.key, cipher_key.data,
704
             TLS_CIPHER_CHACHA20_POLY1305_KEY_SIZE);
705
706
      if (setsockopt(sockin, SOL_TLS, TLS_RX, &crypto_info,
707
               sizeof(crypto_info))) {
708
        session->internals.ktls_enabled &=
709
          ~GNUTLS_KTLS_RECV;
710
        return gnutls_assert_val(
711
          GNUTLS_E_INTERNAL_ERROR);
712
      }
713
    } break;
714
    default:
715
      assert(0);
716
    }
717
  }
718
719
  ret = gnutls_record_get_state(session, 0, &mac_key, &iv, &cipher_key,
720
              seq_number);
721
  if (ret < 0) {
722
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
723
  }
724
725
  if (in & GNUTLS_KTLS_SEND) {
726
    switch (cipher) {
727
    case GNUTLS_CIPHER_AES_128_GCM: {
728
      struct tls12_crypto_info_aes_gcm_128 crypto_info;
729
      memset(&crypto_info, 0, sizeof(crypto_info));
730
731
      crypto_info.info.cipher_type = TLS_CIPHER_AES_GCM_128;
732
733
      assert(cipher_key.size ==
734
             TLS_CIPHER_AES_GCM_128_KEY_SIZE);
735
736
      /* for TLS 1.2 IV is generated in kernel */
737
      if (version == GNUTLS_TLS1_2) {
738
        crypto_info.info.version = TLS_1_2_VERSION;
739
        memcpy(crypto_info.iv, seq_number,
740
               TLS_CIPHER_AES_GCM_128_IV_SIZE);
741
      } else {
742
        crypto_info.info.version = TLS_1_3_VERSION;
743
        assert(iv.size ==
744
               TLS_CIPHER_AES_GCM_128_SALT_SIZE +
745
                 TLS_CIPHER_AES_GCM_128_IV_SIZE);
746
747
        memcpy(crypto_info.iv,
748
               iv.data +
749
                 TLS_CIPHER_AES_GCM_128_SALT_SIZE,
750
               TLS_CIPHER_AES_GCM_128_IV_SIZE);
751
      }
752
753
      memcpy(crypto_info.salt, iv.data,
754
             TLS_CIPHER_AES_GCM_128_SALT_SIZE);
755
      memcpy(crypto_info.rec_seq, seq_number,
756
             TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);
757
      memcpy(crypto_info.key, cipher_key.data,
758
             TLS_CIPHER_AES_GCM_128_KEY_SIZE);
759
760
      if (setsockopt(sockout, SOL_TLS, TLS_TX, &crypto_info,
761
               sizeof(crypto_info))) {
762
        session->internals.ktls_enabled &=
763
          ~GNUTLS_KTLS_SEND;
764
        return gnutls_assert_val(
765
          GNUTLS_E_INTERNAL_ERROR);
766
      }
767
    } break;
768
    case GNUTLS_CIPHER_AES_256_GCM: {
769
      struct tls12_crypto_info_aes_gcm_256 crypto_info;
770
      memset(&crypto_info, 0, sizeof(crypto_info));
771
772
      crypto_info.info.cipher_type = TLS_CIPHER_AES_GCM_256;
773
      assert(cipher_key.size ==
774
             TLS_CIPHER_AES_GCM_256_KEY_SIZE);
775
776
      /* for TLS 1.2 IV is generated in kernel */
777
      if (version == GNUTLS_TLS1_2) {
778
        crypto_info.info.version = TLS_1_2_VERSION;
779
        memcpy(crypto_info.iv, seq_number,
780
               TLS_CIPHER_AES_GCM_256_IV_SIZE);
781
      } else {
782
        crypto_info.info.version = TLS_1_3_VERSION;
783
        assert(iv.size ==
784
               TLS_CIPHER_AES_GCM_256_SALT_SIZE +
785
                 TLS_CIPHER_AES_GCM_256_IV_SIZE);
786
787
        memcpy(crypto_info.iv,
788
               iv.data +
789
                 TLS_CIPHER_AES_GCM_256_SALT_SIZE,
790
               TLS_CIPHER_AES_GCM_256_IV_SIZE);
791
      }
792
793
      memcpy(crypto_info.salt, iv.data,
794
             TLS_CIPHER_AES_GCM_256_SALT_SIZE);
795
      memcpy(crypto_info.rec_seq, seq_number,
796
             TLS_CIPHER_AES_GCM_256_REC_SEQ_SIZE);
797
      memcpy(crypto_info.key, cipher_key.data,
798
             TLS_CIPHER_AES_GCM_256_KEY_SIZE);
799
800
      if (setsockopt(sockout, SOL_TLS, TLS_TX, &crypto_info,
801
               sizeof(crypto_info))) {
802
        session->internals.ktls_enabled &=
803
          ~GNUTLS_KTLS_SEND;
804
        return gnutls_assert_val(
805
          GNUTLS_E_INTERNAL_ERROR);
806
      }
807
    } break;
808
    case GNUTLS_CIPHER_AES_128_CCM: {
809
      struct tls12_crypto_info_aes_ccm_128 crypto_info;
810
      memset(&crypto_info, 0, sizeof(crypto_info));
811
812
      crypto_info.info.cipher_type = TLS_CIPHER_AES_CCM_128;
813
      assert(cipher_key.size ==
814
             TLS_CIPHER_AES_CCM_128_KEY_SIZE);
815
816
      /* for TLS 1.2 IV is generated in kernel */
817
      if (version == GNUTLS_TLS1_2) {
818
        crypto_info.info.version = TLS_1_2_VERSION;
819
        memcpy(crypto_info.iv, seq_number,
820
               TLS_CIPHER_AES_CCM_128_IV_SIZE);
821
      } else {
822
        crypto_info.info.version = TLS_1_3_VERSION;
823
        assert(iv.size ==
824
               TLS_CIPHER_AES_CCM_128_SALT_SIZE +
825
                 TLS_CIPHER_AES_CCM_128_IV_SIZE);
826
827
        memcpy(crypto_info.iv,
828
               iv.data +
829
                 TLS_CIPHER_AES_CCM_128_SALT_SIZE,
830
               TLS_CIPHER_AES_CCM_128_IV_SIZE);
831
      }
832
833
      memcpy(crypto_info.salt, iv.data,
834
             TLS_CIPHER_AES_CCM_128_SALT_SIZE);
835
      memcpy(crypto_info.rec_seq, seq_number,
836
             TLS_CIPHER_AES_CCM_128_REC_SEQ_SIZE);
837
      memcpy(crypto_info.key, cipher_key.data,
838
             TLS_CIPHER_AES_CCM_128_KEY_SIZE);
839
840
      if (setsockopt(sockout, SOL_TLS, TLS_TX, &crypto_info,
841
               sizeof(crypto_info))) {
842
        session->internals.ktls_enabled &=
843
          ~GNUTLS_KTLS_SEND;
844
        return gnutls_assert_val(
845
          GNUTLS_E_INTERNAL_ERROR);
846
      }
847
    } break;
848
    case GNUTLS_CIPHER_CHACHA20_POLY1305: {
849
      struct tls12_crypto_info_chacha20_poly1305 crypto_info;
850
      memset(&crypto_info, 0, sizeof(crypto_info));
851
852
      crypto_info.info.cipher_type =
853
        TLS_CIPHER_CHACHA20_POLY1305;
854
      assert(cipher_key.size ==
855
             TLS_CIPHER_CHACHA20_POLY1305_KEY_SIZE);
856
857
      /* for TLS 1.2 IV is generated in kernel */
858
      if (version == GNUTLS_TLS1_2) {
859
        crypto_info.info.version = TLS_1_2_VERSION;
860
        memcpy(crypto_info.iv, seq_number,
861
               TLS_CIPHER_CHACHA20_POLY1305_IV_SIZE);
862
      } else {
863
        crypto_info.info.version = TLS_1_3_VERSION;
864
        assert(iv.size ==
865
               TLS_CIPHER_CHACHA20_POLY1305_SALT_SIZE +
866
                 TLS_CIPHER_CHACHA20_POLY1305_IV_SIZE);
867
868
        memcpy(crypto_info.iv,
869
               iv.data +
870
                 TLS_CIPHER_CHACHA20_POLY1305_SALT_SIZE,
871
               TLS_CIPHER_CHACHA20_POLY1305_IV_SIZE);
872
      }
873
874
      memcpy(crypto_info.salt, iv.data,
875
             TLS_CIPHER_CHACHA20_POLY1305_SALT_SIZE);
876
      memcpy(crypto_info.rec_seq, seq_number,
877
             TLS_CIPHER_CHACHA20_POLY1305_REC_SEQ_SIZE);
878
      memcpy(crypto_info.key, cipher_key.data,
879
             TLS_CIPHER_CHACHA20_POLY1305_KEY_SIZE);
880
881
      if (setsockopt(sockout, SOL_TLS, TLS_TX, &crypto_info,
882
               sizeof(crypto_info))) {
883
        session->internals.ktls_enabled &=
884
          ~GNUTLS_KTLS_SEND;
885
        return gnutls_assert_val(
886
          GNUTLS_E_INTERNAL_ERROR);
887
      }
888
    } break;
889
    default:
890
      assert(0);
891
    }
892
893
    // set callback for sending handshake messages
894
    gnutls_handshake_set_read_function(
895
      session, _gnutls_ktls_send_handshake_msg);
896
897
    // set callback for sending alert messages
898
    gnutls_alert_set_read_function(session,
899
                 _gnutls_ktls_send_alert_msg);
900
  }
901
902
  return in;
903
}
904
#endif
905
906
ssize_t _gnutls_ktls_send_file(gnutls_session_t session, int fd, off_t *offset,
907
             size_t count)
908
{
909
  ssize_t ret;
910
  int sockin, sockout;
911
912
  assert(session != NULL);
913
#if defined(__FreeBSD__)
914
  off_t sbytes = 0;
915
  assert(offset != NULL);
916
#endif
917
918
  gnutls_transport_get_int2(session, &sockin, &sockout);
919
#if defined(__FreeBSD__)
920
  ret = sendfile(fd, sockout, *offset, count, NULL, &sbytes, 0);
921
#else
922
  ret = sendfile(sockout, fd, offset, count);
923
#endif
924
  if (ret == -1) {
925
    switch (errno) {
926
    case EINTR:
927
      return GNUTLS_E_INTERRUPTED;
928
    case EAGAIN:
929
      return GNUTLS_E_AGAIN;
930
    default:
931
      return GNUTLS_E_PUSH_ERROR;
932
    }
933
  }
934
#if defined(__FreeBSD__)
935
  *offset += sbytes; /* follow linux sendfile behavior */
936
  return sbytes;
937
#else
938
  return ret;
939
#endif
940
}
941
942
int _gnutls_ktls_send_control_msg(gnutls_session_t session,
943
          unsigned char record_type, const void *data,
944
          size_t data_size)
945
{
946
  const char *buf = data;
947
  ssize_t ret;
948
  int sockin, sockout;
949
  size_t data_to_send = data_size;
950
951
  assert(session != NULL);
952
953
  gnutls_transport_get_int2(session, &sockin, &sockout);
954
955
  while (data_to_send > 0) {
956
    char cmsg[CMSG_SPACE(sizeof(unsigned char))];
957
    struct msghdr msg = { 0 };
958
    struct iovec msg_iov; /* Vector of data to send/receive into. */
959
    struct cmsghdr *hdr;
960
961
    msg.msg_control = cmsg;
962
    msg.msg_controllen = sizeof cmsg;
963
964
    hdr = CMSG_FIRSTHDR(&msg);
965
#if defined(__FreeBSD__)
966
    hdr->cmsg_level = IPPROTO_TCP;
967
#else
968
    hdr->cmsg_level = SOL_TLS;
969
#endif
970
    hdr->cmsg_type = TLS_SET_RECORD_TYPE;
971
    hdr->cmsg_len = CMSG_LEN(sizeof(unsigned char));
972
973
    // construct record header
974
    *CMSG_DATA(hdr) = record_type;
975
    msg.msg_controllen = hdr->cmsg_len;
976
977
    msg_iov.iov_base = (void *)buf;
978
    msg_iov.iov_len = data_to_send;
979
980
    msg.msg_iov = &msg_iov;
981
    msg.msg_iovlen = 1;
982
983
    ret = sendmsg(sockout, &msg, MSG_DONTWAIT);
984
985
    if (ret == -1) {
986
      switch (errno) {
987
      case EINTR:
988
        if (data_to_send < data_size) {
989
          return data_size - data_to_send;
990
        } else {
991
          return GNUTLS_E_INTERRUPTED;
992
        }
993
      case EAGAIN:
994
        if (data_to_send < data_size) {
995
          return data_size - data_to_send;
996
        } else {
997
          return GNUTLS_E_AGAIN;
998
        }
999
      default:
1000
        return GNUTLS_E_PUSH_ERROR;
1001
      }
1002
    }
1003
1004
    buf += ret;
1005
    data_to_send -= ret;
1006
  }
1007
1008
  return data_size;
1009
}
1010
1011
int _gnutls_ktls_send_handshake_msg(gnutls_session_t session,
1012
            gnutls_record_encryption_level_t level,
1013
            gnutls_handshake_description_t htype,
1014
            const void *data, size_t data_size)
1015
{
1016
  return _gnutls_ktls_send_control_msg(session, GNUTLS_HANDSHAKE, data,
1017
               data_size);
1018
}
1019
1020
int _gnutls_ktls_send_alert_msg(gnutls_session_t session,
1021
        gnutls_record_encryption_level_t level,
1022
        gnutls_alert_level_t alert_level,
1023
        gnutls_alert_description_t alert_desc)
1024
{
1025
  uint8_t data[2];
1026
  data[0] = (uint8_t)alert_level;
1027
  data[1] = (uint8_t)alert_desc;
1028
  return _gnutls_ktls_send_control_msg(session, GNUTLS_ALERT, data, 2);
1029
}
1030
1031
int _gnutls_ktls_recv_control_msg(gnutls_session_t session,
1032
          unsigned char *record_type, void *data,
1033
          size_t data_size)
1034
{
1035
  char *buf = data;
1036
  ssize_t ret;
1037
  int sockin, sockout;
1038
1039
  char cmsg[CMSG_SPACE(sizeof(unsigned char))];
1040
  struct msghdr msg = { 0 };
1041
  struct iovec msg_iov;
1042
  struct cmsghdr *hdr;
1043
1044
  assert(session != NULL);
1045
1046
  gnutls_transport_get_int2(session, &sockin, &sockout);
1047
1048
  if (session->internals.read_eof != 0) {
1049
    return 0;
1050
  } else if (session->internals.invalid_connection != 0 ||
1051
       session->internals.may_not_read != 0)
1052
    return GNUTLS_E_INVALID_SESSION;
1053
1054
  /* receive message */
1055
  msg.msg_control = cmsg;
1056
  msg.msg_controllen = sizeof cmsg;
1057
1058
  msg_iov.iov_base = buf;
1059
  msg_iov.iov_len = data_size;
1060
1061
  msg.msg_iov = &msg_iov;
1062
  msg.msg_iovlen = 1;
1063
1064
  ret = recvmsg(sockin, &msg, MSG_DONTWAIT);
1065
1066
  if (ret == -1) {
1067
    switch (errno) {
1068
    case EAGAIN:
1069
      return GNUTLS_E_AGAIN;
1070
    case EINVAL:
1071
      return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
1072
    case EMSGSIZE:
1073
      return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
1074
    case EBADMSG:
1075
      return GNUTLS_E_DECRYPTION_FAILED;
1076
    default:
1077
      return GNUTLS_E_PULL_ERROR;
1078
    }
1079
  } else if (unlikely(ret == -EKEYEXPIRED)) {
1080
    /* This will be received until a keyupdate is performed on the
1081
       scoket. */
1082
    _gnutls_debug_log("kTLS: socket(recv) has not yet received "
1083
          "updated keys\n");
1084
    gnutls_assert();
1085
    return GNUTLS_E_AGAIN;
1086
  }
1087
1088
  /* connection closed */
1089
  if (ret == 0)
1090
    return 0;
1091
1092
  /* get record type from header */
1093
  hdr = CMSG_FIRSTHDR(&msg);
1094
  if (hdr == NULL) {
1095
    return GNUTLS_E_PULL_ERROR;
1096
  }
1097
#if defined(__FreeBSD__)
1098
  if (hdr->cmsg_level == IPPROTO_TCP && hdr->cmsg_type == TLS_GET_RECORD)
1099
#else
1100
  if (hdr->cmsg_level == SOL_TLS && hdr->cmsg_type == TLS_GET_RECORD_TYPE)
1101
#endif
1102
    *record_type = *(unsigned char *)CMSG_DATA(hdr);
1103
  else
1104
    *record_type = GNUTLS_APPLICATION_DATA;
1105
1106
  return ret;
1107
}
1108
1109
int _gnutls_ktls_recv_int(gnutls_session_t session, content_type_t type,
1110
        void *data, size_t data_size)
1111
{
1112
  unsigned char record_type;
1113
  int ret;
1114
1115
  ret = _gnutls_ktls_recv_control_msg(session, &record_type, data,
1116
              data_size);
1117
1118
  if (ret > 0) {
1119
    switch (record_type) {
1120
    case GNUTLS_CHANGE_CIPHER_SPEC:
1121
      return gnutls_assert_val(
1122
        GNUTLS_E_UNIMPLEMENTED_FEATURE);
1123
      break;
1124
    case GNUTLS_ALERT:
1125
      if (ret < 2) {
1126
        return gnutls_assert_val(
1127
          GNUTLS_E_UNEXPECTED_PACKET);
1128
      }
1129
1130
      uint8_t level = ((uint8_t *)data)[0];
1131
      uint8_t desc = ((uint8_t *)data)[1];
1132
1133
      _gnutls_record_log(
1134
        "REC[%p]: Alert[%d|%d] - %s - was received\n",
1135
        session, level, desc,
1136
        gnutls_alert_get_name((int)desc));
1137
1138
      session->internals.last_alert = desc;
1139
1140
      /* if close notify is received and
1141
       * the alert is not fatal
1142
       */
1143
      if (desc == GNUTLS_A_CLOSE_NOTIFY &&
1144
          level != GNUTLS_AL_FATAL) {
1145
        /* If we have been expecting for an alert do
1146
         */
1147
        session->internals.read_eof = 1;
1148
        return 0;
1149
      }
1150
      /* if the alert is FATAL or WARNING
1151
       * return the appropriate message
1152
       */
1153
      gnutls_assert();
1154
      if (level == GNUTLS_AL_FATAL) {
1155
        session->internals.resumable = false;
1156
        session->internals.invalid_connection = 1;
1157
        return gnutls_assert_val(
1158
          GNUTLS_E_FATAL_ALERT_RECEIVED);
1159
      }
1160
1161
      ret = GNUTLS_E_WARNING_ALERT_RECEIVED;
1162
      session_invalidate(session);
1163
      break;
1164
    case GNUTLS_HANDSHAKE:
1165
      ret = gnutls_handshake_write(
1166
        session, GNUTLS_ENCRYPTION_LEVEL_APPLICATION,
1167
        data, ret);
1168
1169
      if (ret < 0)
1170
        return gnutls_assert_val(ret);
1171
1172
      if (type != record_type)
1173
        return GNUTLS_E_AGAIN;
1174
      break;
1175
    case GNUTLS_APPLICATION_DATA:
1176
      if (type != record_type)
1177
        ret = GNUTLS_E_GOT_APPLICATION_DATA;
1178
      break;
1179
    case GNUTLS_HEARTBEAT:
1180
      break;
1181
    default:
1182
      gnutls_assert();
1183
      return GNUTLS_E_UNEXPECTED_PACKET;
1184
    }
1185
  }
1186
  return ret;
1187
}
1188
#else //ENABLE_KTLS
1189
gnutls_transport_ktls_enable_flags_t
1190
gnutls_transport_is_ktls_enabled(gnutls_session_t session)
1191
0
{
1192
0
  return 0;
1193
0
}
1194
1195
void _gnutls_ktls_enable(gnutls_session_t session)
1196
0
{
1197
0
}
1198
1199
int _gnutls_ktls_set_keys(gnutls_session_t sessioni,
1200
        gnutls_transport_ktls_enable_flags_t in)
1201
0
{
1202
0
  return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
1203
0
}
1204
1205
ssize_t _gnutls_ktls_send_file(gnutls_session_t session, int fd, off_t *offset,
1206
             size_t count)
1207
0
{
1208
0
  return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
1209
0
}
1210
1211
int _gnutls_ktls_send_control_msg(gnutls_session_t session,
1212
          unsigned char record_type, const void *data,
1213
          size_t data_size)
1214
0
{
1215
0
  return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
1216
0
}
1217
1218
int _gnutls_ktls_send_handshake_msg(gnutls_session_t session,
1219
            gnutls_record_encryption_level_t level,
1220
            gnutls_handshake_description_t htype,
1221
            const void *data, size_t data_size)
1222
0
{
1223
0
  (void)level;
1224
0
  return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
1225
0
}
1226
1227
int _gnutls_ktls_recv_int(gnutls_session_t session, content_type_t type,
1228
        void *data, size_t data_size)
1229
0
{
1230
0
  return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
1231
0
}
1232
1233
#endif //ENABLE_KTLS