Coverage Report

Created: 2026-08-14 07:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/freeradius-server/src/lib/tls/verify.c
Line
Count
Source
1
/*
2
 *   This program is free software; you can redistribute it and/or modify
3
 *   it under the terms of the GNU General Public License as published by
4
 *   the Free Software Foundation; either version 2 of the License, or
5
 *   (at your option) any later version.
6
 *
7
 *   This program is distributed in the hope that it will be useful,
8
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 *   GNU General Public License for more details.
11
 *
12
 *   You should have received a copy of the GNU General Public License
13
 *   along with this program; if not, write to the Free Software
14
 *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15
 */
16
17
/**
18
 * $Id: d14b1103fe9eda9a3fea20448c416204bb2ea887 $
19
 *
20
 * @file tls/verify.c
21
 * @brief Expose certificate OIDs as attributes, and call validation virtual
22
 *  server to check cert is valid.
23
 *
24
 * @copyright 2001 hereUare Communications, Inc. (raghud@hereuare.com)
25
 * @copyright 2003 Alan DeKok (aland@freeradius.org)
26
 * @copyright 2006-2016 The FreeRADIUS server project
27
 */
28
#ifdef WITH_TLS
29
0
#define LOG_PREFIX "tls"
30
31
#include <freeradius-devel/server/exec.h>
32
#include <freeradius-devel/server/pair.h>
33
#include <freeradius-devel/tls/log.h>
34
#include <freeradius-devel/unlang/function.h>
35
#include <freeradius-devel/unlang/subrequest.h>
36
#include <freeradius-devel/util/debug.h>
37
#include <freeradius-devel/util/strerror.h>
38
#include <freeradius-devel/util/syserror.h>
39
40
#include "attrs.h"
41
#include "base.h"
42
43
/** Check to see if a verification operation should apply to a certificate
44
 *
45
 * @param[in] depth starting at 0.
46
 *      Certificate 0 is the leaf cert (i.e. the client or server cert);
47
 * @param[in] untrusted The number of untrusted certificates.
48
 * @param[in] mode  to check
49
 * @return
50
 *  - true if a given validation check should apply.
51
 **     - false if a validation check should not apply.
52
 */
53
static inline CC_HINT(always_inline)
54
bool verify_applies(fr_tls_verify_mode_t mode, int depth, int untrusted)
55
0
{
56
0
  if (mode == FR_TLS_VERIFY_MODE_ALL) return true;
57
0
  if (mode == FR_TLS_VERIFY_MODE_DISABLED) return false;
58
59
0
  if ((mode & FR_TLS_VERIFY_MODE_LEAF) && (depth == 0)) return true;
60
0
  if ((mode & FR_TLS_VERIFY_MODE_ISSUER) && (depth == 1)) return true;
61
0
  if ((mode & FR_TLS_VERIFY_MODE_UNTRUSTED) && (depth < untrusted)) return true;
62
63
0
  return false;
64
0
}
65
66
DIAG_OFF(DIAG_UNKNOWN_PRAGMAS)
67
DIAG_OFF(used-but-marked-unused)  /* fix spurious warnings for sk macros */
68
69
/** Print verbose humanly readable messages about why certificate validation failed
70
 *
71
 */
