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