crypto_libtomcrypt.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  1. /*
  2. * WPA Supplicant / Crypto wrapper for LibTomCrypt (for internal TLSv1)
  3. * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * Alternatively, this software may be distributed under the terms of BSD
  10. * license.
  11. *
  12. * See README and COPYING for more details.
  13. */
  14. #include "includes.h"
  15. #include <tomcrypt.h>
  16. #include "common.h"
  17. #include "crypto.h"
  18. #ifndef mp_init_multi
  19. #define mp_init_multi ltc_init_multi
  20. #define mp_clear_multi ltc_deinit_multi
  21. #define mp_unsigned_bin_size(a) ltc_mp.unsigned_size(a)
  22. #define mp_to_unsigned_bin(a, b) ltc_mp.unsigned_write(a, b)
  23. #define mp_read_unsigned_bin(a, b, c) ltc_mp.unsigned_read(a, b, c)
  24. #define mp_exptmod(a,b,c,d) ltc_mp.exptmod(a,b,c,d)
  25. #endif
  26. int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
  27. {
  28. hash_state md;
  29. size_t i;
  30. md4_init(&md);
  31. for (i = 0; i < num_elem; i++)
  32. md4_process(&md, addr[i], len[i]);
  33. md4_done(&md, mac);
  34. return 0;
  35. }
  36. void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
  37. {
  38. u8 pkey[8], next, tmp;
  39. int i;
  40. symmetric_key skey;
  41. /* Add parity bits to the key */
  42. next = 0;
  43. for (i = 0; i < 7; i++) {
  44. tmp = key[i];
  45. pkey[i] = (tmp >> i) | next | 1;
  46. next = tmp << (7 - i);
  47. }
  48. pkey[i] = next | 1;
  49. des_setup(pkey, 8, 0, &skey);
  50. des_ecb_encrypt(clear, cypher, &skey);
  51. des_done(&skey);
  52. }
  53. #ifdef EAP_TLS_FUNCS
  54. int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
  55. {
  56. hash_state md;
  57. size_t i;
  58. md5_init(&md);
  59. for (i = 0; i < num_elem; i++)
  60. md5_process(&md, addr[i], len[i]);
  61. md5_done(&md, mac);
  62. return 0;
  63. }
  64. int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
  65. {
  66. hash_state md;
  67. size_t i;
  68. sha1_init(&md);
  69. for (i = 0; i < num_elem; i++)
  70. sha1_process(&md, addr[i], len[i]);
  71. sha1_done(&md, mac);
  72. return 0;
  73. }
  74. void * aes_encrypt_init(const u8 *key, size_t len)
  75. {
  76. symmetric_key *skey;
  77. skey = os_malloc(sizeof(*skey));
  78. if (skey == NULL)
  79. return NULL;
  80. if (aes_setup(key, len, 0, skey) != CRYPT_OK) {
  81. os_free(skey);
  82. return NULL;
  83. }
  84. return skey;
  85. }
  86. void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
  87. {
  88. symmetric_key *skey = ctx;
  89. aes_ecb_encrypt(plain, crypt, skey);
  90. }
  91. void aes_encrypt_deinit(void *ctx)
  92. {
  93. symmetric_key *skey = ctx;
  94. aes_done(skey);
  95. os_free(skey);
  96. }
  97. void * aes_decrypt_init(const u8 *key, size_t len)
  98. {
  99. symmetric_key *skey;
  100. skey = os_malloc(sizeof(*skey));
  101. if (skey == NULL)
  102. return NULL;
  103. if (aes_setup(key, len, 0, skey) != CRYPT_OK) {
  104. os_free(skey);
  105. return NULL;
  106. }
  107. return skey;
  108. }
  109. void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
  110. {
  111. symmetric_key *skey = ctx;
  112. aes_ecb_encrypt(plain, (u8 *) crypt, skey);
  113. }
  114. void aes_decrypt_deinit(void *ctx)
  115. {
  116. symmetric_key *skey = ctx;
  117. aes_done(skey);
  118. os_free(skey);
  119. }
  120. #ifdef CONFIG_TLS_INTERNAL
  121. struct crypto_hash {
  122. enum crypto_hash_alg alg;
  123. int error;
  124. union {
  125. hash_state md;
  126. hmac_state hmac;
  127. } u;
  128. };
  129. struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
  130. size_t key_len)
  131. {
  132. struct crypto_hash *ctx;
  133. ctx = os_zalloc(sizeof(*ctx));
  134. if (ctx == NULL)
  135. return NULL;
  136. ctx->alg = alg;
  137. switch (alg) {
  138. case CRYPTO_HASH_ALG_MD5:
  139. if (md5_init(&ctx->u.md) != CRYPT_OK)
  140. goto fail;
  141. break;
  142. case CRYPTO_HASH_ALG_SHA1:
  143. if (sha1_init(&ctx->u.md) != CRYPT_OK)
  144. goto fail;
  145. break;
  146. case CRYPTO_HASH_ALG_HMAC_MD5:
  147. if (hmac_init(&ctx->u.hmac, find_hash("md5"), key, key_len) !=
  148. CRYPT_OK)
  149. goto fail;
  150. break;
  151. case CRYPTO_HASH_ALG_HMAC_SHA1:
  152. if (hmac_init(&ctx->u.hmac, find_hash("sha1"), key, key_len) !=
  153. CRYPT_OK)
  154. goto fail;
  155. break;
  156. default:
  157. goto fail;
  158. }
  159. return ctx;
  160. fail:
  161. os_free(ctx);
  162. return NULL;
  163. }
  164. void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
  165. {
  166. if (ctx == NULL || ctx->error)
  167. return;
  168. switch (ctx->alg) {
  169. case CRYPTO_HASH_ALG_MD5:
  170. ctx->error = md5_process(&ctx->u.md, data, len) != CRYPT_OK;
  171. break;
  172. case CRYPTO_HASH_ALG_SHA1:
  173. ctx->error = sha1_process(&ctx->u.md, data, len) != CRYPT_OK;
  174. break;
  175. case CRYPTO_HASH_ALG_HMAC_MD5:
  176. case CRYPTO_HASH_ALG_HMAC_SHA1:
  177. ctx->error = hmac_process(&ctx->u.hmac, data, len) != CRYPT_OK;
  178. break;
  179. }
  180. }
  181. int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
  182. {
  183. int ret = 0;
  184. unsigned long clen;
  185. if (ctx == NULL)
  186. return -2;
  187. if (mac == NULL || len == NULL) {
  188. os_free(ctx);
  189. return 0;
  190. }
  191. if (ctx->error) {
  192. os_free(ctx);
  193. return -2;
  194. }
  195. switch (ctx->alg) {
  196. case CRYPTO_HASH_ALG_MD5:
  197. if (*len < 16) {
  198. *len = 16;
  199. os_free(ctx);
  200. return -1;
  201. }
  202. *len = 16;
  203. if (md5_done(&ctx->u.md, mac) != CRYPT_OK)
  204. ret = -2;
  205. break;
  206. case CRYPTO_HASH_ALG_SHA1:
  207. if (*len < 20) {
  208. *len = 20;
  209. os_free(ctx);
  210. return -1;
  211. }
  212. *len = 20;
  213. if (sha1_done(&ctx->u.md, mac) != CRYPT_OK)
  214. ret = -2;
  215. break;
  216. case CRYPTO_HASH_ALG_HMAC_SHA1:
  217. if (*len < 20) {
  218. *len = 20;
  219. os_free(ctx);
  220. return -1;
  221. }
  222. /* continue */
  223. case CRYPTO_HASH_ALG_HMAC_MD5:
  224. if (*len < 16) {
  225. *len = 16;
  226. os_free(ctx);
  227. return -1;
  228. }
  229. clen = *len;
  230. if (hmac_done(&ctx->u.hmac, mac, &clen) != CRYPT_OK) {
  231. os_free(ctx);
  232. return -1;
  233. }
  234. *len = clen;
  235. break;
  236. default:
  237. ret = -2;
  238. break;
  239. }
  240. os_free(ctx);
  241. return ret;
  242. }
  243. struct crypto_cipher {
  244. int rc4;
  245. union {
  246. symmetric_CBC cbc;
  247. struct {
  248. size_t used_bytes;
  249. u8 key[16];
  250. size_t keylen;
  251. } rc4;
  252. } u;
  253. };
  254. struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
  255. const u8 *iv, const u8 *key,
  256. size_t key_len)
  257. {
  258. struct crypto_cipher *ctx;
  259. int idx, res, rc4 = 0;
  260. switch (alg) {
  261. case CRYPTO_CIPHER_ALG_AES:
  262. idx = find_cipher("aes");
  263. break;
  264. case CRYPTO_CIPHER_ALG_3DES:
  265. idx = find_cipher("3des");
  266. break;
  267. case CRYPTO_CIPHER_ALG_DES:
  268. idx = find_cipher("des");
  269. break;
  270. case CRYPTO_CIPHER_ALG_RC2:
  271. idx = find_cipher("rc2");
  272. break;
  273. case CRYPTO_CIPHER_ALG_RC4:
  274. idx = -1;
  275. rc4 = 1;
  276. break;
  277. default:
  278. return NULL;
  279. }
  280. ctx = os_zalloc(sizeof(*ctx));
  281. if (ctx == NULL)
  282. return NULL;
  283. if (rc4) {
  284. ctx->rc4 = 1;
  285. if (key_len > sizeof(ctx->u.rc4.key)) {
  286. os_free(ctx);
  287. return NULL;
  288. }
  289. ctx->u.rc4.keylen = key_len;
  290. os_memcpy(ctx->u.rc4.key, key, key_len);
  291. } else {
  292. res = cbc_start(idx, iv, key, key_len, 0, &ctx->u.cbc);
  293. if (res != CRYPT_OK) {
  294. wpa_printf(MSG_DEBUG, "LibTomCrypt: Cipher start "
  295. "failed: %s", error_to_string(res));
  296. os_free(ctx);
  297. return NULL;
  298. }
  299. }
  300. return ctx;
  301. }
  302. int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
  303. u8 *crypt, size_t len)
  304. {
  305. int res;
  306. if (ctx->rc4) {
  307. if (plain != crypt)
  308. os_memcpy(crypt, plain, len);
  309. rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
  310. ctx->u.rc4.used_bytes, crypt, len);
  311. ctx->u.rc4.used_bytes += len;
  312. return 0;
  313. }
  314. res = cbc_encrypt(plain, crypt, len, &ctx->u.cbc);
  315. if (res != CRYPT_OK) {
  316. wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC encryption "
  317. "failed: %s", error_to_string(res));
  318. return -1;
  319. }
  320. return 0;
  321. }
  322. int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
  323. u8 *plain, size_t len)
  324. {
  325. int res;
  326. if (ctx->rc4) {
  327. if (plain != crypt)
  328. os_memcpy(plain, crypt, len);
  329. rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
  330. ctx->u.rc4.used_bytes, plain, len);
  331. ctx->u.rc4.used_bytes += len;
  332. return 0;
  333. }
  334. res = cbc_decrypt(crypt, plain, len, &ctx->u.cbc);
  335. if (res != CRYPT_OK) {
  336. wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC decryption "
  337. "failed: %s", error_to_string(res));
  338. return -1;
  339. }
  340. return 0;
  341. }
  342. void crypto_cipher_deinit(struct crypto_cipher *ctx)
  343. {
  344. if (!ctx->rc4)
  345. cbc_done(&ctx->u.cbc);
  346. os_free(ctx);
  347. }
  348. struct crypto_public_key {
  349. rsa_key rsa;
  350. };
  351. struct crypto_private_key {
  352. rsa_key rsa;
  353. };
  354. struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len)
  355. {
  356. int res;
  357. struct crypto_public_key *pk;
  358. pk = os_zalloc(sizeof(*pk));
  359. if (pk == NULL)
  360. return NULL;
  361. res = rsa_import(key, len, &pk->rsa);
  362. if (res != CRYPT_OK) {
  363. wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import "
  364. "public key (res=%d '%s')",
  365. res, error_to_string(res));
  366. os_free(pk);
  367. return NULL;
  368. }
  369. if (pk->rsa.type != PK_PUBLIC) {
  370. wpa_printf(MSG_ERROR, "LibTomCrypt: Public key was not of "
  371. "correct type");
  372. rsa_free(&pk->rsa);
  373. os_free(pk);
  374. return NULL;
  375. }
  376. return pk;
  377. }
  378. struct crypto_private_key * crypto_private_key_import(const u8 *key,
  379. size_t len)
  380. {
  381. int res;
  382. struct crypto_private_key *pk;
  383. pk = os_zalloc(sizeof(*pk));
  384. if (pk == NULL)
  385. return NULL;
  386. res = rsa_import(key, len, &pk->rsa);
  387. if (res != CRYPT_OK) {
  388. wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import "
  389. "private key (res=%d '%s')",
  390. res, error_to_string(res));
  391. os_free(pk);
  392. return NULL;
  393. }
  394. if (pk->rsa.type != PK_PRIVATE) {
  395. wpa_printf(MSG_ERROR, "LibTomCrypt: Private key was not of "
  396. "correct type");
  397. rsa_free(&pk->rsa);
  398. os_free(pk);
  399. return NULL;
  400. }
  401. return pk;
  402. }
  403. struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf,
  404. size_t len)
  405. {
  406. /* No X.509 support in LibTomCrypt */
  407. return NULL;
  408. }
  409. static int pkcs1_generate_encryption_block(u8 block_type, size_t modlen,
  410. const u8 *in, size_t inlen,
  411. u8 *out, size_t *outlen)
  412. {
  413. size_t ps_len;
  414. u8 *pos;
  415. /*
  416. * PKCS #1 v1.5, 8.1:
  417. *
  418. * EB = 00 || BT || PS || 00 || D
  419. * BT = 00 or 01 for private-key operation; 02 for public-key operation
  420. * PS = k-3-||D||; at least eight octets
  421. * (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero)
  422. * k = length of modulus in octets (modlen)
  423. */
  424. if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) {
  425. wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer "
  426. "lengths (modlen=%lu outlen=%lu inlen=%lu)",
  427. __func__, (unsigned long) modlen,
  428. (unsigned long) *outlen,
  429. (unsigned long) inlen);
  430. return -1;
  431. }
  432. pos = out;
  433. *pos++ = 0x00;
  434. *pos++ = block_type; /* BT */
  435. ps_len = modlen - inlen - 3;
  436. switch (block_type) {
  437. case 0:
  438. os_memset(pos, 0x00, ps_len);
  439. pos += ps_len;
  440. break;
  441. case 1:
  442. os_memset(pos, 0xff, ps_len);
  443. pos += ps_len;
  444. break;
  445. case 2:
  446. if (os_get_random(pos, ps_len) < 0) {
  447. wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get "
  448. "random data for PS", __func__);
  449. return -1;
  450. }
  451. while (ps_len--) {
  452. if (*pos == 0x00)
  453. *pos = 0x01;
  454. pos++;
  455. }
  456. break;
  457. default:
  458. wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type "
  459. "%d", __func__, block_type);
  460. return -1;
  461. }
  462. *pos++ = 0x00;
  463. os_memcpy(pos, in, inlen); /* D */
  464. return 0;
  465. }
  466. static int crypto_rsa_encrypt_pkcs1(int block_type, rsa_key *key, int key_type,
  467. const u8 *in, size_t inlen,
  468. u8 *out, size_t *outlen)
  469. {
  470. unsigned long len, modlen;
  471. int res;
  472. modlen = mp_unsigned_bin_size(key->N);
  473. if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen,
  474. out, outlen) < 0)
  475. return -1;
  476. len = *outlen;
  477. res = rsa_exptmod(out, modlen, out, &len, key_type, key);
  478. if (res != CRYPT_OK) {
  479. wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s",
  480. error_to_string(res));
  481. return -1;
  482. }
  483. *outlen = len;
  484. return 0;
  485. }
  486. int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key,
  487. const u8 *in, size_t inlen,
  488. u8 *out, size_t *outlen)
  489. {
  490. return crypto_rsa_encrypt_pkcs1(2, &key->rsa, PK_PUBLIC, in, inlen,
  491. out, outlen);
  492. }
  493. int crypto_private_key_sign_pkcs1(struct crypto_private_key *key,
  494. const u8 *in, size_t inlen,
  495. u8 *out, size_t *outlen)
  496. {
  497. return crypto_rsa_encrypt_pkcs1(1, &key->rsa, PK_PRIVATE, in, inlen,
  498. out, outlen);
  499. }
  500. void crypto_public_key_free(struct crypto_public_key *key)
  501. {
  502. if (key) {
  503. rsa_free(&key->rsa);
  504. os_free(key);
  505. }
  506. }
  507. void crypto_private_key_free(struct crypto_private_key *key)
  508. {
  509. if (key) {
  510. rsa_free(&key->rsa);
  511. os_free(key);
  512. }
  513. }
  514. int crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key,
  515. const u8 *crypt, size_t crypt_len,
  516. u8 *plain, size_t *plain_len)
  517. {
  518. int res;
  519. unsigned long len;
  520. u8 *pos;
  521. len = *plain_len;
  522. res = rsa_exptmod(crypt, crypt_len, plain, &len, PK_PUBLIC,
  523. &key->rsa);
  524. if (res != CRYPT_OK) {
  525. wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s",
  526. error_to_string(res));
  527. return -1;
  528. }
  529. /*
  530. * PKCS #1 v1.5, 8.1:
  531. *
  532. * EB = 00 || BT || PS || 00 || D
  533. * BT = 01
  534. * PS = k-3-||D|| times FF
  535. * k = length of modulus in octets
  536. */
  537. if (len < 3 + 8 + 16 /* min hash len */ ||
  538. plain[0] != 0x00 || plain[1] != 0x01 || plain[2] != 0xff) {
  539. wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
  540. "structure");
  541. return -1;
  542. }
  543. pos = plain + 3;
  544. while (pos < plain + len && *pos == 0xff)
  545. pos++;
  546. if (pos - plain - 2 < 8) {
  547. /* PKCS #1 v1.5, 8.1: At least eight octets long PS */
  548. wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature "
  549. "padding");
  550. return -1;
  551. }
  552. if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) {
  553. wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
  554. "structure (2)");
  555. return -1;
  556. }
  557. pos++;
  558. len -= pos - plain;
  559. /* Strip PKCS #1 header */
  560. os_memmove(plain, pos, len);
  561. *plain_len = len;
  562. return 0;
  563. }
  564. int crypto_global_init(void)
  565. {
  566. ltc_mp = tfm_desc;
  567. /* TODO: only register algorithms that are really needed */
  568. if (register_hash(&md4_desc) < 0 ||
  569. register_hash(&md5_desc) < 0 ||
  570. register_hash(&sha1_desc) < 0 ||
  571. register_cipher(&aes_desc) < 0 ||
  572. register_cipher(&des_desc) < 0 ||
  573. register_cipher(&des3_desc) < 0) {
  574. wpa_printf(MSG_ERROR, "TLSv1: Failed to register "
  575. "hash/cipher functions");
  576. return -1;
  577. }
  578. return 0;
  579. }
  580. void crypto_global_deinit(void)
  581. {
  582. }
  583. #if defined(EAP_FAST) || defined(EAP_SERVER_FAST)
  584. int crypto_mod_exp(const u8 *base, size_t base_len,
  585. const u8 *power, size_t power_len,
  586. const u8 *modulus, size_t modulus_len,
  587. u8 *result, size_t *result_len)
  588. {
  589. void *b, *p, *m, *r;
  590. if (mp_init_multi(&b, &p, &m, &r, NULL) != CRYPT_OK)
  591. return -1;
  592. if (mp_read_unsigned_bin(b, (u8 *) base, base_len) != CRYPT_OK ||
  593. mp_read_unsigned_bin(p, (u8 *) power, power_len) != CRYPT_OK ||
  594. mp_read_unsigned_bin(m, (u8 *) modulus, modulus_len) != CRYPT_OK)
  595. goto fail;
  596. if (mp_exptmod(b, p, m, r) != CRYPT_OK)
  597. goto fail;
  598. *result_len = mp_unsigned_bin_size(r);
  599. if (mp_to_unsigned_bin(r, result) != CRYPT_OK)
  600. goto fail;
  601. mp_clear_multi(b, p, m, r, NULL);
  602. return 0;
  603. fail:
  604. mp_clear_multi(b, p, m, r, NULL);
  605. return -1;
  606. }
  607. #endif /* EAP_FAST || EAP_SERVER_FAST */
  608. #endif /* CONFIG_TLS_INTERNAL */
  609. #endif /* EAP_TLS_FUNCS */