72
static void tls_verify_error_detail(request_t *request, SSL_CTX *ctx, int err)
73
0
{
74
0
  X509_STORE  *store = SSL_CTX_get_ex_data(ctx, FR_TLS_EX_CTX_INDEX_VERIFY_STORE);
75
76
0
  switch (err) {
77
  /*
78
   *  We linked the provided cert to at least one
79
   *  other in a chain, but the chain doesn't terminate
80
   *  in a root CA.
81
   */
82
0
  case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
83
0
    FALL_THROUGH;
84
85
  /*
86
   *  We failed to link the provided cert to any
87
   *  other local certificates in the chain.
88
   */
89
0
  case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
90
0
    RDEBUG2("Static certificates in verification store are");
91
0
    if (RDEBUG_ENABLED2) {
92
0
      RINDENT();
93
0
      fr_tls_x509_objects_log(request, L_DBG, X509_STORE_get0_objects(store));
94
0
      REXDENT();
95
0
    }
96
0
    break;
97
98
0
  default:
99
0
    break;
100
0
  }
101
0
}
102
103
/** Validates a certificate using custom logic
104
 *
105
 * Before trusting a certificate, we make sure that the certificate is
106
 * 'valid'. There are several checks we perform to verify its validity.
107
 *
108
 *   1. Verify the certificate's signature, and verifying that the certificate has
109
 *      been issued by a trusted Certificate Authority (this is done for us by OpenSSL).
110
 *
111
 *   2. Verify that the certificate is valid for the present date (i.e. it is being
112
 *      presented within its validity dates).
113
 *
114
 *   3. Verify that the certificate has not been revoked by its issuing Certificate
115
 *      Authority, by checking with respect to a Certificate Revocation List (CRL).
116
 *
117
 * @note This callback will be called multiple times based on the depth of the root
118
 *  certificate chain.
119
 *
120
 * @note As a byproduct of validation, various OIDs will be extracted from the
121
 *  certificates, and inserted into the session-state list as fr_pair_t.
122
 *
123
 * @param ok    preverify ok.  1 if true, 0 if false.
124
 * @param x509_ctx  containing certs to verify.
125
 * @return
126
 *  - 0 if not valid.
127
 *  - 1 if valid.
128
 */
