00001
00016 #include "includes.h"
00017 #include <gnutls/gnutls.h>
00018 #include <gnutls/x509.h>
00019 #ifdef PKCS12_FUNCS
00020 #include <gnutls/pkcs12.h>
00021 #endif
00022
00023 #ifdef CONFIG_GNUTLS_EXTRA
00024 #if LIBGNUTLS_VERSION_NUMBER >= 0x010302
00025 #define GNUTLS_IA
00026 #include <gnutls/extra.h>
00027 #if LIBGNUTLS_VERSION_NUMBER == 0x010302
00028
00029
00030 int gnutls_ia_verify_endphase(gnutls_session_t session, char *checksum);
00031 #endif
00032 #endif
00033 #endif
00034
00035 #include "common.h"
00036 #include "tls.h"
00037
00038
00039 #define TLS_RANDOM_SIZE 32
00040 #define TLS_MASTER_SIZE 48
00041
00042
00043 #if LIBGNUTLS_VERSION_NUMBER < 0x010302
00044
00045
00046
00047
00048 #define GNUTLS_INTERNAL_STRUCTURE_HACK
00049 #endif
00050
00051
00052 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
00053
00054
00055
00056
00057
00058
00059
00060
00061 typedef u8 uint8;
00062 typedef unsigned char opaque;
00063 typedef struct {
00064 uint8 suite[2];
00065 } cipher_suite_st;
00066
00067 typedef struct {
00068 gnutls_connection_end_t entity;
00069 gnutls_kx_algorithm_t kx_algorithm;
00070 gnutls_cipher_algorithm_t read_bulk_cipher_algorithm;
00071 gnutls_mac_algorithm_t read_mac_algorithm;
00072 gnutls_compression_method_t read_compression_algorithm;
00073 gnutls_cipher_algorithm_t write_bulk_cipher_algorithm;
00074 gnutls_mac_algorithm_t write_mac_algorithm;
00075 gnutls_compression_method_t write_compression_algorithm;
00076 cipher_suite_st current_cipher_suite;
00077 opaque master_secret[TLS_MASTER_SIZE];
00078 opaque client_random[TLS_RANDOM_SIZE];
00079 opaque server_random[TLS_RANDOM_SIZE];
00080
00081 } security_parameters_st;
00082
00083 struct gnutls_session_int {
00084 security_parameters_st security_parameters;
00085
00086 };
00087 #endif
00088
00089 static int tls_gnutls_ref_count = 0;
00090
00091 struct tls_global {
00092
00093 void *session_data;
00094 size_t session_data_size;
00095
00096 int server;
00097
00098 int params_set;
00099 gnutls_certificate_credentials_t xcred;
00100 };
00101
00102 struct tls_connection {
00103 gnutls_session session;
00104 char *subject_match, *altsubject_match;
00105 int read_alerts, write_alerts, failed;
00106
00107 u8 *pre_shared_secret;
00108 size_t pre_shared_secret_len;
00109 int established;
00110 int verify_peer;
00111
00112 u8 *push_buf, *pull_buf, *pull_buf_offset;
00113 size_t push_buf_len, pull_buf_len;
00114
00115 int params_set;
00116 gnutls_certificate_credentials_t xcred;
00117
00118 int tls_ia;
00119 int final_phase_finished;
00120
00121 #ifdef GNUTLS_IA
00122 gnutls_ia_server_credentials_t iacred_srv;
00123 gnutls_ia_client_credentials_t iacred_cli;
00124
00125
00126
00127 u8 *session_keys;
00128 size_t session_keys_len;
00129
00130 u8 inner_secret[TLS_MASTER_SIZE];
00131 #endif
00132 };
00133
00134
00135 static void tls_log_func(int level, const char *msg)
00136 {
00137 char *s, *pos;
00138 if (level == 6 || level == 7) {
00139
00140 return;
00141 }
00142
00143 s = os_strdup(msg);
00144 if (s == NULL)
00145 return;
00146
00147 pos = s;
00148 while (*pos != '\0') {
00149 if (*pos == '\n') {
00150 *pos = '\0';
00151 break;
00152 }
00153 pos++;
00154 }
00155 wpa_printf(level > 3 ? MSG_MSGDUMP : MSG_DEBUG,
00156 "gnutls<%d> %s", level, s);
00157 os_free(s);
00158 }
00159
00160
00161 extern int wpa_debug_show_keys;
00162
00163 void * tls_init(const struct tls_config *conf)
00164 {
00165 struct tls_global *global;
00166
00167 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
00168
00169
00170
00171
00172 const char *ver;
00173 const char *ok_ver[] = { "1.2.3", "1.2.4", "1.2.5", "1.2.6", "1.2.9",
00174 "1.3.2",
00175 NULL };
00176 int i;
00177 #endif
00178
00179 global = os_zalloc(sizeof(*global));
00180 if (global == NULL)
00181 return NULL;
00182
00183 if (tls_gnutls_ref_count == 0 && gnutls_global_init() < 0) {
00184 os_free(global);
00185 return NULL;
00186 }
00187 tls_gnutls_ref_count++;
00188
00189 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
00190 ver = gnutls_check_version(NULL);
00191 if (ver == NULL) {
00192 tls_deinit(global);
00193 return NULL;
00194 }
00195 wpa_printf(MSG_DEBUG, "%s - gnutls version %s", __func__, ver);
00196 for (i = 0; ok_ver[i]; i++) {
00197 if (strcmp(ok_ver[i], ver) == 0)
00198 break;
00199 }
00200 if (ok_ver[i] == NULL) {
00201 wpa_printf(MSG_INFO, "Untested gnutls version %s - this needs "
00202 "to be tested and enabled in tls_gnutls.c", ver);
00203 tls_deinit(global);
00204 return NULL;
00205 }
00206 #endif
00207
00208 gnutls_global_set_log_function(tls_log_func);
00209 if (wpa_debug_show_keys)
00210 gnutls_global_set_log_level(11);
00211 return global;
00212 }
00213
00214
00215 void tls_deinit(void *ssl_ctx)
00216 {
00217 struct tls_global *global = ssl_ctx;
00218 if (global) {
00219 if (global->params_set)
00220 gnutls_certificate_free_credentials(global->xcred);
00221 os_free(global->session_data);
00222 os_free(global);
00223 }
00224
00225 tls_gnutls_ref_count--;
00226 if (tls_gnutls_ref_count == 0)
00227 gnutls_global_deinit();
00228 }
00229
00230
00231 int tls_get_errors(void *ssl_ctx)
00232 {
00233 return 0;
00234 }
00235
00236
00237 static ssize_t tls_pull_func(gnutls_transport_ptr ptr, void *buf,
00238 size_t len)
00239 {
00240 struct tls_connection *conn = (struct tls_connection *) ptr;
00241 u8 *end;
00242 if (conn->pull_buf == NULL) {
00243 errno = EWOULDBLOCK;
00244 return -1;
00245 }
00246
00247 end = conn->pull_buf + conn->pull_buf_len;
00248 if ((size_t) (end - conn->pull_buf_offset) < len)
00249 len = end - conn->pull_buf_offset;
00250 os_memcpy(buf, conn->pull_buf_offset, len);
00251 conn->pull_buf_offset += len;
00252 if (conn->pull_buf_offset == end) {
00253 wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__);
00254 os_free(conn->pull_buf);
00255 conn->pull_buf = conn->pull_buf_offset = NULL;
00256 conn->pull_buf_len = 0;
00257 } else {
00258 wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in pull_buf",
00259 __func__, end - conn->pull_buf_offset);
00260 }
00261 return len;
00262 }
00263
00264
00265 static ssize_t tls_push_func(gnutls_transport_ptr ptr, const void *buf,
00266 size_t len)
00267 {
00268 struct tls_connection *conn = (struct tls_connection *) ptr;
00269 u8 *nbuf;
00270
00271 nbuf = os_realloc(conn->push_buf, conn->push_buf_len + len);
00272 if (nbuf == NULL) {
00273 errno = ENOMEM;
00274 return -1;
00275 }
00276 os_memcpy(nbuf + conn->push_buf_len, buf, len);
00277 conn->push_buf = nbuf;
00278 conn->push_buf_len += len;
00279
00280 return len;
00281 }
00282
00283
00284 static int tls_gnutls_init_session(struct tls_global *global,
00285 struct tls_connection *conn)
00286 {
00287 const int cert_types[2] = { GNUTLS_CRT_X509, 0 };
00288 const int protos[2] = { GNUTLS_TLS1, 0 };
00289 int ret;
00290
00291 ret = gnutls_init(&conn->session,
00292 global->server ? GNUTLS_SERVER : GNUTLS_CLIENT);
00293 if (ret < 0) {
00294 wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS "
00295 "connection: %s", gnutls_strerror(ret));
00296 return -1;
00297 }
00298
00299 ret = gnutls_set_default_priority(conn->session);
00300 if (ret < 0)
00301 goto fail;
00302
00303 ret = gnutls_certificate_type_set_priority(conn->session, cert_types);
00304 if (ret < 0)
00305 goto fail;
00306
00307 ret = gnutls_protocol_set_priority(conn->session, protos);
00308 if (ret < 0)
00309 goto fail;
00310
00311 gnutls_transport_set_pull_function(conn->session, tls_pull_func);
00312 gnutls_transport_set_push_function(conn->session, tls_push_func);
00313 gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr) conn);
00314
00315 return 0;
00316
00317 fail:
00318 wpa_printf(MSG_INFO, "TLS: Failed to setup new TLS connection: %s",
00319 gnutls_strerror(ret));
00320 gnutls_deinit(conn->session);
00321 return -1;
00322 }
00323
00324
00325 struct tls_connection * tls_connection_init(void *ssl_ctx)
00326 {
00327 struct tls_global *global = ssl_ctx;
00328 struct tls_connection *conn;
00329 int ret;
00330
00331 conn = os_zalloc(sizeof(*conn));
00332 if (conn == NULL)
00333 return NULL;
00334
00335 if (tls_gnutls_init_session(global, conn)) {
00336 os_free(conn);
00337 return NULL;
00338 }
00339
00340 if (global->params_set) {
00341 ret = gnutls_credentials_set(conn->session,
00342 GNUTLS_CRD_CERTIFICATE,
00343 global->xcred);
00344 if (ret < 0) {
00345 wpa_printf(MSG_INFO, "Failed to configure "
00346 "credentials: %s", gnutls_strerror(ret));
00347 os_free(conn);
00348 return NULL;
00349 }
00350 }
00351
00352 if (gnutls_certificate_allocate_credentials(&conn->xcred)) {
00353 os_free(conn);
00354 return NULL;
00355 }
00356
00357 return conn;
00358 }
00359
00360
00361 void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
00362 {
00363 if (conn == NULL)
00364 return;
00365
00366 #ifdef GNUTLS_IA
00367 if (conn->iacred_srv)
00368 gnutls_ia_free_server_credentials(conn->iacred_srv);
00369 if (conn->iacred_cli)
00370 gnutls_ia_free_client_credentials(conn->iacred_cli);
00371 if (conn->session_keys) {
00372 os_memset(conn->session_keys, 0, conn->session_keys_len);
00373 os_free(conn->session_keys);
00374 }
00375 #endif
00376
00377 gnutls_certificate_free_credentials(conn->xcred);
00378 gnutls_deinit(conn->session);
00379 os_free(conn->pre_shared_secret);
00380 os_free(conn->subject_match);
00381 os_free(conn->altsubject_match);
00382 os_free(conn->push_buf);
00383 os_free(conn->pull_buf);
00384 os_free(conn);
00385 }
00386
00387
00388 int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
00389 {
00390 return conn ? conn->established : 0;
00391 }
00392
00393
00394 int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
00395 {
00396 struct tls_global *global = ssl_ctx;
00397 int ret;
00398
00399 if (conn == NULL)
00400 return -1;
00401
00402
00403
00404
00405 gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
00406 os_free(conn->push_buf);
00407 conn->push_buf = NULL;
00408 conn->push_buf_len = 0;
00409 conn->established = 0;
00410 conn->final_phase_finished = 0;
00411 #ifdef GNUTLS_IA
00412 if (conn->session_keys) {
00413 os_memset(conn->session_keys, 0, conn->session_keys_len);
00414 os_free(conn->session_keys);
00415 }
00416 conn->session_keys_len = 0;
00417 #endif
00418
00419 gnutls_deinit(conn->session);
00420 if (tls_gnutls_init_session(global, conn)) {
00421 wpa_printf(MSG_INFO, "GnuTLS: Failed to preparare new session "
00422 "for session resumption use");
00423 return -1;
00424 }
00425
00426 ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
00427 conn->params_set ? conn->xcred :
00428 global->xcred);
00429 if (ret < 0) {
00430 wpa_printf(MSG_INFO, "GnuTLS: Failed to configure credentials "
00431 "for session resumption: %s", gnutls_strerror(ret));
00432 return -1;
00433 }
00434
00435 if (global->session_data) {
00436 ret = gnutls_session_set_data(conn->session,
00437 global->session_data,
00438 global->session_data_size);
00439 if (ret < 0) {
00440 wpa_printf(MSG_INFO, "GnuTLS: Failed to set session "
00441 "data: %s", gnutls_strerror(ret));
00442 return -1;
00443 }
00444 }
00445
00446 return 0;
00447 }
00448
00449
00450 #if 0
00451 static int tls_match_altsubject(X509 *cert, const char *match)
00452 {
00453 GENERAL_NAME *gen;
00454 char *field, *tmp;
00455 void *ext;
00456 int i, found = 0;
00457 size_t len;
00458
00459 ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
00460
00461 for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {
00462 gen = sk_GENERAL_NAME_value(ext, i);
00463 switch (gen->type) {
00464 case GEN_EMAIL:
00465 field = "EMAIL";
00466 break;
00467 case GEN_DNS:
00468 field = "DNS";
00469 break;
00470 case GEN_URI:
00471 field = "URI";
00472 break;
00473 default:
00474 field = NULL;
00475 wpa_printf(MSG_DEBUG, "TLS: altSubjectName: "
00476 "unsupported type=%d", gen->type);
00477 break;
00478 }
00479
00480 if (!field)
00481 continue;
00482
00483 wpa_printf(MSG_DEBUG, "TLS: altSubjectName: %s:%s",
00484 field, gen->d.ia5->data);
00485 len = os_strlen(field) + 1 +
00486 strlen((char *) gen->d.ia5->data) + 1;
00487 tmp = os_malloc(len);
00488 if (tmp == NULL)
00489 continue;
00490 snprintf(tmp, len, "%s:%s", field, gen->d.ia5->data);
00491 if (strstr(tmp, match))
00492 found++;
00493 os_free(tmp);
00494 }
00495
00496 return found;
00497 }
00498 #endif
00499
00500
00501 #if 0
00502 static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
00503 {
00504 char buf[256];
00505 X509 *err_cert;
00506 int err, depth;
00507 SSL *ssl;
00508 struct tls_connection *conn;
00509 char *match, *altmatch;
00510
00511 err_cert = X509_STORE_CTX_get_current_cert(x509_ctx);
00512 err = X509_STORE_CTX_get_error(x509_ctx);
00513 depth = X509_STORE_CTX_get_error_depth(x509_ctx);
00514 ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
00515 SSL_get_ex_data_X509_STORE_CTX_idx());
00516 X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
00517
00518 conn = SSL_get_app_data(ssl);
00519 match = conn ? conn->subject_match : NULL;
00520 altmatch = conn ? conn->altsubject_match : NULL;
00521
00522 if (!preverify_ok) {
00523 wpa_printf(MSG_WARNING, "TLS: Certificate verification failed,"
00524 " error %d (%s) depth %d for '%s'", err,
00525 X509_verify_cert_error_string(err), depth, buf);
00526 } else {
00527 wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - "
00528 "preverify_ok=%d err=%d (%s) depth=%d buf='%s'",
00529 preverify_ok, err,
00530 X509_verify_cert_error_string(err), depth, buf);
00531 if (depth == 0 && match && strstr(buf, match) == NULL) {
00532 wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not "
00533 "match with '%s'", buf, match);
00534 preverify_ok = 0;
00535 } else if (depth == 0 && altmatch &&
00536 !tls_match_altsubject(err_cert, altmatch)) {
00537 wpa_printf(MSG_WARNING, "TLS: altSubjectName match "
00538 "'%s' not found", altmatch);
00539 preverify_ok = 0;
00540 }
00541 }
00542
00543 return preverify_ok;
00544 }
00545 #endif
00546
00547
00548 int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
00549 const struct tls_connection_params *params)
00550 {
00551 int ret;
00552
00553 if (conn == NULL || params == NULL)
00554 return -1;
00555
00556 os_free(conn->subject_match);
00557 conn->subject_match = NULL;
00558 if (params->subject_match) {
00559 conn->subject_match = os_strdup(params->subject_match);
00560 if (conn->subject_match == NULL)
00561 return -1;
00562 }
00563
00564 os_free(conn->altsubject_match);
00565 conn->altsubject_match = NULL;
00566 if (params->altsubject_match) {
00567 conn->altsubject_match = os_strdup(params->altsubject_match);
00568 if (conn->altsubject_match == NULL)
00569 return -1;
00570 }
00571
00572
00573
00574
00575 if (params->ca_cert) {
00576 conn->verify_peer = 1;
00577 ret = gnutls_certificate_set_x509_trust_file(
00578 conn->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM);
00579 if (ret < 0) {
00580 wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' "
00581 "in PEM format: %s", params->ca_cert,
00582 gnutls_strerror(ret));
00583 ret = gnutls_certificate_set_x509_trust_file(
00584 conn->xcred, params->ca_cert,
00585 GNUTLS_X509_FMT_DER);
00586 if (ret < 0) {
00587 wpa_printf(MSG_DEBUG, "Failed to read CA cert "
00588 "'%s' in DER format: %s",
00589 params->ca_cert,
00590 gnutls_strerror(ret));
00591 return -1;
00592 }
00593 }
00594 }
00595
00596 if (params->client_cert && params->private_key) {
00597
00598 ret = gnutls_certificate_set_x509_key_file(
00599 conn->xcred, params->client_cert, params->private_key,
00600 GNUTLS_X509_FMT_PEM);
00601 if (ret < 0) {
00602 wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
00603 "in PEM format: %s", gnutls_strerror(ret));
00604 ret = gnutls_certificate_set_x509_key_file(
00605 conn->xcred, params->client_cert,
00606 params->private_key, GNUTLS_X509_FMT_DER);
00607 if (ret < 0) {
00608 wpa_printf(MSG_DEBUG, "Failed to read client "
00609 "cert/key in DER format: %s",
00610 gnutls_strerror(ret));
00611 return ret;
00612 }
00613 }
00614 } else if (params->private_key) {
00615 int pkcs12_ok = 0;
00616 #ifdef PKCS12_FUNCS
00617
00618 #if LIBGNUTLS_VERSION_NUMBER >= 0x010302
00619 ret = gnutls_certificate_set_x509_simple_pkcs12_file(
00620 conn->xcred, params->private_key, GNUTLS_X509_FMT_DER,
00621 params->private_key_passwd);
00622 if (ret != 0) {
00623 wpa_printf(MSG_DEBUG, "Failed to load private_key in "
00624 "PKCS#12 format: %s", gnutls_strerror(ret));
00625 return -1;
00626 } else
00627 pkcs12_ok = 1;
00628 #endif
00629 #endif
00630
00631 if (!pkcs12_ok) {
00632 wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
00633 "included");
00634 return -1;
00635 }
00636 }
00637
00638 conn->tls_ia = params->tls_ia;
00639 conn->params_set = 1;
00640
00641 ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
00642 conn->xcred);
00643 if (ret < 0) {
00644 wpa_printf(MSG_INFO, "Failed to configure credentials: %s",
00645 gnutls_strerror(ret));
00646 }
00647
00648 #ifdef GNUTLS_IA
00649 if (conn->iacred_cli)
00650 gnutls_ia_free_client_credentials(conn->iacred_cli);
00651
00652 ret = gnutls_ia_allocate_client_credentials(&conn->iacred_cli);
00653 if (ret) {
00654 wpa_printf(MSG_DEBUG, "Failed to allocate IA credentials: %s",
00655 gnutls_strerror(ret));
00656 return -1;
00657 }
00658
00659 ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_IA,
00660 conn->iacred_cli);
00661 if (ret) {
00662 wpa_printf(MSG_DEBUG, "Failed to configure IA credentials: %s",
00663 gnutls_strerror(ret));
00664 gnutls_ia_free_client_credentials(conn->iacred_cli);
00665 conn->iacred_cli = NULL;
00666 return -1;
00667 }
00668 #endif
00669
00670 return ret;
00671 }
00672
00673
00674 int tls_global_set_params(void *tls_ctx,
00675 const struct tls_connection_params *params)
00676 {
00677 struct tls_global *global = tls_ctx;
00678 int ret;
00679
00680
00681
00682 global->server = 1;
00683
00684 if (global->params_set) {
00685 gnutls_certificate_free_credentials(global->xcred);
00686 global->params_set = 0;
00687 }
00688
00689 ret = gnutls_certificate_allocate_credentials(&global->xcred);
00690 if (ret) {
00691 wpa_printf(MSG_DEBUG, "Failed to allocate global credentials "
00692 "%s", gnutls_strerror(ret));
00693 return -1;
00694 }
00695
00696 if (params->ca_cert) {
00697 ret = gnutls_certificate_set_x509_trust_file(
00698 global->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM);
00699 if (ret < 0) {
00700 wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' "
00701 "in PEM format: %s", params->ca_cert,
00702 gnutls_strerror(ret));
00703 ret = gnutls_certificate_set_x509_trust_file(
00704 global->xcred, params->ca_cert,
00705 GNUTLS_X509_FMT_DER);
00706 if (ret < 0) {
00707 wpa_printf(MSG_DEBUG, "Failed to read CA cert "
00708 "'%s' in DER format: %s",
00709 params->ca_cert,
00710 gnutls_strerror(ret));
00711 goto fail;
00712 }
00713 }
00714 }
00715
00716 if (params->client_cert && params->private_key) {
00717
00718 ret = gnutls_certificate_set_x509_key_file(
00719 global->xcred, params->client_cert,
00720 params->private_key, GNUTLS_X509_FMT_PEM);
00721 if (ret < 0) {
00722 wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
00723 "in PEM format: %s", gnutls_strerror(ret));
00724 ret = gnutls_certificate_set_x509_key_file(
00725 global->xcred, params->client_cert,
00726 params->private_key, GNUTLS_X509_FMT_DER);
00727 if (ret < 0) {
00728 wpa_printf(MSG_DEBUG, "Failed to read client "
00729 "cert/key in DER format: %s",
00730 gnutls_strerror(ret));
00731 goto fail;
00732 }
00733 }
00734 } else if (params->private_key) {
00735 int pkcs12_ok = 0;
00736 #ifdef PKCS12_FUNCS
00737
00738 #if LIBGNUTLS_VERSION_NUMBER >= 0x010302
00739 ret = gnutls_certificate_set_x509_simple_pkcs12_file(
00740 global->xcred, params->private_key,
00741 GNUTLS_X509_FMT_DER, params->private_key_passwd);
00742 if (ret != 0) {
00743 wpa_printf(MSG_DEBUG, "Failed to load private_key in "
00744 "PKCS#12 format: %s", gnutls_strerror(ret));
00745 goto fail;
00746 } else
00747 pkcs12_ok = 1;
00748 #endif
00749 #endif
00750
00751 if (!pkcs12_ok) {
00752 wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
00753 "included");
00754 goto fail;
00755 }
00756 }
00757
00758 global->params_set = 1;
00759
00760 return 0;
00761
00762 fail:
00763 gnutls_certificate_free_credentials(global->xcred);
00764 return -1;
00765 }
00766
00767
00768 int tls_global_set_verify(void *ssl_ctx, int check_crl)
00769 {
00770
00771 return 0;
00772 }
00773
00774
00775 int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
00776 int verify_peer)
00777 {
00778 if (conn == NULL || conn->session == NULL)
00779 return -1;
00780
00781 conn->verify_peer = verify_peer;
00782 gnutls_certificate_server_set_request(conn->session,
00783 verify_peer ? GNUTLS_CERT_REQUIRE
00784 : GNUTLS_CERT_REQUEST);
00785
00786 return 0;
00787 }
00788
00789
00790 int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
00791 struct tls_keys *keys)
00792 {
00793 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
00794 security_parameters_st *sec;
00795 #endif
00796
00797 if (conn == NULL || conn->session == NULL || keys == NULL)
00798 return -1;
00799
00800 os_memset(keys, 0, sizeof(*keys));
00801
00802 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
00803 sec = &conn->session->security_parameters;
00804 keys->master_key = sec->master_secret;
00805 keys->master_key_len = TLS_MASTER_SIZE;
00806 keys->client_random = sec->client_random;
00807 keys->server_random = sec->server_random;
00808 #else
00809 keys->client_random = gnutls_session_get_client_random(conn->session);
00810 keys->server_random = gnutls_session_get_server_random(conn->session);
00811
00812 #endif
00813
00814 #ifdef GNUTLS_IA
00815 gnutls_ia_extract_inner_secret(conn->session, conn->inner_secret);
00816 keys->inner_secret = conn->inner_secret;
00817 keys->inner_secret_len = TLS_MASTER_SIZE;
00818 #endif
00819
00820 keys->client_random_len = TLS_RANDOM_SIZE;
00821 keys->server_random_len = TLS_RANDOM_SIZE;
00822
00823 return 0;
00824 }
00825
00826
00827 int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
00828 const char *label, int server_random_first,
00829 u8 *out, size_t out_len)
00830 {
00831 #if LIBGNUTLS_VERSION_NUMBER >= 0x010302
00832 if (conn == NULL || conn->session == NULL)
00833 return -1;
00834
00835 return gnutls_prf(conn->session, os_strlen(label), label,
00836 server_random_first, 0, NULL, out_len, out);
00837 #else
00838 return -1;
00839 #endif
00840 }
00841
00842
00843 static int tls_connection_verify_peer(struct tls_connection *conn)
00844 {
00845 unsigned int status, num_certs, i;
00846 struct os_time now;
00847 const gnutls_datum_t *certs;
00848 gnutls_x509_crt_t cert;
00849
00850 if (gnutls_certificate_verify_peers2(conn->session, &status) < 0) {
00851 wpa_printf(MSG_INFO, "TLS: Failed to verify peer "
00852 "certificate chain");
00853 return -1;
00854 }
00855
00856 if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) {
00857 wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted");
00858 return -1;
00859 }
00860
00861 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
00862 wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a "
00863 "known issuer");
00864 return -1;
00865 }
00866
00867 if (status & GNUTLS_CERT_REVOKED) {
00868 wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked");
00869 return -1;
00870 }
00871
00872 os_get_time(&now);
00873
00874 certs = gnutls_certificate_get_peers(conn->session, &num_certs);
00875 if (certs == NULL) {
00876 wpa_printf(MSG_INFO, "TLS: No peer certificate chain "
00877 "received");
00878 return -1;
00879 }
00880
00881 for (i = 0; i < num_certs; i++) {
00882 char *buf;
00883 size_t len;
00884 if (gnutls_x509_crt_init(&cert) < 0) {
00885 wpa_printf(MSG_INFO, "TLS: Certificate initialization "
00886 "failed");
00887 return -1;
00888 }
00889
00890 if (gnutls_x509_crt_import(cert, &certs[i],
00891 GNUTLS_X509_FMT_DER) < 0) {
00892 wpa_printf(MSG_INFO, "TLS: Could not parse peer "
00893 "certificate %d/%d", i + 1, num_certs);
00894 gnutls_x509_crt_deinit(cert);
00895 return -1;
00896 }
00897
00898 gnutls_x509_crt_get_dn(cert, NULL, &len);
00899 len++;
00900 buf = os_malloc(len + 1);
00901 if (buf) {
00902 buf[0] = buf[len] = '\0';
00903 gnutls_x509_crt_get_dn(cert, buf, &len);
00904 }
00905 wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s",
00906 i + 1, num_certs, buf);
00907
00908 if (i == 0) {
00909
00910 }
00911
00912 os_free(buf);
00913
00914 if (gnutls_x509_crt_get_expiration_time(cert) < now.sec ||
00915 gnutls_x509_crt_get_activation_time(cert) > now.sec) {
00916 wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is "
00917 "not valid at this time",
00918 i + 1, num_certs);
00919 gnutls_x509_crt_deinit(cert);
00920 return -1;
00921 }
00922
00923 gnutls_x509_crt_deinit(cert);
00924 }
00925
00926 return 0;
00927 }
00928
00929
00930 u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
00931 const u8 *in_data, size_t in_len,
00932 size_t *out_len, u8 **appl_data,
00933 size_t *appl_data_len)
00934 {
00935 struct tls_global *global = ssl_ctx;
00936 u8 *out_data;
00937 int ret;
00938
00939 if (appl_data)
00940 *appl_data = NULL;
00941
00942 if (in_data && in_len) {
00943 if (conn->pull_buf) {
00944 wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in "
00945 "pull_buf", __func__, conn->pull_buf_len);
00946 os_free(conn->pull_buf);
00947 }
00948 conn->pull_buf = os_malloc(in_len);
00949 if (conn->pull_buf == NULL)
00950 return NULL;
00951 os_memcpy(conn->pull_buf, in_data, in_len);
00952 conn->pull_buf_offset = conn->pull_buf;
00953 conn->pull_buf_len = in_len;
00954 }
00955
00956 ret = gnutls_handshake(conn->session);
00957 if (ret < 0) {
00958 switch (ret) {
00959 case GNUTLS_E_AGAIN:
00960 if (global->server && conn->established &&
00961 conn->push_buf == NULL) {
00962
00963
00964 conn->push_buf = os_malloc(1);
00965 }
00966 break;
00967 case GNUTLS_E_FATAL_ALERT_RECEIVED:
00968 wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert",
00969 __func__, gnutls_alert_get_name(
00970 gnutls_alert_get(conn->session)));
00971 conn->read_alerts++;
00972
00973 default:
00974 wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed "
00975 "-> %s", __func__, gnutls_strerror(ret));
00976 conn->failed++;
00977 }
00978 } else {
00979 size_t size;
00980
00981 if (conn->verify_peer && tls_connection_verify_peer(conn)) {
00982 wpa_printf(MSG_INFO, "TLS: Peer certificate chain "
00983 "failed validation");
00984 conn->failed++;
00985 return NULL;
00986 }
00987
00988 if (conn->tls_ia && !gnutls_ia_handshake_p(conn->session)) {
00989 wpa_printf(MSG_INFO, "TLS: No TLS/IA negotiation");
00990 conn->failed++;
00991 return NULL;
00992 }
00993
00994 if (conn->tls_ia)
00995 wpa_printf(MSG_DEBUG, "TLS: Start TLS/IA handshake");
00996 else {
00997 wpa_printf(MSG_DEBUG, "TLS: Handshake completed "
00998 "successfully");
00999 }
01000 conn->established = 1;
01001 if (conn->push_buf == NULL) {
01002
01003 conn->push_buf = os_malloc(1);
01004 }
01005
01006 gnutls_session_get_data(conn->session, NULL, &size);
01007 if (global->session_data == NULL ||
01008 global->session_data_size < size) {
01009 os_free(global->session_data);
01010 global->session_data = os_malloc(size);
01011 }
01012 if (global->session_data) {
01013 global->session_data_size = size;
01014 gnutls_session_get_data(conn->session,
01015 global->session_data,
01016 &global->session_data_size);
01017 }
01018 }
01019
01020 out_data = conn->push_buf;
01021 *out_len = conn->push_buf_len;
01022 conn->push_buf = NULL;
01023 conn->push_buf_len = 0;
01024 return out_data;
01025 }
01026
01027
01028 u8 * tls_connection_server_handshake(void *ssl_ctx,
01029 struct tls_connection *conn,
01030 const u8 *in_data, size_t in_len,
01031 size_t *out_len)
01032 {
01033 return tls_connection_handshake(ssl_ctx, conn, in_data, in_len,
01034 out_len);
01035 }
01036
01037
01038 int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
01039 const u8 *in_data, size_t in_len,
01040 u8 *out_data, size_t out_len)
01041 {
01042 ssize_t res;
01043
01044 #ifdef GNUTLS_IA
01045 if (conn->tls_ia)
01046 res = gnutls_ia_send(conn->session, (char *) in_data, in_len);
01047 else
01048 #endif
01049 res = gnutls_record_send(conn->session, in_data, in_len);
01050 if (res < 0) {
01051 wpa_printf(MSG_INFO, "%s: Encryption failed: %s",
01052 __func__, gnutls_strerror(res));
01053 return -1;
01054 }
01055 if (conn->push_buf == NULL)
01056 return -1;
01057 if (conn->push_buf_len < out_len)
01058 out_len = conn->push_buf_len;
01059 os_memcpy(out_data, conn->push_buf, out_len);
01060 os_free(conn->push_buf);
01061 conn->push_buf = NULL;
01062 conn->push_buf_len = 0;
01063 return out_len;
01064 }
01065
01066
01067 int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
01068 const u8 *in_data, size_t in_len,
01069 u8 *out_data, size_t out_len)
01070 {
01071 ssize_t res;
01072
01073 if (conn->pull_buf) {
01074 wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in "
01075 "pull_buf", __func__, conn->pull_buf_len);
01076 os_free(conn->pull_buf);
01077 }
01078 conn->pull_buf = os_malloc(in_len);
01079 if (conn->pull_buf == NULL)
01080 return -1;
01081 os_memcpy(conn->pull_buf, in_data, in_len);
01082 conn->pull_buf_offset = conn->pull_buf;
01083 conn->pull_buf_len = in_len;
01084
01085 #ifdef GNUTLS_IA
01086 if (conn->tls_ia) {
01087 res = gnutls_ia_recv(conn->session, out_data, out_len);
01088 if (out_len >= 12 &&
01089 (res == GNUTLS_E_WARNING_IA_IPHF_RECEIVED ||
01090 res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED)) {
01091 int final = res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED;
01092 wpa_printf(MSG_DEBUG, "%s: Received %sPhaseFinished",
01093 __func__, final ? "Final" : "Intermediate");
01094
01095 res = gnutls_ia_permute_inner_secret(
01096 conn->session, conn->session_keys_len,
01097 conn->session_keys);
01098 if (conn->session_keys) {
01099 os_memset(conn->session_keys, 0,
01100 conn->session_keys_len);
01101 os_free(conn->session_keys);
01102 }
01103 conn->session_keys = NULL;
01104 conn->session_keys_len = 0;
01105 if (res) {
01106 wpa_printf(MSG_DEBUG, "%s: Failed to permute "
01107 "inner secret: %s",
01108 __func__, gnutls_strerror(res));
01109 return -1;
01110 }
01111
01112 res = gnutls_ia_verify_endphase(conn->session,
01113 out_data);
01114 if (res == 0) {
01115 wpa_printf(MSG_DEBUG, "%s: Correct endphase "
01116 "checksum", __func__);
01117 } else {
01118 wpa_printf(MSG_INFO, "%s: Endphase "
01119 "verification failed: %s",
01120 __func__, gnutls_strerror(res));
01121 return -1;
01122 }
01123
01124 if (final)
01125 conn->final_phase_finished = 1;
01126
01127 return 0;
01128 }
01129
01130 if (res < 0) {
01131 wpa_printf(MSG_DEBUG, "%s - gnutls_ia_recv failed: %d "
01132 "(%s)", __func__, res,
01133 gnutls_strerror(res));
01134 }
01135 return res;
01136 }
01137 #endif
01138
01139 res = gnutls_record_recv(conn->session, out_data, out_len);
01140 if (res < 0) {
01141 wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
01142 "(%s)", __func__, res, gnutls_strerror(res));
01143 }
01144
01145 return res;
01146 }
01147
01148
01149 int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
01150 {
01151 if (conn == NULL)
01152 return 0;
01153 return gnutls_session_is_resumed(conn->session);
01154 }
01155
01156
01157 int tls_connection_set_master_key(void *ssl_ctx, struct tls_connection *conn,
01158 const u8 *key, size_t key_len)
01159 {
01160
01161 return -1;
01162 }
01163
01164
01165 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
01166 u8 *ciphers)
01167 {
01168
01169 return -1;
01170 }
01171
01172
01173 int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
01174 char *buf, size_t buflen)
01175 {
01176
01177 buf[0] = '\0';
01178 return 0;
01179 }
01180
01181
01182 int tls_connection_enable_workaround(void *ssl_ctx,
01183 struct tls_connection *conn)
01184 {
01185
01186 return 0;
01187 }
01188
01189
01190 int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
01191 int ext_type, const u8 *data,
01192 size_t data_len)
01193 {
01194
01195 return -1;
01196 }
01197
01198
01199 int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
01200 {
01201 if (conn == NULL)
01202 return -1;
01203 return conn->failed;
01204 }
01205
01206
01207 int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
01208 {
01209 if (conn == NULL)
01210 return -1;
01211 return conn->read_alerts;
01212 }
01213
01214
01215 int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
01216 {
01217 if (conn == NULL)
01218 return -1;
01219 return conn->write_alerts;
01220 }
01221
01222
01223 int tls_connection_get_keyblock_size(void *tls_ctx,
01224 struct tls_connection *conn)
01225 {
01226
01227 return -1;
01228 }
01229
01230
01231 unsigned int tls_capabilities(void *tls_ctx)
01232 {
01233 unsigned int capa = 0;
01234
01235 #ifdef GNUTLS_IA
01236 capa |= TLS_CAPABILITY_IA;
01237 #endif
01238
01239 return capa;
01240 }
01241
01242
01243 int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
01244 int tls_ia)
01245 {
01246 #ifdef GNUTLS_IA
01247 int ret;
01248
01249 if (conn == NULL)
01250 return -1;
01251
01252 conn->tls_ia = tls_ia;
01253 if (!tls_ia)
01254 return 0;
01255
01256 ret = gnutls_ia_allocate_server_credentials(&conn->iacred_srv);
01257 if (ret) {
01258 wpa_printf(MSG_DEBUG, "Failed to allocate IA credentials: %s",
01259 gnutls_strerror(ret));
01260 return -1;
01261 }
01262
01263 ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_IA,
01264 conn->iacred_srv);
01265 if (ret) {
01266 wpa_printf(MSG_DEBUG, "Failed to configure IA credentials: %s",
01267 gnutls_strerror(ret));
01268 gnutls_ia_free_server_credentials(conn->iacred_srv);
01269 conn->iacred_srv = NULL;
01270 return -1;
01271 }
01272
01273 return 0;
01274 #else
01275 return -1;
01276 #endif
01277 }
01278
01279
01280 int tls_connection_ia_send_phase_finished(void *tls_ctx,
01281 struct tls_connection *conn,
01282 int final,
01283 u8 *out_data, size_t out_len)
01284 {
01285 #ifdef GNUTLS_IA
01286 int ret;
01287
01288 if (conn == NULL || conn->session == NULL || !conn->tls_ia)
01289 return -1;
01290
01291 ret = gnutls_ia_permute_inner_secret(conn->session,
01292 conn->session_keys_len,
01293 conn->session_keys);
01294 if (conn->session_keys) {
01295 os_memset(conn->session_keys, 0, conn->session_keys_len);
01296 os_free(conn->session_keys);
01297 }
01298 conn->session_keys = NULL;
01299 conn->session_keys_len = 0;
01300 if (ret) {
01301 wpa_printf(MSG_DEBUG, "%s: Failed to permute inner secret: %s",
01302 __func__, gnutls_strerror(ret));
01303 return -1;
01304 }
01305
01306 ret = gnutls_ia_endphase_send(conn->session, final);
01307 if (ret) {
01308 wpa_printf(MSG_DEBUG, "%s: Failed to send endphase: %s",
01309 __func__, gnutls_strerror(ret));
01310 return -1;
01311 }
01312
01313 if (conn->push_buf == NULL)
01314 return -1;
01315 if (conn->push_buf_len < out_len)
01316 out_len = conn->push_buf_len;
01317 os_memcpy(out_data, conn->push_buf, out_len);
01318 os_free(conn->push_buf);
01319 conn->push_buf = NULL;
01320 conn->push_buf_len = 0;
01321 return out_len;
01322 #else
01323 return -1;
01324 #endif
01325 }
01326
01327
01328 int tls_connection_ia_final_phase_finished(void *tls_ctx,
01329 struct tls_connection *conn)
01330 {
01331 if (conn == NULL)
01332 return -1;
01333
01334 return conn->final_phase_finished;
01335 }
01336
01337
01338 int tls_connection_ia_permute_inner_secret(void *tls_ctx,
01339 struct tls_connection *conn,
01340 const u8 *key, size_t key_len)
01341 {
01342 #ifdef GNUTLS_IA
01343 if (conn == NULL || !conn->tls_ia)
01344 return -1;
01345
01346 if (conn->session_keys) {
01347 os_memset(conn->session_keys, 0, conn->session_keys_len);
01348 os_free(conn->session_keys);
01349 }
01350 conn->session_keys_len = 0;
01351
01352 if (key) {
01353 conn->session_keys = os_malloc(key_len);
01354 if (conn->session_keys == NULL)
01355 return -1;
01356 os_memcpy(conn->session_keys, key, key_len);
01357 conn->session_keys_len = key_len;
01358 } else {
01359 conn->session_keys = NULL;
01360 conn->session_keys_len = 0;
01361 }
01362
01363 return 0;
01364 #else
01365 return -1;
01366 #endif
01367 }
01368