tls.h revision 1f69aa52ea2e0a73ac502565df8c666ee49cab6a
136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/* 236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * SSL/TLS interface definition 336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi> 436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * 536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * This program is free software; you can redistribute it and/or modify 636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * it under the terms of the GNU General Public License version 2 as 736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * published by the Free Software Foundation. 836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * 936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * Alternatively, this software may be distributed under the terms of BSD 1036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * license. 1136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * 1236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * See README and COPYING for more details. 1336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines */ 1436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 1536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#ifndef TLS_H 1636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#define TLS_H 1736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 1836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstruct tls_connection; 1936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 2036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstruct tls_keys { 2136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const u8 *master_key; /* TLS master secret */ 2236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines size_t master_key_len; 2336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const u8 *client_random; 2436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines size_t client_random_len; 2536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const u8 *server_random; 2636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines size_t server_random_len; 2736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}; 2836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 2936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesenum tls_event { 3036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines TLS_CERT_CHAIN_FAILURE, 3136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines TLS_PEER_CERTIFICATE 3236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}; 3336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 3436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/* 3536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * Note: These are used as identifier with external programs and as such, the 3636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * values must not be changed. 3736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines */ 3836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesenum tls_fail_reason { 3936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines TLS_FAIL_UNSPECIFIED = 0, 4036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines TLS_FAIL_UNTRUSTED = 1, 4136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines TLS_FAIL_REVOKED = 2, 4236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines TLS_FAIL_NOT_YET_VALID = 3, 4336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines TLS_FAIL_EXPIRED = 4, 4436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines TLS_FAIL_SUBJECT_MISMATCH = 5, 4536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines TLS_FAIL_ALTSUBJECT_MISMATCH = 6, 4636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines TLS_FAIL_BAD_CERTIFICATE = 7, 4736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines TLS_FAIL_SERVER_CHAIN_PROBE = 8 4836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}; 4936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 50union tls_event_data { 51 struct { 52 int depth; 53 const char *subject; 54 enum tls_fail_reason reason; 55 const char *reason_txt; 56 const struct wpabuf *cert; 57 } cert_fail; 58 59 struct { 60 int depth; 61 const char *subject; 62 const struct wpabuf *cert; 63 const u8 *hash; 64 size_t hash_len; 65 } peer_cert; 66}; 67 68struct tls_config { 69 const char *opensc_engine_path; 70 const char *pkcs11_engine_path; 71 const char *pkcs11_module_path; 72 int fips_mode; 73 int cert_in_cb; 74 75 void (*event_cb)(void *ctx, enum tls_event ev, 76 union tls_event_data *data); 77 void *cb_ctx; 78}; 79 80#define TLS_CONN_ALLOW_SIGN_RSA_MD5 BIT(0) 81#define TLS_CONN_DISABLE_TIME_CHECKS BIT(1) 82 83/** 84 * struct tls_connection_params - Parameters for TLS connection 85 * @ca_cert: File or reference name for CA X.509 certificate in PEM or DER 86 * format 87 * @ca_cert_blob: ca_cert as inlined data or %NULL if not used 88 * @ca_cert_blob_len: ca_cert_blob length 89 * @ca_path: Path to CA certificates (OpenSSL specific) 90 * @subject_match: String to match in the subject of the peer certificate or 91 * %NULL to allow all subjects 92 * @altsubject_match: String to match in the alternative subject of the peer 93 * certificate or %NULL to allow all alternative subjects 94 * @client_cert: File or reference name for client X.509 certificate in PEM or 95 * DER format 96 * @client_cert_blob: client_cert as inlined data or %NULL if not used 97 * @client_cert_blob_len: client_cert_blob length 98 * @private_key: File or reference name for client private key in PEM or DER 99 * format (traditional format (RSA PRIVATE KEY) or PKCS#8 (PRIVATE KEY) 100 * @private_key_blob: private_key as inlined data or %NULL if not used 101 * @private_key_blob_len: private_key_blob length 102 * @private_key_passwd: Passphrase for decrypted private key, %NULL if no 103 * passphrase is used. 104 * @dh_file: File name for DH/DSA data in PEM format, or %NULL if not used 105 * @dh_blob: dh_file as inlined data or %NULL if not used 106 * @dh_blob_len: dh_blob length 107 * @engine: 1 = use engine (e.g., a smartcard) for private key operations 108 * (this is OpenSSL specific for now) 109 * @engine_id: engine id string (this is OpenSSL specific for now) 110 * @ppin: pointer to the pin variable in the configuration 111 * (this is OpenSSL specific for now) 112 * @key_id: the private key's id when using engine (this is OpenSSL 113 * specific for now) 114 * @cert_id: the certificate's id when using engine 115 * @ca_cert_id: the CA certificate's id when using engine 116 * @flags: Parameter options (TLS_CONN_*) 117 * 118 * TLS connection parameters to be configured with tls_connection_set_params() 119 * and tls_global_set_params(). 120 * 121 * Certificates and private key can be configured either as a reference name 122 * (file path or reference to certificate store) or by providing the same data 123 * as a pointer to the data in memory. Only one option will be used for each 124 * field. 125 */ 126struct tls_connection_params { 127 const char *ca_cert; 128 const u8 *ca_cert_blob; 129 size_t ca_cert_blob_len; 130 const char *ca_path; 131 const char *subject_match; 132 const char *altsubject_match; 133 const char *client_cert; 134 const u8 *client_cert_blob; 135 size_t client_cert_blob_len; 136 const char *private_key; 137 const u8 *private_key_blob; 138 size_t private_key_blob_len; 139 const char *private_key_passwd; 140 const char *dh_file; 141 const u8 *dh_blob; 142 size_t dh_blob_len; 143 144 /* OpenSSL specific variables */ 145 int engine; 146 const char *engine_id; 147 const char *pin; 148 const char *key_id; 149 const char *cert_id; 150 const char *ca_cert_id; 151 152 unsigned int flags; 153}; 154 155 156/** 157 * tls_init - Initialize TLS library 158 * @conf: Configuration data for TLS library 159 * Returns: Context data to be used as tls_ctx in calls to other functions, 160 * or %NULL on failure. 161 * 162 * Called once during program startup and once for each RSN pre-authentication 163 * session. In other words, there can be two concurrent TLS contexts. If global 164 * library initialization is needed (i.e., one that is shared between both 165 * authentication types), the TLS library wrapper should maintain a reference 166 * counter and do global initialization only when moving from 0 to 1 reference. 167 */ 168void * tls_init(const struct tls_config *conf); 169 170/** 171 * tls_deinit - Deinitialize TLS library 172 * @tls_ctx: TLS context data from tls_init() 173 * 174 * Called once during program shutdown and once for each RSN pre-authentication 175 * session. If global library deinitialization is needed (i.e., one that is 176 * shared between both authentication types), the TLS library wrapper should 177 * maintain a reference counter and do global deinitialization only when moving 178 * from 1 to 0 references. 179 */ 180void tls_deinit(void *tls_ctx); 181 182/** 183 * tls_get_errors - Process pending errors 184 * @tls_ctx: TLS context data from tls_init() 185 * Returns: Number of found error, 0 if no errors detected. 186 * 187 * Process all pending TLS errors. 188 */ 189int tls_get_errors(void *tls_ctx); 190 191/** 192 * tls_connection_init - Initialize a new TLS connection 193 * @tls_ctx: TLS context data from tls_init() 194 * Returns: Connection context data, conn for other function calls 195 */ 196struct tls_connection * tls_connection_init(void *tls_ctx); 197 198/** 199 * tls_connection_deinit - Free TLS connection data 200 * @tls_ctx: TLS context data from tls_init() 201 * @conn: Connection context data from tls_connection_init() 202 * 203 * Release all resources allocated for TLS connection. 204 */ 205void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn); 206 207/** 208 * tls_connection_established - Has the TLS connection been completed? 209 * @tls_ctx: TLS context data from tls_init() 210 * @conn: Connection context data from tls_connection_init() 211 * Returns: 1 if TLS connection has been completed, 0 if not. 212 */ 213int tls_connection_established(void *tls_ctx, struct tls_connection *conn); 214 215/** 216 * tls_connection_shutdown - Shutdown TLS connection 217 * @tls_ctx: TLS context data from tls_init() 218 * @conn: Connection context data from tls_connection_init() 219 * Returns: 0 on success, -1 on failure 220 * 221 * Shutdown current TLS connection without releasing all resources. New 222 * connection can be started by using the same conn without having to call 223 * tls_connection_init() or setting certificates etc. again. The new 224 * connection should try to use session resumption. 225 */ 226int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn); 227 228enum { 229 TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED = -3, 230 TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED = -2 231}; 232 233/** 234 * tls_connection_set_params - Set TLS connection parameters 235 * @tls_ctx: TLS context data from tls_init() 236 * @conn: Connection context data from tls_connection_init() 237 * @params: Connection parameters 238 * Returns: 0 on success, -1 on failure, 239 * TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED (-2) on possible PIN error causing 240 * PKCS#11 engine failure, or 241 * TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED (-3) on failure to verify the 242 * PKCS#11 engine private key. 243 */ 244int __must_check 245tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, 246 const struct tls_connection_params *params); 247 248/** 249 * tls_global_set_params - Set TLS parameters for all TLS connection 250 * @tls_ctx: TLS context data from tls_init() 251 * @params: Global TLS parameters 252 * Returns: 0 on success, -1 on failure, 253 * TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED (-2) on possible PIN error causing 254 * PKCS#11 engine failure, or 255 * TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED (-3) on failure to verify the 256 * PKCS#11 engine private key. 257 */ 258int __must_check tls_global_set_params( 259 void *tls_ctx, const struct tls_connection_params *params); 260 261/** 262 * tls_global_set_verify - Set global certificate verification options 263 * @tls_ctx: TLS context data from tls_init() 264 * @check_crl: 0 = do not verify CRLs, 1 = verify CRL for the user certificate, 265 * 2 = verify CRL for all certificates 266 * Returns: 0 on success, -1 on failure 267 */ 268int __must_check tls_global_set_verify(void *tls_ctx, int check_crl); 269 270/** 271 * tls_connection_set_verify - Set certificate verification options 272 * @tls_ctx: TLS context data from tls_init() 273 * @conn: Connection context data from tls_connection_init() 274 * @verify_peer: 1 = verify peer certificate 275 * Returns: 0 on success, -1 on failure 276 */ 277int __must_check tls_connection_set_verify(void *tls_ctx, 278 struct tls_connection *conn, 279 int verify_peer); 280 281/** 282 * tls_connection_get_keys - Get master key and random data from TLS connection 283 * @tls_ctx: TLS context data from tls_init() 284 * @conn: Connection context data from tls_connection_init() 285 * @keys: Structure of key/random data (filled on success) 286 * Returns: 0 on success, -1 on failure 287 */ 288int __must_check tls_connection_get_keys(void *tls_ctx, 289 struct tls_connection *conn, 290 struct tls_keys *keys); 291 292/** 293 * tls_connection_prf - Use TLS-PRF to derive keying material 294 * @tls_ctx: TLS context data from tls_init() 295 * @conn: Connection context data from tls_connection_init() 296 * @label: Label (e.g., description of the key) for PRF 297 * @server_random_first: seed is 0 = client_random|server_random, 298 * 1 = server_random|client_random 299 * @out: Buffer for output data from TLS-PRF 300 * @out_len: Length of the output buffer 301 * Returns: 0 on success, -1 on failure 302 * 303 * This function is optional to implement if tls_connection_get_keys() provides 304 * access to master secret and server/client random values. If these values are 305 * not exported from the TLS library, tls_connection_prf() is required so that 306 * further keying material can be derived from the master secret. If not 307 * implemented, the function will still need to be defined, but it can just 308 * return -1. Example implementation of this function is in tls_prf_sha1_md5() 309 * when it is called with seed set to client_random|server_random (or 310 * server_random|client_random). 311 */ 312int __must_check tls_connection_prf(void *tls_ctx, 313 struct tls_connection *conn, 314 const char *label, 315 int server_random_first, 316 u8 *out, size_t out_len); 317 318/** 319 * tls_connection_handshake - Process TLS handshake (client side) 320 * @tls_ctx: TLS context data from tls_init() 321 * @conn: Connection context data from tls_connection_init() 322 * @in_data: Input data from TLS server 323 * @appl_data: Pointer to application data pointer, or %NULL if dropped 324 * Returns: Output data, %NULL on failure 325 * 326 * The caller is responsible for freeing the returned output data. If the final 327 * handshake message includes application data, this is decrypted and 328 * appl_data (if not %NULL) is set to point this data. The caller is 329 * responsible for freeing appl_data. 330 * 331 * This function is used during TLS handshake. The first call is done with 332 * in_data == %NULL and the library is expected to return ClientHello packet. 333 * This packet is then send to the server and a response from server is given 334 * to TLS library by calling this function again with in_data pointing to the 335 * TLS message from the server. 336 * 337 * If the TLS handshake fails, this function may return %NULL. However, if the 338 * TLS library has a TLS alert to send out, that should be returned as the 339 * output data. In this case, tls_connection_get_failed() must return failure 340 * (> 0). 341 * 342 * tls_connection_established() should return 1 once the TLS handshake has been 343 * completed successfully. 344 */ 345struct wpabuf * tls_connection_handshake(void *tls_ctx, 346 struct tls_connection *conn, 347 const struct wpabuf *in_data, 348 struct wpabuf **appl_data); 349 350struct wpabuf * tls_connection_handshake2(void *tls_ctx, 351 struct tls_connection *conn, 352 const struct wpabuf *in_data, 353 struct wpabuf **appl_data, 354 int *more_data_needed); 355 356/** 357 * tls_connection_server_handshake - Process TLS handshake (server side) 358 * @tls_ctx: TLS context data from tls_init() 359 * @conn: Connection context data from tls_connection_init() 360 * @in_data: Input data from TLS peer 361 * @appl_data: Pointer to application data pointer, or %NULL if dropped 362 * Returns: Output data, %NULL on failure 363 * 364 * The caller is responsible for freeing the returned output data. 365 */ 366struct wpabuf * tls_connection_server_handshake(void *tls_ctx, 367 struct tls_connection *conn, 368 const struct wpabuf *in_data, 369 struct wpabuf **appl_data); 370 371/** 372 * tls_connection_encrypt - Encrypt data into TLS tunnel 373 * @tls_ctx: TLS context data from tls_init() 374 * @conn: Connection context data from tls_connection_init() 375 * @in_data: Plaintext data to be encrypted 376 * Returns: Encrypted TLS data or %NULL on failure 377 * 378 * This function is used after TLS handshake has been completed successfully to 379 * send data in the encrypted tunnel. The caller is responsible for freeing the 380 * returned output data. 381 */ 382struct wpabuf * tls_connection_encrypt(void *tls_ctx, 383 struct tls_connection *conn, 384 const struct wpabuf *in_data); 385 386/** 387 * tls_connection_decrypt - Decrypt data from TLS tunnel 388 * @tls_ctx: TLS context data from tls_init() 389 * @conn: Connection context data from tls_connection_init() 390 * @in_data: Encrypted TLS data 391 * Returns: Decrypted TLS data or %NULL on failure 392 * 393 * This function is used after TLS handshake has been completed successfully to 394 * receive data from the encrypted tunnel. The caller is responsible for 395 * freeing the returned output data. 396 */ 397struct wpabuf * tls_connection_decrypt(void *tls_ctx, 398 struct tls_connection *conn, 399 const struct wpabuf *in_data); 400 401struct wpabuf * tls_connection_decrypt2(void *tls_ctx, 402 struct tls_connection *conn, 403 const struct wpabuf *in_data, 404 int *more_data_needed); 405 406/** 407 * tls_connection_resumed - Was session resumption used 408 * @tls_ctx: TLS context data from tls_init() 409 * @conn: Connection context data from tls_connection_init() 410 * Returns: 1 if current session used session resumption, 0 if not 411 */ 412int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn); 413 414enum { 415 TLS_CIPHER_NONE, 416 TLS_CIPHER_RC4_SHA /* 0x0005 */, 417 TLS_CIPHER_AES128_SHA /* 0x002f */, 418 TLS_CIPHER_RSA_DHE_AES128_SHA /* 0x0031 */, 419 TLS_CIPHER_ANON_DH_AES128_SHA /* 0x0034 */ 420}; 421 422/** 423 * tls_connection_set_cipher_list - Configure acceptable cipher suites 424 * @tls_ctx: TLS context data from tls_init() 425 * @conn: Connection context data from tls_connection_init() 426 * @ciphers: Zero (TLS_CIPHER_NONE) terminated list of allowed ciphers 427 * (TLS_CIPHER_*). 428 * Returns: 0 on success, -1 on failure 429 */ 430int __must_check tls_connection_set_cipher_list(void *tls_ctx, 431 struct tls_connection *conn, 432 u8 *ciphers); 433 434/** 435 * tls_get_cipher - Get current cipher name 436 * @tls_ctx: TLS context data from tls_init() 437 * @conn: Connection context data from tls_connection_init() 438 * @buf: Buffer for the cipher name 439 * @buflen: buf size 440 * Returns: 0 on success, -1 on failure 441 * 442 * Get the name of the currently used cipher. 443 */ 444int __must_check tls_get_cipher(void *tls_ctx, struct tls_connection *conn, 445 char *buf, size_t buflen); 446 447/** 448 * tls_connection_enable_workaround - Enable TLS workaround options 449 * @tls_ctx: TLS context data from tls_init() 450 * @conn: Connection context data from tls_connection_init() 451 * Returns: 0 on success, -1 on failure 452 * 453 * This function is used to enable connection-specific workaround options for 454 * buffer SSL/TLS implementations. 455 */ 456int __must_check tls_connection_enable_workaround(void *tls_ctx, 457 struct tls_connection *conn); 458 459/** 460 * tls_connection_client_hello_ext - Set TLS extension for ClientHello 461 * @tls_ctx: TLS context data from tls_init() 462 * @conn: Connection context data from tls_connection_init() 463 * @ext_type: Extension type 464 * @data: Extension payload (%NULL to remove extension) 465 * @data_len: Extension payload length 466 * Returns: 0 on success, -1 on failure 467 */ 468int __must_check tls_connection_client_hello_ext(void *tls_ctx, 469 struct tls_connection *conn, 470 int ext_type, const u8 *data, 471 size_t data_len); 472 473/** 474 * tls_connection_get_failed - Get connection failure status 475 * @tls_ctx: TLS context data from tls_init() 476 * @conn: Connection context data from tls_connection_init() 477 * 478 * Returns >0 if connection has failed, 0 if not. 479 */ 480int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn); 481 482/** 483 * tls_connection_get_read_alerts - Get connection read alert status 484 * @tls_ctx: TLS context data from tls_init() 485 * @conn: Connection context data from tls_connection_init() 486 * Returns: Number of times a fatal read (remote end reported error) has 487 * happened during this connection. 488 */ 489int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn); 490 491/** 492 * tls_connection_get_write_alerts - Get connection write alert status 493 * @tls_ctx: TLS context data from tls_init() 494 * @conn: Connection context data from tls_connection_init() 495 * Returns: Number of times a fatal write (locally detected error) has happened 496 * during this connection. 497 */ 498int tls_connection_get_write_alerts(void *tls_ctx, 499 struct tls_connection *conn); 500 501/** 502 * tls_connection_get_keyblock_size - Get TLS key_block size 503 * @tls_ctx: TLS context data from tls_init() 504 * @conn: Connection context data from tls_connection_init() 505 * Returns: Size of the key_block for the negotiated cipher suite or -1 on 506 * failure 507 */ 508int tls_connection_get_keyblock_size(void *tls_ctx, 509 struct tls_connection *conn); 510 511/** 512 * tls_capabilities - Get supported TLS capabilities 513 * @tls_ctx: TLS context data from tls_init() 514 * Returns: Bit field of supported TLS capabilities (TLS_CAPABILITY_*) 515 */ 516unsigned int tls_capabilities(void *tls_ctx); 517 518typedef int (*tls_session_ticket_cb) 519(void *ctx, const u8 *ticket, size_t len, const u8 *client_random, 520 const u8 *server_random, u8 *master_secret); 521 522int __must_check tls_connection_set_session_ticket_cb( 523 void *tls_ctx, struct tls_connection *conn, 524 tls_session_ticket_cb cb, void *ctx); 525 526#endif /* TLS_H */ 527