129
int fr_tls_verify_cert_cb(int ok, X509_STORE_CTX *x509_ctx)
130
0
{
131
0
  X509      *cert;
132
133
0
  SSL_CTX     *ssl_ctx;
134
0
  SSL     *ssl;
135
0
  fr_tls_session_t  *tls_session;
136
0
  int     err, depth;
137
0
  fr_tls_conf_t   *conf;
138
0
  int     my_ok = ok;
139
0
  int     untrusted;
140
141
0
  request_t   *request;
142
0
  fr_pair_t   *container = NULL;
143
0
  fr_pair_t   *depth_pair;
144
145
0
  cert = X509_STORE_CTX_get_current_cert(x509_ctx);
146
0
  err = X509_STORE_CTX_get_error(x509_ctx);
147
0
  depth = X509_STORE_CTX_get_error_depth(x509_ctx);
148
0
  untrusted = X509_STORE_CTX_get_num_untrusted(x509_ctx);
149
150
  /*
151
   *  Retrieve the pointer to the SSL of the connection currently treated
152
   *  and the application specific data stored into the SSL object.
153
   */
154
0
  ssl = X509_STORE_CTX_get_ex_data(x509_ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
155
0
  ssl_ctx = SSL_get_SSL_CTX(ssl);
156
0
  conf = fr_tls_session_conf(ssl);
157
0
  tls_session = talloc_get_type_abort(SSL_get_ex_data(ssl, FR_TLS_EX_INDEX_TLS_SESSION), fr_tls_session_t);
158
0
  request = fr_tls_session_request(tls_session->ssl);
159
160
  /*
161
   *  If this error appears it suggests
162
   *  that OpenSSL is trying to perform post-handshake
163
   *  certificate validation which we don't support.
164
   */
165
0
  if (!tls_session->can_pause) {
166
0
    fr_assert_msg("Unexpected call to %s. "
167
0
            "tls_session_async_handshake_cont must be in call stack", __FUNCTION__);
168
0
    return 0;
169
0
  }
170
171
  /*
172
   *  Bail out as quickly as possible, producing
173
   *  as few errors as possible.
174
   */
175
0
  if (unlang_request_is_cancelled(request)) {
176
0
    X509_STORE_CTX_set_error(x509_ctx, 0);
177
0
    return 1;
178
0
  }
179
180
  /*
181
   *  Find or add the chain depth attribute and record the greatest depth we see + 1,
182
   *  as depth is zero based.
183
   */
184
0
  if (unlikely(fr_pair_find_or_append_by_da(request->session_state_ctx, &depth_pair, &request->session_state_pairs,
185
0
           attr_tls_certificate_chain_depth) < 0)) {
186
0
    RERROR("Failed to add certificate chain depth pair");
187
0
    return 0;
188
0
  }
189
0
  if (depth_pair->vp_uint32 < ((uint32_t)depth) + 1) depth_pair->vp_uint32 = (uint32_t)depth + 1;
190
191
0
  if (RDEBUG_ENABLED3) {
192
0
    char    subject[2048];
193
0
    STACK_OF(X509)  *our_chain;
194
0
    int   i;
195
196
0
    our_chain = X509_STORE_CTX_get0_chain(x509_ctx);
197
0
    RDEBUG3("Certificate chain - %i cert(s) untrusted", untrusted);
198
0
    for (i = sk_X509_num(our_chain); i > 0 ; i--) {
199
0
      X509 *this_cert = sk_X509_value(our_chain, i - 1);
200
201
0
      X509_NAME_oneline(X509_get_subject_name(this_cert), subject, sizeof(subject));
202
0
      subject[sizeof(subject) - 1] = '\0';
203
204
0
      RDEBUG3("%s [%i] %s", this_cert == cert ? ">" : " ", i - 1, subject);
205
0
    }
206
0
  }
207
208
  /*
209
   *  See if the user has disabled verification for
210
   *      this certificate.  If they have, force verification
211
   *  to succeed.
212
   */
213
0
  if (!my_ok) {
214
0
    char const *p = X509_verify_cert_error_string(err);
215
0
    if (!verify_applies(conf->verify.mode, depth, untrusted)) {
216
0
      RDEBUG2("Ignoring verification error - %s (%i)", p, err);
217
0
      tls_verify_error_detail(request, ssl_ctx, err);
218
219
0
      my_ok = 1;
220
0
      X509_STORE_CTX_set_error(x509_ctx, 0);
221
0
    } else {
222
0
      RERROR("Verification error - %s (%i)", p, err);
223
0
      tls_verify_error_detail(request, ssl_ctx, err);
224
0
      goto done;
225
0
    }
226
0
  }
227
228
0
  if (verify_applies(conf->verify.attribute_mode, depth, untrusted) &&
229
0
      (!(container = fr_pair_find_by_da_idx(&request->session_state_pairs, attr_tls_certificate, depth)) ||
230
0
       fr_pair_list_empty(&container->vp_group))) {
231
0
        if (!container) {
232
0
              unsigned int i;
233
234
      /*
235
       *  Build a stack of container attributes.
236
       *
237
       *  OpenSSL passes us the deepest certificate
238
       *      first, so we need to build out sufficient
239
       *      TLS-Certificate container TLVs so the TLS-Certificate
240
       *  indexes match the attribute depth.
241
       */
242
0
      for (i = fr_pair_count_by_da(&request->session_state_pairs, attr_tls_certificate);
243
0
           i <= (unsigned int)depth;
244
0
           i++) {
245
0
        MEM(container = fr_pair_afrom_da(request->session_state_ctx, attr_tls_certificate));
246
0
        fr_pair_append(&request->session_state_pairs, container);
247
0
      }
248
0
        }
249
250
#ifdef STATIC_ANALYZER
251
    /*
252
     *  Container can never be NULL, because if container
253
     *  was previously NULL, i will be <= depth.
254
     */
255
    if (!fr_cond_assert(container)) {
256
      my_ok = 0;
257
      goto done;
258
    }
259
#endif
260
    /*
261
     *  If we fail to populate the cert attributes,
262
     *  trash all instances in the session-state list
263
     *  and cause validation to fail.
264
     */
265
0
    if (fr_tls_session_pairs_from_x509_cert(&container->vp_group, container,
266
0
              request, cert, conf->verify.der_decode) < 0) {
267
0
      fr_pair_delete_by_da(&request->session_state_pairs, attr_tls_certificate);
268
0
      if (conf->verify.der_decode) {
269
0
        fr_pair_delete_by_da(&request->session_state_pairs, attr_der_certificate);
270
0
      }
271
0
      my_ok = 0;
272
0
      goto done;
273
0
    }
274
275
0
    log_request_pair(L_DBG_LVL_2, request, NULL, container, "session-state.");
276
0
  }
277
0
done:
278
  /*
279
   *  If verification hasn't already failed
280
   *  and we're meant to verify this cert
281
   *  then call the virtual server.
282
   *
283
   *  We only call the virtual server for
284
   *      the certificate at depth 0 as all
285
   *      other certificate attributes should
286
   *  have been added by this point.
287
   */
288
0
  if (my_ok && (depth == 0)) {
289
0
    if (conf->verify_certificate && tls_session->verify_client_cert) {
290
0
      RDEBUG2("Requesting certificate validation");
291
292
      /*
293
       *  This sets the validation state of the tls_session
294
       *  so that when we call ASYNC_pause_job(), and execution
295
       *  jumps back to tls_session_async_handshake_cont
296
       *  (just under SSL_read())
297
       *  the code there knows what job it needs to push onto
298
       *  the unlang stack.
299
       */
300
0
      fr_tls_verify_cert_request(tls_session, SSL_session_reused(tls_session->ssl));
301
302
      /*
303
       *  Jumps back to SSL_read() in session.c
304
       *
305
       *  Be aware that if the request is cancelled
306
       *  whatever was meant to be done during the
307
       *  time we yielded may not have been completed.
308
       */
309
0
      ASYNC_pause_job();
310
311
      /*
312
       *  Just try and bail out as quickly as possible.
313
       */
314
0
      if (unlang_request_is_cancelled(request)) {
315
0
        X509_STORE_CTX_set_error(x509_ctx, 0);
316
0
        fr_tls_verify_cert_reset(tls_session);
317
0
        return 1;
318
0
      }
319
320
321
      /*
322
       *  If we couldn't validate the certificate
323
       *  then validation overall fails.
324
       */
325
0
      if (!fr_tls_verify_cert_result(tls_session)) {
326
0
        REDEBUG("Certificate validation failed");
327
0
        my_ok = 0;
328
0
        X509_STORE_CTX_set_error(x509_ctx, X509_V_ERR_APPLICATION_VERIFICATION);
329
0
      }
330
0
    }
331
0
  }
332
333
0
  tls_session->client_cert_ok = (my_ok > 0);
334
0
  RDEBUG2("[verify] = %s", my_ok ? "ok" : "invalid");
335
336
0
  return my_ok;
337
0
}
338
DIAG_ON(used-but-marked-unused)
339
DIAG_ON(DIAG_UNKNOWN_PRAGMAS)
340
341
/** Revalidates the client's certificate chain
342
 *
343
 * Wraps the fr_tls_verify_cert_cb callback, allowing us to use the same
344
 * validation logic whenever we need to.
345
 *
346
 * @note Only use so far is forcing the chain to be re-validated on session
347
 *  resumption.
348
 *
349
 * @return
350
 *  - 1 if the chain could be validated.
351
 *  - 0 if the chain failed validation.
352
 */
353
int fr_tls_verify_cert_chain(request_t *request, SSL *ssl)
354
0
{
355
0
  int   err;
356
0
  int   verify;
357
0
  int   ret = 1;
358
359
0
  SSL_CTX   *ssl_ctx;
360
0
  STACK_OF(X509)  *chain;
361
0
  X509    *cert;
362
0
  X509_STORE  *store;
363
0
  X509_STORE_CTX  *store_ctx;
364
365
  /*
366
   *  If there's no client certificate, we just return OK.
367
   */
368
0
  cert = SSL_get0_peer_certificate(ssl);      /* Does not increase ref count */
369
0
  if (!cert) return 1;
370
371
0
  ssl_ctx = SSL_get_SSL_CTX(ssl);
372
0
  store_ctx = X509_STORE_CTX_new();
373
0
  if (unlikely(store_ctx == NULL)) {
374
0
    REDEBUG("Failed allocating X509_STORE_CTX");
375
0
    return 0;
376
0
  }
377
378
0
  chain = SSL_get_peer_cert_chain(ssl);     /* Does not increase ref count */
379
0
  store = SSL_CTX_get_ex_data(ssl_ctx, FR_TLS_EX_CTX_INDEX_VERIFY_STORE);  /* Gets the verification store */
380
381
  /*
382
   *  This sets up a store_ctx for doing peer certificate verification.
383
   *
384
   *  store_ctx - Is the ctx to initialise
385
   *  store   - Is an X509_STORE of implicitly
386
   *        trusted certificates.  Here we're using
387
   *        the verify store that was created when we
388
   *        allocated the SSL_CTX.
389
   *  cert    - Is the certificate to validate.
390
   *  chain   - Is any other certificates the peer provided
391
   *        us in order to build a chain from a trusted
392
   *            root or intermediary to its leaf (cert).
393
   *
394
   *  Note: SSL_CTX_get_cert_store() returns the ctx->cert_store, which
395
   *      is not the same as the verification cert store.
396
   */
397
0
  if (unlikely(X509_STORE_CTX_init(store_ctx, store, cert, chain) != 1)) {
398
0
    REDEBUG("Failed initialising X509_STORE_CTX");
399
0
    X509_STORE_CTX_free(store_ctx);
400
0
    return 0;
401
0
  }
402
403
0
  X509_STORE_CTX_set_ex_data(store_ctx, SSL_get_ex_data_X509_STORE_CTX_idx(), ssl);
404
0
  X509_STORE_CTX_set_verify_cb(store_ctx, fr_tls_verify_cert_cb);
405
406
0
  verify = X509_verify_cert(store_ctx);
407
0
  if (verify != 1) {
408
0
    err = X509_STORE_CTX_get_error(store_ctx);
409
410
0
    if (err != X509_V_OK) {
411
0
      REDEBUG("Failed re-validating resumed session: %s", X509_verify_cert_error_string(err));
412
0
      ret = 0;
413
0
    }
414
0
  }
415
416
0
  X509_STORE_CTX_free(store_ctx);
417
418
0
  return ret;
419
0
}
420
421
/** Process the result of `verify certificate { ... }`
422
 *
423
 */
424
static unlang_action_t tls_verify_client_cert_result(request_t *request, void *uctx)
425
0
{
426
0
  fr_tls_session_t  *tls_session = talloc_get_type_abort(uctx, fr_tls_session_t);
427
0
  fr_pair_t   *vp, *next;
428
429
0
  fr_assert(tls_session->validate.state == FR_TLS_VALIDATION_REQUESTED);
430
431
0
  vp = fr_pair_find_by_da(&request->reply_pairs, NULL, attr_tls_packet_type);
432
0
  if (!vp || (vp->vp_uint32 != enum_tls_packet_type_success->vb_uint32)) {
433
0
    REDEBUG("Failed (re-)validating certificates");
434
435
    /*
436
     *  Hoist any instances of Module-Failure-Message from the subrequest
437
     *  so they can be used for logging failures.
438
     */
439
0
    vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_module_failure_message);
440
0
    while (vp && request->parent) {
441
0
      next = fr_pair_find_by_da(&request->request_pairs, vp, attr_module_failure_message);
442
0
      fr_pair_remove(&request->request_pairs, vp);
443
0
      fr_pair_steal_append(request->parent->request_ctx, &request->parent->request_pairs, vp);
444
0
      vp = next;
445
0
    }
446
447
0
    tls_session->validate.state = FR_TLS_VALIDATION_FAILED;
448
0
    return UNLANG_ACTION_CALCULATE_RESULT;
449
0
  }
450
451
0
  tls_session->validate.state = FR_TLS_VALIDATION_SUCCESS;
452
453
0
  RDEBUG2("Certificates (re-)validated");
454
455
0
  return UNLANG_ACTION_CALCULATE_RESULT;
456
0
}
457
458
/** Push a `verify certificate { ... }` call into the current request, using a subrequest
459
 *
460
 * @param[in] request   The current request.
461
 * @param[in] tls_session The current TLS session.
462
 * @return
463
 *      - UNLANG_ACTION_CALCULATE_RESULT on noop.
464
 *  - UNLANG_ACTION_PUSHED_CHILD on success.
465
 *      - UNLANG_ACTION_FAIL on failure.
466
 */
