tls_gnutls.c 29 KB

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