tls_gnutls.c 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223
  1. /*
  2. * SSL/TLS interface functions for GnuTLS
  3. * Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi>
  4. *
  5. * This software may be distributed under the terms of the BSD license.
  6. * See README for more details.
  7. */
  8. #include "includes.h"
  9. #include <gnutls/gnutls.h>
  10. #include <gnutls/x509.h>
  11. #ifdef PKCS12_FUNCS
  12. #include <gnutls/pkcs12.h>
  13. #endif /* PKCS12_FUNCS */
  14. #include "common.h"
  15. #include "tls.h"
  16. static int tls_gnutls_ref_count = 0;
  17. struct tls_global {
  18. /* Data for session resumption */
  19. void *session_data;
  20. size_t session_data_size;
  21. int server;
  22. int params_set;
  23. gnutls_certificate_credentials_t xcred;
  24. void (*event_cb)(void *ctx, enum tls_event ev,
  25. union tls_event_data *data);
  26. void *cb_ctx;
  27. int cert_in_cb;
  28. };
  29. struct tls_connection {
  30. struct tls_global *global;
  31. gnutls_session_t session;
  32. int read_alerts, write_alerts, failed;
  33. u8 *pre_shared_secret;
  34. size_t pre_shared_secret_len;
  35. int established;
  36. int verify_peer;
  37. unsigned int disable_time_checks:1;
  38. struct wpabuf *push_buf;
  39. struct wpabuf *pull_buf;
  40. const u8 *pull_buf_offset;
  41. int params_set;
  42. gnutls_certificate_credentials_t xcred;
  43. char *suffix_match;
  44. };
  45. static int tls_connection_verify_peer(gnutls_session_t session);
  46. static void tls_log_func(int level, const char *msg)
  47. {
  48. char *s, *pos;
  49. if (level == 6 || level == 7) {
  50. /* These levels seem to be mostly I/O debug and msg dumps */
  51. return;
  52. }
  53. s = os_strdup(msg);
  54. if (s == NULL)
  55. return;
  56. pos = s;
  57. while (*pos != '\0') {
  58. if (*pos == '\n') {
  59. *pos = '\0';
  60. break;
  61. }
  62. pos++;
  63. }
  64. wpa_printf(level > 3 ? MSG_MSGDUMP : MSG_DEBUG,
  65. "gnutls<%d> %s", level, s);
  66. os_free(s);
  67. }
  68. void * tls_init(const struct tls_config *conf)
  69. {
  70. struct tls_global *global;
  71. if (tls_gnutls_ref_count == 0) {
  72. wpa_printf(MSG_DEBUG,
  73. "GnuTLS: Library version %s (runtime) - %s (build)",
  74. gnutls_check_version(NULL), GNUTLS_VERSION);
  75. }
  76. global = os_zalloc(sizeof(*global));
  77. if (global == NULL)
  78. return NULL;
  79. if (tls_gnutls_ref_count == 0 && gnutls_global_init() < 0) {
  80. os_free(global);
  81. return NULL;
  82. }
  83. tls_gnutls_ref_count++;
  84. gnutls_global_set_log_function(tls_log_func);
  85. if (wpa_debug_show_keys)
  86. gnutls_global_set_log_level(11);
  87. if (conf) {
  88. global->event_cb = conf->event_cb;
  89. global->cb_ctx = conf->cb_ctx;
  90. global->cert_in_cb = conf->cert_in_cb;
  91. }
  92. return global;
  93. }
  94. void tls_deinit(void *ssl_ctx)
  95. {
  96. struct tls_global *global = ssl_ctx;
  97. if (global) {
  98. if (global->params_set)
  99. gnutls_certificate_free_credentials(global->xcred);
  100. os_free(global->session_data);
  101. os_free(global);
  102. }
  103. tls_gnutls_ref_count--;
  104. if (tls_gnutls_ref_count == 0)
  105. gnutls_global_deinit();
  106. }
  107. int tls_get_errors(void *ssl_ctx)
  108. {
  109. return 0;
  110. }
  111. static ssize_t tls_pull_func(gnutls_transport_ptr_t ptr, void *buf,
  112. size_t len)
  113. {
  114. struct tls_connection *conn = (struct tls_connection *) ptr;
  115. const u8 *end;
  116. if (conn->pull_buf == NULL) {
  117. errno = EWOULDBLOCK;
  118. return -1;
  119. }
  120. end = wpabuf_head_u8(conn->pull_buf) + wpabuf_len(conn->pull_buf);
  121. if ((size_t) (end - conn->pull_buf_offset) < len)
  122. len = end - conn->pull_buf_offset;
  123. os_memcpy(buf, conn->pull_buf_offset, len);
  124. conn->pull_buf_offset += len;
  125. if (conn->pull_buf_offset == end) {
  126. wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__);
  127. wpabuf_free(conn->pull_buf);
  128. conn->pull_buf = NULL;
  129. conn->pull_buf_offset = NULL;
  130. } else {
  131. wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf",
  132. __func__,
  133. (unsigned long) (end - conn->pull_buf_offset));
  134. }
  135. return len;
  136. }
  137. static ssize_t tls_push_func(gnutls_transport_ptr_t ptr, const void *buf,
  138. size_t len)
  139. {
  140. struct tls_connection *conn = (struct tls_connection *) ptr;
  141. if (wpabuf_resize(&conn->push_buf, len) < 0) {
  142. errno = ENOMEM;
  143. return -1;
  144. }
  145. wpabuf_put_data(conn->push_buf, buf, len);
  146. return len;
  147. }
  148. static int tls_gnutls_init_session(struct tls_global *global,
  149. struct tls_connection *conn)
  150. {
  151. const char *err;
  152. int ret;
  153. ret = gnutls_init(&conn->session,
  154. global->server ? GNUTLS_SERVER : GNUTLS_CLIENT);
  155. if (ret < 0) {
  156. wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS "
  157. "connection: %s", gnutls_strerror(ret));
  158. return -1;
  159. }
  160. ret = gnutls_set_default_priority(conn->session);
  161. if (ret < 0)
  162. goto fail;
  163. ret = gnutls_priority_set_direct(conn->session, "NORMAL:-VERS-SSL3.0",
  164. &err);
  165. if (ret < 0) {
  166. wpa_printf(MSG_ERROR, "GnuTLS: Priority string failure at "
  167. "'%s'", err);
  168. goto fail;
  169. }
  170. gnutls_transport_set_pull_function(conn->session, tls_pull_func);
  171. gnutls_transport_set_push_function(conn->session, tls_push_func);
  172. gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr_t) conn);
  173. gnutls_session_set_ptr(conn->session, conn);
  174. return 0;
  175. fail:
  176. wpa_printf(MSG_INFO, "TLS: Failed to setup new TLS connection: %s",
  177. gnutls_strerror(ret));
  178. gnutls_deinit(conn->session);
  179. return -1;
  180. }
  181. struct tls_connection * tls_connection_init(void *ssl_ctx)
  182. {
  183. struct tls_global *global = ssl_ctx;
  184. struct tls_connection *conn;
  185. int ret;
  186. conn = os_zalloc(sizeof(*conn));
  187. if (conn == NULL)
  188. return NULL;
  189. conn->global = global;
  190. if (tls_gnutls_init_session(global, conn)) {
  191. os_free(conn);
  192. return NULL;
  193. }
  194. if (global->params_set) {
  195. ret = gnutls_credentials_set(conn->session,
  196. GNUTLS_CRD_CERTIFICATE,
  197. global->xcred);
  198. if (ret < 0) {
  199. wpa_printf(MSG_INFO, "Failed to configure "
  200. "credentials: %s", gnutls_strerror(ret));
  201. os_free(conn);
  202. return NULL;
  203. }
  204. }
  205. if (gnutls_certificate_allocate_credentials(&conn->xcred)) {
  206. os_free(conn);
  207. return NULL;
  208. }
  209. return conn;
  210. }
  211. void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
  212. {
  213. if (conn == NULL)
  214. return;
  215. gnutls_certificate_free_credentials(conn->xcred);
  216. gnutls_deinit(conn->session);
  217. os_free(conn->pre_shared_secret);
  218. wpabuf_free(conn->push_buf);
  219. wpabuf_free(conn->pull_buf);
  220. os_free(conn->suffix_match);
  221. os_free(conn);
  222. }
  223. int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
  224. {
  225. return conn ? conn->established : 0;
  226. }
  227. int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
  228. {
  229. struct tls_global *global = ssl_ctx;
  230. int ret;
  231. if (conn == NULL)
  232. return -1;
  233. /* Shutdown previous TLS connection without notifying the peer
  234. * because the connection was already terminated in practice
  235. * and "close notify" shutdown alert would confuse AS. */
  236. gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
  237. wpabuf_free(conn->push_buf);
  238. conn->push_buf = NULL;
  239. conn->established = 0;
  240. gnutls_deinit(conn->session);
  241. if (tls_gnutls_init_session(global, conn)) {
  242. wpa_printf(MSG_INFO, "GnuTLS: Failed to preparare new session "
  243. "for session resumption use");
  244. return -1;
  245. }
  246. ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
  247. conn->params_set ? conn->xcred :
  248. global->xcred);
  249. if (ret < 0) {
  250. wpa_printf(MSG_INFO, "GnuTLS: Failed to configure credentials "
  251. "for session resumption: %s", gnutls_strerror(ret));
  252. return -1;
  253. }
  254. if (global->session_data) {
  255. ret = gnutls_session_set_data(conn->session,
  256. global->session_data,
  257. global->session_data_size);
  258. if (ret < 0) {
  259. wpa_printf(MSG_INFO, "GnuTLS: Failed to set session "
  260. "data: %s", gnutls_strerror(ret));
  261. return -1;
  262. }
  263. }
  264. return 0;
  265. }
  266. int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
  267. const struct tls_connection_params *params)
  268. {
  269. int ret;
  270. if (conn == NULL || params == NULL)
  271. return -1;
  272. if (params->subject_match) {
  273. wpa_printf(MSG_INFO, "GnuTLS: subject_match not supported");
  274. return -1;
  275. }
  276. if (params->altsubject_match) {
  277. wpa_printf(MSG_INFO, "GnuTLS: altsubject_match not supported");
  278. return -1;
  279. }
  280. os_free(conn->suffix_match);
  281. conn->suffix_match = NULL;
  282. if (params->suffix_match) {
  283. conn->suffix_match = os_strdup(params->suffix_match);
  284. if (conn->suffix_match == NULL)
  285. return -1;
  286. }
  287. if (params->openssl_ciphers) {
  288. wpa_printf(MSG_INFO, "GnuTLS: openssl_ciphers not supported");
  289. return -1;
  290. }
  291. /* TODO: gnutls_certificate_set_verify_flags(xcred, flags);
  292. * to force peer validation(?) */
  293. if (params->ca_cert) {
  294. wpa_printf(MSG_DEBUG, "GnuTLS: Try to parse %s in DER format",
  295. params->ca_cert);
  296. ret = gnutls_certificate_set_x509_trust_file(
  297. conn->xcred, params->ca_cert, GNUTLS_X509_FMT_DER);
  298. if (ret < 0) {
  299. wpa_printf(MSG_DEBUG,
  300. "GnuTLS: Failed to read CA cert '%s' in DER format (%s) - try in PEM format",
  301. params->ca_cert,
  302. gnutls_strerror(ret));
  303. ret = gnutls_certificate_set_x509_trust_file(
  304. conn->xcred, params->ca_cert,
  305. GNUTLS_X509_FMT_PEM);
  306. if (ret < 0) {
  307. wpa_printf(MSG_DEBUG,
  308. "Failed to read CA cert '%s' in PEM format: %s",
  309. params->ca_cert,
  310. gnutls_strerror(ret));
  311. return -1;
  312. }
  313. }
  314. } else if (params->ca_cert_blob) {
  315. gnutls_datum_t ca;
  316. ca.data = (unsigned char *) params->ca_cert_blob;
  317. ca.size = params->ca_cert_blob_len;
  318. ret = gnutls_certificate_set_x509_trust_mem(
  319. conn->xcred, &ca, GNUTLS_X509_FMT_DER);
  320. if (ret < 0) {
  321. wpa_printf(MSG_DEBUG,
  322. "Failed to parse CA cert in DER format: %s",
  323. gnutls_strerror(ret));
  324. ret = gnutls_certificate_set_x509_trust_mem(
  325. conn->xcred, &ca, GNUTLS_X509_FMT_PEM);
  326. if (ret < 0) {
  327. wpa_printf(MSG_DEBUG,
  328. "Failed to parse CA cert in PEM format: %s",
  329. gnutls_strerror(ret));
  330. return -1;
  331. }
  332. }
  333. } else if (params->ca_path) {
  334. wpa_printf(MSG_INFO, "GnuTLS: ca_path not supported");
  335. return -1;
  336. }
  337. conn->disable_time_checks = 0;
  338. if (params->ca_cert || params->ca_cert_blob) {
  339. conn->verify_peer = 1;
  340. gnutls_certificate_set_verify_function(
  341. conn->xcred, tls_connection_verify_peer);
  342. if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) {
  343. gnutls_certificate_set_verify_flags(
  344. conn->xcred, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
  345. }
  346. if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
  347. conn->disable_time_checks = 1;
  348. gnutls_certificate_set_verify_flags(
  349. conn->xcred,
  350. GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
  351. }
  352. }
  353. if (params->client_cert && params->private_key) {
  354. #if GNUTLS_VERSION_NUMBER >= 0x03010b
  355. ret = gnutls_certificate_set_x509_key_file2(
  356. conn->xcred, params->client_cert, params->private_key,
  357. GNUTLS_X509_FMT_DER, params->private_key_passwd, 0);
  358. #else
  359. /* private_key_passwd not (easily) supported here */
  360. ret = gnutls_certificate_set_x509_key_file(
  361. conn->xcred, params->client_cert, params->private_key,
  362. GNUTLS_X509_FMT_DER);
  363. #endif
  364. if (ret < 0) {
  365. wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
  366. "in DER format: %s", gnutls_strerror(ret));
  367. #if GNUTLS_VERSION_NUMBER >= 0x03010b
  368. ret = gnutls_certificate_set_x509_key_file2(
  369. conn->xcred, params->client_cert,
  370. params->private_key, GNUTLS_X509_FMT_PEM,
  371. params->private_key_passwd, 0);
  372. #else
  373. ret = gnutls_certificate_set_x509_key_file(
  374. conn->xcred, params->client_cert,
  375. params->private_key, GNUTLS_X509_FMT_PEM);
  376. #endif
  377. if (ret < 0) {
  378. wpa_printf(MSG_DEBUG, "Failed to read client "
  379. "cert/key in PEM format: %s",
  380. gnutls_strerror(ret));
  381. return ret;
  382. }
  383. }
  384. } else if (params->private_key) {
  385. int pkcs12_ok = 0;
  386. #ifdef PKCS12_FUNCS
  387. /* Try to load in PKCS#12 format */
  388. ret = gnutls_certificate_set_x509_simple_pkcs12_file(
  389. conn->xcred, params->private_key, GNUTLS_X509_FMT_DER,
  390. params->private_key_passwd);
  391. if (ret != 0) {
  392. wpa_printf(MSG_DEBUG, "Failed to load private_key in "
  393. "PKCS#12 format: %s", gnutls_strerror(ret));
  394. return -1;
  395. } else
  396. pkcs12_ok = 1;
  397. #endif /* PKCS12_FUNCS */
  398. if (!pkcs12_ok) {
  399. wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
  400. "included");
  401. return -1;
  402. }
  403. } else if (params->client_cert_blob && params->private_key_blob) {
  404. gnutls_datum_t cert, key;
  405. cert.data = (unsigned char *) params->client_cert_blob;
  406. cert.size = params->client_cert_blob_len;
  407. key.data = (unsigned char *) params->private_key_blob;
  408. key.size = params->private_key_blob_len;
  409. #if GNUTLS_VERSION_NUMBER >= 0x03010b
  410. ret = gnutls_certificate_set_x509_key_mem2(
  411. conn->xcred, &cert, &key, GNUTLS_X509_FMT_DER,
  412. params->private_key_passwd, 0);
  413. #else
  414. /* private_key_passwd not (easily) supported here */
  415. ret = gnutls_certificate_set_x509_key_mem(
  416. conn->xcred, &cert, &key, GNUTLS_X509_FMT_DER);
  417. #endif
  418. if (ret < 0) {
  419. wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
  420. "in DER format: %s", gnutls_strerror(ret));
  421. #if GNUTLS_VERSION_NUMBER >= 0x03010b
  422. ret = gnutls_certificate_set_x509_key_mem2(
  423. conn->xcred, &cert, &key, GNUTLS_X509_FMT_PEM,
  424. params->private_key_passwd, 0);
  425. #else
  426. /* private_key_passwd not (easily) supported here */
  427. ret = gnutls_certificate_set_x509_key_mem(
  428. conn->xcred, &cert, &key, GNUTLS_X509_FMT_PEM);
  429. #endif
  430. if (ret < 0) {
  431. wpa_printf(MSG_DEBUG, "Failed to read client "
  432. "cert/key in PEM format: %s",
  433. gnutls_strerror(ret));
  434. return ret;
  435. }
  436. }
  437. } else if (params->private_key_blob) {
  438. #ifdef PKCS12_FUNCS
  439. gnutls_datum_t key;
  440. key.data = (unsigned char *) params->private_key_blob;
  441. key.size = params->private_key_blob_len;
  442. /* Try to load in PKCS#12 format */
  443. ret = gnutls_certificate_set_x509_simple_pkcs12_mem(
  444. conn->xcred, &key, GNUTLS_X509_FMT_DER,
  445. params->private_key_passwd);
  446. if (ret != 0) {
  447. wpa_printf(MSG_DEBUG, "Failed to load private_key in "
  448. "PKCS#12 format: %s", gnutls_strerror(ret));
  449. return -1;
  450. }
  451. #else /* PKCS12_FUNCS */
  452. wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not included");
  453. return -1;
  454. #endif /* PKCS12_FUNCS */
  455. }
  456. conn->params_set = 1;
  457. ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
  458. conn->xcred);
  459. if (ret < 0) {
  460. wpa_printf(MSG_INFO, "Failed to configure credentials: %s",
  461. gnutls_strerror(ret));
  462. }
  463. return ret;
  464. }
  465. int tls_global_set_params(void *tls_ctx,
  466. const struct tls_connection_params *params)
  467. {
  468. struct tls_global *global = tls_ctx;
  469. int ret;
  470. /* Currently, global parameters are only set when running in server
  471. * mode. */
  472. global->server = 1;
  473. if (global->params_set) {
  474. gnutls_certificate_free_credentials(global->xcred);
  475. global->params_set = 0;
  476. }
  477. ret = gnutls_certificate_allocate_credentials(&global->xcred);
  478. if (ret) {
  479. wpa_printf(MSG_DEBUG, "Failed to allocate global credentials "
  480. "%s", gnutls_strerror(ret));
  481. return -1;
  482. }
  483. if (params->ca_cert) {
  484. ret = gnutls_certificate_set_x509_trust_file(
  485. global->xcred, params->ca_cert, GNUTLS_X509_FMT_DER);
  486. if (ret < 0) {
  487. wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' "
  488. "in DER format: %s", params->ca_cert,
  489. gnutls_strerror(ret));
  490. ret = gnutls_certificate_set_x509_trust_file(
  491. global->xcred, params->ca_cert,
  492. GNUTLS_X509_FMT_PEM);
  493. if (ret < 0) {
  494. wpa_printf(MSG_DEBUG, "Failed to read CA cert "
  495. "'%s' in PEM format: %s",
  496. params->ca_cert,
  497. gnutls_strerror(ret));
  498. goto fail;
  499. }
  500. }
  501. if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) {
  502. gnutls_certificate_set_verify_flags(
  503. global->xcred,
  504. GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
  505. }
  506. if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
  507. gnutls_certificate_set_verify_flags(
  508. global->xcred,
  509. GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
  510. }
  511. }
  512. if (params->client_cert && params->private_key) {
  513. /* TODO: private_key_passwd? */
  514. ret = gnutls_certificate_set_x509_key_file(
  515. global->xcred, params->client_cert,
  516. params->private_key, GNUTLS_X509_FMT_DER);
  517. if (ret < 0) {
  518. wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
  519. "in DER format: %s", gnutls_strerror(ret));
  520. ret = gnutls_certificate_set_x509_key_file(
  521. global->xcred, params->client_cert,
  522. params->private_key, GNUTLS_X509_FMT_PEM);
  523. if (ret < 0) {
  524. wpa_printf(MSG_DEBUG, "Failed to read client "
  525. "cert/key in PEM format: %s",
  526. gnutls_strerror(ret));
  527. goto fail;
  528. }
  529. }
  530. } else if (params->private_key) {
  531. int pkcs12_ok = 0;
  532. #ifdef PKCS12_FUNCS
  533. /* Try to load in PKCS#12 format */
  534. ret = gnutls_certificate_set_x509_simple_pkcs12_file(
  535. global->xcred, params->private_key,
  536. GNUTLS_X509_FMT_DER, params->private_key_passwd);
  537. if (ret != 0) {
  538. wpa_printf(MSG_DEBUG, "Failed to load private_key in "
  539. "PKCS#12 format: %s", gnutls_strerror(ret));
  540. goto fail;
  541. } else
  542. pkcs12_ok = 1;
  543. #endif /* PKCS12_FUNCS */
  544. if (!pkcs12_ok) {
  545. wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
  546. "included");
  547. goto fail;
  548. }
  549. }
  550. global->params_set = 1;
  551. return 0;
  552. fail:
  553. gnutls_certificate_free_credentials(global->xcred);
  554. return -1;
  555. }
  556. int tls_global_set_verify(void *ssl_ctx, int check_crl)
  557. {
  558. /* TODO */
  559. return 0;
  560. }
  561. int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
  562. int verify_peer)
  563. {
  564. if (conn == NULL || conn->session == NULL)
  565. return -1;
  566. conn->verify_peer = verify_peer;
  567. gnutls_certificate_server_set_request(conn->session,
  568. verify_peer ? GNUTLS_CERT_REQUIRE
  569. : GNUTLS_CERT_REQUEST);
  570. return 0;
  571. }
  572. int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
  573. struct tls_keys *keys)
  574. {
  575. #if GNUTLS_VERSION_NUMBER >= 0x030012
  576. gnutls_datum_t client, server;
  577. if (conn == NULL || conn->session == NULL || keys == NULL)
  578. return -1;
  579. os_memset(keys, 0, sizeof(*keys));
  580. gnutls_session_get_random(conn->session, &client, &server);
  581. keys->client_random = client.data;
  582. keys->server_random = server.data;
  583. keys->client_random_len = client.size;
  584. keys->server_random_len = client.size;
  585. return 0;
  586. #else /* 3.0.18 */
  587. return -1;
  588. #endif /* 3.0.18 */
  589. }
  590. int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
  591. const char *label, int server_random_first,
  592. u8 *out, size_t out_len)
  593. {
  594. if (conn == NULL || conn->session == NULL)
  595. return -1;
  596. return gnutls_prf(conn->session, os_strlen(label), label,
  597. server_random_first, 0, NULL, out_len, (char *) out);
  598. }
  599. static void gnutls_tls_fail_event(struct tls_connection *conn,
  600. const gnutls_datum_t *cert, int depth,
  601. const char *subject, const char *err_str,
  602. enum tls_fail_reason reason)
  603. {
  604. union tls_event_data ev;
  605. struct tls_global *global = conn->global;
  606. struct wpabuf *cert_buf = NULL;
  607. if (global->event_cb == NULL)
  608. return;
  609. os_memset(&ev, 0, sizeof(ev));
  610. ev.cert_fail.depth = depth;
  611. ev.cert_fail.subject = subject ? subject : "";
  612. ev.cert_fail.reason = reason;
  613. ev.cert_fail.reason_txt = err_str;
  614. if (cert) {
  615. cert_buf = wpabuf_alloc_copy(cert->data, cert->size);
  616. ev.cert_fail.cert = cert_buf;
  617. }
  618. global->event_cb(global->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
  619. wpabuf_free(cert_buf);
  620. }
  621. static int tls_connection_verify_peer(gnutls_session_t session)
  622. {
  623. struct tls_connection *conn;
  624. unsigned int status, num_certs, i;
  625. struct os_time now;
  626. const gnutls_datum_t *certs;
  627. gnutls_x509_crt_t cert;
  628. gnutls_alert_description_t err;
  629. conn = gnutls_session_get_ptr(session);
  630. if (!conn->verify_peer) {
  631. wpa_printf(MSG_DEBUG,
  632. "GnuTLS: No peer certificate verification enabled");
  633. return 0;
  634. }
  635. wpa_printf(MSG_DEBUG, "GnuTSL: Verifying peer certificate");
  636. if (gnutls_certificate_verify_peers2(session, &status) < 0) {
  637. wpa_printf(MSG_INFO, "TLS: Failed to verify peer "
  638. "certificate chain");
  639. err = GNUTLS_A_INTERNAL_ERROR;
  640. goto out;
  641. }
  642. #if GNUTLS_VERSION_NUMBER >= 0x030104
  643. {
  644. gnutls_datum_t info;
  645. int ret, type;
  646. type = gnutls_certificate_type_get(session);
  647. ret = gnutls_certificate_verification_status_print(status, type,
  648. &info, 0);
  649. if (ret < 0) {
  650. wpa_printf(MSG_DEBUG,
  651. "GnuTLS: Failed to print verification status");
  652. err = GNUTLS_A_INTERNAL_ERROR;
  653. goto out;
  654. }
  655. wpa_printf(MSG_DEBUG, "GnuTLS: %s", info.data);
  656. gnutls_free(info.data);
  657. }
  658. #endif /* GnuTLS 3.1.4 or newer */
  659. if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) {
  660. wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted");
  661. if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {
  662. wpa_printf(MSG_INFO, "TLS: Certificate uses insecure "
  663. "algorithm");
  664. gnutls_tls_fail_event(conn, NULL, 0, NULL,
  665. "certificate uses insecure algorithm",
  666. TLS_FAIL_BAD_CERTIFICATE);
  667. err = GNUTLS_A_INSUFFICIENT_SECURITY;
  668. goto out;
  669. }
  670. if (status & GNUTLS_CERT_NOT_ACTIVATED) {
  671. wpa_printf(MSG_INFO, "TLS: Certificate not yet "
  672. "activated");
  673. gnutls_tls_fail_event(conn, NULL, 0, NULL,
  674. "certificate not yet valid",
  675. TLS_FAIL_NOT_YET_VALID);
  676. err = GNUTLS_A_CERTIFICATE_EXPIRED;
  677. goto out;
  678. }
  679. if (status & GNUTLS_CERT_EXPIRED) {
  680. wpa_printf(MSG_INFO, "TLS: Certificate expired");
  681. gnutls_tls_fail_event(conn, NULL, 0, NULL,
  682. "certificate has expired",
  683. TLS_FAIL_EXPIRED);
  684. err = GNUTLS_A_CERTIFICATE_EXPIRED;
  685. goto out;
  686. }
  687. gnutls_tls_fail_event(conn, NULL, 0, NULL,
  688. "untrusted certificate",
  689. TLS_FAIL_UNTRUSTED);
  690. err = GNUTLS_A_INTERNAL_ERROR;
  691. goto out;
  692. }
  693. if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
  694. wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a "
  695. "known issuer");
  696. gnutls_tls_fail_event(conn, NULL, 0, NULL, "signed not found",
  697. TLS_FAIL_UNTRUSTED);
  698. err = GNUTLS_A_UNKNOWN_CA;
  699. goto out;
  700. }
  701. if (status & GNUTLS_CERT_REVOKED) {
  702. wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked");
  703. gnutls_tls_fail_event(conn, NULL, 0, NULL,
  704. "certificate revoked",
  705. TLS_FAIL_REVOKED);
  706. err = GNUTLS_A_CERTIFICATE_REVOKED;
  707. goto out;
  708. }
  709. if (status != 0) {
  710. wpa_printf(MSG_INFO, "TLS: Unknown verification status: %d",
  711. status);
  712. err = GNUTLS_A_INTERNAL_ERROR;
  713. goto out;
  714. }
  715. os_get_time(&now);
  716. certs = gnutls_certificate_get_peers(session, &num_certs);
  717. if (certs == NULL) {
  718. wpa_printf(MSG_INFO, "TLS: No peer certificate chain "
  719. "received");
  720. err = GNUTLS_A_UNKNOWN_CA;
  721. goto out;
  722. }
  723. for (i = 0; i < num_certs; i++) {
  724. char *buf;
  725. size_t len;
  726. if (gnutls_x509_crt_init(&cert) < 0) {
  727. wpa_printf(MSG_INFO, "TLS: Certificate initialization "
  728. "failed");
  729. err = GNUTLS_A_BAD_CERTIFICATE;
  730. goto out;
  731. }
  732. if (gnutls_x509_crt_import(cert, &certs[i],
  733. GNUTLS_X509_FMT_DER) < 0) {
  734. wpa_printf(MSG_INFO, "TLS: Could not parse peer "
  735. "certificate %d/%d", i + 1, num_certs);
  736. gnutls_x509_crt_deinit(cert);
  737. err = GNUTLS_A_BAD_CERTIFICATE;
  738. goto out;
  739. }
  740. gnutls_x509_crt_get_dn(cert, NULL, &len);
  741. len++;
  742. buf = os_malloc(len + 1);
  743. if (buf) {
  744. buf[0] = buf[len] = '\0';
  745. gnutls_x509_crt_get_dn(cert, buf, &len);
  746. }
  747. wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s",
  748. i + 1, num_certs, buf);
  749. if (i == 0) {
  750. if (conn->suffix_match &&
  751. !gnutls_x509_crt_check_hostname(
  752. cert, conn->suffix_match)) {
  753. wpa_printf(MSG_WARNING,
  754. "TLS: Domain suffix match '%s' not found",
  755. conn->suffix_match);
  756. gnutls_tls_fail_event(
  757. conn, &certs[i], i, buf,
  758. "Domain suffix mismatch",
  759. TLS_FAIL_DOMAIN_SUFFIX_MISMATCH);
  760. err = GNUTLS_A_BAD_CERTIFICATE;
  761. gnutls_x509_crt_deinit(cert);
  762. os_free(buf);
  763. goto out;
  764. }
  765. /* TODO: validate altsubject_match.
  766. * For now, any such configuration is rejected in
  767. * tls_connection_set_params() */
  768. }
  769. if (!conn->disable_time_checks &&
  770. (gnutls_x509_crt_get_expiration_time(cert) < now.sec ||
  771. gnutls_x509_crt_get_activation_time(cert) > now.sec)) {
  772. wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is "
  773. "not valid at this time",
  774. i + 1, num_certs);
  775. gnutls_tls_fail_event(
  776. conn, &certs[i], i, buf,
  777. "Certificate is not valid at this time",
  778. TLS_FAIL_EXPIRED);
  779. gnutls_x509_crt_deinit(cert);
  780. os_free(buf);
  781. err = GNUTLS_A_CERTIFICATE_EXPIRED;
  782. goto out;
  783. }
  784. os_free(buf);
  785. gnutls_x509_crt_deinit(cert);
  786. }
  787. return 0;
  788. out:
  789. conn->failed++;
  790. gnutls_alert_send(session, GNUTLS_AL_FATAL, err);
  791. return GNUTLS_E_CERTIFICATE_ERROR;
  792. }
  793. static struct wpabuf * gnutls_get_appl_data(struct tls_connection *conn)
  794. {
  795. int res;
  796. struct wpabuf *ad;
  797. wpa_printf(MSG_DEBUG, "GnuTLS: Check for possible Application Data");
  798. ad = wpabuf_alloc((wpabuf_len(conn->pull_buf) + 500) * 3);
  799. if (ad == NULL)
  800. return NULL;
  801. res = gnutls_record_recv(conn->session, wpabuf_mhead(ad),
  802. wpabuf_size(ad));
  803. wpa_printf(MSG_DEBUG, "GnuTLS: gnutls_record_recv: %d", res);
  804. if (res < 0) {
  805. wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
  806. "(%s)", __func__, (int) res,
  807. gnutls_strerror(res));
  808. wpabuf_free(ad);
  809. return NULL;
  810. }
  811. wpabuf_put(ad, res);
  812. wpa_printf(MSG_DEBUG, "GnuTLS: Received %d bytes of Application Data",
  813. res);
  814. return ad;
  815. }
  816. struct wpabuf * tls_connection_handshake(void *tls_ctx,
  817. struct tls_connection *conn,
  818. const struct wpabuf *in_data,
  819. struct wpabuf **appl_data)
  820. {
  821. struct tls_global *global = tls_ctx;
  822. struct wpabuf *out_data;
  823. int ret;
  824. if (appl_data)
  825. *appl_data = NULL;
  826. if (in_data && wpabuf_len(in_data) > 0) {
  827. if (conn->pull_buf) {
  828. wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
  829. "pull_buf", __func__,
  830. (unsigned long) wpabuf_len(conn->pull_buf));
  831. wpabuf_free(conn->pull_buf);
  832. }
  833. conn->pull_buf = wpabuf_dup(in_data);
  834. if (conn->pull_buf == NULL)
  835. return NULL;
  836. conn->pull_buf_offset = wpabuf_head(conn->pull_buf);
  837. }
  838. ret = gnutls_handshake(conn->session);
  839. if (ret < 0) {
  840. switch (ret) {
  841. case GNUTLS_E_AGAIN:
  842. if (global->server && conn->established &&
  843. conn->push_buf == NULL) {
  844. /* Need to return something to trigger
  845. * completion of EAP-TLS. */
  846. conn->push_buf = wpabuf_alloc(0);
  847. }
  848. break;
  849. case GNUTLS_E_FATAL_ALERT_RECEIVED:
  850. wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert",
  851. __func__, gnutls_alert_get_name(
  852. gnutls_alert_get(conn->session)));
  853. conn->read_alerts++;
  854. /* continue */
  855. default:
  856. wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed "
  857. "-> %s", __func__, gnutls_strerror(ret));
  858. conn->failed++;
  859. }
  860. } else {
  861. size_t size;
  862. wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully");
  863. #if GNUTLS_VERSION_NUMBER >= 0x03010a
  864. {
  865. char *desc;
  866. desc = gnutls_session_get_desc(conn->session);
  867. if (desc) {
  868. wpa_printf(MSG_DEBUG, "GnuTLS: %s", desc);
  869. gnutls_free(desc);
  870. }
  871. }
  872. #endif /* GnuTLS 3.1.10 or newer */
  873. conn->established = 1;
  874. if (conn->push_buf == NULL) {
  875. /* Need to return something to get final TLS ACK. */
  876. conn->push_buf = wpabuf_alloc(0);
  877. }
  878. gnutls_session_get_data(conn->session, NULL, &size);
  879. if (global->session_data == NULL ||
  880. global->session_data_size < size) {
  881. os_free(global->session_data);
  882. global->session_data = os_malloc(size);
  883. }
  884. if (global->session_data) {
  885. global->session_data_size = size;
  886. gnutls_session_get_data(conn->session,
  887. global->session_data,
  888. &global->session_data_size);
  889. }
  890. if (conn->pull_buf && appl_data)
  891. *appl_data = gnutls_get_appl_data(conn);
  892. }
  893. out_data = conn->push_buf;
  894. conn->push_buf = NULL;
  895. return out_data;
  896. }
  897. struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
  898. struct tls_connection *conn,
  899. const struct wpabuf *in_data,
  900. struct wpabuf **appl_data)
  901. {
  902. return tls_connection_handshake(tls_ctx, conn, in_data, appl_data);
  903. }
  904. struct wpabuf * tls_connection_encrypt(void *tls_ctx,
  905. struct tls_connection *conn,
  906. const struct wpabuf *in_data)
  907. {
  908. ssize_t res;
  909. struct wpabuf *buf;
  910. res = gnutls_record_send(conn->session, wpabuf_head(in_data),
  911. wpabuf_len(in_data));
  912. if (res < 0) {
  913. wpa_printf(MSG_INFO, "%s: Encryption failed: %s",
  914. __func__, gnutls_strerror(res));
  915. return NULL;
  916. }
  917. buf = conn->push_buf;
  918. conn->push_buf = NULL;
  919. return buf;
  920. }
  921. struct wpabuf * tls_connection_decrypt(void *tls_ctx,
  922. struct tls_connection *conn,
  923. const struct wpabuf *in_data)
  924. {
  925. ssize_t res;
  926. struct wpabuf *out;
  927. if (conn->pull_buf) {
  928. wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
  929. "pull_buf", __func__,
  930. (unsigned long) wpabuf_len(conn->pull_buf));
  931. wpabuf_free(conn->pull_buf);
  932. }
  933. conn->pull_buf = wpabuf_dup(in_data);
  934. if (conn->pull_buf == NULL)
  935. return NULL;
  936. conn->pull_buf_offset = wpabuf_head(conn->pull_buf);
  937. /*
  938. * Even though we try to disable TLS compression, it is possible that
  939. * this cannot be done with all TLS libraries. Add extra buffer space
  940. * to handle the possibility of the decrypted data being longer than
  941. * input data.
  942. */
  943. out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
  944. if (out == NULL)
  945. return NULL;
  946. res = gnutls_record_recv(conn->session, wpabuf_mhead(out),
  947. wpabuf_size(out));
  948. if (res < 0) {
  949. wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
  950. "(%s)", __func__, (int) res, gnutls_strerror(res));
  951. wpabuf_free(out);
  952. return NULL;
  953. }
  954. wpabuf_put(out, res);
  955. return out;
  956. }
  957. int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
  958. {
  959. if (conn == NULL)
  960. return 0;
  961. return gnutls_session_is_resumed(conn->session);
  962. }
  963. int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
  964. u8 *ciphers)
  965. {
  966. /* TODO */
  967. return -1;
  968. }
  969. int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
  970. char *buf, size_t buflen)
  971. {
  972. /* TODO */
  973. buf[0] = '\0';
  974. return 0;
  975. }
  976. int tls_connection_enable_workaround(void *ssl_ctx,
  977. struct tls_connection *conn)
  978. {
  979. gnutls_record_disable_padding(conn->session);
  980. return 0;
  981. }
  982. int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
  983. int ext_type, const u8 *data,
  984. size_t data_len)
  985. {
  986. /* TODO */
  987. return -1;
  988. }
  989. int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
  990. {
  991. if (conn == NULL)
  992. return -1;
  993. return conn->failed;
  994. }
  995. int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
  996. {
  997. if (conn == NULL)
  998. return -1;
  999. return conn->read_alerts;
  1000. }
  1001. int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
  1002. {
  1003. if (conn == NULL)
  1004. return -1;
  1005. return conn->write_alerts;
  1006. }
  1007. int tls_connection_get_keyblock_size(void *tls_ctx,
  1008. struct tls_connection *conn)
  1009. {
  1010. /* TODO */
  1011. return -1;
  1012. }
  1013. unsigned int tls_capabilities(void *tls_ctx)
  1014. {
  1015. return 0;
  1016. }
  1017. int tls_connection_set_session_ticket_cb(void *tls_ctx,
  1018. struct tls_connection *conn,
  1019. tls_session_ticket_cb cb, void *ctx)
  1020. {
  1021. return -1;
  1022. }
  1023. int tls_get_library_version(char *buf, size_t buf_len)
  1024. {
  1025. return os_snprintf(buf, buf_len, "GnuTLS build=%s run=%s",
  1026. GNUTLS_VERSION, gnutls_check_version(NULL));
  1027. }