467
static unlang_action_t tls_verify_client_cert_push(request_t *request, fr_tls_session_t *tls_session)
468
0
{
469
0
  fr_tls_conf_t   *conf = fr_tls_session_conf(tls_session->ssl);
470
0
  request_t   *child;
471
0
  fr_pair_t   *vp;
472
0
  unlang_action_t   ua;
473
474
0
  MEM(child = unlang_subrequest_alloc(request, dict_tls));
475
0
  request = child;
476
477
  /*
478
   *  Add extra pairs to the subrequest
479
   */
480
0
  fr_tls_session_extra_pairs_copy_to_child(child, tls_session);
481
482
  /*
483
   *  Setup the child request for loading
484
   *  session resumption data.
485
   */
486
0
  MEM(pair_prepend_request(&vp, attr_tls_packet_type) >= 0);
487
0
  vp->vp_uint32 = enum_tls_packet_type_verify_certificate->vb_uint32;
488
489
  /*
490
   *  Copy certificate pairs to the child session state
491
   */
492
0
  vp = NULL;
493
0
  while ((vp = fr_pair_find_by_da(&request->parent->session_state_pairs, vp, attr_tls_certificate))) {
494
0
    fr_pair_append(&request->session_state_pairs, fr_pair_copy(request->session_state_ctx, vp));
495
0
  }
496
0
  if (conf->verify.der_decode) {
497
0
    while ((vp = fr_pair_find_by_da(&request->parent->session_state_pairs, vp, attr_der_certificate))) {
498
0
      fr_pair_append(&request->session_state_pairs, fr_pair_copy(request->session_state_ctx, vp));
499
0
    }
500
0
  }
501
502
0
  MEM(pair_append_request(&vp, attr_tls_session_resumed) >= 0);
503
0
  vp->vp_bool = tls_session->validate.resumed;
504
505
  /*
506
   *  Allocate a child, and set it up to call
507
   *      the TLS virtual server.
508
   */
509
0
  ua = fr_tls_call_push(child, tls_verify_client_cert_result, conf, tls_session, false);
510
0
  if (ua < 0) {
511
0
          PERROR("Failed calling TLS virtual server");
512
0
    talloc_free(child);
513
0
    return UNLANG_ACTION_FAIL;
514
0
  }
515
516
0
  return ua;
517
0
}
518
519
/** Clear any previous validation result
520
 *
521
 * Should be called by the validation requestor to get the result and reset
522
 * the validation state.
523
 *
524
 * @return
525
 *  - true if the certificate chain was validated.
526
 *  - false if the certificate chain failed validation.
527
 */
528
bool fr_tls_verify_cert_result(fr_tls_session_t *tls_session)
529
0
{
530
0
  bool result;
531
532
0
  fr_assert(tls_session->validate.state != FR_TLS_VALIDATION_INIT);
533
534
0
  result = tls_session->validate.state == FR_TLS_VALIDATION_SUCCESS;
535
536
0
  tls_session->validate.state = FR_TLS_VALIDATION_INIT;
537
0
  tls_session->validate.resumed = false;
538
539
0
  return result;
540
0
}
541
542
/** Reset the verification state
543
 *
544
 */
545
void fr_tls_verify_cert_reset(fr_tls_session_t *tls_session)
546
0
{
547
0
  tls_session->validate.state = FR_TLS_VALIDATION_INIT;
548
0
  tls_session->validate.resumed  = false;
549
0
}
550
551
/** Setup a verification request
552
 *
553
 */
554
void fr_tls_verify_cert_request(fr_tls_session_t *tls_session, bool session_resumed)
555
0
{
556
0
  fr_assert(tls_session->validate.state == FR_TLS_VALIDATION_INIT);
557
558
0
  tls_session->validate.state = FR_TLS_VALIDATION_REQUESTED;
559
0
  tls_session->validate.resumed = session_resumed;
560
0
}
561
562
/** Push a `verify certificate { ... }` section
563
 *
564
 * @param[in] request   The current request.
565
 * @param[in] tls_session The current TLS session.
566
 * @return
567
 *  - UNLANG_ACTION_CALCULATE_RESULT  - No pending actions
568
 *  - UNLANG_ACTION_PUSHED_CHILD    - Pending operations to evaluate.
569
 */
570
unlang_action_t fr_tls_verify_cert_pending_push(request_t *request, fr_tls_session_t *tls_session)
571
0
{
572
0
  if (tls_session->validate.state == FR_TLS_VALIDATION_REQUESTED) {
573
0
    return tls_verify_client_cert_push(request, tls_session);
574
0
  }
575
576
0
  return UNLANG_ACTION_CALCULATE_RESULT;
577
0
}
578
#endif /* WITH_TLS */