merge conflicts.

This commit is contained in:
christos 2014-10-16 19:29:29 +00:00
parent 3c260e6046
commit 3c5783d32c
26 changed files with 1672 additions and 4701 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.5 2014/01/03 02:15:43 christos Exp $
# $NetBSD: Makefile,v 1.6 2014/10/16 19:29:29 christos Exp $
.include "${.CURDIR}/../Makefile.inc"
@ -65,7 +65,6 @@ SRCS+= \
main.c \
config_file.c \
ctrl_iface.c \
dump_state.c \
eap_register.c
# l2_packet

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.3 2014/01/03 02:07:31 christos Exp $
# $NetBSD: Makefile,v 1.4 2014/10/16 19:29:29 christos Exp $
.include "${.CURDIR}/../Makefile.inc"
@ -22,6 +22,7 @@ eap_register.c \
eapol_supp_sm.c \
eloop.c \
events.c \
ieee802_11_common.c \
l2_packet_freebsd.c \
main.c \
md5.c \

View File

@ -1,180 +0,0 @@
/*
* hostapd / State dump
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
#include <time.h>
#include "utils/common.h"
#include "radius/radius_client.h"
#include "radius/radius_server.h"
#include "eapol_auth/eapol_auth_sm.h"
#include "eapol_auth/eapol_auth_sm_i.h"
#include "eap_server/eap.h"
#include "ap/hostapd.h"
#include "ap/ap_config.h"
#include "ap/sta_info.h"
#include "dump_state.h"
static void fprint_char(FILE *f, char c)
{
if (c >= 32 && c < 127)
fprintf(f, "%c", c);
else
fprintf(f, "<%02x>", c);
}
static void ieee802_1x_dump_state(FILE *f, const char *prefix,
struct sta_info *sta)
{
struct eapol_state_machine *sm = sta->eapol_sm;
if (sm == NULL)
return;
fprintf(f, "%sIEEE 802.1X:\n", prefix);
if (sm->identity) {
size_t i;
fprintf(f, "%sidentity=", prefix);
for (i = 0; i < sm->identity_len; i++)
fprint_char(f, sm->identity[i]);
fprintf(f, "\n");
}
fprintf(f, "%slast EAP type: Authentication Server: %d (%s) "
"Supplicant: %d (%s)\n", prefix,
sm->eap_type_authsrv,
eap_server_get_name(0, sm->eap_type_authsrv),
sm->eap_type_supp, eap_server_get_name(0, sm->eap_type_supp));
fprintf(f, "%scached_packets=%s\n", prefix,
sm->last_recv_radius ? "[RX RADIUS]" : "");
eapol_auth_dump_state(f, prefix, sm);
}
/**
* hostapd_dump_state - SIGUSR1 handler to dump hostapd state to a text file
*/
static void hostapd_dump_state(struct hostapd_data *hapd)
{
FILE *f;
time_t now;
struct sta_info *sta;
int i;
#ifndef CONFIG_NO_RADIUS
char *buf;
#endif /* CONFIG_NO_RADIUS */
if (!hapd->conf->dump_log_name) {
wpa_printf(MSG_DEBUG, "Dump file not defined - ignoring dump "
"request");
return;
}
wpa_printf(MSG_DEBUG, "Dumping hostapd state to '%s'",
hapd->conf->dump_log_name);
f = fopen(hapd->conf->dump_log_name, "w");
if (f == NULL) {
wpa_printf(MSG_WARNING, "Could not open dump file '%s' for "
"writing.", hapd->conf->dump_log_name);
return;
}
time(&now);
fprintf(f, "hostapd state dump - %s", ctime(&now));
fprintf(f, "num_sta=%d num_sta_non_erp=%d "
"num_sta_no_short_slot_time=%d\n"
"num_sta_no_short_preamble=%d\n",
hapd->num_sta, hapd->iface->num_sta_non_erp,
hapd->iface->num_sta_no_short_slot_time,
hapd->iface->num_sta_no_short_preamble);
for (sta = hapd->sta_list; sta != NULL; sta = sta->next) {
fprintf(f, "\nSTA=" MACSTR "\n", MAC2STR(sta->addr));
fprintf(f,
" AID=%d flags=0x%x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
"\n"
" capability=0x%x listen_interval=%d\n",
sta->aid,
sta->flags,
(sta->flags & WLAN_STA_AUTH ? "[AUTH]" : ""),
(sta->flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""),
(sta->flags & WLAN_STA_PS ? "[PS]" : ""),
(sta->flags & WLAN_STA_TIM ? "[TIM]" : ""),
(sta->flags & WLAN_STA_PERM ? "[PERM]" : ""),
(ap_sta_is_authorized(sta) ? "[AUTHORIZED]" : ""),
(sta->flags & WLAN_STA_PENDING_POLL ? "[PENDING_POLL" :
""),
(sta->flags & WLAN_STA_SHORT_PREAMBLE ?
"[SHORT_PREAMBLE]" : ""),
(sta->flags & WLAN_STA_PREAUTH ? "[PREAUTH]" : ""),
(sta->flags & WLAN_STA_WMM ? "[WMM]" : ""),
(sta->flags & WLAN_STA_MFP ? "[MFP]" : ""),
(sta->flags & WLAN_STA_WPS ? "[WPS]" : ""),
(sta->flags & WLAN_STA_MAYBE_WPS ? "[MAYBE_WPS]" : ""),
(sta->flags & WLAN_STA_WDS ? "[WDS]" : ""),
(sta->flags & WLAN_STA_NONERP ? "[NonERP]" : ""),
(sta->flags & WLAN_STA_WPS2 ? "[WPS2]" : ""),
sta->capability,
sta->listen_interval);
fprintf(f, " supported_rates=");
for (i = 0; i < sta->supported_rates_len; i++)
fprintf(f, "%02x ", sta->supported_rates[i]);
fprintf(f, "\n");
fprintf(f,
" timeout_next=%s\n",
(sta->timeout_next == STA_NULLFUNC ? "NULLFUNC POLL" :
(sta->timeout_next == STA_DISASSOC ? "DISASSOC" :
"DEAUTH")));
ieee802_1x_dump_state(f, " ", sta);
}
#ifndef CONFIG_NO_RADIUS
buf = os_malloc(4096);
if (buf) {
int count = radius_client_get_mib(hapd->radius, buf, 4096);
if (count < 0)
count = 0;
else if (count > 4095)
count = 4095;
buf[count] = '\0';
fprintf(f, "%s", buf);
#ifdef RADIUS_SERVER
count = radius_server_get_mib(hapd->radius_srv, buf, 4096);
if (count < 0)
count = 0;
else if (count > 4095)
count = 4095;
buf[count] = '\0';
fprintf(f, "%s", buf);
#endif /* RADIUS_SERVER */
os_free(buf);
}
#endif /* CONFIG_NO_RADIUS */
fclose(f);
}
int handle_dump_state_iface(struct hostapd_iface *iface, void *ctx)
{
size_t i;
for (i = 0; i < iface->num_bss; i++)
hostapd_dump_state(iface->bss[i]);
return 0;
}

View File

@ -1,14 +0,0 @@
/*
* hostapd / State dump
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef DUMP_STATE_H
#define DUMP_STATE_H
int handle_dump_state_iface(struct hostapd_iface *iface, void *ctx);
#endif /* DUMP_STATE_H */

View File

@ -1,6 +1,6 @@
/*
* hostapd - command line interface for hostapd daemon
* Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@ -18,7 +18,7 @@
static const char *hostapd_cli_version =
"hostapd_cli v" VERSION_STR "\n"
"Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi> and contributors";
"Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi> and contributors";
static const char *hostapd_cli_license =
@ -79,6 +79,7 @@ static const char *commands_help =
#endif /* CONFIG_WPS_NFC */
" wps_ap_pin <cmd> [params..] enable/disable AP PIN\n"
" wps_config <SSID> <auth> <encr> <key> configure AP\n"
" wps_get_status show current WPS status\n"
#endif /* CONFIG_WPS */
" get_config show current configuration\n"
" help show this usage help\n"
@ -90,7 +91,12 @@ static const char *commands_help =
static struct wpa_ctrl *ctrl_conn;
static int hostapd_cli_quit = 0;
static int hostapd_cli_attached = 0;
static const char *ctrl_iface_dir = "/var/run/hostapd";
#ifndef CONFIG_CTRL_IFACE_DIR
#define CONFIG_CTRL_IFACE_DIR "/var/run/hostapd"
#endif /* CONFIG_CTRL_IFACE_DIR */
static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
static char *ctrl_ifname = NULL;
static const char *pid_file = NULL;
static const char *action_file = NULL;
@ -210,8 +216,21 @@ static int hostapd_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
}
static int hostapd_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
return wpa_ctrl_command(ctrl, "STATUS");
}
static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
if (argc > 0) {
char buf[100];
os_snprintf(buf, sizeof(buf), "MIB %s", argv[0]);
return wpa_ctrl_command(ctrl, buf);
}
return wpa_ctrl_command(ctrl, "MIB");
}
@ -219,28 +238,19 @@ static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
static int hostapd_cli_exec(const char *program, const char *arg1,
const char *arg2)
{
char *cmd;
char *arg;
size_t len;
int res;
int ret = 0;
len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
cmd = os_malloc(len);
if (cmd == NULL)
len = os_strlen(arg1) + os_strlen(arg2) + 2;
arg = os_malloc(len);
if (arg == NULL)
return -1;
res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
if (res < 0 || (size_t) res >= len) {
os_free(cmd);
return -1;
}
cmd[len - 1] = '\0';
#ifndef _WIN32_WCE
if (system(cmd) < 0)
ret = -1;
#endif /* _WIN32_WCE */
os_free(cmd);
os_snprintf(arg, len, "%s %s", arg1, arg2);
res = os_exec(program, arg, 1);
os_free(arg);
return ret;
return res;
}
@ -264,12 +274,15 @@ static void hostapd_cli_action_process(char *msg, size_t len)
static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
char buf[64];
if (argc != 1) {
printf("Invalid 'sta' command - exactly one argument, STA "
if (argc < 1) {
printf("Invalid 'sta' command - at least one argument, STA "
"address, is required.\n");
return -1;
}
snprintf(buf, sizeof(buf), "STA %s", argv[0]);
if (argc > 1)
snprintf(buf, sizeof(buf), "STA %s %s", argv[0], argv[1]);
else
snprintf(buf, sizeof(buf), "STA %s", argv[0]);
return wpa_ctrl_command(ctrl, buf);
}
@ -470,6 +483,29 @@ static int hostapd_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl,
}
return wpa_ctrl_command(ctrl, cmd);
}
static int hostapd_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl,
int argc, char *argv[])
{
char cmd[64];
int res;
if (argc != 2) {
printf("Invalid 'nfc_get_handover_sel' command - two arguments "
"are required.\n");
return -1;
}
res = os_snprintf(cmd, sizeof(cmd), "NFC_GET_HANDOVER_SEL %s %s",
argv[0], argv[1]);
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
printf("Too long NFC_GET_HANDOVER_SEL command.\n");
return -1;
}
return wpa_ctrl_command(ctrl, cmd);
}
#endif /* CONFIG_WPS_NFC */
@ -494,6 +530,13 @@ static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
}
static int hostapd_cli_cmd_wps_get_status(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
return wpa_ctrl_command(ctrl, "WPS_GET_STATUS");
}
static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
@ -565,14 +608,14 @@ static int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc,
char buf[300];
int res;
if (argc < 2) {
printf("Invalid 'ess_disassoc' command - two arguments (STA "
"addr and URL) are needed\n");
if (argc < 3) {
printf("Invalid 'ess_disassoc' command - three arguments (STA "
"addr, disassoc timer, and URL) are needed\n");
return -1;
}
res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s",
argv[0], argv[1]);
res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s %s",
argv[0], argv[1], argv[2]);
if (res < 0 || res >= (int) sizeof(buf))
return -1;
return wpa_ctrl_command(ctrl, buf);
@ -652,6 +695,90 @@ static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
}
static int hostapd_cli_cmd_set_qos_map_set(struct wpa_ctrl *ctrl,
int argc, char *argv[])
{
char buf[200];
int res;
if (argc != 1) {
printf("Invalid 'set_qos_map_set' command - "
"one argument (comma delimited QoS map set) "
"is needed\n");
return -1;
}
res = os_snprintf(buf, sizeof(buf), "SET_QOS_MAP_SET %s", argv[0]);
if (res < 0 || res >= (int) sizeof(buf))
return -1;
return wpa_ctrl_command(ctrl, buf);
}
static int hostapd_cli_cmd_send_qos_map_conf(struct wpa_ctrl *ctrl,
int argc, char *argv[])
{
char buf[50];
int res;
if (argc != 1) {
printf("Invalid 'send_qos_map_conf' command - "
"one argument (STA addr) is needed\n");
return -1;
}
res = os_snprintf(buf, sizeof(buf), "SEND_QOS_MAP_CONF %s", argv[0]);
if (res < 0 || res >= (int) sizeof(buf))
return -1;
return wpa_ctrl_command(ctrl, buf);
}
static int hostapd_cli_cmd_hs20_wnm_notif(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
char buf[300];
int res;
if (argc < 2) {
printf("Invalid 'hs20_wnm_notif' command - two arguments (STA "
"addr and URL) are needed\n");
return -1;
}
res = os_snprintf(buf, sizeof(buf), "HS20_WNM_NOTIF %s %s",
argv[0], argv[1]);
if (res < 0 || res >= (int) sizeof(buf))
return -1;
return wpa_ctrl_command(ctrl, buf);
}
static int hostapd_cli_cmd_hs20_deauth_req(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
char buf[300];
int res;
if (argc < 3) {
printf("Invalid 'hs20_deauth_req' command - at least three arguments (STA addr, Code, Re-auth Delay) are needed\n");
return -1;
}
if (argc > 3)
res = os_snprintf(buf, sizeof(buf),
"HS20_DEAUTH_REQ %s %s %s %s",
argv[0], argv[1], argv[2], argv[3]);
else
res = os_snprintf(buf, sizeof(buf),
"HS20_DEAUTH_REQ %s %s %s",
argv[0], argv[1], argv[2]);
if (res < 0 || res >= (int) sizeof(buf))
return -1;
return wpa_ctrl_command(ctrl, buf);
}
static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
hostapd_cli_quit = 1;
@ -706,8 +833,10 @@ static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
}
hostapd_cli_close_connection();
free(ctrl_ifname);
ctrl_ifname = strdup(argv[0]);
os_free(ctrl_ifname);
ctrl_ifname = os_strdup(argv[0]);
if (ctrl_ifname == NULL)
return -1;
if (hostapd_cli_open_connection(ctrl_ifname)) {
printf("Connected to interface '%s.\n", ctrl_ifname);
@ -765,6 +894,66 @@ static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
}
static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
int argc, char *argv[])
{
char cmd[256];
int res;
int i;
char *tmp;
int total;
if (argc < 2) {
printf("Invalid chan_switch command: needs at least two "
"arguments (count and freq)\n"
"usage: <cs_count> <freq> [sec_channel_offset=] "
"[center_freq1=] [center_freq2=] [bandwidth=] "
"[blocktx] [ht|vht]\n");
return -1;
}
res = os_snprintf(cmd, sizeof(cmd), "CHAN_SWITCH %s %s",
argv[0], argv[1]);
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
printf("Too long CHAN_SWITCH command.\n");
return -1;
}
total = res;
for (i = 2; i < argc; i++) {
tmp = cmd + total;
res = os_snprintf(tmp, sizeof(cmd) - total, " %s", argv[i]);
if (res < 0 || (size_t) res >= sizeof(cmd) - total - 1) {
printf("Too long CHAN_SWITCH command.\n");
return -1;
}
total += res;
}
return wpa_ctrl_command(ctrl, cmd);
}
static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
char cmd[256];
int res;
if (argc < 2 || argc > 3) {
printf("Invalid vendor command\n"
"usage: <vendor id> <command id> [<hex formatted command argument>]\n");
return -1;
}
res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s", argv[0], argv[1],
argc == 3 ? argv[2] : "");
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
printf("Too long VENDOR command.\n");
return -1;
}
return wpa_ctrl_command(ctrl, cmd);
}
struct hostapd_cli_cmd {
const char *cmd;
int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
@ -774,6 +963,7 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = {
{ "ping", hostapd_cli_cmd_ping },
{ "mib", hostapd_cli_cmd_mib },
{ "relog", hostapd_cli_cmd_relog },
{ "status", hostapd_cli_cmd_status },
{ "sta", hostapd_cli_cmd_sta },
{ "all_sta", hostapd_cli_cmd_all_sta },
{ "new_sta", hostapd_cli_cmd_new_sta },
@ -791,9 +981,11 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = {
{ "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read },
{ "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token },
{ "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token },
{ "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel },
#endif /* CONFIG_WPS_NFC */
{ "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin },
{ "wps_config", hostapd_cli_cmd_wps_config },
{ "wps_get_status", hostapd_cli_cmd_wps_get_status },
#endif /* CONFIG_WPS */
{ "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent },
{ "ess_disassoc", hostapd_cli_cmd_ess_disassoc },
@ -805,6 +997,12 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = {
{ "quit", hostapd_cli_cmd_quit },
{ "set", hostapd_cli_cmd_set },
{ "get", hostapd_cli_cmd_get },
{ "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set },
{ "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf },
{ "chan_switch", hostapd_cli_cmd_chan_switch },
{ "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif },
{ "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req },
{ "vendor", hostapd_cli_cmd_vendor },
{ NULL, NULL }
};

View File

@ -1,429 +0,0 @@
This patch is adding support for TLS hello extensions and externally
generated pre-shared key material to OpenSSL 0.9.8. This is
based on the patch from Alexey Kobozev <akobozev@cisco.com>
(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300).
diff -uprN openssl-0.9.8.orig/include/openssl/ssl.h openssl-0.9.8/include/openssl/ssl.h
--- openssl-0.9.8.orig/include/openssl/ssl.h 2005-06-10 12:51:16.000000000 -0700
+++ openssl-0.9.8/include/openssl/ssl.h 2005-07-19 20:02:15.000000000 -0700
@@ -340,6 +340,7 @@ extern "C" {
* 'struct ssl_st *' function parameters used to prototype callbacks
* in SSL_CTX. */
typedef struct ssl_st *ssl_crock_st;
+typedef struct tls_extension_st TLS_EXTENSION;
/* used to hold info on the particular ciphers used */
typedef struct ssl_cipher_st
@@ -361,6 +362,8 @@ DECLARE_STACK_OF(SSL_CIPHER)
typedef struct ssl_st SSL;
typedef struct ssl_ctx_st SSL_CTX;
+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
+
/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
typedef struct ssl_method_st
{
@@ -968,6 +971,15 @@ struct ssl_st
int first_packet;
int client_version; /* what was passed, used for
* SSLv3/TLS rollback check */
+
+ /* TLS externsions */
+ TLS_EXTENSION *tls_extension;
+ int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg);
+ void *tls_extension_cb_arg;
+
+ /* TLS pre-shared secret session resumption */
+ tls_session_secret_cb_fn tls_session_secret_cb;
+ void *tls_session_secret_cb_arg;
};
#ifdef __cplusplus
@@ -1533,6 +1545,13 @@ void *SSL_COMP_get_compression_methods(v
int SSL_COMP_add_compression_method(int id,void *cm);
#endif
+/* TLS extensions functions */
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len);
+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg);
+
+/* Pre-shared secret session resumption functions */
+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
+
/* BEGIN ERROR CODES */
/* The following lines are auto generated by the script mkerr.pl. Any changes
* made after this point may be overwritten when the script is next run.
@@ -1714,6 +1733,7 @@ void ERR_load_SSL_strings(void);
#define SSL_F_TLS1_ENC 210
#define SSL_F_TLS1_SETUP_KEY_BLOCK 211
#define SSL_F_WRITE_PENDING 212
+#define SSL_F_SSL_SET_HELLO_EXTENSION 213
/* Reason codes. */
#define SSL_R_APP_DATA_IN_HANDSHAKE 100
diff -uprN openssl-0.9.8.orig/include/openssl/tls1.h openssl-0.9.8/include/openssl/tls1.h
--- openssl-0.9.8.orig/include/openssl/tls1.h 2003-07-22 05:34:21.000000000 -0700
+++ openssl-0.9.8/include/openssl/tls1.h 2005-07-19 20:02:15.000000000 -0700
@@ -282,6 +282,14 @@ extern "C" {
#define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/
#endif
+/* TLS extension struct */
+struct tls_extension_st
+{
+ unsigned short type;
+ unsigned short length;
+ void *data;
+};
+
#ifdef __cplusplus
}
#endif
diff -uprN openssl-0.9.8.orig/ssl/Makefile openssl-0.9.8/ssl/Makefile
--- openssl-0.9.8.orig/ssl/Makefile 2005-05-30 16:20:30.000000000 -0700
+++ openssl-0.9.8/ssl/Makefile 2005-07-19 20:02:15.000000000 -0700
@@ -24,7 +24,7 @@ LIBSRC= \
s2_meth.c s2_srvr.c s2_clnt.c s2_lib.c s2_enc.c s2_pkt.c \
s3_meth.c s3_srvr.c s3_clnt.c s3_lib.c s3_enc.c s3_pkt.c s3_both.c \
s23_meth.c s23_srvr.c s23_clnt.c s23_lib.c s23_pkt.c \
- t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c \
+ t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c t1_ext.c \
d1_meth.c d1_srvr.c d1_clnt.c d1_lib.c d1_pkt.c \
d1_both.c d1_enc.c \
ssl_lib.c ssl_err2.c ssl_cert.c ssl_sess.c \
@@ -35,7 +35,7 @@ LIBOBJ= \
s2_meth.o s2_srvr.o s2_clnt.o s2_lib.o s2_enc.o s2_pkt.o \
s3_meth.o s3_srvr.o s3_clnt.o s3_lib.o s3_enc.o s3_pkt.o s3_both.o \
s23_meth.o s23_srvr.o s23_clnt.o s23_lib.o s23_pkt.o \
- t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o \
+ t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o t1_ext.o \
d1_meth.o d1_srvr.o d1_clnt.o d1_lib.o d1_pkt.o \
d1_both.o d1_enc.o \
ssl_lib.o ssl_err2.o ssl_cert.o ssl_sess.o \
@@ -968,3 +968,4 @@ t1_srvr.o: ../include/openssl/ssl23.h ..
t1_srvr.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
t1_srvr.o: ../include/openssl/tls1.h ../include/openssl/x509.h
t1_srvr.o: ../include/openssl/x509_vfy.h ssl_locl.h t1_srvr.c
+t1_ext.o: t1_ext.c ssl_locl.h
diff -uprN openssl-0.9.8.orig/ssl/s3_clnt.c openssl-0.9.8/ssl/s3_clnt.c
--- openssl-0.9.8.orig/ssl/s3_clnt.c 2005-05-16 03:11:03.000000000 -0700
+++ openssl-0.9.8/ssl/s3_clnt.c 2005-07-19 20:02:15.000000000 -0700
@@ -606,6 +606,20 @@ int ssl3_client_hello(SSL *s)
}
*(p++)=0; /* Add the NULL method */
+ /* send client hello extensions if any */
+ if (s->version >= TLS1_VERSION && s->tls_extension)
+ {
+ // set the total extensions length
+ s2n(s->tls_extension->length + 4, p);
+
+ // put the extensions with type and length
+ s2n(s->tls_extension->type, p);
+ s2n(s->tls_extension->length, p);
+
+ memcpy(p, s->tls_extension->data, s->tls_extension->length);
+ p+=s->tls_extension->length;
+ }
+
l=(p-d);
d=buf;
*(d++)=SSL3_MT_CLIENT_HELLO;
@@ -628,7 +642,7 @@ int ssl3_get_server_hello(SSL *s)
STACK_OF(SSL_CIPHER) *sk;
SSL_CIPHER *c;
unsigned char *p,*d;
- int i,al,ok;
+ int i,al,ok,pre_shared;
unsigned int j;
long n;
SSL_COMP *comp;
@@ -693,7 +707,24 @@ int ssl3_get_server_hello(SSL *s)
goto f_err;
}
- if (j != 0 && j == s->session->session_id_length
+ /* check if we want to resume the session based on external pre-shared secret */
+ pre_shared = 0;
+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
+ {
+ SSL_CIPHER *pref_cipher=NULL;
+ s->session->master_key_length=sizeof(s->session->master_key);
+ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
+ NULL, &pref_cipher, s->tls_session_secret_cb_arg))
+ {
+ s->hit=1;
+ s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j);
+ s->session->session_id_length = j;
+ memcpy(s->session->session_id, p, j);
+ pre_shared = 1;
+ }
+ }
+
+ if ((pre_shared || j != 0) && j == s->session->session_id_length
&& memcmp(p,s->session->session_id,j) == 0)
{
if(s->sid_ctx_length != s->session->sid_ctx_length
diff -uprN openssl-0.9.8.orig/ssl/s3_srvr.c openssl-0.9.8/ssl/s3_srvr.c
--- openssl-0.9.8.orig/ssl/s3_srvr.c 2005-05-22 17:32:55.000000000 -0700
+++ openssl-0.9.8/ssl/s3_srvr.c 2005-07-19 20:02:15.000000000 -0700
@@ -955,6 +955,75 @@ int ssl3_get_client_hello(SSL *s)
}
#endif
+ /* Check for TLS client hello extension here */
+ if (p < (d+n) && s->version >= TLS1_VERSION)
+ {
+ if (s->tls_extension_cb)
+ {
+ TLS_EXTENSION tls_ext;
+ unsigned short ext_total_len;
+
+ n2s(p, ext_total_len);
+ n2s(p, tls_ext.type);
+ n2s(p, tls_ext.length);
+
+ // sanity check in TLS extension len
+ if (tls_ext.length > (d+n) - p)
+ {
+ // just cut the lenth to packet border
+ tls_ext.length = (d+n) - p;
+ }
+
+ tls_ext.data = p;
+
+ // returns an alert code or 0
+ al = s->tls_extension_cb(s, &tls_ext, s->tls_extension_cb_arg);
+ if (al != 0)
+ {
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PEER_ERROR);
+ goto f_err;
+ }
+ }
+ }
+
+ /* Check if we want to use external pre-shared secret for this handshake */
+ /* for not reused session only */
+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb)
+ {
+ SSL_CIPHER *pref_cipher=NULL;
+
+ s->session->master_key_length=sizeof(s->session->master_key);
+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg))
+ {
+ s->hit=1;
+ s->session->ciphers=ciphers;
+ s->session->verify_result=X509_V_OK;
+
+ ciphers=NULL;
+
+ /* check if some cipher was preferred by call back */
+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
+ if (pref_cipher == NULL)
+ {
+ al=SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
+ goto f_err;
+ }
+
+ s->session->cipher=pref_cipher;
+
+ if (s->cipher_list)
+ sk_SSL_CIPHER_free(s->cipher_list);
+
+ if (s->cipher_list_by_id)
+ sk_SSL_CIPHER_free(s->cipher_list_by_id);
+
+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
+ }
+ }
+
/* Given s->session->ciphers and SSL_get_ciphers, we must
* pick a cipher */
diff -uprN openssl-0.9.8.orig/ssl/ssl_err.c openssl-0.9.8/ssl/ssl_err.c
--- openssl-0.9.8.orig/ssl/ssl_err.c 2005-06-10 12:51:16.000000000 -0700
+++ openssl-0.9.8/ssl/ssl_err.c 2005-07-19 20:02:15.000000000 -0700
@@ -242,6 +242,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
{ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"},
{ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"},
{ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"},
+{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"},
{0,NULL}
};
diff -uprN openssl-0.9.8.orig/ssl/ssl.h openssl-0.9.8/ssl/ssl.h
--- openssl-0.9.8.orig/ssl/ssl.h 2005-06-10 12:51:16.000000000 -0700
+++ openssl-0.9.8/ssl/ssl.h 2005-07-19 20:02:15.000000000 -0700
@@ -340,6 +340,7 @@ extern "C" {
* 'struct ssl_st *' function parameters used to prototype callbacks
* in SSL_CTX. */
typedef struct ssl_st *ssl_crock_st;
+typedef struct tls_extension_st TLS_EXTENSION;
/* used to hold info on the particular ciphers used */
typedef struct ssl_cipher_st
@@ -361,6 +362,8 @@ DECLARE_STACK_OF(SSL_CIPHER)
typedef struct ssl_st SSL;
typedef struct ssl_ctx_st SSL_CTX;
+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
+
/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
typedef struct ssl_method_st
{
@@ -968,6 +971,15 @@ struct ssl_st
int first_packet;
int client_version; /* what was passed, used for
* SSLv3/TLS rollback check */
+
+ /* TLS externsions */
+ TLS_EXTENSION *tls_extension;
+ int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg);
+ void *tls_extension_cb_arg;
+
+ /* TLS pre-shared secret session resumption */
+ tls_session_secret_cb_fn tls_session_secret_cb;
+ void *tls_session_secret_cb_arg;
};
#ifdef __cplusplus
@@ -1533,6 +1545,13 @@ void *SSL_COMP_get_compression_methods(v
int SSL_COMP_add_compression_method(int id,void *cm);
#endif
+/* TLS extensions functions */
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len);
+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg);
+
+/* Pre-shared secret session resumption functions */
+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
+
/* BEGIN ERROR CODES */
/* The following lines are auto generated by the script mkerr.pl. Any changes
* made after this point may be overwritten when the script is next run.
@@ -1714,6 +1733,7 @@ void ERR_load_SSL_strings(void);
#define SSL_F_TLS1_ENC 210
#define SSL_F_TLS1_SETUP_KEY_BLOCK 211
#define SSL_F_WRITE_PENDING 212
+#define SSL_F_SSL_SET_HELLO_EXTENSION 213
/* Reason codes. */
#define SSL_R_APP_DATA_IN_HANDSHAKE 100
diff -uprN openssl-0.9.8.orig/ssl/ssl_sess.c openssl-0.9.8/ssl/ssl_sess.c
--- openssl-0.9.8.orig/ssl/ssl_sess.c 2005-04-29 13:10:06.000000000 -0700
+++ openssl-0.9.8/ssl/ssl_sess.c 2005-07-19 20:02:15.000000000 -0700
@@ -656,6 +656,15 @@ long SSL_CTX_get_timeout(const SSL_CTX *
return(s->session_timeout);
}
+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len,
+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg)
+{
+ if (s == NULL) return(0);
+ s->tls_session_secret_cb = tls_session_secret_cb;
+ s->tls_session_secret_cb_arg = arg;
+ return(1);
+}
+
typedef struct timeout_param_st
{
SSL_CTX *ctx;
diff -uprN openssl-0.9.8.orig/ssl/t1_ext.c openssl-0.9.8/ssl/t1_ext.c
--- openssl-0.9.8.orig/ssl/t1_ext.c 1969-12-31 16:00:00.000000000 -0800
+++ openssl-0.9.8/ssl/t1_ext.c 2005-07-19 20:03:29.000000000 -0700
@@ -0,0 +1,48 @@
+
+#include <stdio.h>
+#include "ssl_locl.h"
+
+
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len)
+{
+ if(s->version >= TLS1_VERSION)
+ {
+ if(s->tls_extension)
+ {
+ OPENSSL_free(s->tls_extension);
+ s->tls_extension = NULL;
+ }
+
+ if(ext_data)
+ {
+ s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len);
+ if(!s->tls_extension)
+ {
+ SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ s->tls_extension->type = ext_type;
+ s->tls_extension->length = ext_len;
+ s->tls_extension->data = s->tls_extension + 1;
+ memcpy(s->tls_extension->data, ext_data, ext_len);
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg)
+{
+ if(s->version >= TLS1_VERSION)
+ {
+ s->tls_extension_cb = cb;
+ s->tls_extension_cb_arg = arg;
+
+ return 1;
+ }
+
+ return 0;
+}
diff -uprN openssl-0.9.8.orig/ssl/t1_lib.c openssl-0.9.8/ssl/t1_lib.c
--- openssl-0.9.8.orig/ssl/t1_lib.c 2005-04-26 09:02:40.000000000 -0700
+++ openssl-0.9.8/ssl/t1_lib.c 2005-07-19 20:02:15.000000000 -0700
@@ -131,6 +131,10 @@ int tls1_new(SSL *s)
void tls1_free(SSL *s)
{
+ if(s->tls_extension)
+ {
+ OPENSSL_free(s->tls_extension);
+ }
ssl3_free(s);
}
diff -uprN openssl-0.9.8.orig/ssl/tls1.h openssl-0.9.8/ssl/tls1.h
--- openssl-0.9.8.orig/ssl/tls1.h 2003-07-22 05:34:21.000000000 -0700
+++ openssl-0.9.8/ssl/tls1.h 2005-07-19 20:02:15.000000000 -0700
@@ -282,6 +282,14 @@ extern "C" {
#define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/
#endif
+/* TLS extension struct */
+struct tls_extension_st
+{
+ unsigned short type;
+ unsigned short length;
+ void *data;
+};
+
#ifdef __cplusplus
}
#endif
diff -uprN openssl-0.9.8.orig/util/ssleay.num openssl-0.9.8/util/ssleay.num
--- openssl-0.9.8.orig/util/ssleay.num 2005-05-08 17:22:02.000000000 -0700
+++ openssl-0.9.8/util/ssleay.num 2005-07-19 20:02:15.000000000 -0700
@@ -226,3 +226,6 @@ DTLSv1_server_method
SSL_COMP_get_compression_methods 276 EXIST:!VMS:FUNCTION:COMP
SSL_COMP_get_compress_methods 276 EXIST:VMS:FUNCTION:COMP
SSL_SESSION_get_id 277 EXIST::FUNCTION:
+SSL_set_hello_extension 278 EXIST::FUNCTION:
+SSL_set_hello_extension_cb 279 EXIST::FUNCTION:
+SSL_set_session_secret_cb 280 EXIST::FUNCTION:

View File

@ -1,429 +0,0 @@
This patch is adding support for TLS hello extensions and externally
generated pre-shared key material to OpenSSL 0.9.8d. This is
based on the patch from Alexey Kobozev <akobozev@cisco.com>
(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300).
diff -uprN openssl-0.9.8d.orig/include/openssl/ssl.h openssl-0.9.8d/include/openssl/ssl.h
--- openssl-0.9.8d.orig/include/openssl/ssl.h 2006-06-14 06:52:49.000000000 -0700
+++ openssl-0.9.8d/include/openssl/ssl.h 2006-12-10 08:20:02.000000000 -0800
@@ -345,6 +345,7 @@ extern "C" {
* 'struct ssl_st *' function parameters used to prototype callbacks
* in SSL_CTX. */
typedef struct ssl_st *ssl_crock_st;
+typedef struct tls_extension_st TLS_EXTENSION;
/* used to hold info on the particular ciphers used */
typedef struct ssl_cipher_st
@@ -366,6 +367,8 @@ DECLARE_STACK_OF(SSL_CIPHER)
typedef struct ssl_st SSL;
typedef struct ssl_ctx_st SSL_CTX;
+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
+
/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
typedef struct ssl_method_st
{
@@ -973,6 +976,15 @@ struct ssl_st
int first_packet;
int client_version; /* what was passed, used for
* SSLv3/TLS rollback check */
+
+ /* TLS externsions */
+ TLS_EXTENSION *tls_extension;
+ int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg);
+ void *tls_extension_cb_arg;
+
+ /* TLS pre-shared secret session resumption */
+ tls_session_secret_cb_fn tls_session_secret_cb;
+ void *tls_session_secret_cb_arg;
};
#ifdef __cplusplus
@@ -1538,6 +1550,13 @@ void *SSL_COMP_get_compression_methods(v
int SSL_COMP_add_compression_method(int id,void *cm);
#endif
+/* TLS extensions functions */
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len);
+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg);
+
+/* Pre-shared secret session resumption functions */
+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
+
/* BEGIN ERROR CODES */
/* The following lines are auto generated by the script mkerr.pl. Any changes
* made after this point may be overwritten when the script is next run.
@@ -1719,6 +1738,7 @@ void ERR_load_SSL_strings(void);
#define SSL_F_TLS1_ENC 210
#define SSL_F_TLS1_SETUP_KEY_BLOCK 211
#define SSL_F_WRITE_PENDING 212
+#define SSL_F_SSL_SET_HELLO_EXTENSION 213
/* Reason codes. */
#define SSL_R_APP_DATA_IN_HANDSHAKE 100
diff -uprN openssl-0.9.8d.orig/include/openssl/tls1.h openssl-0.9.8d/include/openssl/tls1.h
--- openssl-0.9.8d.orig/include/openssl/tls1.h 2006-06-14 10:52:01.000000000 -0700
+++ openssl-0.9.8d/include/openssl/tls1.h 2006-12-10 08:20:02.000000000 -0800
@@ -296,6 +296,14 @@ extern "C" {
#define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/
#endif
+/* TLS extension struct */
+struct tls_extension_st
+{
+ unsigned short type;
+ unsigned short length;
+ void *data;
+};
+
#ifdef __cplusplus
}
#endif
diff -uprN openssl-0.9.8d.orig/ssl/Makefile openssl-0.9.8d/ssl/Makefile
--- openssl-0.9.8d.orig/ssl/Makefile 2006-02-03 17:49:35.000000000 -0800
+++ openssl-0.9.8d/ssl/Makefile 2006-12-10 08:20:02.000000000 -0800
@@ -24,7 +24,7 @@ LIBSRC= \
s2_meth.c s2_srvr.c s2_clnt.c s2_lib.c s2_enc.c s2_pkt.c \
s3_meth.c s3_srvr.c s3_clnt.c s3_lib.c s3_enc.c s3_pkt.c s3_both.c \
s23_meth.c s23_srvr.c s23_clnt.c s23_lib.c s23_pkt.c \
- t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c \
+ t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c t1_ext.c \
d1_meth.c d1_srvr.c d1_clnt.c d1_lib.c d1_pkt.c \
d1_both.c d1_enc.c \
ssl_lib.c ssl_err2.c ssl_cert.c ssl_sess.c \
@@ -35,7 +35,7 @@ LIBOBJ= \
s2_meth.o s2_srvr.o s2_clnt.o s2_lib.o s2_enc.o s2_pkt.o \
s3_meth.o s3_srvr.o s3_clnt.o s3_lib.o s3_enc.o s3_pkt.o s3_both.o \
s23_meth.o s23_srvr.o s23_clnt.o s23_lib.o s23_pkt.o \
- t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o \
+ t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o t1_ext.o \
d1_meth.o d1_srvr.o d1_clnt.o d1_lib.o d1_pkt.o \
d1_both.o d1_enc.o \
ssl_lib.o ssl_err2.o ssl_cert.o ssl_sess.o \
@@ -968,3 +968,4 @@ t1_srvr.o: ../include/openssl/ssl23.h ..
t1_srvr.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
t1_srvr.o: ../include/openssl/tls1.h ../include/openssl/x509.h
t1_srvr.o: ../include/openssl/x509_vfy.h ssl_locl.h t1_srvr.c
+t1_ext.o: t1_ext.c ssl_locl.h
diff -uprN openssl-0.9.8d.orig/ssl/s3_clnt.c openssl-0.9.8d/ssl/s3_clnt.c
--- openssl-0.9.8d.orig/ssl/s3_clnt.c 2005-12-12 23:41:46.000000000 -0800
+++ openssl-0.9.8d/ssl/s3_clnt.c 2006-12-10 08:20:02.000000000 -0800
@@ -601,6 +601,20 @@ int ssl3_client_hello(SSL *s)
#endif
*(p++)=0; /* Add the NULL method */
+ /* send client hello extensions if any */
+ if (s->version >= TLS1_VERSION && s->tls_extension)
+ {
+ // set the total extensions length
+ s2n(s->tls_extension->length + 4, p);
+
+ // put the extensions with type and length
+ s2n(s->tls_extension->type, p);
+ s2n(s->tls_extension->length, p);
+
+ memcpy(p, s->tls_extension->data, s->tls_extension->length);
+ p+=s->tls_extension->length;
+ }
+
l=(p-d);
d=buf;
*(d++)=SSL3_MT_CLIENT_HELLO;
@@ -623,7 +637,7 @@ int ssl3_get_server_hello(SSL *s)
STACK_OF(SSL_CIPHER) *sk;
SSL_CIPHER *c;
unsigned char *p,*d;
- int i,al,ok;
+ int i,al,ok,pre_shared;
unsigned int j;
long n;
#ifndef OPENSSL_NO_COMP
@@ -690,7 +704,24 @@ int ssl3_get_server_hello(SSL *s)
goto f_err;
}
- if (j != 0 && j == s->session->session_id_length
+ /* check if we want to resume the session based on external pre-shared secret */
+ pre_shared = 0;
+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
+ {
+ SSL_CIPHER *pref_cipher=NULL;
+ s->session->master_key_length=sizeof(s->session->master_key);
+ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
+ NULL, &pref_cipher, s->tls_session_secret_cb_arg))
+ {
+ s->hit=1;
+ s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j);
+ s->session->session_id_length = j;
+ memcpy(s->session->session_id, p, j);
+ pre_shared = 1;
+ }
+ }
+
+ if ((pre_shared || j != 0) && j == s->session->session_id_length
&& memcmp(p,s->session->session_id,j) == 0)
{
if(s->sid_ctx_length != s->session->sid_ctx_length
diff -uprN openssl-0.9.8d.orig/ssl/s3_srvr.c openssl-0.9.8d/ssl/s3_srvr.c
--- openssl-0.9.8d.orig/ssl/s3_srvr.c 2006-09-28 04:29:03.000000000 -0700
+++ openssl-0.9.8d/ssl/s3_srvr.c 2006-12-10 08:20:02.000000000 -0800
@@ -943,6 +943,75 @@ int ssl3_get_client_hello(SSL *s)
}
#endif
+ /* Check for TLS client hello extension here */
+ if (p < (d+n) && s->version >= TLS1_VERSION)
+ {
+ if (s->tls_extension_cb)
+ {
+ TLS_EXTENSION tls_ext;
+ unsigned short ext_total_len;
+
+ n2s(p, ext_total_len);
+ n2s(p, tls_ext.type);
+ n2s(p, tls_ext.length);
+
+ // sanity check in TLS extension len
+ if (tls_ext.length > (d+n) - p)
+ {
+ // just cut the lenth to packet border
+ tls_ext.length = (d+n) - p;
+ }
+
+ tls_ext.data = p;
+
+ // returns an alert code or 0
+ al = s->tls_extension_cb(s, &tls_ext, s->tls_extension_cb_arg);
+ if (al != 0)
+ {
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PEER_ERROR);
+ goto f_err;
+ }
+ }
+ }
+
+ /* Check if we want to use external pre-shared secret for this handshake */
+ /* for not reused session only */
+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb)
+ {
+ SSL_CIPHER *pref_cipher=NULL;
+
+ s->session->master_key_length=sizeof(s->session->master_key);
+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg))
+ {
+ s->hit=1;
+ s->session->ciphers=ciphers;
+ s->session->verify_result=X509_V_OK;
+
+ ciphers=NULL;
+
+ /* check if some cipher was preferred by call back */
+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
+ if (pref_cipher == NULL)
+ {
+ al=SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
+ goto f_err;
+ }
+
+ s->session->cipher=pref_cipher;
+
+ if (s->cipher_list)
+ sk_SSL_CIPHER_free(s->cipher_list);
+
+ if (s->cipher_list_by_id)
+ sk_SSL_CIPHER_free(s->cipher_list_by_id);
+
+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
+ }
+ }
+
/* Given s->session->ciphers and SSL_get_ciphers, we must
* pick a cipher */
diff -uprN openssl-0.9.8d.orig/ssl/ssl.h openssl-0.9.8d/ssl/ssl.h
--- openssl-0.9.8d.orig/ssl/ssl.h 2006-06-14 06:52:49.000000000 -0700
+++ openssl-0.9.8d/ssl/ssl.h 2006-12-10 08:20:02.000000000 -0800
@@ -345,6 +345,7 @@ extern "C" {
* 'struct ssl_st *' function parameters used to prototype callbacks
* in SSL_CTX. */
typedef struct ssl_st *ssl_crock_st;
+typedef struct tls_extension_st TLS_EXTENSION;
/* used to hold info on the particular ciphers used */
typedef struct ssl_cipher_st
@@ -366,6 +367,8 @@ DECLARE_STACK_OF(SSL_CIPHER)
typedef struct ssl_st SSL;
typedef struct ssl_ctx_st SSL_CTX;
+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
+
/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
typedef struct ssl_method_st
{
@@ -973,6 +976,15 @@ struct ssl_st
int first_packet;
int client_version; /* what was passed, used for
* SSLv3/TLS rollback check */
+
+ /* TLS externsions */
+ TLS_EXTENSION *tls_extension;
+ int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg);
+ void *tls_extension_cb_arg;
+
+ /* TLS pre-shared secret session resumption */
+ tls_session_secret_cb_fn tls_session_secret_cb;
+ void *tls_session_secret_cb_arg;
};
#ifdef __cplusplus
@@ -1538,6 +1550,13 @@ void *SSL_COMP_get_compression_methods(v
int SSL_COMP_add_compression_method(int id,void *cm);
#endif
+/* TLS extensions functions */
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len);
+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg);
+
+/* Pre-shared secret session resumption functions */
+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
+
/* BEGIN ERROR CODES */
/* The following lines are auto generated by the script mkerr.pl. Any changes
* made after this point may be overwritten when the script is next run.
@@ -1719,6 +1738,7 @@ void ERR_load_SSL_strings(void);
#define SSL_F_TLS1_ENC 210
#define SSL_F_TLS1_SETUP_KEY_BLOCK 211
#define SSL_F_WRITE_PENDING 212
+#define SSL_F_SSL_SET_HELLO_EXTENSION 213
/* Reason codes. */
#define SSL_R_APP_DATA_IN_HANDSHAKE 100
diff -uprN openssl-0.9.8d.orig/ssl/ssl_err.c openssl-0.9.8d/ssl/ssl_err.c
--- openssl-0.9.8d.orig/ssl/ssl_err.c 2006-01-08 13:52:46.000000000 -0800
+++ openssl-0.9.8d/ssl/ssl_err.c 2006-12-10 08:20:02.000000000 -0800
@@ -242,6 +242,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
{ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"},
{ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"},
{ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"},
+{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"},
{0,NULL}
};
diff -uprN openssl-0.9.8d.orig/ssl/ssl_sess.c openssl-0.9.8d/ssl/ssl_sess.c
--- openssl-0.9.8d.orig/ssl/ssl_sess.c 2005-12-30 15:51:57.000000000 -0800
+++ openssl-0.9.8d/ssl/ssl_sess.c 2006-12-10 08:20:02.000000000 -0800
@@ -656,6 +656,15 @@ long SSL_CTX_get_timeout(const SSL_CTX *
return(s->session_timeout);
}
+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len,
+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg)
+{
+ if (s == NULL) return(0);
+ s->tls_session_secret_cb = tls_session_secret_cb;
+ s->tls_session_secret_cb_arg = arg;
+ return(1);
+}
+
typedef struct timeout_param_st
{
SSL_CTX *ctx;
diff -uprN openssl-0.9.8d.orig/ssl/t1_ext.c openssl-0.9.8d/ssl/t1_ext.c
--- openssl-0.9.8d.orig/ssl/t1_ext.c 1969-12-31 16:00:00.000000000 -0800
+++ openssl-0.9.8d/ssl/t1_ext.c 2006-12-10 08:20:02.000000000 -0800
@@ -0,0 +1,48 @@
+
+#include <stdio.h>
+#include "ssl_locl.h"
+
+
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len)
+{
+ if(s->version >= TLS1_VERSION)
+ {
+ if(s->tls_extension)
+ {
+ OPENSSL_free(s->tls_extension);
+ s->tls_extension = NULL;
+ }
+
+ if(ext_data)
+ {
+ s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len);
+ if(!s->tls_extension)
+ {
+ SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ s->tls_extension->type = ext_type;
+ s->tls_extension->length = ext_len;
+ s->tls_extension->data = s->tls_extension + 1;
+ memcpy(s->tls_extension->data, ext_data, ext_len);
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg)
+{
+ if(s->version >= TLS1_VERSION)
+ {
+ s->tls_extension_cb = cb;
+ s->tls_extension_cb_arg = arg;
+
+ return 1;
+ }
+
+ return 0;
+}
diff -uprN openssl-0.9.8d.orig/ssl/t1_lib.c openssl-0.9.8d/ssl/t1_lib.c
--- openssl-0.9.8d.orig/ssl/t1_lib.c 2005-08-05 16:52:07.000000000 -0700
+++ openssl-0.9.8d/ssl/t1_lib.c 2006-12-10 08:20:02.000000000 -0800
@@ -97,6 +97,10 @@ int tls1_new(SSL *s)
void tls1_free(SSL *s)
{
+ if(s->tls_extension)
+ {
+ OPENSSL_free(s->tls_extension);
+ }
ssl3_free(s);
}
diff -uprN openssl-0.9.8d.orig/ssl/tls1.h openssl-0.9.8d/ssl/tls1.h
--- openssl-0.9.8d.orig/ssl/tls1.h 2006-06-14 10:52:01.000000000 -0700
+++ openssl-0.9.8d/ssl/tls1.h 2006-12-10 08:20:02.000000000 -0800
@@ -296,6 +296,14 @@ extern "C" {
#define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/
#endif
+/* TLS extension struct */
+struct tls_extension_st
+{
+ unsigned short type;
+ unsigned short length;
+ void *data;
+};
+
#ifdef __cplusplus
}
#endif
diff -uprN openssl-0.9.8d.orig/util/ssleay.num openssl-0.9.8d/util/ssleay.num
--- openssl-0.9.8d.orig/util/ssleay.num 2005-05-08 17:22:02.000000000 -0700
+++ openssl-0.9.8d/util/ssleay.num 2006-12-10 08:20:02.000000000 -0800
@@ -226,3 +226,6 @@ DTLSv1_server_method
SSL_COMP_get_compression_methods 276 EXIST:!VMS:FUNCTION:COMP
SSL_COMP_get_compress_methods 276 EXIST:VMS:FUNCTION:COMP
SSL_SESSION_get_id 277 EXIST::FUNCTION:
+SSL_set_hello_extension 278 EXIST::FUNCTION:
+SSL_set_hello_extension_cb 279 EXIST::FUNCTION:
+SSL_set_session_secret_cb 280 EXIST::FUNCTION:

View File

@ -1,353 +0,0 @@
This patch is adding support for TLS hello extensions and externally
generated pre-shared key material to OpenSSL 0.9.8e. This is
based on the patch from Alexey Kobozev <akobozev@cisco.com>
(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300).
diff -uprN openssl-0.9.8e.orig/ssl/Makefile openssl-0.9.8e/ssl/Makefile
--- openssl-0.9.8e.orig/ssl/Makefile 2006-02-03 17:49:35.000000000 -0800
+++ openssl-0.9.8e/ssl/Makefile 2007-03-22 20:23:19.000000000 -0700
@@ -24,7 +24,7 @@ LIBSRC= \
s2_meth.c s2_srvr.c s2_clnt.c s2_lib.c s2_enc.c s2_pkt.c \
s3_meth.c s3_srvr.c s3_clnt.c s3_lib.c s3_enc.c s3_pkt.c s3_both.c \
s23_meth.c s23_srvr.c s23_clnt.c s23_lib.c s23_pkt.c \
- t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c \
+ t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c t1_ext.c \
d1_meth.c d1_srvr.c d1_clnt.c d1_lib.c d1_pkt.c \
d1_both.c d1_enc.c \
ssl_lib.c ssl_err2.c ssl_cert.c ssl_sess.c \
@@ -35,7 +35,7 @@ LIBOBJ= \
s2_meth.o s2_srvr.o s2_clnt.o s2_lib.o s2_enc.o s2_pkt.o \
s3_meth.o s3_srvr.o s3_clnt.o s3_lib.o s3_enc.o s3_pkt.o s3_both.o \
s23_meth.o s23_srvr.o s23_clnt.o s23_lib.o s23_pkt.o \
- t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o \
+ t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o t1_ext.o \
d1_meth.o d1_srvr.o d1_clnt.o d1_lib.o d1_pkt.o \
d1_both.o d1_enc.o \
ssl_lib.o ssl_err2.o ssl_cert.o ssl_sess.o \
@@ -968,3 +968,4 @@ t1_srvr.o: ../include/openssl/ssl23.h ..
t1_srvr.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
t1_srvr.o: ../include/openssl/tls1.h ../include/openssl/x509.h
t1_srvr.o: ../include/openssl/x509_vfy.h ssl_locl.h t1_srvr.c
+t1_ext.o: t1_ext.c ssl_locl.h
diff -uprN openssl-0.9.8e.orig/ssl/s3_clnt.c openssl-0.9.8e/ssl/s3_clnt.c
--- openssl-0.9.8e.orig/ssl/s3_clnt.c 2006-09-28 05:23:15.000000000 -0700
+++ openssl-0.9.8e/ssl/s3_clnt.c 2007-03-22 20:23:19.000000000 -0700
@@ -601,6 +601,20 @@ int ssl3_client_hello(SSL *s)
#endif
*(p++)=0; /* Add the NULL method */
+ /* send client hello extensions if any */
+ if (s->version >= TLS1_VERSION && s->tls_extension)
+ {
+ // set the total extensions length
+ s2n(s->tls_extension->length + 4, p);
+
+ // put the extensions with type and length
+ s2n(s->tls_extension->type, p);
+ s2n(s->tls_extension->length, p);
+
+ memcpy(p, s->tls_extension->data, s->tls_extension->length);
+ p+=s->tls_extension->length;
+ }
+
l=(p-d);
d=buf;
*(d++)=SSL3_MT_CLIENT_HELLO;
@@ -623,7 +637,7 @@ int ssl3_get_server_hello(SSL *s)
STACK_OF(SSL_CIPHER) *sk;
SSL_CIPHER *c;
unsigned char *p,*d;
- int i,al,ok;
+ int i,al,ok,pre_shared;
unsigned int j;
long n;
#ifndef OPENSSL_NO_COMP
@@ -690,7 +704,24 @@ int ssl3_get_server_hello(SSL *s)
goto f_err;
}
- if (j != 0 && j == s->session->session_id_length
+ /* check if we want to resume the session based on external pre-shared secret */
+ pre_shared = 0;
+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
+ {
+ SSL_CIPHER *pref_cipher=NULL;
+ s->session->master_key_length=sizeof(s->session->master_key);
+ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
+ NULL, &pref_cipher, s->tls_session_secret_cb_arg))
+ {
+ s->hit=1;
+ s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j);
+ s->session->session_id_length = j;
+ memcpy(s->session->session_id, p, j);
+ pre_shared = 1;
+ }
+ }
+
+ if ((pre_shared || j != 0) && j == s->session->session_id_length
&& memcmp(p,s->session->session_id,j) == 0)
{
if(s->sid_ctx_length != s->session->sid_ctx_length
diff -uprN openssl-0.9.8e.orig/ssl/s3_srvr.c openssl-0.9.8e/ssl/s3_srvr.c
--- openssl-0.9.8e.orig/ssl/s3_srvr.c 2007-02-07 12:36:40.000000000 -0800
+++ openssl-0.9.8e/ssl/s3_srvr.c 2007-03-22 20:23:19.000000000 -0700
@@ -945,6 +945,75 @@ int ssl3_get_client_hello(SSL *s)
}
#endif
+ /* Check for TLS client hello extension here */
+ if (p < (d+n) && s->version >= TLS1_VERSION)
+ {
+ if (s->tls_extension_cb)
+ {
+ TLS_EXTENSION tls_ext;
+ unsigned short ext_total_len;
+
+ n2s(p, ext_total_len);
+ n2s(p, tls_ext.type);
+ n2s(p, tls_ext.length);
+
+ // sanity check in TLS extension len
+ if (tls_ext.length > (d+n) - p)
+ {
+ // just cut the lenth to packet border
+ tls_ext.length = (d+n) - p;
+ }
+
+ tls_ext.data = p;
+
+ // returns an alert code or 0
+ al = s->tls_extension_cb(s, &tls_ext, s->tls_extension_cb_arg);
+ if (al != 0)
+ {
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PEER_ERROR);
+ goto f_err;
+ }
+ }
+ }
+
+ /* Check if we want to use external pre-shared secret for this handshake */
+ /* for not reused session only */
+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb)
+ {
+ SSL_CIPHER *pref_cipher=NULL;
+
+ s->session->master_key_length=sizeof(s->session->master_key);
+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg))
+ {
+ s->hit=1;
+ s->session->ciphers=ciphers;
+ s->session->verify_result=X509_V_OK;
+
+ ciphers=NULL;
+
+ /* check if some cipher was preferred by call back */
+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
+ if (pref_cipher == NULL)
+ {
+ al=SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
+ goto f_err;
+ }
+
+ s->session->cipher=pref_cipher;
+
+ if (s->cipher_list)
+ sk_SSL_CIPHER_free(s->cipher_list);
+
+ if (s->cipher_list_by_id)
+ sk_SSL_CIPHER_free(s->cipher_list_by_id);
+
+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
+ }
+ }
+
/* Given s->session->ciphers and SSL_get_ciphers, we must
* pick a cipher */
diff -uprN openssl-0.9.8e.orig/ssl/ssl.h openssl-0.9.8e/ssl/ssl.h
--- openssl-0.9.8e.orig/ssl/ssl.h 2007-02-19 09:55:07.000000000 -0800
+++ openssl-0.9.8e/ssl/ssl.h 2007-03-22 20:23:19.000000000 -0700
@@ -345,6 +345,7 @@ extern "C" {
* 'struct ssl_st *' function parameters used to prototype callbacks
* in SSL_CTX. */
typedef struct ssl_st *ssl_crock_st;
+typedef struct tls_extension_st TLS_EXTENSION;
/* used to hold info on the particular ciphers used */
typedef struct ssl_cipher_st
@@ -366,6 +367,8 @@ DECLARE_STACK_OF(SSL_CIPHER)
typedef struct ssl_st SSL;
typedef struct ssl_ctx_st SSL_CTX;
+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
+
/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
typedef struct ssl_method_st
{
@@ -973,6 +976,15 @@ struct ssl_st
int first_packet;
int client_version; /* what was passed, used for
* SSLv3/TLS rollback check */
+
+ /* TLS externsions */
+ TLS_EXTENSION *tls_extension;
+ int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg);
+ void *tls_extension_cb_arg;
+
+ /* TLS pre-shared secret session resumption */
+ tls_session_secret_cb_fn tls_session_secret_cb;
+ void *tls_session_secret_cb_arg;
};
#ifdef __cplusplus
@@ -1538,6 +1550,13 @@ void *SSL_COMP_get_compression_methods(v
int SSL_COMP_add_compression_method(int id,void *cm);
#endif
+/* TLS extensions functions */
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len);
+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg);
+
+/* Pre-shared secret session resumption functions */
+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
+
/* BEGIN ERROR CODES */
/* The following lines are auto generated by the script mkerr.pl. Any changes
* made after this point may be overwritten when the script is next run.
@@ -1719,6 +1738,7 @@ void ERR_load_SSL_strings(void);
#define SSL_F_TLS1_ENC 210
#define SSL_F_TLS1_SETUP_KEY_BLOCK 211
#define SSL_F_WRITE_PENDING 212
+#define SSL_F_SSL_SET_HELLO_EXTENSION 213
/* Reason codes. */
#define SSL_R_APP_DATA_IN_HANDSHAKE 100
diff -uprN openssl-0.9.8e.orig/ssl/ssl_err.c openssl-0.9.8e/ssl/ssl_err.c
--- openssl-0.9.8e.orig/ssl/ssl_err.c 2006-11-21 12:14:46.000000000 -0800
+++ openssl-0.9.8e/ssl/ssl_err.c 2007-03-22 20:23:19.000000000 -0700
@@ -242,6 +242,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
{ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"},
{ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"},
{ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"},
+{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"},
{0,NULL}
};
diff -uprN openssl-0.9.8e.orig/ssl/ssl_sess.c openssl-0.9.8e/ssl/ssl_sess.c
--- openssl-0.9.8e.orig/ssl/ssl_sess.c 2007-02-10 02:40:24.000000000 -0800
+++ openssl-0.9.8e/ssl/ssl_sess.c 2007-03-22 20:23:19.000000000 -0700
@@ -656,6 +656,15 @@ long SSL_CTX_get_timeout(const SSL_CTX *
return(s->session_timeout);
}
+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len,
+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg)
+{
+ if (s == NULL) return(0);
+ s->tls_session_secret_cb = tls_session_secret_cb;
+ s->tls_session_secret_cb_arg = arg;
+ return(1);
+}
+
typedef struct timeout_param_st
{
SSL_CTX *ctx;
diff -uprN openssl-0.9.8e.orig/ssl/t1_ext.c openssl-0.9.8e/ssl/t1_ext.c
--- openssl-0.9.8e.orig/ssl/t1_ext.c 1969-12-31 16:00:00.000000000 -0800
+++ openssl-0.9.8e/ssl/t1_ext.c 2007-03-22 20:23:19.000000000 -0700
@@ -0,0 +1,48 @@
+
+#include <stdio.h>
+#include "ssl_locl.h"
+
+
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len)
+{
+ if(s->version >= TLS1_VERSION)
+ {
+ if(s->tls_extension)
+ {
+ OPENSSL_free(s->tls_extension);
+ s->tls_extension = NULL;
+ }
+
+ if(ext_data)
+ {
+ s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len);
+ if(!s->tls_extension)
+ {
+ SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ s->tls_extension->type = ext_type;
+ s->tls_extension->length = ext_len;
+ s->tls_extension->data = s->tls_extension + 1;
+ memcpy(s->tls_extension->data, ext_data, ext_len);
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg)
+{
+ if(s->version >= TLS1_VERSION)
+ {
+ s->tls_extension_cb = cb;
+ s->tls_extension_cb_arg = arg;
+
+ return 1;
+ }
+
+ return 0;
+}
diff -uprN openssl-0.9.8e.orig/ssl/t1_lib.c openssl-0.9.8e/ssl/t1_lib.c
--- openssl-0.9.8e.orig/ssl/t1_lib.c 2007-01-21 08:07:25.000000000 -0800
+++ openssl-0.9.8e/ssl/t1_lib.c 2007-03-22 20:23:19.000000000 -0700
@@ -97,6 +97,10 @@ int tls1_new(SSL *s)
void tls1_free(SSL *s)
{
+ if(s->tls_extension)
+ {
+ OPENSSL_free(s->tls_extension);
+ }
ssl3_free(s);
}
diff -uprN openssl-0.9.8e.orig/ssl/tls1.h openssl-0.9.8e/ssl/tls1.h
--- openssl-0.9.8e.orig/ssl/tls1.h 2006-06-14 10:52:01.000000000 -0700
+++ openssl-0.9.8e/ssl/tls1.h 2007-03-22 20:23:19.000000000 -0700
@@ -296,6 +296,14 @@ extern "C" {
#define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/
#endif
+/* TLS extension struct */
+struct tls_extension_st
+{
+ unsigned short type;
+ unsigned short length;
+ void *data;
+};
+
#ifdef __cplusplus
}
#endif
diff -uprN openssl-0.9.8e.orig/util/ssleay.num openssl-0.9.8e/util/ssleay.num
--- openssl-0.9.8e.orig/util/ssleay.num 2006-11-30 05:04:43.000000000 -0800
+++ openssl-0.9.8e/util/ssleay.num 2007-03-22 20:24:07.000000000 -0700
@@ -238,3 +238,6 @@ SSL_CTX_set_info_callback
SSL_CTX_sess_get_new_cb 287 EXIST::FUNCTION:
SSL_CTX_get_client_cert_cb 288 EXIST::FUNCTION:
SSL_CTX_sess_get_remove_cb 289 EXIST::FUNCTION:
+SSL_set_hello_extension 290 EXIST::FUNCTION:
+SSL_set_hello_extension_cb 291 EXIST::FUNCTION:
+SSL_set_session_secret_cb 292 EXIST::FUNCTION:

View File

@ -1,330 +0,0 @@
This patch adds support for TLS SessionTicket extension (RFC 5077) for
the parts used by EAP-FAST (RFC 4851).
This is based on the patch from Alexey Kobozev <akobozev@cisco.com>
(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300).
OpenSSL 0.9.8g does not enable TLS extension support by default, so it
will need to be enabled by adding enable-tlsext to config script
command line.
diff -upr openssl-0.9.8g.orig/ssl/s3_clnt.c openssl-0.9.8g/ssl/s3_clnt.c
--- openssl-0.9.8g.orig/ssl/s3_clnt.c 2007-08-31 03:28:51.000000000 +0300
+++ openssl-0.9.8g/ssl/s3_clnt.c 2008-04-15 17:11:46.000000000 +0300
@@ -727,6 +727,20 @@ int ssl3_get_server_hello(SSL *s)
goto f_err;
}
+#ifndef OPENSSL_NO_TLSEXT
+ /* check if we want to resume the session based on external pre-shared secret */
+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
+ {
+ SSL_CIPHER *pref_cipher=NULL;
+ s->session->master_key_length=sizeof(s->session->master_key);
+ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
+ NULL, &pref_cipher, s->tls_session_secret_cb_arg))
+ {
+ s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j);
+ }
+ }
+#endif /* OPENSSL_NO_TLSEXT */
+
if (j != 0 && j == s->session->session_id_length
&& memcmp(p,s->session->session_id,j) == 0)
{
diff -upr openssl-0.9.8g.orig/ssl/s3_srvr.c openssl-0.9.8g/ssl/s3_srvr.c
--- openssl-0.9.8g.orig/ssl/s3_srvr.c 2007-09-30 21:55:59.000000000 +0300
+++ openssl-0.9.8g/ssl/s3_srvr.c 2008-04-15 17:10:37.000000000 +0300
@@ -928,6 +928,59 @@ int ssl3_get_client_hello(SSL *s)
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
goto err;
}
+
+ /* Check if we want to use external pre-shared secret for this
+ * handshake for not reused session only. We need to generate
+ * server_random before calling tls_session_secret_cb in order to allow
+ * SessionTicket processing to use it in key derivation. */
+ {
+ unsigned long Time;
+ unsigned char *pos;
+ Time=(unsigned long)time(NULL); /* Time */
+ pos=s->s3->server_random;
+ l2n(Time,pos);
+ if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0)
+ {
+ al=SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
+ }
+
+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb)
+ {
+ SSL_CIPHER *pref_cipher=NULL;
+
+ s->session->master_key_length=sizeof(s->session->master_key);
+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg))
+ {
+ s->hit=1;
+ s->session->ciphers=ciphers;
+ s->session->verify_result=X509_V_OK;
+
+ ciphers=NULL;
+
+ /* check if some cipher was preferred by call back */
+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
+ if (pref_cipher == NULL)
+ {
+ al=SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
+ goto f_err;
+ }
+
+ s->session->cipher=pref_cipher;
+
+ if (s->cipher_list)
+ sk_SSL_CIPHER_free(s->cipher_list);
+
+ if (s->cipher_list_by_id)
+ sk_SSL_CIPHER_free(s->cipher_list_by_id);
+
+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
+ }
+ }
#endif
/* Worst case, we will use the NULL compression, but if we have other
* options, we will now look for them. We have i-1 compression
@@ -1066,16 +1119,22 @@ int ssl3_send_server_hello(SSL *s)
unsigned char *buf;
unsigned char *p,*d;
int i,sl;
- unsigned long l,Time;
+ unsigned long l;
+#ifdef OPENSSL_NO_TLSEXT
+ unsigned long Time;
+#endif
if (s->state == SSL3_ST_SW_SRVR_HELLO_A)
{
buf=(unsigned char *)s->init_buf->data;
+#ifdef OPENSSL_NO_TLSEXT
p=s->s3->server_random;
+ /* Generate server_random if it was not needed previously */
Time=(unsigned long)time(NULL); /* Time */
l2n(Time,p);
if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
return -1;
+#endif
/* Do the message type and length last */
d=p= &(buf[4]);
diff -upr openssl-0.9.8g.orig/ssl/ssl.h openssl-0.9.8g/ssl/ssl.h
--- openssl-0.9.8g.orig/ssl/ssl.h 2007-10-19 10:42:38.000000000 +0300
+++ openssl-0.9.8g/ssl/ssl.h 2008-04-15 17:10:37.000000000 +0300
@@ -342,6 +342,7 @@ extern "C" {
* 'struct ssl_st *' function parameters used to prototype callbacks
* in SSL_CTX. */
typedef struct ssl_st *ssl_crock_st;
+typedef struct tls_extension_st TLS_EXTENSION;
/* used to hold info on the particular ciphers used */
typedef struct ssl_cipher_st
@@ -363,6 +364,8 @@ DECLARE_STACK_OF(SSL_CIPHER)
typedef struct ssl_st SSL;
typedef struct ssl_ctx_st SSL_CTX;
+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
+
/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
typedef struct ssl_method_st
{
@@ -1004,6 +1007,14 @@ struct ssl_st
*/
/* RFC4507 session ticket expected to be received or sent */
int tlsext_ticket_expected;
+
+ /* TLS extensions */
+ TLS_EXTENSION *tls_extension;
+
+ /* TLS pre-shared secret session resumption */
+ tls_session_secret_cb_fn tls_session_secret_cb;
+ void *tls_session_secret_cb_arg;
+
SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
#define session_ctx initial_ctx
#else
@@ -1589,6 +1600,12 @@ void *SSL_COMP_get_compression_methods(v
int SSL_COMP_add_compression_method(int id,void *cm);
#endif
+/* TLS extensions functions */
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len);
+
+/* Pre-shared secret session resumption functions */
+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
+
/* BEGIN ERROR CODES */
/* The following lines are auto generated by the script mkerr.pl. Any changes
* made after this point may be overwritten when the script is next run.
@@ -1778,6 +1795,7 @@ void ERR_load_SSL_strings(void);
#define SSL_F_TLS1_ENC 210
#define SSL_F_TLS1_SETUP_KEY_BLOCK 211
#define SSL_F_WRITE_PENDING 212
+#define SSL_F_SSL_SET_HELLO_EXTENSION 213
/* Reason codes. */
#define SSL_R_APP_DATA_IN_HANDSHAKE 100
diff -upr openssl-0.9.8g.orig/ssl/ssl_err.c openssl-0.9.8g/ssl/ssl_err.c
--- openssl-0.9.8g.orig/ssl/ssl_err.c 2007-10-11 17:36:59.000000000 +0300
+++ openssl-0.9.8g/ssl/ssl_err.c 2008-04-15 17:10:37.000000000 +0300
@@ -250,6 +250,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
{ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"},
{ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"},
{ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"},
+{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"},
{0,NULL}
};
diff -upr openssl-0.9.8g.orig/ssl/ssl_sess.c openssl-0.9.8g/ssl/ssl_sess.c
--- openssl-0.9.8g.orig/ssl/ssl_sess.c 2007-10-19 10:36:34.000000000 +0300
+++ openssl-0.9.8g/ssl/ssl_sess.c 2008-04-15 17:10:37.000000000 +0300
@@ -704,6 +704,52 @@ long SSL_CTX_get_timeout(const SSL_CTX *
return(s->session_timeout);
}
+#ifndef OPENSSL_NO_TLSEXT
+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len,
+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg)
+{
+ if (s == NULL) return(0);
+ s->tls_session_secret_cb = tls_session_secret_cb;
+ s->tls_session_secret_cb_arg = arg;
+ return(1);
+}
+
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len)
+{
+ if(s->version >= TLS1_VERSION)
+ {
+ if(s->tls_extension)
+ {
+ OPENSSL_free(s->tls_extension);
+ s->tls_extension = NULL;
+ }
+
+ s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len);
+ if(!s->tls_extension)
+ {
+ SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ s->tls_extension->type = ext_type;
+
+ if(ext_data)
+ {
+ s->tls_extension->length = ext_len;
+ s->tls_extension->data = s->tls_extension + 1;
+ memcpy(s->tls_extension->data, ext_data, ext_len);
+ } else {
+ s->tls_extension->length = 0;
+ s->tls_extension->data = NULL;
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+#endif /* OPENSSL_NO_TLSEXT */
+
typedef struct timeout_param_st
{
SSL_CTX *ctx;
diff -upr openssl-0.9.8g.orig/ssl/t1_lib.c openssl-0.9.8g/ssl/t1_lib.c
--- openssl-0.9.8g.orig/ssl/t1_lib.c 2007-10-19 10:44:10.000000000 +0300
+++ openssl-0.9.8g/ssl/t1_lib.c 2008-04-15 17:10:37.000000000 +0300
@@ -105,6 +105,12 @@ int tls1_new(SSL *s)
void tls1_free(SSL *s)
{
+#ifndef OPENSSL_NO_TLSEXT
+ if(s->tls_extension)
+ {
+ OPENSSL_free(s->tls_extension);
+ }
+#endif
ssl3_free(s);
}
@@ -174,8 +180,24 @@ unsigned char *ssl_add_clienthello_tlsex
int ticklen;
if (s->session && s->session->tlsext_tick)
ticklen = s->session->tlsext_ticklen;
+ else if (s->session && s->tls_extension &&
+ s->tls_extension->type == TLSEXT_TYPE_session_ticket &&
+ s->tls_extension->data)
+ {
+ ticklen = s->tls_extension->length;
+ s->session->tlsext_tick = OPENSSL_malloc(ticklen);
+ if (!s->session->tlsext_tick)
+ return NULL;
+ memcpy(s->session->tlsext_tick, s->tls_extension->data,
+ ticklen);
+ s->session->tlsext_ticklen = ticklen;
+ }
else
ticklen = 0;
+ if (ticklen == 0 && s->tls_extension &&
+ s->tls_extension->type == TLSEXT_TYPE_session_ticket &&
+ s->tls_extension->data == NULL)
+ goto skip_ext;
/* Check for enough room 2 for extension type, 2 for len
* rest for ticket
*/
@@ -189,6 +211,7 @@ unsigned char *ssl_add_clienthello_tlsex
ret += ticklen;
}
}
+ skip_ext:
if ((extdatalen = ret-p-2)== 0)
return p;
@@ -543,6 +566,8 @@ int tls1_process_ticket(SSL *s, unsigned
s->tlsext_ticket_expected = 1;
return 0; /* Cache miss */
}
+ if (s->tls_session_secret_cb)
+ return 0;
return tls_decrypt_ticket(s, p, size, session_id, len,
ret);
}
diff -upr openssl-0.9.8g.orig/ssl/tls1.h openssl-0.9.8g/ssl/tls1.h
--- openssl-0.9.8g.orig/ssl/tls1.h 2007-08-28 04:12:44.000000000 +0300
+++ openssl-0.9.8g/ssl/tls1.h 2008-04-15 17:10:37.000000000 +0300
@@ -365,6 +365,14 @@ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SER
#define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/
#endif
+/* TLS extension struct */
+struct tls_extension_st
+{
+ unsigned short type;
+ unsigned short length;
+ void *data;
+};
+
#ifdef __cplusplus
}
#endif
diff -upr openssl-0.9.8g.orig/util/ssleay.num openssl-0.9.8g/util/ssleay.num
--- openssl-0.9.8g.orig/util/ssleay.num 2007-08-13 01:31:16.000000000 +0300
+++ openssl-0.9.8g/util/ssleay.num 2008-04-15 17:10:37.000000000 +0300
@@ -241,3 +241,5 @@ SSL_CTX_sess_get_remove_cb
SSL_set_SSL_CTX 290 EXIST::FUNCTION:
SSL_get_servername 291 EXIST::FUNCTION:TLSEXT
SSL_get_servername_type 292 EXIST::FUNCTION:TLSEXT
+SSL_set_hello_extension 305 EXIST::FUNCTION:TLSEXT
+SSL_set_session_secret_cb 306 EXIST::FUNCTION:TLSEXT

View File

@ -1,344 +0,0 @@
This patch adds support for TLS SessionTicket extension (RFC 5077) for
the parts used by EAP-FAST (RFC 4851).
This is based on the patch from Alexey Kobozev <akobozev@cisco.com>
(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300).
OpenSSL 0.9.8h does not enable TLS extension support by default, so it
will need to be enabled by adding enable-tlsext to config script
command line.
diff -upr openssl-0.9.8h.orig/ssl/s3_clnt.c openssl-0.9.8h/ssl/s3_clnt.c
--- openssl-0.9.8h.orig/ssl/s3_clnt.c 2008-05-28 10:29:27.000000000 +0300
+++ openssl-0.9.8h/ssl/s3_clnt.c 2008-05-29 10:44:25.000000000 +0300
@@ -752,6 +752,20 @@ int ssl3_get_server_hello(SSL *s)
goto f_err;
}
+#ifndef OPENSSL_NO_TLSEXT
+ /* check if we want to resume the session based on external pre-shared secret */
+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
+ {
+ SSL_CIPHER *pref_cipher=NULL;
+ s->session->master_key_length=sizeof(s->session->master_key);
+ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
+ NULL, &pref_cipher, s->tls_session_secret_cb_arg))
+ {
+ s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j);
+ }
+ }
+#endif /* OPENSSL_NO_TLSEXT */
+
if (j != 0 && j == s->session->session_id_length
&& memcmp(p,s->session->session_id,j) == 0)
{
@@ -2693,11 +2707,8 @@ static int ssl3_check_finished(SSL *s)
{
int ok;
long n;
- /* If we have no ticket or session ID is non-zero length (a match of
- * a non-zero session length would never reach here) it cannot be a
- * resumed session.
- */
- if (!s->session->tlsext_tick || s->session->session_id_length)
+ /* If we have no ticket it cannot be a resumed session. */
+ if (!s->session->tlsext_tick)
return 1;
/* this function is called when we really expect a Certificate
* message, so permit appropriate message length */
diff -upr openssl-0.9.8h.orig/ssl/s3_srvr.c openssl-0.9.8h/ssl/s3_srvr.c
--- openssl-0.9.8h.orig/ssl/s3_srvr.c 2008-04-30 19:11:32.000000000 +0300
+++ openssl-0.9.8h/ssl/s3_srvr.c 2008-05-28 18:49:34.000000000 +0300
@@ -959,6 +959,59 @@ int ssl3_get_client_hello(SSL *s)
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
goto err;
}
+
+ /* Check if we want to use external pre-shared secret for this
+ * handshake for not reused session only. We need to generate
+ * server_random before calling tls_session_secret_cb in order to allow
+ * SessionTicket processing to use it in key derivation. */
+ {
+ unsigned long Time;
+ unsigned char *pos;
+ Time=(unsigned long)time(NULL); /* Time */
+ pos=s->s3->server_random;
+ l2n(Time,pos);
+ if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0)
+ {
+ al=SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
+ }
+
+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb)
+ {
+ SSL_CIPHER *pref_cipher=NULL;
+
+ s->session->master_key_length=sizeof(s->session->master_key);
+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg))
+ {
+ s->hit=1;
+ s->session->ciphers=ciphers;
+ s->session->verify_result=X509_V_OK;
+
+ ciphers=NULL;
+
+ /* check if some cipher was preferred by call back */
+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
+ if (pref_cipher == NULL)
+ {
+ al=SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
+ goto f_err;
+ }
+
+ s->session->cipher=pref_cipher;
+
+ if (s->cipher_list)
+ sk_SSL_CIPHER_free(s->cipher_list);
+
+ if (s->cipher_list_by_id)
+ sk_SSL_CIPHER_free(s->cipher_list_by_id);
+
+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
+ }
+ }
#endif
/* Worst case, we will use the NULL compression, but if we have other
* options, we will now look for them. We have i-1 compression
@@ -1097,16 +1150,22 @@ int ssl3_send_server_hello(SSL *s)
unsigned char *buf;
unsigned char *p,*d;
int i,sl;
- unsigned long l,Time;
+ unsigned long l;
+#ifdef OPENSSL_NO_TLSEXT
+ unsigned long Time;
+#endif
if (s->state == SSL3_ST_SW_SRVR_HELLO_A)
{
buf=(unsigned char *)s->init_buf->data;
+#ifdef OPENSSL_NO_TLSEXT
p=s->s3->server_random;
+ /* Generate server_random if it was not needed previously */
Time=(unsigned long)time(NULL); /* Time */
l2n(Time,p);
if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
return -1;
+#endif
/* Do the message type and length last */
d=p= &(buf[4]);
diff -upr openssl-0.9.8h.orig/ssl/ssl.h openssl-0.9.8h/ssl/ssl.h
--- openssl-0.9.8h.orig/ssl/ssl.h 2008-04-30 19:11:32.000000000 +0300
+++ openssl-0.9.8h/ssl/ssl.h 2008-05-28 18:49:34.000000000 +0300
@@ -343,6 +343,7 @@ extern "C" {
* 'struct ssl_st *' function parameters used to prototype callbacks
* in SSL_CTX. */
typedef struct ssl_st *ssl_crock_st;
+typedef struct tls_extension_st TLS_EXTENSION;
/* used to hold info on the particular ciphers used */
typedef struct ssl_cipher_st
@@ -364,6 +365,8 @@ DECLARE_STACK_OF(SSL_CIPHER)
typedef struct ssl_st SSL;
typedef struct ssl_ctx_st SSL_CTX;
+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
+
/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
typedef struct ssl_method_st
{
@@ -1027,6 +1030,14 @@ struct ssl_st
/* RFC4507 session ticket expected to be received or sent */
int tlsext_ticket_expected;
+
+ /* TLS extensions */
+ TLS_EXTENSION *tls_extension;
+
+ /* TLS pre-shared secret session resumption */
+ tls_session_secret_cb_fn tls_session_secret_cb;
+ void *tls_session_secret_cb_arg;
+
SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
#define session_ctx initial_ctx
#else
@@ -1625,6 +1636,12 @@ void *SSL_COMP_get_compression_methods(v
int SSL_COMP_add_compression_method(int id,void *cm);
#endif
+/* TLS extensions functions */
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len);
+
+/* Pre-shared secret session resumption functions */
+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
+
/* BEGIN ERROR CODES */
/* The following lines are auto generated by the script mkerr.pl. Any changes
* made after this point may be overwritten when the script is next run.
@@ -1815,6 +1832,7 @@ void ERR_load_SSL_strings(void);
#define SSL_F_TLS1_ENC 210
#define SSL_F_TLS1_SETUP_KEY_BLOCK 211
#define SSL_F_WRITE_PENDING 212
+#define SSL_F_SSL_SET_HELLO_EXTENSION 213
/* Reason codes. */
#define SSL_R_APP_DATA_IN_HANDSHAKE 100
diff -upr openssl-0.9.8h.orig/ssl/ssl_err.c openssl-0.9.8h/ssl/ssl_err.c
--- openssl-0.9.8h.orig/ssl/ssl_err.c 2007-10-12 03:00:30.000000000 +0300
+++ openssl-0.9.8h/ssl/ssl_err.c 2008-05-28 18:49:34.000000000 +0300
@@ -251,6 +251,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
{ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"},
{ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"},
{ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"},
+{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"},
{0,NULL}
};
diff -upr openssl-0.9.8h.orig/ssl/ssl_sess.c openssl-0.9.8h/ssl/ssl_sess.c
--- openssl-0.9.8h.orig/ssl/ssl_sess.c 2007-10-17 20:30:15.000000000 +0300
+++ openssl-0.9.8h/ssl/ssl_sess.c 2008-05-28 18:49:34.000000000 +0300
@@ -704,6 +704,52 @@ long SSL_CTX_get_timeout(const SSL_CTX *
return(s->session_timeout);
}
+#ifndef OPENSSL_NO_TLSEXT
+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len,
+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg)
+{
+ if (s == NULL) return(0);
+ s->tls_session_secret_cb = tls_session_secret_cb;
+ s->tls_session_secret_cb_arg = arg;
+ return(1);
+}
+
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len)
+{
+ if(s->version >= TLS1_VERSION)
+ {
+ if(s->tls_extension)
+ {
+ OPENSSL_free(s->tls_extension);
+ s->tls_extension = NULL;
+ }
+
+ s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len);
+ if(!s->tls_extension)
+ {
+ SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ s->tls_extension->type = ext_type;
+
+ if(ext_data)
+ {
+ s->tls_extension->length = ext_len;
+ s->tls_extension->data = s->tls_extension + 1;
+ memcpy(s->tls_extension->data, ext_data, ext_len);
+ } else {
+ s->tls_extension->length = 0;
+ s->tls_extension->data = NULL;
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+#endif /* OPENSSL_NO_TLSEXT */
+
typedef struct timeout_param_st
{
SSL_CTX *ctx;
diff -upr openssl-0.9.8h.orig/ssl/t1_lib.c openssl-0.9.8h/ssl/t1_lib.c
--- openssl-0.9.8h.orig/ssl/t1_lib.c 2008-05-28 10:26:33.000000000 +0300
+++ openssl-0.9.8h/ssl/t1_lib.c 2008-05-28 18:49:34.000000000 +0300
@@ -106,6 +106,12 @@ int tls1_new(SSL *s)
void tls1_free(SSL *s)
{
+#ifndef OPENSSL_NO_TLSEXT
+ if(s->tls_extension)
+ {
+ OPENSSL_free(s->tls_extension);
+ }
+#endif
ssl3_free(s);
}
@@ -175,8 +181,24 @@ unsigned char *ssl_add_clienthello_tlsex
int ticklen;
if (s->session && s->session->tlsext_tick)
ticklen = s->session->tlsext_ticklen;
+ else if (s->session && s->tls_extension &&
+ s->tls_extension->type == TLSEXT_TYPE_session_ticket &&
+ s->tls_extension->data)
+ {
+ ticklen = s->tls_extension->length;
+ s->session->tlsext_tick = OPENSSL_malloc(ticklen);
+ if (!s->session->tlsext_tick)
+ return NULL;
+ memcpy(s->session->tlsext_tick, s->tls_extension->data,
+ ticklen);
+ s->session->tlsext_ticklen = ticklen;
+ }
else
ticklen = 0;
+ if (ticklen == 0 && s->tls_extension &&
+ s->tls_extension->type == TLSEXT_TYPE_session_ticket &&
+ s->tls_extension->data == NULL)
+ goto skip_ext;
/* Check for enough room 2 for extension type, 2 for len
* rest for ticket
*/
@@ -190,6 +212,7 @@ unsigned char *ssl_add_clienthello_tlsex
ret += ticklen;
}
}
+ skip_ext:
if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp)
{
@@ -774,6 +797,8 @@ int tls1_process_ticket(SSL *s, unsigned
s->tlsext_ticket_expected = 1;
return 0; /* Cache miss */
}
+ if (s->tls_session_secret_cb)
+ return 0;
return tls_decrypt_ticket(s, p, size, session_id, len,
ret);
}
diff -upr openssl-0.9.8h.orig/ssl/tls1.h openssl-0.9.8h/ssl/tls1.h
--- openssl-0.9.8h.orig/ssl/tls1.h 2008-04-30 19:11:33.000000000 +0300
+++ openssl-0.9.8h/ssl/tls1.h 2008-05-28 18:49:34.000000000 +0300
@@ -398,6 +398,14 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_T
#define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/
#endif
+/* TLS extension struct */
+struct tls_extension_st
+{
+ unsigned short type;
+ unsigned short length;
+ void *data;
+};
+
#ifdef __cplusplus
}
#endif
diff -upr openssl-0.9.8h.orig/util/ssleay.num openssl-0.9.8h/util/ssleay.num
--- openssl-0.9.8h.orig/util/ssleay.num 2007-08-13 01:31:16.000000000 +0300
+++ openssl-0.9.8h/util/ssleay.num 2008-05-28 18:49:34.000000000 +0300
@@ -241,3 +241,5 @@ SSL_CTX_sess_get_remove_cb
SSL_set_SSL_CTX 290 EXIST::FUNCTION:
SSL_get_servername 291 EXIST::FUNCTION:TLSEXT
SSL_get_servername_type 292 EXIST::FUNCTION:TLSEXT
+SSL_set_hello_extension 305 EXIST::FUNCTION:TLSEXT
+SSL_set_session_secret_cb 306 EXIST::FUNCTION:TLSEXT

View File

@ -1,404 +0,0 @@
This patch adds support for TLS SessionTicket extension (RFC 5077) for
the parts used by EAP-FAST (RFC 4851).
This is based on the patch from Alexey Kobozev <akobozev@cisco.com>
(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300).
OpenSSL 0.9.8i does not enable TLS extension support by default, so it
will need to be enabled by adding enable-tlsext to config script
command line.
Index: openssl-0.9.8i/ssl/s3_clnt.c
===================================================================
--- openssl-0.9.8i.orig/ssl/s3_clnt.c 2008-06-16 19:56:41.000000000 +0300
+++ openssl-0.9.8i/ssl/s3_clnt.c 2008-11-23 20:39:40.000000000 +0200
@@ -759,6 +759,21 @@
goto f_err;
}
+#ifndef OPENSSL_NO_TLSEXT
+ /* check if we want to resume the session based on external pre-shared secret */
+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
+ {
+ SSL_CIPHER *pref_cipher=NULL;
+ s->session->master_key_length=sizeof(s->session->master_key);
+ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
+ NULL, &pref_cipher, s->tls_session_secret_cb_arg))
+ {
+ s->session->cipher=pref_cipher ?
+ pref_cipher : ssl_get_cipher_by_char(s,p+j);
+ }
+ }
+#endif /* OPENSSL_NO_TLSEXT */
+
if (j != 0 && j == s->session->session_id_length
&& memcmp(p,s->session->session_id,j) == 0)
{
@@ -2701,11 +2716,8 @@
{
int ok;
long n;
- /* If we have no ticket or session ID is non-zero length (a match of
- * a non-zero session length would never reach here) it cannot be a
- * resumed session.
- */
- if (!s->session->tlsext_tick || s->session->session_id_length)
+ /* If we have no ticket it cannot be a resumed session. */
+ if (!s->session->tlsext_tick)
return 1;
/* this function is called when we really expect a Certificate
* message, so permit appropriate message length */
Index: openssl-0.9.8i/ssl/s3_srvr.c
===================================================================
--- openssl-0.9.8i.orig/ssl/s3_srvr.c 2008-09-14 21:16:09.000000000 +0300
+++ openssl-0.9.8i/ssl/s3_srvr.c 2008-11-23 20:37:40.000000000 +0200
@@ -959,6 +959,59 @@
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
goto err;
}
+
+ /* Check if we want to use external pre-shared secret for this
+ * handshake for not reused session only. We need to generate
+ * server_random before calling tls_session_secret_cb in order to allow
+ * SessionTicket processing to use it in key derivation. */
+ {
+ unsigned long Time;
+ unsigned char *pos;
+ Time=(unsigned long)time(NULL); /* Time */
+ pos=s->s3->server_random;
+ l2n(Time,pos);
+ if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0)
+ {
+ al=SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
+ }
+
+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb)
+ {
+ SSL_CIPHER *pref_cipher=NULL;
+
+ s->session->master_key_length=sizeof(s->session->master_key);
+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg))
+ {
+ s->hit=1;
+ s->session->ciphers=ciphers;
+ s->session->verify_result=X509_V_OK;
+
+ ciphers=NULL;
+
+ /* check if some cipher was preferred by call back */
+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
+ if (pref_cipher == NULL)
+ {
+ al=SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
+ goto f_err;
+ }
+
+ s->session->cipher=pref_cipher;
+
+ if (s->cipher_list)
+ sk_SSL_CIPHER_free(s->cipher_list);
+
+ if (s->cipher_list_by_id)
+ sk_SSL_CIPHER_free(s->cipher_list_by_id);
+
+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
+ }
+ }
#endif
/* Worst case, we will use the NULL compression, but if we have other
* options, we will now look for them. We have i-1 compression
@@ -1097,16 +1150,22 @@
unsigned char *buf;
unsigned char *p,*d;
int i,sl;
- unsigned long l,Time;
+ unsigned long l;
+#ifdef OPENSSL_NO_TLSEXT
+ unsigned long Time;
+#endif
if (s->state == SSL3_ST_SW_SRVR_HELLO_A)
{
buf=(unsigned char *)s->init_buf->data;
+#ifdef OPENSSL_NO_TLSEXT
p=s->s3->server_random;
+ /* Generate server_random if it was not needed previously */
Time=(unsigned long)time(NULL); /* Time */
l2n(Time,p);
if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
return -1;
+#endif
/* Do the message type and length last */
d=p= &(buf[4]);
Index: openssl-0.9.8i/ssl/ssl_err.c
===================================================================
--- openssl-0.9.8i.orig/ssl/ssl_err.c 2008-08-13 22:44:44.000000000 +0300
+++ openssl-0.9.8i/ssl/ssl_err.c 2008-11-23 20:33:43.000000000 +0200
@@ -253,6 +253,7 @@
{ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"},
{ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"},
{ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"},
+{ERR_FUNC(SSL_F_SSL_SET_SESSION_TICKET_EXT), "SSL_set_session_ticket_ext"},
{0,NULL}
};
Index: openssl-0.9.8i/ssl/ssl.h
===================================================================
--- openssl-0.9.8i.orig/ssl/ssl.h 2008-08-13 22:44:44.000000000 +0300
+++ openssl-0.9.8i/ssl/ssl.h 2008-11-23 20:35:41.000000000 +0200
@@ -344,6 +344,7 @@
* 'struct ssl_st *' function parameters used to prototype callbacks
* in SSL_CTX. */
typedef struct ssl_st *ssl_crock_st;
+typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT;
/* used to hold info on the particular ciphers used */
typedef struct ssl_cipher_st
@@ -362,6 +363,9 @@
DECLARE_STACK_OF(SSL_CIPHER)
+typedef int (*tls_session_ticket_ext_cb_fn)(SSL *s, const unsigned char *data, int len, void *arg);
+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
+
/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
typedef struct ssl_method_st
{
@@ -1034,6 +1038,18 @@
/* RFC4507 session ticket expected to be received or sent */
int tlsext_ticket_expected;
+
+ /* TLS Session Ticket extension override */
+ TLS_SESSION_TICKET_EXT *tlsext_session_ticket;
+
+ /* TLS Session Ticket extension callback */
+ tls_session_ticket_ext_cb_fn tls_session_ticket_ext_cb;
+ void *tls_session_ticket_ext_cb_arg;
+
+ /* TLS pre-shared secret session resumption */
+ tls_session_secret_cb_fn tls_session_secret_cb;
+ void *tls_session_secret_cb_arg;
+
SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
#define session_ctx initial_ctx
#else
@@ -1632,6 +1648,15 @@
int SSL_COMP_add_compression_method(int id,void *cm);
#endif
+/* TLS extensions functions */
+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len);
+
+int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb,
+ void *arg);
+
+/* Pre-shared secret session resumption functions */
+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
+
/* BEGIN ERROR CODES */
/* The following lines are auto generated by the script mkerr.pl. Any changes
* made after this point may be overwritten when the script is next run.
@@ -1824,6 +1849,7 @@
#define SSL_F_TLS1_ENC 210
#define SSL_F_TLS1_SETUP_KEY_BLOCK 211
#define SSL_F_WRITE_PENDING 212
+#define SSL_F_SSL_SET_SESSION_TICKET_EXT 213
/* Reason codes. */
#define SSL_R_APP_DATA_IN_HANDSHAKE 100
Index: openssl-0.9.8i/ssl/ssl_sess.c
===================================================================
--- openssl-0.9.8i.orig/ssl/ssl_sess.c 2008-06-04 21:35:27.000000000 +0300
+++ openssl-0.9.8i/ssl/ssl_sess.c 2008-11-23 20:32:24.000000000 +0200
@@ -707,6 +707,61 @@
return(s->session_timeout);
}
+#ifndef OPENSSL_NO_TLSEXT
+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len,
+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg)
+ {
+ if (s == NULL) return(0);
+ s->tls_session_secret_cb = tls_session_secret_cb;
+ s->tls_session_secret_cb_arg = arg;
+ return(1);
+ }
+
+int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb,
+ void *arg)
+ {
+ if (s == NULL) return(0);
+ s->tls_session_ticket_ext_cb = cb;
+ s->tls_session_ticket_ext_cb_arg = arg;
+ return(1);
+ }
+
+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len)
+ {
+ if (s->version >= TLS1_VERSION)
+ {
+ if (s->tlsext_session_ticket)
+ {
+ OPENSSL_free(s->tlsext_session_ticket);
+ s->tlsext_session_ticket = NULL;
+ }
+
+ s->tlsext_session_ticket = OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len);
+ if (!s->tlsext_session_ticket)
+ {
+ SSLerr(SSL_F_SSL_SET_SESSION_TICKET_EXT, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ if (ext_data)
+ {
+ s->tlsext_session_ticket->length = ext_len;
+ s->tlsext_session_ticket->data = s->tlsext_session_ticket + 1;
+ memcpy(s->tlsext_session_ticket->data, ext_data, ext_len);
+ }
+ else
+ {
+ s->tlsext_session_ticket->length = 0;
+ s->tlsext_session_ticket->data = NULL;
+ }
+
+ return 1;
+ }
+
+ return 0;
+ }
+#endif /* OPENSSL_NO_TLSEXT */
+
typedef struct timeout_param_st
{
SSL_CTX *ctx;
Index: openssl-0.9.8i/ssl/t1_lib.c
===================================================================
--- openssl-0.9.8i.orig/ssl/t1_lib.c 2008-09-04 01:13:04.000000000 +0300
+++ openssl-0.9.8i/ssl/t1_lib.c 2008-11-23 20:31:20.000000000 +0200
@@ -106,6 +106,12 @@
void tls1_free(SSL *s)
{
+#ifndef OPENSSL_NO_TLSEXT
+ if (s->tlsext_session_ticket)
+ {
+ OPENSSL_free(s->tlsext_session_ticket);
+ }
+#endif
ssl3_free(s);
}
@@ -175,8 +181,23 @@
int ticklen;
if (s->session && s->session->tlsext_tick)
ticklen = s->session->tlsext_ticklen;
+ else if (s->session && s->tlsext_session_ticket &&
+ s->tlsext_session_ticket->data)
+ {
+ ticklen = s->tlsext_session_ticket->length;
+ s->session->tlsext_tick = OPENSSL_malloc(ticklen);
+ if (!s->session->tlsext_tick)
+ return NULL;
+ memcpy(s->session->tlsext_tick,
+ s->tlsext_session_ticket->data,
+ ticklen);
+ s->session->tlsext_ticklen = ticklen;
+ }
else
ticklen = 0;
+ if (ticklen == 0 && s->tlsext_session_ticket &&
+ s->tlsext_session_ticket->data == NULL)
+ goto skip_ext;
/* Check for enough room 2 for extension type, 2 for len
* rest for ticket
*/
@@ -190,6 +211,7 @@
ret += ticklen;
}
}
+ skip_ext:
if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp)
{
@@ -407,6 +429,15 @@
}
}
+ else if (type == TLSEXT_TYPE_session_ticket)
+ {
+ if (s->tls_session_ticket_ext_cb &&
+ !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg))
+ {
+ *al = TLS1_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ }
else if (type == TLSEXT_TYPE_status_request
&& s->ctx->tlsext_status_cb)
{
@@ -553,6 +584,12 @@
}
else if (type == TLSEXT_TYPE_session_ticket)
{
+ if (s->tls_session_ticket_ext_cb &&
+ !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg))
+ {
+ *al = TLS1_AD_INTERNAL_ERROR;
+ return 0;
+ }
if ((SSL_get_options(s) & SSL_OP_NO_TICKET)
|| (size > 0))
{
@@ -776,6 +813,15 @@
s->tlsext_ticket_expected = 1;
return 0; /* Cache miss */
}
+ if (s->tls_session_secret_cb)
+ {
+ /* Indicate cache miss here and instead of
+ * generating the session from ticket now,
+ * trigger abbreviated handshake based on
+ * external mechanism to calculate the master
+ * secret later. */
+ return 0;
+ }
return tls_decrypt_ticket(s, p, size, session_id, len,
ret);
}
Index: openssl-0.9.8i/ssl/tls1.h
===================================================================
--- openssl-0.9.8i.orig/ssl/tls1.h 2008-04-30 19:11:33.000000000 +0300
+++ openssl-0.9.8i/ssl/tls1.h 2008-11-23 20:22:38.000000000 +0200
@@ -398,6 +398,13 @@
#define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/
#endif
+/* TLS extension struct */
+struct tls_session_ticket_ext_st
+ {
+ unsigned short length;
+ void *data;
+ };
+
#ifdef __cplusplus
}
#endif
Index: openssl-0.9.8i/util/ssleay.num
===================================================================
--- openssl-0.9.8i.orig/util/ssleay.num 2008-06-05 13:57:21.000000000 +0300
+++ openssl-0.9.8i/util/ssleay.num 2008-11-23 20:22:05.000000000 +0200
@@ -242,3 +242,5 @@
SSL_get_servername 291 EXIST::FUNCTION:TLSEXT
SSL_get_servername_type 292 EXIST::FUNCTION:TLSEXT
SSL_CTX_set_client_cert_engine 293 EXIST::FUNCTION:ENGINE
+SSL_set_session_ticket_ext 306 EXIST::FUNCTION:TLSEXT
+SSL_set_session_secret_cb 307 EXIST::FUNCTION:TLSEXT

View File

@ -1,396 +0,0 @@
This patch adds support for TLS SessionTicket extension (RFC 5077) for
the parts used by EAP-FAST (RFC 4851).
This is based on the patch from Alexey Kobozev <akobozev@cisco.com>
(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300).
OpenSSL 0.9.8x does not enable TLS extension support by default, so it
will need to be enabled by adding enable-tlsext to config script
command line.
diff -upr openssl-0.9.8x.orig/ssl/s3_clnt.c openssl-0.9.8x/ssl/s3_clnt.c
--- openssl-0.9.8x.orig/ssl/s3_clnt.c 2011-12-26 21:38:28.000000000 +0200
+++ openssl-0.9.8x/ssl/s3_clnt.c 2012-07-07 10:46:31.501140621 +0300
@@ -757,6 +757,21 @@ int ssl3_get_server_hello(SSL *s)
goto f_err;
}
+#ifndef OPENSSL_NO_TLSEXT
+ /* check if we want to resume the session based on external pre-shared secret */
+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
+ {
+ SSL_CIPHER *pref_cipher=NULL;
+ s->session->master_key_length=sizeof(s->session->master_key);
+ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
+ NULL, &pref_cipher, s->tls_session_secret_cb_arg))
+ {
+ s->session->cipher=pref_cipher ?
+ pref_cipher : ssl_get_cipher_by_char(s,p+j);
+ }
+ }
+#endif /* OPENSSL_NO_TLSEXT */
+
if (j != 0 && j == s->session->session_id_length
&& memcmp(p,s->session->session_id,j) == 0)
{
@@ -2725,11 +2740,8 @@ int ssl3_check_finished(SSL *s)
{
int ok;
long n;
- /* If we have no ticket or session ID is non-zero length (a match of
- * a non-zero session length would never reach here) it cannot be a
- * resumed session.
- */
- if (!s->session->tlsext_tick || s->session->session_id_length)
+ /* If we have no ticket it cannot be a resumed session. */
+ if (!s->session->tlsext_tick)
return 1;
/* this function is called when we really expect a Certificate
* message, so permit appropriate message length */
diff -upr openssl-0.9.8x.orig/ssl/s3_srvr.c openssl-0.9.8x/ssl/s3_srvr.c
--- openssl-0.9.8x.orig/ssl/s3_srvr.c 2012-02-16 17:21:17.000000000 +0200
+++ openssl-0.9.8x/ssl/s3_srvr.c 2012-07-07 10:46:31.501140621 +0300
@@ -1009,6 +1009,59 @@ int ssl3_get_client_hello(SSL *s)
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
goto err;
}
+
+ /* Check if we want to use external pre-shared secret for this
+ * handshake for not reused session only. We need to generate
+ * server_random before calling tls_session_secret_cb in order to allow
+ * SessionTicket processing to use it in key derivation. */
+ {
+ unsigned long Time;
+ unsigned char *pos;
+ Time=(unsigned long)time(NULL); /* Time */
+ pos=s->s3->server_random;
+ l2n(Time,pos);
+ if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0)
+ {
+ al=SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
+ }
+
+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb)
+ {
+ SSL_CIPHER *pref_cipher=NULL;
+
+ s->session->master_key_length=sizeof(s->session->master_key);
+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg))
+ {
+ s->hit=1;
+ s->session->ciphers=ciphers;
+ s->session->verify_result=X509_V_OK;
+
+ ciphers=NULL;
+
+ /* check if some cipher was preferred by call back */
+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
+ if (pref_cipher == NULL)
+ {
+ al=SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
+ goto f_err;
+ }
+
+ s->session->cipher=pref_cipher;
+
+ if (s->cipher_list)
+ sk_SSL_CIPHER_free(s->cipher_list);
+
+ if (s->cipher_list_by_id)
+ sk_SSL_CIPHER_free(s->cipher_list_by_id);
+
+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
+ }
+ }
#endif
/* Worst case, we will use the NULL compression, but if we have other
* options, we will now look for them. We have i-1 compression
@@ -1147,16 +1200,22 @@ int ssl3_send_server_hello(SSL *s)
unsigned char *buf;
unsigned char *p,*d;
int i,sl;
- unsigned long l,Time;
+ unsigned long l;
+#ifdef OPENSSL_NO_TLSEXT
+ unsigned long Time;
+#endif
if (s->state == SSL3_ST_SW_SRVR_HELLO_A)
{
buf=(unsigned char *)s->init_buf->data;
+#ifdef OPENSSL_NO_TLSEXT
p=s->s3->server_random;
+ /* Generate server_random if it was not needed previously */
Time=(unsigned long)time(NULL); /* Time */
l2n(Time,p);
if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
return -1;
+#endif
/* Do the message type and length last */
d=p= &(buf[4]);
diff -upr openssl-0.9.8x.orig/ssl/ssl_err.c openssl-0.9.8x/ssl/ssl_err.c
--- openssl-0.9.8x.orig/ssl/ssl_err.c 2012-03-12 16:50:55.000000000 +0200
+++ openssl-0.9.8x/ssl/ssl_err.c 2012-07-07 10:46:31.501140621 +0300
@@ -264,6 +264,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
{ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"},
{ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"},
{ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"},
+{ERR_FUNC(SSL_F_SSL_SET_SESSION_TICKET_EXT), "SSL_set_session_ticket_ext"},
{0,NULL}
};
diff -upr openssl-0.9.8x.orig/ssl/ssl.h openssl-0.9.8x/ssl/ssl.h
--- openssl-0.9.8x.orig/ssl/ssl.h 2012-03-12 16:50:55.000000000 +0200
+++ openssl-0.9.8x/ssl/ssl.h 2012-07-07 10:46:31.501140621 +0300
@@ -344,6 +344,7 @@ extern "C" {
* 'struct ssl_st *' function parameters used to prototype callbacks
* in SSL_CTX. */
typedef struct ssl_st *ssl_crock_st;
+typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT;
/* used to hold info on the particular ciphers used */
typedef struct ssl_cipher_st
@@ -362,6 +363,9 @@ typedef struct ssl_cipher_st
DECLARE_STACK_OF(SSL_CIPHER)
+typedef int (*tls_session_ticket_ext_cb_fn)(SSL *s, const unsigned char *data, int len, void *arg);
+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
+
/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
typedef struct ssl_method_st
{
@@ -1050,6 +1054,18 @@ struct ssl_st
/* RFC4507 session ticket expected to be received or sent */
int tlsext_ticket_expected;
+
+ /* TLS Session Ticket extension override */
+ TLS_SESSION_TICKET_EXT *tlsext_session_ticket;
+
+ /* TLS Session Ticket extension callback */
+ tls_session_ticket_ext_cb_fn tls_session_ticket_ext_cb;
+ void *tls_session_ticket_ext_cb_arg;
+
+ /* TLS pre-shared secret session resumption */
+ tls_session_secret_cb_fn tls_session_secret_cb;
+ void *tls_session_secret_cb_arg;
+
SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
#define session_ctx initial_ctx
#else
@@ -1663,6 +1679,15 @@ void *SSL_COMP_get_compression_methods(v
int SSL_COMP_add_compression_method(int id,void *cm);
#endif
+/* TLS extensions functions */
+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len);
+
+int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb,
+ void *arg);
+
+/* Pre-shared secret session resumption functions */
+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
+
/* BEGIN ERROR CODES */
/* The following lines are auto generated by the script mkerr.pl. Any changes
* made after this point may be overwritten when the script is next run.
@@ -1866,6 +1891,7 @@ void ERR_load_SSL_strings(void);
#define SSL_F_TLS1_ENC 210
#define SSL_F_TLS1_SETUP_KEY_BLOCK 211
#define SSL_F_WRITE_PENDING 212
+#define SSL_F_SSL_SET_SESSION_TICKET_EXT 213
/* Reason codes. */
#define SSL_R_APP_DATA_IN_HANDSHAKE 100
diff -upr openssl-0.9.8x.orig/ssl/ssl_sess.c openssl-0.9.8x/ssl/ssl_sess.c
--- openssl-0.9.8x.orig/ssl/ssl_sess.c 2010-02-01 18:48:40.000000000 +0200
+++ openssl-0.9.8x/ssl/ssl_sess.c 2012-07-07 10:46:31.501140621 +0300
@@ -712,6 +712,61 @@ long SSL_CTX_get_timeout(const SSL_CTX *
return(s->session_timeout);
}
+#ifndef OPENSSL_NO_TLSEXT
+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len,
+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg)
+ {
+ if (s == NULL) return(0);
+ s->tls_session_secret_cb = tls_session_secret_cb;
+ s->tls_session_secret_cb_arg = arg;
+ return(1);
+ }
+
+int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb,
+ void *arg)
+ {
+ if (s == NULL) return(0);
+ s->tls_session_ticket_ext_cb = cb;
+ s->tls_session_ticket_ext_cb_arg = arg;
+ return(1);
+ }
+
+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len)
+ {
+ if (s->version >= TLS1_VERSION)
+ {
+ if (s->tlsext_session_ticket)
+ {
+ OPENSSL_free(s->tlsext_session_ticket);
+ s->tlsext_session_ticket = NULL;
+ }
+
+ s->tlsext_session_ticket = OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len);
+ if (!s->tlsext_session_ticket)
+ {
+ SSLerr(SSL_F_SSL_SET_SESSION_TICKET_EXT, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ if (ext_data)
+ {
+ s->tlsext_session_ticket->length = ext_len;
+ s->tlsext_session_ticket->data = s->tlsext_session_ticket + 1;
+ memcpy(s->tlsext_session_ticket->data, ext_data, ext_len);
+ }
+ else
+ {
+ s->tlsext_session_ticket->length = 0;
+ s->tlsext_session_ticket->data = NULL;
+ }
+
+ return 1;
+ }
+
+ return 0;
+ }
+#endif /* OPENSSL_NO_TLSEXT */
+
typedef struct timeout_param_st
{
SSL_CTX *ctx;
diff -upr openssl-0.9.8x.orig/ssl/t1_lib.c openssl-0.9.8x/ssl/t1_lib.c
--- openssl-0.9.8x.orig/ssl/t1_lib.c 2012-01-04 16:25:10.000000000 +0200
+++ openssl-0.9.8x/ssl/t1_lib.c 2012-07-07 10:47:31.153140501 +0300
@@ -106,6 +106,12 @@ int tls1_new(SSL *s)
void tls1_free(SSL *s)
{
+#ifndef OPENSSL_NO_TLSEXT
+ if (s->tlsext_session_ticket)
+ {
+ OPENSSL_free(s->tlsext_session_ticket);
+ }
+#endif
ssl3_free(s);
}
@@ -206,8 +212,23 @@ unsigned char *ssl_add_clienthello_tlsex
int ticklen;
if (!s->new_session && s->session && s->session->tlsext_tick)
ticklen = s->session->tlsext_ticklen;
+ else if (s->session && s->tlsext_session_ticket &&
+ s->tlsext_session_ticket->data)
+ {
+ ticklen = s->tlsext_session_ticket->length;
+ s->session->tlsext_tick = OPENSSL_malloc(ticklen);
+ if (!s->session->tlsext_tick)
+ return NULL;
+ memcpy(s->session->tlsext_tick,
+ s->tlsext_session_ticket->data,
+ ticklen);
+ s->session->tlsext_ticklen = ticklen;
+ }
else
ticklen = 0;
+ if (ticklen == 0 && s->tlsext_session_ticket &&
+ s->tlsext_session_ticket->data == NULL)
+ goto skip_ext;
/* Check for enough room 2 for extension type, 2 for len
* rest for ticket
*/
@@ -221,6 +242,7 @@ unsigned char *ssl_add_clienthello_tlsex
ret += ticklen;
}
}
+ skip_ext:
if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp &&
s->version != DTLS1_VERSION)
@@ -486,6 +508,15 @@ int ssl_parse_clienthello_tlsext(SSL *s,
return 0;
renegotiate_seen = 1;
}
+ else if (type == TLSEXT_TYPE_session_ticket)
+ {
+ if (s->tls_session_ticket_ext_cb &&
+ !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg))
+ {
+ *al = TLS1_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ }
else if (type == TLSEXT_TYPE_status_request &&
s->version != DTLS1_VERSION && s->ctx->tlsext_status_cb)
{
@@ -663,6 +694,12 @@ int ssl_parse_serverhello_tlsext(SSL *s,
}
else if (type == TLSEXT_TYPE_session_ticket)
{
+ if (s->tls_session_ticket_ext_cb &&
+ !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg))
+ {
+ *al = TLS1_AD_INTERNAL_ERROR;
+ return 0;
+ }
if ((SSL_get_options(s) & SSL_OP_NO_TICKET)
|| (size > 0))
{
@@ -920,6 +957,15 @@ int tls1_process_ticket(SSL *s, unsigned
s->tlsext_ticket_expected = 1;
return 0; /* Cache miss */
}
+ if (s->tls_session_secret_cb)
+ {
+ /* Indicate cache miss here and instead of
+ * generating the session from ticket now,
+ * trigger abbreviated handshake based on
+ * external mechanism to calculate the master
+ * secret later. */
+ return 0;
+ }
return tls_decrypt_ticket(s, p, size, session_id, len,
ret);
}
diff -upr openssl-0.9.8x.orig/ssl/tls1.h openssl-0.9.8x/ssl/tls1.h
--- openssl-0.9.8x.orig/ssl/tls1.h 2009-11-08 16:51:54.000000000 +0200
+++ openssl-0.9.8x/ssl/tls1.h 2012-07-07 10:46:31.501140621 +0300
@@ -401,6 +401,13 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_T
#define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/
#endif
+/* TLS extension struct */
+struct tls_session_ticket_ext_st
+ {
+ unsigned short length;
+ void *data;
+ };
+
#ifdef __cplusplus
}
#endif
diff -upr openssl-0.9.8x.orig/util/ssleay.num openssl-0.9.8x/util/ssleay.num
--- openssl-0.9.8x.orig/util/ssleay.num 2008-06-05 13:57:21.000000000 +0300
+++ openssl-0.9.8x/util/ssleay.num 2012-07-07 10:46:31.505140623 +0300
@@ -242,3 +242,5 @@ SSL_set_SSL_CTX
SSL_get_servername 291 EXIST::FUNCTION:TLSEXT
SSL_get_servername_type 292 EXIST::FUNCTION:TLSEXT
SSL_CTX_set_client_cert_engine 293 EXIST::FUNCTION:ENGINE
+SSL_set_session_ticket_ext 306 EXIST::FUNCTION:TLSEXT
+SSL_set_session_secret_cb 307 EXIST::FUNCTION:TLSEXT

View File

@ -1,374 +0,0 @@
This patch adds support for TLS SessionTicket extension (RFC 5077) for
the parts used by EAP-FAST (RFC 4851).
This is based on the patch from Alexey Kobozev <akobozev@cisco.com>
(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300).
NOTE: This patch (without SSL_set_hello_extension() wrapper) was
merged into the upstream OpenSSL 0.9.9 tree and as such, an external
patch for EAP-FAST support is not needed anymore.
Index: openssl-SNAP-20081111/ssl/s3_clnt.c
===================================================================
--- openssl-SNAP-20081111.orig/ssl/s3_clnt.c
+++ openssl-SNAP-20081111/ssl/s3_clnt.c
@@ -788,6 +788,23 @@ int ssl3_get_server_hello(SSL *s)
goto f_err;
}
+#ifndef OPENSSL_NO_TLSEXT
+ /* check if we want to resume the session based on external pre-shared secret */
+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
+ {
+ SSL_CIPHER *pref_cipher=NULL;
+ s->session->master_key_length=sizeof(s->session->master_key);
+ if (s->tls_session_secret_cb(s, s->session->master_key,
+ &s->session->master_key_length,
+ NULL, &pref_cipher,
+ s->tls_session_secret_cb_arg))
+ {
+ s->session->cipher = pref_cipher ?
+ pref_cipher : ssl_get_cipher_by_char(s, p+j);
+ }
+ }
+#endif /* OPENSSL_NO_TLSEXT */
+
if (j != 0 && j == s->session->session_id_length
&& memcmp(p,s->session->session_id,j) == 0)
{
@@ -2927,11 +2944,8 @@ static int ssl3_check_finished(SSL *s)
{
int ok;
long n;
- /* If we have no ticket or session ID is non-zero length (a match of
- * a non-zero session length would never reach here) it cannot be a
- * resumed session.
- */
- if (!s->session->tlsext_tick || s->session->session_id_length)
+ /* If we have no ticket it cannot be a resumed session. */
+ if (!s->session->tlsext_tick)
return 1;
/* this function is called when we really expect a Certificate
* message, so permit appropriate message length */
Index: openssl-SNAP-20081111/ssl/s3_srvr.c
===================================================================
--- openssl-SNAP-20081111.orig/ssl/s3_srvr.c
+++ openssl-SNAP-20081111/ssl/s3_srvr.c
@@ -1010,6 +1010,59 @@ int ssl3_get_client_hello(SSL *s)
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
goto err;
}
+
+ /* Check if we want to use external pre-shared secret for this
+ * handshake for not reused session only. We need to generate
+ * server_random before calling tls_session_secret_cb in order to allow
+ * SessionTicket processing to use it in key derivation. */
+ {
+ unsigned long Time;
+ unsigned char *pos;
+ Time=(unsigned long)time(NULL); /* Time */
+ pos=s->s3->server_random;
+ l2n(Time,pos);
+ if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0)
+ {
+ al=SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
+ }
+
+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb)
+ {
+ SSL_CIPHER *pref_cipher=NULL;
+
+ s->session->master_key_length=sizeof(s->session->master_key);
+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg))
+ {
+ s->hit=1;
+ s->session->ciphers=ciphers;
+ s->session->verify_result=X509_V_OK;
+
+ ciphers=NULL;
+
+ /* check if some cipher was preferred by call back */
+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
+ if (pref_cipher == NULL)
+ {
+ al=SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
+ goto f_err;
+ }
+
+ s->session->cipher=pref_cipher;
+
+ if (s->cipher_list)
+ sk_SSL_CIPHER_free(s->cipher_list);
+
+ if (s->cipher_list_by_id)
+ sk_SSL_CIPHER_free(s->cipher_list_by_id);
+
+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
+ }
+ }
#endif
/* Worst case, we will use the NULL compression, but if we have other
@@ -1134,16 +1187,22 @@ int ssl3_send_server_hello(SSL *s)
unsigned char *buf;
unsigned char *p,*d;
int i,sl;
- unsigned long l,Time;
+ unsigned long l;
+#ifdef OPENSSL_NO_TLSEXT
+ unsigned long Time;
+#endif
if (s->state == SSL3_ST_SW_SRVR_HELLO_A)
{
buf=(unsigned char *)s->init_buf->data;
+#ifdef OPENSSL_NO_TLSEXT
p=s->s3->server_random;
+ /* Generate server_random if it was not needed previously */
Time=(unsigned long)time(NULL); /* Time */
l2n(Time,p);
if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
return -1;
+#endif
/* Do the message type and length last */
d=p= &(buf[4]);
Index: openssl-SNAP-20081111/ssl/ssl_err.c
===================================================================
--- openssl-SNAP-20081111.orig/ssl/ssl_err.c
+++ openssl-SNAP-20081111/ssl/ssl_err.c
@@ -263,6 +263,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
{ERR_FUNC(SSL_F_TLS1_PRF), "tls1_prf"},
{ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"},
{ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"},
+{ERR_FUNC(SSL_F_SSL_SET_SESSION_TICKET_EXT), "SSL_set_session_ticket_ext"},
{0,NULL}
};
Index: openssl-SNAP-20081111/ssl/ssl.h
===================================================================
--- openssl-SNAP-20081111.orig/ssl/ssl.h
+++ openssl-SNAP-20081111/ssl/ssl.h
@@ -355,6 +355,7 @@ extern "C" {
* 'struct ssl_st *' function parameters used to prototype callbacks
* in SSL_CTX. */
typedef struct ssl_st *ssl_crock_st;
+typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT;
/* used to hold info on the particular ciphers used */
typedef struct ssl_cipher_st
@@ -378,6 +379,8 @@ typedef struct ssl_cipher_st
DECLARE_STACK_OF(SSL_CIPHER)
+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
+
/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
typedef struct ssl_method_st
{
@@ -1145,6 +1148,13 @@ struct ssl_st
void *tlsext_opaque_prf_input;
size_t tlsext_opaque_prf_input_len;
+ /* TLS Session Ticket extension override */
+ TLS_SESSION_TICKET_EXT *tlsext_session_ticket;
+
+ /* TLS pre-shared secret session resumption */
+ tls_session_secret_cb_fn tls_session_secret_cb;
+ void *tls_session_secret_cb_arg;
+
SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
#define session_ctx initial_ctx
#else
@@ -1746,6 +1756,16 @@ void *SSL_COMP_get_compression_methods(v
int SSL_COMP_add_compression_method(int id,void *cm);
#endif
+/* NOTE: This function will be removed; it is only here for backwards
+ * compatibility for the API during testing. */
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len);
+
+/* TLS extensions functions */
+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len);
+
+/* Pre-shared secret session resumption functions */
+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
+
/* BEGIN ERROR CODES */
/* The following lines are auto generated by the script mkerr.pl. Any changes
* made after this point may be overwritten when the script is next run.
@@ -1948,6 +1968,7 @@ void ERR_load_SSL_strings(void);
#define SSL_F_TLS1_PRF 284
#define SSL_F_TLS1_SETUP_KEY_BLOCK 211
#define SSL_F_WRITE_PENDING 212
+#define SSL_F_SSL_SET_SESSION_TICKET_EXT 213
/* Reason codes. */
#define SSL_R_APP_DATA_IN_HANDSHAKE 100
Index: openssl-SNAP-20081111/ssl/ssl_sess.c
===================================================================
--- openssl-SNAP-20081111.orig/ssl/ssl_sess.c
+++ openssl-SNAP-20081111/ssl/ssl_sess.c
@@ -834,6 +834,62 @@ long SSL_CTX_get_timeout(const SSL_CTX *
return(s->session_timeout);
}
+#ifndef OPENSSL_NO_TLSEXT
+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len,
+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg)
+ {
+ if (s == NULL) return(0);
+ s->tls_session_secret_cb = tls_session_secret_cb;
+ s->tls_session_secret_cb_arg = arg;
+ return(1);
+ }
+
+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len)
+ {
+ if (s->version >= TLS1_VERSION)
+ {
+ if (s->tlsext_session_ticket)
+ {
+ OPENSSL_free(s->tlsext_session_ticket);
+ s->tlsext_session_ticket = NULL;
+ }
+
+ s->tlsext_session_ticket = OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len);
+ if (!s->tlsext_session_ticket)
+ {
+ SSLerr(SSL_F_SSL_SET_SESSION_TICKET_EXT, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ if (ext_data)
+ {
+ s->tlsext_session_ticket->length = ext_len;
+ s->tlsext_session_ticket->data = s->tlsext_session_ticket + 1;
+ memcpy(s->tlsext_session_ticket->data, ext_data, ext_len);
+ }
+ else
+ {
+ s->tlsext_session_ticket->length = 0;
+ s->tlsext_session_ticket->data = NULL;
+ }
+
+ return 1;
+ }
+
+ return 0;
+ }
+
+/* NOTE: This function will be removed; it is only here for backwards
+ * compatibility for the API during testing. */
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len)
+ {
+ if (ext_type != TLSEXT_TYPE_session_ticket)
+ return 0;
+
+ return SSL_set_session_ticket_ext(s, ext_data, ext_len);
+ }
+#endif /* OPENSSL_NO_TLSEXT */
+
typedef struct timeout_param_st
{
SSL_CTX *ctx;
Index: openssl-SNAP-20081111/ssl/t1_lib.c
===================================================================
--- openssl-SNAP-20081111.orig/ssl/t1_lib.c
+++ openssl-SNAP-20081111/ssl/t1_lib.c
@@ -154,6 +154,12 @@ int tls1_new(SSL *s)
void tls1_free(SSL *s)
{
+#ifndef OPENSSL_NO_TLSEXT
+ if (s->tlsext_session_ticket)
+ {
+ OPENSSL_free(s->tlsext_session_ticket);
+ }
+#endif /* OPENSSL_NO_TLSEXT */
ssl3_free(s);
}
@@ -357,8 +363,23 @@ unsigned char *ssl_add_clienthello_tlsex
int ticklen;
if (s->session && s->session->tlsext_tick)
ticklen = s->session->tlsext_ticklen;
+ else if (s->session && s->tlsext_session_ticket &&
+ s->tlsext_session_ticket->data)
+ {
+ ticklen = s->tlsext_session_ticket->length;
+ s->session->tlsext_tick = OPENSSL_malloc(ticklen);
+ if (!s->session->tlsext_tick)
+ return NULL;
+ memcpy(s->session->tlsext_tick,
+ s->tlsext_session_ticket->data,
+ ticklen);
+ s->session->tlsext_ticklen = ticklen;
+ }
else
ticklen = 0;
+ if (ticklen == 0 && s->tlsext_session_ticket &&
+ s->tlsext_session_ticket->data == NULL)
+ goto skip_ext;
/* Check for enough room 2 for extension type, 2 for len
* rest for ticket
*/
@@ -371,6 +392,7 @@ unsigned char *ssl_add_clienthello_tlsex
ret += ticklen;
}
}
+ skip_ext:
#ifdef TLSEXT_TYPE_opaque_prf_input
if (s->s3->client_opaque_prf_input != NULL)
@@ -1435,6 +1457,15 @@ int tls1_process_ticket(SSL *s, unsigned
s->tlsext_ticket_expected = 1;
return 0; /* Cache miss */
}
+ if (s->tls_session_secret_cb)
+ {
+ /* Indicate cache miss here and instead of
+ * generating the session from ticket now,
+ * trigger abbreviated handshake based on
+ * external mechanism to calculate the master
+ * secret later. */
+ return 0;
+ }
return tls_decrypt_ticket(s, p, size, session_id, len,
ret);
}
Index: openssl-SNAP-20081111/ssl/tls1.h
===================================================================
--- openssl-SNAP-20081111.orig/ssl/tls1.h
+++ openssl-SNAP-20081111/ssl/tls1.h
@@ -512,6 +512,13 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_T
#define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/
#endif
+/* TLS Session Ticket extension struct */
+struct tls_session_ticket_ext_st
+ {
+ unsigned short length;
+ void *data;
+ };
+
#ifdef __cplusplus
}
#endif
Index: openssl-SNAP-20081111/util/ssleay.num
===================================================================
--- openssl-SNAP-20081111.orig/util/ssleay.num
+++ openssl-SNAP-20081111/util/ssleay.num
@@ -254,3 +254,5 @@ PEM_read_bio_SSL_SESSION
SSL_CTX_set_psk_server_callback 303 EXIST::FUNCTION:PSK
SSL_get_psk_identity 304 EXIST::FUNCTION:PSK
PEM_write_SSL_SESSION 305 EXIST:!WIN16:FUNCTION:
+SSL_set_session_ticket_ext 306 EXIST::FUNCTION:TLSEXT
+SSL_set_session_secret_cb 307 EXIST::FUNCTION:TLSEXT

View File

@ -1,6 +1,6 @@
/*
* IEEE 802.11 RSN / WPA Authenticator
* Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@ -11,6 +11,7 @@
#include "utils/common.h"
#include "utils/eloop.h"
#include "utils/state_machine.h"
#include "utils/bitfield.h"
#include "common/ieee802_11_defs.h"
#include "crypto/aes_wrap.h"
#include "crypto/crypto.h"
@ -82,11 +83,14 @@ static inline int wpa_auth_get_eapol(struct wpa_authenticator *wpa_auth,
static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth,
const u8 *addr, const u8 *prev_psk)
const u8 *addr,
const u8 *p2p_dev_addr,
const u8 *prev_psk)
{
if (wpa_auth->cb.get_psk == NULL)
return NULL;
return wpa_auth->cb.get_psk(wpa_auth->cb.ctx, addr, prev_psk);
return wpa_auth->cb.get_psk(wpa_auth->cb.ctx, addr, p2p_dev_addr,
prev_psk);
}
@ -207,6 +211,8 @@ static int wpa_use_aes_cmac(struct wpa_state_machine *sm)
if (wpa_key_mgmt_sha256(sm->wpa_key_mgmt))
ret = 1;
#endif /* CONFIG_IEEE80211W */
if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN)
ret = 1;
return ret;
}
@ -282,8 +288,9 @@ static void wpa_auth_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry,
static int wpa_group_init_gmk_and_counter(struct wpa_authenticator *wpa_auth,
struct wpa_group *group)
{
u8 buf[ETH_ALEN + 8 + sizeof(group)];
u8 buf[ETH_ALEN + 8 + sizeof(unsigned long)];
u8 rkey[32];
unsigned long ptr;
if (random_get_bytes(group->GMK, WPA_GMK_LEN) < 0)
return -1;
@ -295,7 +302,8 @@ static int wpa_group_init_gmk_and_counter(struct wpa_authenticator *wpa_auth,
*/
os_memcpy(buf, wpa_auth->addr, ETH_ALEN);
wpa_get_ntp_timestamp(buf + ETH_ALEN);
os_memcpy(buf + ETH_ALEN + 8, &group, sizeof(group));
ptr = (unsigned long) group;
os_memcpy(buf + ETH_ALEN + 8, &ptr, sizeof(ptr));
if (random_get_bytes(rkey, sizeof(rkey)) < 0)
return -1;
@ -419,6 +427,17 @@ struct wpa_authenticator * wpa_init(const u8 *addr,
wpa_rekey_gtk, wpa_auth, NULL);
}
#ifdef CONFIG_P2P
if (WPA_GET_BE32(conf->ip_addr_start)) {
int count = WPA_GET_BE32(conf->ip_addr_end) -
WPA_GET_BE32(conf->ip_addr_start) + 1;
if (count > 1000)
count = 1000;
if (count > 0)
wpa_auth->ip_pool = bitfield_alloc(count);
}
#endif /* CONFIG_P2P */
return wpa_auth;
}
@ -432,6 +451,8 @@ int wpa_init_keys(struct wpa_authenticator *wpa_auth)
wpa_group_sm_step(wpa_auth, group);
group->GInit = FALSE;
wpa_group_sm_step(wpa_auth, group);
if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
return -1;
return 0;
}
@ -459,6 +480,11 @@ void wpa_deinit(struct wpa_authenticator *wpa_auth)
wpa_auth->ft_pmk_cache = NULL;
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_P2P
bitfield_free(wpa_auth->ip_pool);
#endif /* CONFIG_P2P */
os_free(wpa_auth->wpa_ie);
group = wpa_auth->group;
@ -506,14 +532,20 @@ int wpa_reconfig(struct wpa_authenticator *wpa_auth,
struct wpa_state_machine *
wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr)
wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr,
const u8 *p2p_dev_addr)
{
struct wpa_state_machine *sm;
if (wpa_auth->group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
return NULL;
sm = os_zalloc(sizeof(struct wpa_state_machine));
if (sm == NULL)
return NULL;
os_memcpy(sm->addr, addr, ETH_ALEN);
if (p2p_dev_addr)
os_memcpy(sm->p2p_dev_addr, p2p_dev_addr, ETH_ALEN);
sm->wpa_auth = wpa_auth;
sm->group = wpa_auth->group;
@ -533,6 +565,8 @@ int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
"FT authentication already completed - do not "
"start 4-way handshake");
/* Go to PTKINITDONE state to allow GTK rekeying */
sm->wpa_ptk_state = WPA_PTK_PTKINITDONE;
return 0;
}
#endif /* CONFIG_IEEE80211R */
@ -570,12 +604,26 @@ void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm)
static void wpa_free_sta_sm(struct wpa_state_machine *sm)
{
#ifdef CONFIG_P2P
if (WPA_GET_BE32(sm->ip_addr)) {
u32 start;
wpa_printf(MSG_DEBUG, "P2P: Free assigned IP "
"address %u.%u.%u.%u from " MACSTR,
sm->ip_addr[0], sm->ip_addr[1],
sm->ip_addr[2], sm->ip_addr[3],
MAC2STR(sm->addr));
start = WPA_GET_BE32(sm->wpa_auth->conf.ip_addr_start);
bitfield_clear(sm->wpa_auth->ip_pool,
WPA_GET_BE32(sm->ip_addr) - start);
}
#endif /* CONFIG_P2P */
if (sm->GUpdateStationKeys) {
sm->group->GKeyDoneStations--;
sm->GUpdateStationKeys = FALSE;
}
#ifdef CONFIG_IEEE80211R
os_free(sm->assoc_resp_ftie);
wpabuf_free(sm->ft_pending_req_ies);
#endif /* CONFIG_IEEE80211R */
os_free(sm->last_rx_eapol_key);
os_free(sm->wpa_ie);
@ -835,6 +883,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
if (sm->pairwise == WPA_CIPHER_CCMP ||
sm->pairwise == WPA_CIPHER_GCMP) {
if (wpa_use_aes_cmac(sm) &&
sm->wpa_key_mgmt != WPA_KEY_MGMT_OSEN &&
ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
wpa_auth_logger(wpa_auth, sm->addr,
LOGGER_WARNING,
@ -958,6 +1007,9 @@ continue_processing:
if (kde.rsn_ie) {
eapol_key_ie = kde.rsn_ie;
eapol_key_ie_len = kde.rsn_ie_len;
} else if (kde.osen) {
eapol_key_ie = kde.osen;
eapol_key_ie_len = kde.osen_len;
} else {
eapol_key_ie = kde.wpa_ie;
eapol_key_ie_len = kde.wpa_ie_len;
@ -987,6 +1039,26 @@ continue_processing:
return;
}
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_P2P
if (kde.ip_addr_req && kde.ip_addr_req[0] &&
wpa_auth->ip_pool && WPA_GET_BE32(sm->ip_addr) == 0) {
int idx;
wpa_printf(MSG_DEBUG, "P2P: IP address requested in "
"EAPOL-Key exchange");
idx = bitfield_get_first_zero(wpa_auth->ip_pool);
if (idx >= 0) {
u32 start = WPA_GET_BE32(wpa_auth->conf.
ip_addr_start);
bitfield_set(wpa_auth->ip_pool, idx);
WPA_PUT_BE32(sm->ip_addr, start + idx);
wpa_printf(MSG_DEBUG, "P2P: Assigned IP "
"address %u.%u.%u.%u to " MACSTR,
sm->ip_addr[0], sm->ip_addr[1],
sm->ip_addr[2], sm->ip_addr[3],
MAC2STR(sm->addr));
}
}
#endif /* CONFIG_P2P */
break;
case PAIRWISE_4:
if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING ||
@ -1223,6 +1295,8 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
if (force_version)
version = force_version;
else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN)
version = WPA_KEY_INFO_TYPE_AKM_DEFINED;
else if (wpa_use_aes_cmac(sm))
version = WPA_KEY_INFO_TYPE_AES_128_CMAC;
else if (sm->pairwise != WPA_CIPHER_TKIP)
@ -1230,7 +1304,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
else
version = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
pairwise = key_info & WPA_KEY_INFO_KEY_TYPE;
pairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE);
wpa_printf(MSG_DEBUG, "WPA: Send EAPOL(version=%d secure=%d mic=%d "
"ack=%d install=%d pairwise=%d kde_len=%lu keyidx=%d "
@ -1245,6 +1319,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
key_data_len = kde_len;
if ((version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN ||
version == WPA_KEY_INFO_TYPE_AES_128_CMAC) && encr) {
pad_len = key_data_len % 8;
if (pad_len)
@ -1313,8 +1388,10 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data",
buf, key_data_len);
if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN ||
version == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
if (aes_wrap(sm->PTK.kek, (key_data_len - 8) / 8, buf,
if (aes_wrap(sm->PTK.kek, 16,
(key_data_len - 8) / 8, buf,
(u8 *) (key + 1))) {
os_free(hdr);
os_free(buf);
@ -1345,6 +1422,16 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
}
wpa_eapol_key_mic(sm->PTK.kck, version, (u8 *) hdr, len,
key->key_mic);
#ifdef CONFIG_TESTING_OPTIONS
if (!pairwise &&
wpa_auth->conf.corrupt_gtk_rekey_mic_probability > 0.0 &&
drand48() <
wpa_auth->conf.corrupt_gtk_rekey_mic_probability) {
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
"Corrupting group EAPOL-Key Key MIC");
key->key_mic[0]++;
}
#endif /* CONFIG_TESTING_OPTIONS */
}
wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx,
@ -1404,7 +1491,7 @@ static int wpa_verify_key_mic(struct wpa_ptk *PTK, u8 *data, size_t data_len)
os_memset(key->key_mic, 0, 16);
if (wpa_eapol_key_mic(PTK->kck, key_info & WPA_KEY_INFO_TYPE_MASK,
data, data_len, key->key_mic) ||
os_memcmp(mic, key->key_mic, 16) != 0)
os_memcmp_const(mic, key->key_mic, 16) != 0)
ret = -1;
os_memcpy(key->key_mic, mic, 16);
return ret;
@ -1596,6 +1683,7 @@ SM_STATE(WPA_PTK, AUTHENTICATION2)
SM_ENTRY_MA(WPA_PTK, AUTHENTICATION2, wpa_ptk);
wpa_group_ensure_init(sm->wpa_auth, sm->group);
sm->ReAuthenticationRequest = FALSE;
/*
* Definition of ANonce selection in IEEE Std 802.11i-2004 is somewhat
@ -1609,12 +1697,11 @@ SM_STATE(WPA_PTK, AUTHENTICATION2)
if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
wpa_printf(MSG_ERROR, "WPA: Failed to get random data for "
"ANonce.");
wpa_sta_disconnect(sm->wpa_auth, sm->addr);
sm->Disconnect = TRUE;
return;
}
wpa_hexdump(MSG_DEBUG, "WPA: Assign ANonce", sm->ANonce,
WPA_NONCE_LEN);
sm->ReAuthenticationRequest = FALSE;
/* IEEE 802.11i does not clear TimeoutCtr here, but this is more
* logical place than INITIALIZE since AUTHENTICATION2 can be
* re-entered on ReAuthenticationRequest without going through
@ -1666,7 +1753,7 @@ SM_STATE(WPA_PTK, INITPSK)
{
const u8 *psk;
SM_ENTRY_MA(WPA_PTK, INITPSK, wpa_ptk);
psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, NULL);
psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, NULL);
if (psk) {
os_memcpy(sm->PMK, psk, PMK_LEN);
#ifdef CONFIG_IEEE80211R
@ -1701,7 +1788,8 @@ SM_STATE(WPA_PTK, PTKSTART)
* one possible PSK for this STA.
*/
if (sm->wpa == WPA_VERSION_WPA2 &&
wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt)) {
wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) &&
sm->wpa_key_mgmt != WPA_KEY_MGMT_OSEN) {
pmkid = buf;
pmkid_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN;
pmkid[0] = WLAN_EID_VENDOR_SPECIFIC;
@ -1729,7 +1817,7 @@ SM_STATE(WPA_PTK, PTKSTART)
static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *pmk,
struct wpa_ptk *ptk)
{
size_t ptk_len = sm->pairwise != WPA_CIPHER_TKIP ? 48 : 64;
size_t ptk_len = wpa_cipher_key_len(sm->pairwise) + 32;
#ifdef CONFIG_IEEE80211R
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt))
return wpa_auth_derive_ptk_ft(sm, pmk, ptk, ptk_len);
@ -1759,7 +1847,8 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
* the packet */
for (;;) {
if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) {
pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, pmk);
pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
sm->p2p_dev_addr, pmk);
if (pmk == NULL)
break;
} else
@ -1789,8 +1878,8 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
* Verify that PMKR1Name from EAPOL-Key message 2/4 matches
* with the value we derived.
*/
if (os_memcmp(sm->sup_pmk_r1_name, sm->pmk_r1_name,
WPA_PMK_NAME_LEN) != 0) {
if (os_memcmp_const(sm->sup_pmk_r1_name, sm->pmk_r1_name,
WPA_PMK_NAME_LEN) != 0) {
wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
"PMKR1Name mismatch in FT 4-way "
"handshake");
@ -1833,7 +1922,9 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING2)
static int ieee80211w_kde_len(struct wpa_state_machine *sm)
{
if (sm->mgmt_frame_prot) {
return 2 + RSN_SELECTOR_LEN + sizeof(struct wpa_igtk_kde);
size_t len;
len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
return 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN + len;
}
return 0;
@ -1844,6 +1935,8 @@ static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos)
{
struct wpa_igtk_kde igtk;
struct wpa_group *gsm = sm->group;
u8 rsc[WPA_KEY_RSC_LEN];
size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
if (!sm->mgmt_frame_prot)
return pos;
@ -1851,19 +1944,22 @@ static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos)
igtk.keyid[0] = gsm->GN_igtk;
igtk.keyid[1] = 0;
if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE ||
wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, igtk.pn) < 0)
wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, rsc) < 0)
os_memset(igtk.pn, 0, sizeof(igtk.pn));
os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN);
else
os_memcpy(igtk.pn, rsc, sizeof(igtk.pn));
os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], len);
if (sm->wpa_auth->conf.disable_gtk) {
/*
* Provide unique random IGTK to each STA to prevent use of
* IGTK in the BSS.
*/
if (random_get_bytes(igtk.igtk, WPA_IGTK_LEN) < 0)
if (random_get_bytes(igtk.igtk, len) < 0)
return pos;
}
pos = wpa_add_kde(pos, RSN_KEY_DATA_IGTK,
(const u8 *) &igtk, sizeof(igtk), NULL, 0);
(const u8 *) &igtk, WPA_IGTK_KDE_PREFIX_LEN + len,
NULL, 0);
return pos;
}
@ -1968,6 +2064,10 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
kde_len += 300; /* FTIE + 2 * TIE */
}
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_P2P
if (WPA_GET_BE32(sm->ip_addr) > 0)
kde_len += 2 + RSN_SELECTOR_LEN + 3 * 4;
#endif /* CONFIG_P2P */
kde = os_malloc(kde_len);
if (kde == NULL)
return;
@ -2029,6 +2129,16 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
pos += 4;
}
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_P2P
if (WPA_GET_BE32(sm->ip_addr) > 0) {
u8 addr[3 * 4];
os_memcpy(addr, sm->ip_addr, 4);
os_memcpy(addr + 4, sm->wpa_auth->conf.ip_addr_mask, 4);
os_memcpy(addr + 8, sm->wpa_auth->conf.ip_addr_go, 4);
pos = wpa_add_kde(pos, WFA_KEY_DATA_IP_ADDR_ALLOC,
addr, sizeof(addr), NULL, 0);
}
#endif /* CONFIG_P2P */
wpa_send_eapol(sm->wpa_auth, sm,
(secure ? WPA_KEY_INFO_SECURE : 0) | WPA_KEY_INFO_MIC |
@ -2146,7 +2256,8 @@ SM_STEP(WPA_PTK)
}
break;
case WPA_PTK_INITPSK:
if (wpa_auth_get_psk(sm->wpa_auth, sm->addr, NULL))
if (wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr,
NULL))
SM_ENTER(WPA_PTK, PTKSTART);
else {
wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO,
@ -2354,15 +2465,16 @@ static int wpa_gtk_update(struct wpa_authenticator *wpa_auth,
#ifdef CONFIG_IEEE80211W
if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) {
size_t len;
len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
inc_byte_array(group->Counter, WPA_NONCE_LEN);
if (wpa_gmk_to_gtk(group->GMK, "IGTK key expansion",
wpa_auth->addr, group->GNonce,
group->IGTK[group->GN_igtk - 4],
WPA_IGTK_LEN) < 0)
group->IGTK[group->GN_igtk - 4], len) < 0)
ret = -1;
wpa_hexdump_key(MSG_DEBUG, "IGTK",
group->IGTK[group->GN_igtk - 4], WPA_IGTK_LEN);
group->IGTK[group->GN_igtk - 4], len);
}
#endif /* CONFIG_IEEE80211W */
@ -2429,7 +2541,7 @@ static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx)
/* update GTK when exiting WNM-Sleep Mode */
void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm)
{
if (sm->is_wnmsleep)
if (sm == NULL || sm->is_wnmsleep)
return;
wpa_group_update_sta(sm, NULL);
@ -2438,7 +2550,8 @@ void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm)
void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag)
{
sm->is_wnmsleep = !!flag;
if (sm)
sm->is_wnmsleep = !!flag;
}
@ -2478,26 +2591,27 @@ int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos)
{
struct wpa_group *gsm = sm->group;
u8 *start = pos;
size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
/*
* IGTK subelement:
* Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16]
*/
*pos++ = WNM_SLEEP_SUBELEM_IGTK;
*pos++ = 2 + 6 + WPA_IGTK_LEN;
*pos++ = 2 + 6 + len;
WPA_PUT_LE16(pos, gsm->GN_igtk);
pos += 2;
if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos) != 0)
return 0;
pos += 6;
os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN);
pos += WPA_IGTK_LEN;
os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], len);
pos += len;
wpa_printf(MSG_DEBUG, "WNM: IGTK Key ID %u in WNM-Sleep Mode exit",
gsm->GN_igtk);
wpa_hexdump_key(MSG_DEBUG, "WNM: IGTK in WNM-Sleep Mode exit",
gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN);
gsm->IGTK[gsm->GN_igtk - 4], len);
return pos - start;
}
@ -2552,18 +2666,48 @@ static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
ret = -1;
#ifdef CONFIG_IEEE80211W
if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION &&
wpa_auth_set_key(wpa_auth, group->vlan_id, WPA_ALG_IGTK,
broadcast_ether_addr, group->GN_igtk,
group->IGTK[group->GN_igtk - 4],
WPA_IGTK_LEN) < 0)
ret = -1;
if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) {
enum wpa_alg alg;
size_t len;
alg = wpa_cipher_to_alg(wpa_auth->conf.group_mgmt_cipher);
len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
if (ret == 0 &&
wpa_auth_set_key(wpa_auth, group->vlan_id, alg,
broadcast_ether_addr, group->GN_igtk,
group->IGTK[group->GN_igtk - 4], len) < 0)
ret = -1;
}
#endif /* CONFIG_IEEE80211W */
return ret;
}
static int wpa_group_disconnect_cb(struct wpa_state_machine *sm, void *ctx)
{
if (sm->group == ctx) {
wpa_printf(MSG_DEBUG, "WPA: Mark STA " MACSTR
" for discconnection due to fatal failure",
MAC2STR(sm->addr));
sm->Disconnect = TRUE;
}
return 0;
}
static void wpa_group_fatal_failure(struct wpa_authenticator *wpa_auth,
struct wpa_group *group)
{
wpa_printf(MSG_DEBUG, "WPA: group state machine entering state FATAL_FAILURE");
group->changed = TRUE;
group->wpa_group_state = WPA_GROUP_FATAL_FAILURE;
wpa_auth_for_each_sta(wpa_auth, wpa_group_disconnect_cb, group);
}
static int wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth,
struct wpa_group *group)
{
@ -2572,8 +2716,10 @@ static int wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth,
group->changed = TRUE;
group->wpa_group_state = WPA_GROUP_SETKEYSDONE;
if (wpa_group_config_group_keys(wpa_auth, group) < 0)
if (wpa_group_config_group_keys(wpa_auth, group) < 0) {
wpa_group_fatal_failure(wpa_auth, group);
return -1;
}
return 0;
}
@ -2584,6 +2730,8 @@ static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth,
{
if (group->GInit) {
wpa_group_gtk_init(wpa_auth, group);
} else if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) {
/* Do not allow group operations */
} else if (group->wpa_group_state == WPA_GROUP_GTK_INIT &&
group->GTKAuthenticator) {
wpa_group_setkeysdone(wpa_auth, group);
@ -2932,6 +3080,22 @@ int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
}
void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth,
const u8 *sta_addr)
{
struct rsn_pmksa_cache_entry *pmksa;
if (wpa_auth == NULL || wpa_auth->pmksa == NULL)
return;
pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, NULL);
if (pmksa) {
wpa_printf(MSG_DEBUG, "WPA: Remove PMKSA cache entry for "
MACSTR " based on request", MAC2STR(sta_addr));
pmksa_cache_free_entry(wpa_auth->pmksa, pmksa);
}
}
static struct wpa_group *
wpa_auth_add_group(struct wpa_authenticator *wpa_auth, int vlan_id)
{
@ -2976,6 +3140,9 @@ int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id)
if (sm->group == group)
return 0;
if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
return -1;
wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR " to use group state "
"machine for VLAN ID %d", MAC2STR(sm->addr), vlan_id);
@ -3020,3 +3187,22 @@ int wpa_auth_uses_sae(struct wpa_state_machine *sm)
return 0;
return wpa_key_mgmt_sae(sm->wpa_key_mgmt);
}
int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm)
{
if (sm == NULL)
return 0;
return sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE;
}
#ifdef CONFIG_P2P
int wpa_auth_get_ip_addr(struct wpa_state_machine *sm, u8 *addr)
{
if (sm == NULL || WPA_GET_BE32(sm->ip_addr) == 0)
return -1;
os_memcpy(addr, sm->ip_addr, 4);
return 0;
}
#endif /* CONFIG_P2P */

View File

@ -1,19 +0,0 @@
/*
* FIPS 186-2 PRF for Microsoft CryptoAPI
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include "common.h"
#include "crypto.h"
int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
{
/* FIX: how to do this with CryptoAPI? */
return -1;
}

View File

@ -1,20 +0,0 @@
/*
* FIPS 186-2 PRF for libgcrypt
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include <gcrypt.h>
#include "common.h"
#include "crypto.h"
int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
{
/* FIX: how to do this with libgcrypt? */
return -1;
}

View File

@ -1,19 +0,0 @@
/*
* FIPS 186-2 PRF for NSS
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include <openssl/sha.h>
#include "common.h"
#include "crypto.h"
int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
{
return -1;
}

View File

@ -62,6 +62,9 @@ struct bsd_driver_data {
int prev_roaming; /* roaming state to restore on deinit */
int prev_privacy; /* privacy state to restore on deinit */
int prev_wpa; /* wpa state to restore on deinit */
enum ieee80211_opmode opmode; /* operation mode */
char *event_buf;
size_t event_buf_len;
};
/* Generic functions for hostapd and wpa_supplicant */
@ -266,10 +269,15 @@ bsd_ctrl_iface(void *priv, int enable)
return -1;
}
if (enable)
if (enable) {
if (ifr.ifr_flags & IFF_UP)
return 0;
ifr.ifr_flags |= IFF_UP;
else
} else {
if (!(ifr.ifr_flags & IFF_UP))
return 0;
ifr.ifr_flags &= ~IFF_UP;
}
if (ioctl(drv->sock, SIOCSIFFLAGS, &ifr) < 0) {
perror("ioctl[SIOCSIFFLAGS]");
@ -285,6 +293,9 @@ bsd_set_key(const char *ifname, void *priv, enum wpa_alg alg,
size_t seq_len, const u8 *key, size_t key_len)
{
struct ieee80211req_key wk;
#ifdef IEEE80211_KEY_NOREPLAY
struct bsd_driver_data *drv = priv;
#endif /* IEEE80211_KEY_NOREPLAY */
wpa_printf(MSG_DEBUG, "%s: alg=%d addr=%p key_idx=%d set_tx=%d "
"seq_len=%zu key_len=%zu", __func__, alg, addr, key_idx,
@ -339,6 +350,16 @@ bsd_set_key(const char *ifname, void *priv, enum wpa_alg alg,
}
if (wk.ik_keyix != IEEE80211_KEYIX_NONE && set_tx)
wk.ik_flags |= IEEE80211_KEY_DEFAULT;
#ifndef HOSTAPD
#ifdef IEEE80211_KEY_NOREPLAY
/*
* Ignore replay failures in IBSS and AHDEMO mode.
*/
if (drv->opmode == IEEE80211_M_IBSS ||
drv->opmode == IEEE80211_M_AHDEMO)
wk.ik_flags |= IEEE80211_KEY_NOREPLAY;
#endif /* IEEE80211_KEY_NOREPLAY */
#endif /* HOSTAPD */
wk.ik_keylen = key_len;
if (seq) {
#ifdef WORDS_BIGENDIAN
@ -474,26 +495,6 @@ bsd_set_ieee8021x(void *priv, struct wpa_bss_params *params)
return bsd_ctrl_iface(priv, 1);
}
static int
bsd_set_sta_authorized(void *priv, const u8 *addr,
int total_flags, int flags_or, int flags_and)
{
int authorized = -1;
/* For now, only support setting Authorized flag */
if (flags_or & WPA_STA_AUTHORIZED)
authorized = 1;
if (!(flags_and & WPA_STA_AUTHORIZED))
authorized = 0;
if (authorized < 0)
return 0;
return bsd_send_mlme_param(priv, authorized ?
IEEE80211_MLME_AUTHORIZE :
IEEE80211_MLME_UNAUTHORIZE, 0, addr);
}
static void
bsd_new_sta(void *priv, void *ctx, u8 addr[IEEE80211_ADDR_LEN])
{
@ -586,7 +587,7 @@ bsd_set_opt_ie(void *priv, const u8 *ie, size_t ie_len)
return 0;
}
static int
static size_t
rtbuf_len(void)
{
size_t len;
@ -726,37 +727,26 @@ static void
bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx)
{
struct bsd_driver_data *drv = ctx;
char *buf;
struct if_announcemsghdr *ifan;
struct rt_msghdr *rtm;
struct ieee80211_michael_event *mic;
struct ieee80211_join_event *join;
struct ieee80211_leave_event *leave;
int n, len;
int n;
union wpa_event_data data;
len = rtbuf_len();
buf = os_malloc(len);
if (buf == NULL) {
wpa_printf(MSG_ERROR, "%s os_malloc() failed\n", __func__);
return;
}
n = read(sock, buf, len);
n = read(sock, drv->event_buf, drv->event_buf_len);
if (n < 0) {
if (errno != EINTR && errno != EAGAIN)
wpa_printf(MSG_ERROR, "%s read() failed: %s\n",
__func__, strerror(errno));
os_free(buf);
return;
}
rtm = (struct rt_msghdr *) buf;
rtm = (struct rt_msghdr *) drv->event_buf;
if (rtm->rtm_version != RTM_VERSION) {
wpa_printf(MSG_DEBUG, "Invalid routing message version=%d",
rtm->rtm_version);
os_free(buf);
return;
}
ifan = (struct if_announcemsghdr *) rtm;
@ -797,7 +787,6 @@ bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx)
}
break;
}
os_free(buf);
}
static void
@ -814,7 +803,15 @@ bsd_init(struct hostapd_data *hapd, struct wpa_init_params *params)
drv = os_zalloc(sizeof(struct bsd_driver_data));
if (drv == NULL) {
printf("Could not allocate memory for bsd driver data\n");
wpa_printf(MSG_ERROR, "Could not allocate memory for bsd driver data");
return NULL;
}
drv->event_buf_len = rtbuf_len();
drv->event_buf = os_malloc(drv->event_buf_len);
if (drv->event_buf == NULL) {
wpa_printf(MSG_ERROR, "%s: os_malloc() failed", __func__);
goto bad;
}
@ -858,6 +855,7 @@ bad:
l2_packet_deinit(drv->sock_xmit);
if (drv->sock >= 0)
close(drv->sock);
os_free(drv->event_buf);
os_free(drv);
}
return NULL;
@ -878,9 +876,37 @@ bsd_deinit(void *priv)
close(drv->sock);
if (drv->sock_xmit != NULL)
l2_packet_deinit(drv->sock_xmit);
os_free(drv->event_buf);
os_free(drv);
}
static int
bsd_commit(void *priv)
{
return bsd_ctrl_iface(priv, 1);
}
static int
bsd_set_sta_authorized(void *priv, const u8 *addr,
int total_flags, int flags_or, int flags_and)
{
int authorized = -1;
/* For now, only support setting Authorized flag */
if (flags_or & WPA_STA_AUTHORIZED)
authorized = 1;
if (!(flags_and & WPA_STA_AUTHORIZED))
authorized = 0;
if (authorized < 0)
return 0;
return bsd_send_mlme_param(priv, authorized ?
IEEE80211_MLME_AUTHORIZE :
IEEE80211_MLME_UNAUTHORIZE, 0, addr);
}
#else /* HOSTAPD */
static int
@ -1058,9 +1084,9 @@ wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params)
if (wpa_driver_bsd_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0)
return -1;
privacy = !(params->pairwise_suite == CIPHER_NONE &&
params->group_suite == CIPHER_NONE &&
params->key_mgmt_suite == KEY_MGMT_NONE &&
privacy = !(params->pairwise_suite == WPA_CIPHER_NONE &&
params->group_suite == WPA_CIPHER_NONE &&
params->key_mgmt_suite == WPA_KEY_MGMT_NONE &&
params->wpa_ie_len == 0);
wpa_printf(MSG_DEBUG, "%s: set PRIVACY %u", __func__, privacy);
@ -1156,7 +1182,6 @@ static void
wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
{
struct bsd_driver_data *drv = sock_ctx;
char *buf;
struct if_announcemsghdr *ifan;
struct if_msghdr *ifm;
struct rt_msghdr *rtm;
@ -1164,30 +1189,20 @@ wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
struct ieee80211_michael_event *mic;
struct ieee80211_leave_event *leave;
struct ieee80211_join_event *join;
int n, len;
int n;
len = rtbuf_len();
buf = os_malloc(len);
if (buf == NULL) {
wpa_printf(MSG_ERROR, "%s os_malloc() failed\n", __func__);
return;
}
n = read(sock, buf, len);
n = read(sock, drv->event_buf, drv->event_buf_len);
if (n < 0) {
if (errno != EINTR && errno != EAGAIN)
wpa_printf(MSG_ERROR, "%s read() failed: %s\n",
__func__, strerror(errno));
os_free(buf);
return;
}
rtm = (struct rt_msghdr *) buf;
rtm = (struct rt_msghdr *) drv->event_buf;
if (rtm->rtm_version != RTM_VERSION) {
wpa_printf(MSG_DEBUG, "Invalid routing message version=%d",
rtm->rtm_version);
os_free(buf);
return;
}
os_memset(&event, 0, sizeof(event));
@ -1206,7 +1221,6 @@ wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
event.interface_status.ievent = EVENT_INTERFACE_ADDED;
break;
#else
os_free(buf);
return;
#endif
}
@ -1331,7 +1345,6 @@ wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
wpa_printf(MSG_DEBUG, "RTM_???: %d", rtm->rtm_type);
break;
}
os_free(buf);
}
static void
@ -1356,6 +1369,11 @@ wpa_driver_bsd_add_scan_entry(struct wpa_scan_results *res,
result->caps = sr->isr_capinfo;
result->level = sr->isr_rssi;
result->noise = sr->isr_noise;
/*
* the rssi value reported by the kernel is in 0.5dB steps relative to
* the reported noise floor. see ieee80211_node.h for details.
*/
result->level = sr->isr_rssi / 2 + sr->isr_noise;
pos = (u8 *)(result + 1);
@ -1497,6 +1515,33 @@ static int wpa_driver_bsd_capa(struct bsd_driver_data *drv)
return 0;
}
static enum ieee80211_opmode
get80211opmode(struct bsd_driver_data *drv)
{
struct ifmediareq ifmr;
(void) memset(&ifmr, 0, sizeof(ifmr));
(void) os_strlcpy(ifmr.ifm_name, drv->ifname, sizeof(ifmr.ifm_name));
if (ioctl(drv->sock, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0) {
if (ifmr.ifm_current & IFM_IEEE80211_ADHOC) {
if (ifmr.ifm_current & IFM_FLAG0)
return IEEE80211_M_AHDEMO;
else
return IEEE80211_M_IBSS;
}
if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP)
return IEEE80211_M_HOSTAP;
if (ifmr.ifm_current & IFM_IEEE80211_MONITOR)
return IEEE80211_M_MONITOR;
#ifdef IEEE80211_M_MBSS
if (ifmr.ifm_current & IFM_IEEE80211_MBSS)
return IEEE80211_M_MBSS;
#endif /* IEEE80211_M_MBSS */
}
return IEEE80211_M_STA;
}
static void *
wpa_driver_bsd_init(void *ctx, const char *ifname)
{
@ -1507,6 +1552,15 @@ wpa_driver_bsd_init(void *ctx, const char *ifname)
drv = os_zalloc(sizeof(*drv));
if (drv == NULL)
return NULL;
drv->event_buf_len = rtbuf_len();
drv->event_buf = os_malloc(drv->event_buf_len);
if (drv->event_buf == NULL) {
wpa_printf(MSG_ERROR, "%s: os_malloc() failed", __func__);
goto fail1;
}
/*
* NB: We require the interface name be mappable to an index.
* This implies we do not support having wpa_supplicant
@ -1522,6 +1576,12 @@ wpa_driver_bsd_init(void *ctx, const char *ifname)
drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
if (drv->sock < 0)
goto fail1;
os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
/* Down interface during setup. */
if (bsd_ctrl_iface(drv, 0) < 0)
goto fail;
drv->route = socket(PF_ROUTE, SOCK_RAW, 0);
if (drv->route < 0)
goto fail;
@ -1529,11 +1589,6 @@ wpa_driver_bsd_init(void *ctx, const char *ifname)
wpa_driver_bsd_event_receive, ctx, drv);
drv->ctx = ctx;
os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
/* Down interface during setup. */
if (bsd_ctrl_iface(drv, 0) < 0)
goto fail;
if (!GETPARAM(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)) {
wpa_printf(MSG_DEBUG, "%s: failed to get roaming state: %s",
@ -1554,10 +1609,13 @@ wpa_driver_bsd_init(void *ctx, const char *ifname)
if (wpa_driver_bsd_capa(drv))
goto fail;
drv->opmode = get80211opmode(drv);
return drv;
fail:
close(drv->sock);
fail1:
os_free(drv->event_buf);
os_free(drv);
return NULL;
#undef GETPARAM
@ -1583,6 +1641,7 @@ wpa_driver_bsd_deinit(void *priv)
l2_packet_deinit(drv->sock_xmit);
(void) close(drv->route); /* ioctl socket */
(void) close(drv->sock); /* event socket */
os_free(drv->event_buf);
os_free(drv);
}
@ -1609,6 +1668,8 @@ const struct wpa_driver_ops wpa_driver_bsd_ops = {
.read_sta_data = bsd_read_sta_driver_data,
.sta_disassoc = bsd_sta_disassoc,
.sta_deauth = bsd_sta_deauth,
.sta_set_flags = bsd_set_sta_authorized,
.commit = bsd_commit,
#else /* HOSTAPD */
.init = wpa_driver_bsd_init,
.deinit = wpa_driver_bsd_deinit,
@ -1627,6 +1688,5 @@ const struct wpa_driver_ops wpa_driver_bsd_ops = {
.hapd_set_ssid = bsd_set_ssid,
.hapd_get_ssid = bsd_get_ssid,
.hapd_send_eapol = bsd_send_eapol,
.sta_set_flags = bsd_set_sta_authorized,
.set_generic_elem = bsd_set_opt_ie,
};

View File

@ -28,7 +28,6 @@
#include "common/ieee802_11_defs.h"
#include "crypto/sha1.h"
#include "l2_packet/l2_packet.h"
#include "p2p/p2p.h"
#include "wps/wps.h"
#include "driver.h"
@ -102,20 +101,6 @@ struct wpa_driver_test_data {
unsigned int remain_on_channel_duration;
int current_freq;
struct p2p_data *p2p;
unsigned int off_channel_freq;
struct wpabuf *pending_action_tx;
u8 pending_action_src[ETH_ALEN];
u8 pending_action_dst[ETH_ALEN];
u8 pending_action_bssid[ETH_ALEN];
unsigned int pending_action_freq;
unsigned int pending_action_no_cck;
unsigned int pending_listen_freq;
unsigned int pending_listen_duration;
int pending_p2p_scan;
struct sockaddr *probe_from;
socklen_t probe_from_len;
};
@ -125,7 +110,6 @@ static int wpa_driver_test_attach(struct wpa_driver_test_data *drv,
static void wpa_driver_test_close_test_socket(
struct wpa_driver_test_data *drv);
static void test_remain_on_channel_timeout(void *eloop_ctx, void *timeout_ctx);
static int wpa_driver_test_init_p2p(struct wpa_driver_test_data *drv);
static void test_driver_free_bss(struct test_driver_bss *bss)
@ -479,34 +463,6 @@ static int wpa_driver_test_send_mlme(void *priv, const u8 *data,
event.tx_status.ack = ret >= 0;
wpa_supplicant_event(drv->ctx, EVENT_TX_STATUS, &event);
#ifdef CONFIG_P2P
if (drv->p2p &&
WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION) {
if (drv->pending_action_tx == NULL) {
wpa_printf(MSG_DEBUG, "P2P: Ignore Action TX status - "
"no pending operation");
return ret;
}
if (os_memcmp(hdr->addr1, drv->pending_action_dst, ETH_ALEN) !=
0) {
wpa_printf(MSG_DEBUG, "P2P: Ignore Action TX status - "
"unknown destination address");
return ret;
}
wpabuf_free(drv->pending_action_tx);
drv->pending_action_tx = NULL;
p2p_send_action_cb(drv->p2p, drv->pending_action_freq,
drv->pending_action_dst,
drv->pending_action_src,
drv->pending_action_bssid,
ret >= 0);
}
#endif /* CONFIG_P2P */
return ret;
}
@ -553,10 +509,6 @@ static void test_driver_scan(struct wpa_driver_test_data *drv,
event.rx_probe_req.ie = ie;
event.rx_probe_req.ie_len = ielen;
wpa_supplicant_event(drv->ctx, EVENT_RX_PROBE_REQ, &event);
#ifdef CONFIG_P2P
if (drv->p2p)
p2p_probe_req_rx(drv->p2p, sa, NULL, NULL, ie, ielen);
#endif /* CONFIG_P2P */
}
dl_list_for_each(bss, &drv->bss, struct test_driver_bss, list) {
@ -1059,7 +1011,7 @@ static int test_driver_if_add(void *priv, enum wpa_driver_if_type type,
const char *ifname, const u8 *addr,
void *bss_ctx, void **drv_priv,
char *force_ifname, u8 *if_addr,
const char *bridge)
const char *bridge, int use_existing)
{
struct test_driver_bss *dbss = priv;
struct wpa_driver_test_data *drv = dbss->drv;
@ -1313,24 +1265,7 @@ static void wpa_driver_test_poll(void *eloop_ctx, void *timeout_ctx)
static void wpa_driver_test_scan_timeout(void *eloop_ctx, void *timeout_ctx)
{
struct wpa_driver_test_data *drv = eloop_ctx;
wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
if (drv->pending_p2p_scan && drv->p2p) {
#ifdef CONFIG_P2P
size_t i;
for (i = 0; i < drv->num_scanres; i++) {
struct wpa_scan_res *bss = drv->scanres[i];
if (p2p_scan_res_handler(drv->p2p, bss->bssid,
bss->freq, bss->age,
bss->level,
(const u8 *) (bss + 1),
bss->ie_len) > 0)
return;
}
p2p_scan_res_handled(drv->p2p);
#endif /* CONFIG_P2P */
return;
}
wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
}
@ -1543,7 +1478,7 @@ static int wpa_driver_test_associate(
struct wpa_driver_test_data *drv = dbss->drv;
wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d pairwise_suite=%d "
"group_suite=%d key_mgmt_suite=%d auth_alg=%d mode=%d",
__func__, priv, params->freq, params->pairwise_suite,
__func__, priv, params->freq.freq, params->pairwise_suite,
params->group_suite, params->key_mgmt_suite,
params->auth_alg, params->mode);
wpa_driver_update_mode(drv, params->mode == IEEE80211_MODE_AP);
@ -1594,7 +1529,8 @@ static int wpa_driver_test_associate(
#endif /* DRIVER_TEST_UNIX */
if (params->mode == IEEE80211_MODE_AP) {
os_memcpy(dbss->ssid, params->ssid, params->ssid_len);
if (params->ssid)
os_memcpy(dbss->ssid, params->ssid, params->ssid_len);
dbss->ssid_len = params->ssid_len;
os_memcpy(dbss->bssid, drv->own_addr, ETH_ALEN);
if (params->wpa_ie && params->wpa_ie_len) {
@ -1615,8 +1551,9 @@ static int wpa_driver_test_associate(
MAC2STR(drv->own_addr));
if (ret >= 0 && ret < end - pos)
pos += ret;
pos += wpa_snprintf_hex(pos, end - pos, params->ssid,
params->ssid_len);
if (params->ssid)
pos += wpa_snprintf_hex(pos, end - pos, params->ssid,
params->ssid_len);
ret = os_snprintf(pos, end - pos, " ");
if (ret >= 0 && ret < end - pos)
pos += ret;
@ -1640,12 +1577,15 @@ static int wpa_driver_test_associate(
return -1;
}
os_memcpy(dbss->ssid, params->ssid, params->ssid_len);
if (params->ssid)
os_memcpy(dbss->ssid, params->ssid, params->ssid_len);
dbss->ssid_len = params->ssid_len;
} else {
drv->associated = 1;
if (params->mode == IEEE80211_MODE_IBSS) {
os_memcpy(dbss->ssid, params->ssid, params->ssid_len);
if (params->ssid)
os_memcpy(dbss->ssid, params->ssid,
params->ssid_len);
dbss->ssid_len = params->ssid_len;
if (params->bssid)
os_memcpy(dbss->bssid, params->bssid,
@ -1948,30 +1888,8 @@ static void wpa_driver_test_mlme(struct wpa_driver_test_data *drv,
data_len - (mgmt->u.probe_req.variable - data);
wpa_supplicant_event(drv->ctx, EVENT_RX_PROBE_REQ,
&event);
#ifdef CONFIG_P2P
if (drv->p2p)
p2p_probe_req_rx(drv->p2p, mgmt->sa,
mgmt->da, mgmt->bssid,
event.rx_probe_req.ie,
event.rx_probe_req.ie_len);
#endif /* CONFIG_P2P */
}
}
#ifdef CONFIG_P2P
if (drv->p2p &&
WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION) {
size_t hdr_len;
hdr_len = (const u8 *)
&mgmt->u.action.u.vs_public_action.action - data;
p2p_rx_action(drv->p2p, mgmt->da, mgmt->sa, mgmt->bssid,
mgmt->u.action.category,
&mgmt->u.action.u.vs_public_action.action,
data_len - hdr_len, freq);
}
#endif /* CONFIG_P2P */
}
@ -1987,31 +1905,8 @@ static void wpa_driver_test_scan_cmd(struct wpa_driver_test_data *drv,
bss = dl_list_first(&drv->bss, struct test_driver_bss, list);
/* data: optional [ STA-addr | ' ' | IEs(hex) ] */
#ifdef CONFIG_P2P
if (drv->probe_req_report && drv->p2p && data_len) {
const char *d = (const char *) data;
u8 sa[ETH_ALEN];
u8 ie[512];
size_t ielen;
if (hwaddr_aton(d, sa))
return;
d += 18;
while (*d == ' ')
d++;
ielen = os_strlen(d) / 2;
if (ielen > sizeof(ie))
ielen = sizeof(ie);
if (hexstr2bin(d, ie, ielen) < 0)
ielen = 0;
drv->probe_from = from;
drv->probe_from_len = fromlen;
p2p_probe_req_rx(drv->p2p, sa, NULL, NULL, ie, ielen);
drv->probe_from = NULL;
}
#endif /* CONFIG_P2P */
if (!drv->ibss)
if (bss == NULL || !drv->ibss)
return;
pos = buf;
@ -2166,12 +2061,6 @@ static void wpa_driver_test_deinit(void *priv)
struct test_client_socket *cli, *prev;
int i;
#ifdef CONFIG_P2P
if (drv->p2p)
p2p_deinit(drv->p2p);
wpabuf_free(drv->pending_action_tx);
#endif /* CONFIG_P2P */
cli = drv->cli;
while (cli) {
prev = cli;
@ -2368,13 +2257,6 @@ static int wpa_driver_test_set_param(void *priv, const char *param)
drv->use_associnfo = 1;
}
if (os_strstr(param, "p2p_mgmt=1")) {
wpa_printf(MSG_DEBUG, "test_driver: Use internal P2P "
"management");
if (wpa_driver_test_init_p2p(drv) < 0)
return -1;
}
return 0;
}
@ -2464,8 +2346,6 @@ static int wpa_driver_test_send_eapol(void *priv, const u8 *dest, u16 proto,
static int wpa_driver_test_get_capa(void *priv, struct wpa_driver_capa *capa)
{
struct test_driver_bss *dbss = priv;
struct wpa_driver_test_data *drv = dbss->drv;
os_memset(capa, 0, sizeof(*capa));
capa->key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |
WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
@ -2481,8 +2361,6 @@ static int wpa_driver_test_get_capa(void *priv, struct wpa_driver_capa *capa)
capa->auth = WPA_DRIVER_AUTH_OPEN |
WPA_DRIVER_AUTH_SHARED |
WPA_DRIVER_AUTH_LEAP;
if (drv->p2p)
capa->flags |= WPA_DRIVER_FLAGS_P2P_MGMT;
capa->flags |= WPA_DRIVER_FLAGS_AP;
capa->flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;
capa->flags |= WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE;
@ -2690,33 +2568,6 @@ static int wpa_driver_test_send_action(void *priv, unsigned int freq,
}
#ifdef CONFIG_P2P
static void test_send_action_cb(void *eloop_ctx, void *timeout_ctx)
{
struct wpa_driver_test_data *drv = eloop_ctx;
if (drv->pending_action_tx == NULL)
return;
if (drv->off_channel_freq != drv->pending_action_freq) {
wpa_printf(MSG_DEBUG, "P2P: Pending Action frame TX "
"waiting for another freq=%u",
drv->pending_action_freq);
return;
}
wpa_printf(MSG_DEBUG, "P2P: Sending pending Action frame to "
MACSTR, MAC2STR(drv->pending_action_dst));
wpa_driver_test_send_action(drv, drv->pending_action_freq, 0,
drv->pending_action_dst,
drv->pending_action_src,
drv->pending_action_bssid,
wpabuf_head(drv->pending_action_tx),
wpabuf_len(drv->pending_action_tx),
drv->pending_action_no_cck);
}
#endif /* CONFIG_P2P */
static void test_remain_on_channel_timeout(void *eloop_ctx, void *timeout_ctx)
{
struct wpa_driver_test_data *drv = eloop_ctx;
@ -2728,9 +2579,6 @@ static void test_remain_on_channel_timeout(void *eloop_ctx, void *timeout_ctx)
data.remain_on_channel.freq = drv->remain_on_channel_freq;
data.remain_on_channel.duration = drv->remain_on_channel_duration;
if (drv->p2p)
drv->off_channel_freq = 0;
drv->remain_on_channel_freq = 0;
wpa_supplicant_event(drv->ctx, EVENT_CANCEL_REMAIN_ON_CHANNEL, &data);
@ -2764,18 +2612,6 @@ static int wpa_driver_test_remain_on_channel(void *priv, unsigned int freq,
data.remain_on_channel.duration = duration;
wpa_supplicant_event(drv->ctx, EVENT_REMAIN_ON_CHANNEL, &data);
#ifdef CONFIG_P2P
if (drv->p2p) {
drv->off_channel_freq = drv->remain_on_channel_freq;
test_send_action_cb(drv, NULL);
if (drv->off_channel_freq == drv->pending_listen_freq) {
p2p_listen_cb(drv->p2p, drv->pending_listen_freq,
drv->pending_listen_duration);
drv->pending_listen_freq = 0;
}
}
#endif /* CONFIG_P2P */
return 0;
}
@ -2803,464 +2639,6 @@ static int wpa_driver_test_probe_req_report(void *priv, int report)
}
#ifdef CONFIG_P2P
static int wpa_driver_test_p2p_find(void *priv, unsigned int timeout, int type)
{
struct test_driver_bss *dbss = priv;
struct wpa_driver_test_data *drv = dbss->drv;
wpa_printf(MSG_DEBUG, "%s(timeout=%u)", __func__, timeout);
if (!drv->p2p)
return -1;
return p2p_find(drv->p2p, timeout, type, 0, NULL, NULL, 0);
}
static int wpa_driver_test_p2p_stop_find(void *priv)
{
struct test_driver_bss *dbss = priv;
struct wpa_driver_test_data *drv = dbss->drv;
wpa_printf(MSG_DEBUG, "%s", __func__);
if (!drv->p2p)
return -1;
p2p_stop_find(drv->p2p);
return 0;
}
static int wpa_driver_test_p2p_listen(void *priv, unsigned int timeout)
{
struct test_driver_bss *dbss = priv;
struct wpa_driver_test_data *drv = dbss->drv;
wpa_printf(MSG_DEBUG, "%s(timeout=%u)", __func__, timeout);
if (!drv->p2p)
return -1;
return p2p_listen(drv->p2p, timeout);
}
static int wpa_driver_test_p2p_connect(void *priv, const u8 *peer_addr,
int wps_method, int go_intent,
const u8 *own_interface_addr,
unsigned int force_freq,
int persistent_group)
{
struct test_driver_bss *dbss = priv;
struct wpa_driver_test_data *drv = dbss->drv;
wpa_printf(MSG_DEBUG, "%s(peer_addr=" MACSTR " wps_method=%d "
"go_intent=%d "
"own_interface_addr=" MACSTR " force_freq=%u "
"persistent_group=%d)",
__func__, MAC2STR(peer_addr), wps_method, go_intent,
MAC2STR(own_interface_addr), force_freq, persistent_group);
if (!drv->p2p)
return -1;
return p2p_connect(drv->p2p, peer_addr, wps_method, go_intent,
own_interface_addr, force_freq, persistent_group,
NULL, 0, 0, 0);
}
static int wpa_driver_test_wps_success_cb(void *priv, const u8 *peer_addr)
{
struct test_driver_bss *dbss = priv;
struct wpa_driver_test_data *drv = dbss->drv;
wpa_printf(MSG_DEBUG, "%s(peer_addr=" MACSTR ")",
__func__, MAC2STR(peer_addr));
if (!drv->p2p)
return -1;
p2p_wps_success_cb(drv->p2p, peer_addr);
return 0;
}
static int wpa_driver_test_p2p_group_formation_failed(void *priv)
{
struct test_driver_bss *dbss = priv;
struct wpa_driver_test_data *drv = dbss->drv;
wpa_printf(MSG_DEBUG, "%s", __func__);
if (!drv->p2p)
return -1;
p2p_group_formation_failed(drv->p2p);
return 0;
}
static int wpa_driver_test_p2p_set_params(void *priv,
const struct p2p_params *params)
{
struct test_driver_bss *dbss = priv;
struct wpa_driver_test_data *drv = dbss->drv;
wpa_printf(MSG_DEBUG, "%s", __func__);
if (!drv->p2p)
return -1;
if (p2p_set_dev_name(drv->p2p, params->dev_name) < 0 ||
p2p_set_pri_dev_type(drv->p2p, params->pri_dev_type) < 0 ||
p2p_set_sec_dev_types(drv->p2p, params->sec_dev_type,
params->num_sec_dev_types) < 0)
return -1;
return 0;
}
static int test_p2p_scan(void *ctx, enum p2p_scan_type type, int freq,
unsigned int num_req_dev_types,
const u8 *req_dev_types, const u8 *dev_id, u16 pw_id)
{
struct wpa_driver_test_data *drv = ctx;
struct wpa_driver_scan_params params;
int ret;
struct wpabuf *wps_ie, *ies;
int social_channels[] = { 2412, 2437, 2462, 0, 0 };
size_t ielen;
wpa_printf(MSG_DEBUG, "%s(type=%d freq=%d)",
__func__, type, freq);
os_memset(&params, 0, sizeof(params));
/* P2P Wildcard SSID */
params.num_ssids = 1;
params.ssids[0].ssid = (u8 *) P2P_WILDCARD_SSID;
params.ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN;
#if 0 /* TODO: WPS IE */
wpa_s->wps->dev.p2p = 1;
wps_ie = wps_build_probe_req_ie(pw_id, &wpa_s->wps->dev,
wpa_s->wps->uuid, WPS_REQ_ENROLLEE);
#else
wps_ie = wpabuf_alloc(1);
#endif
if (wps_ie == NULL)
return -1;
ielen = p2p_scan_ie_buf_len(drv->p2p);
ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen);
if (ies == NULL) {
wpabuf_free(wps_ie);
return -1;
}
wpabuf_put_buf(ies, wps_ie);
wpabuf_free(wps_ie);
p2p_scan_ie(drv->p2p, ies, dev_id);
params.extra_ies = wpabuf_head(ies);
params.extra_ies_len = wpabuf_len(ies);
switch (type) {
case P2P_SCAN_SOCIAL:
params.freqs = social_channels;
break;
case P2P_SCAN_FULL:
break;
case P2P_SCAN_SOCIAL_PLUS_ONE:
social_channels[3] = freq;
params.freqs = social_channels;
break;
}
drv->pending_p2p_scan = 1;
ret = wpa_driver_test_scan(drv, &params);
wpabuf_free(ies);
return ret;
}
static int test_send_action(void *ctx, unsigned int freq, const u8 *dst,
const u8 *src, const u8 *bssid, const u8 *buf,
size_t len, unsigned int wait_time)
{
struct wpa_driver_test_data *drv = ctx;
wpa_printf(MSG_DEBUG, "%s(freq=%u dst=" MACSTR " src=" MACSTR
" bssid=" MACSTR " len=%d",
__func__, freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid),
(int) len);
if (freq <= 0) {
wpa_printf(MSG_WARNING, "P2P: No frequency specified for "
"action frame TX");
return -1;
}
if (drv->pending_action_tx) {
wpa_printf(MSG_DEBUG, "P2P: Dropped pending Action frame TX "
"to " MACSTR, MAC2STR(drv->pending_action_dst));
wpabuf_free(drv->pending_action_tx);
}
drv->pending_action_tx = wpabuf_alloc(len);
if (drv->pending_action_tx == NULL)
return -1;
wpabuf_put_data(drv->pending_action_tx, buf, len);
os_memcpy(drv->pending_action_src, src, ETH_ALEN);
os_memcpy(drv->pending_action_dst, dst, ETH_ALEN);
os_memcpy(drv->pending_action_bssid, bssid, ETH_ALEN);
drv->pending_action_freq = freq;
drv->pending_action_no_cck = 1;
if (drv->off_channel_freq == freq) {
/* Already on requested channel; send immediately */
/* TODO: Would there ever be need to extend the current
* duration on the channel? */
eloop_cancel_timeout(test_send_action_cb, drv, NULL);
eloop_register_timeout(0, 0, test_send_action_cb, drv, NULL);
return 0;
}
wpa_printf(MSG_DEBUG, "P2P: Schedule Action frame to be transmitted "
"once the driver gets to the requested channel");
if (wpa_driver_test_remain_on_channel(drv, freq, wait_time) < 0) {
wpa_printf(MSG_DEBUG, "P2P: Failed to request driver "
"to remain on channel (%u MHz) for Action "
"Frame TX", freq);
return -1;
}
return 0;
}
static void test_send_action_done(void *ctx)
{
wpa_printf(MSG_DEBUG, "%s", __func__);
/* TODO */
}
static void test_go_neg_completed(void *ctx, struct p2p_go_neg_results *res)
{
struct wpa_driver_test_data *drv = ctx;
union wpa_event_data event;
wpa_printf(MSG_DEBUG, "%s", __func__);
os_memset(&event, 0, sizeof(event));
event.p2p_go_neg_completed.res = res;
wpa_supplicant_event(drv->ctx, EVENT_P2P_GO_NEG_COMPLETED, &event);
}
static void test_go_neg_req_rx(void *ctx, const u8 *src, u16 dev_passwd_id)
{
struct wpa_driver_test_data *drv = ctx;
union wpa_event_data event;
wpa_printf(MSG_DEBUG, "%s(src=" MACSTR ")", __func__, MAC2STR(src));
os_memset(&event, 0, sizeof(event));
event.p2p_go_neg_req_rx.src = src;
event.p2p_go_neg_req_rx.dev_passwd_id = dev_passwd_id;
wpa_supplicant_event(drv->ctx, EVENT_P2P_GO_NEG_REQ_RX, &event);
}
static void test_dev_found(void *ctx, const u8 *addr,
const struct p2p_peer_info *info, int new_device)
{
struct wpa_driver_test_data *drv = ctx;
union wpa_event_data event;
char devtype[WPS_DEV_TYPE_BUFSIZE];
wpa_printf(MSG_DEBUG, "%s(" MACSTR " p2p_dev_addr=" MACSTR
" pri_dev_type=%s name='%s' config_methods=0x%x "
"dev_capab=0x%x group_capab=0x%x)",
__func__, MAC2STR(addr), MAC2STR(info->p2p_device_addr),
wps_dev_type_bin2str(info->pri_dev_type, devtype,
sizeof(devtype)),
info->device_name, info->config_methods, info->dev_capab,
info->group_capab);
os_memset(&event, 0, sizeof(event));
event.p2p_dev_found.addr = addr;
event.p2p_dev_found.dev_addr = info->p2p_device_addr;
event.p2p_dev_found.pri_dev_type = info->pri_dev_type;
event.p2p_dev_found.dev_name = info->device_name;
event.p2p_dev_found.config_methods = info->config_methods;
event.p2p_dev_found.dev_capab = info->dev_capab;
event.p2p_dev_found.group_capab = info->group_capab;
wpa_supplicant_event(drv->ctx, EVENT_P2P_DEV_FOUND, &event);
}
static int test_start_listen(void *ctx, unsigned int freq,
unsigned int duration,
const struct wpabuf *probe_resp_ie)
{
struct wpa_driver_test_data *drv = ctx;
wpa_printf(MSG_DEBUG, "%s(freq=%u duration=%u)",
__func__, freq, duration);
if (wpa_driver_test_probe_req_report(drv, 1) < 0)
return -1;
drv->pending_listen_freq = freq;
drv->pending_listen_duration = duration;
if (wpa_driver_test_remain_on_channel(drv, freq, duration) < 0) {
drv->pending_listen_freq = 0;
return -1;
}
return 0;
}
static void test_stop_listen(void *ctx)
{
wpa_printf(MSG_DEBUG, "%s", __func__);
/* TODO */
}
static int test_send_probe_resp(void *ctx, const struct wpabuf *buf)
{
struct wpa_driver_test_data *drv = ctx;
char resp[512], *pos, *end;
int ret;
const struct ieee80211_mgmt *mgmt;
const u8 *ie, *ie_end;
wpa_printf(MSG_DEBUG, "%s", __func__);
wpa_hexdump_buf(MSG_MSGDUMP, "Probe Response", buf);
if (wpabuf_len(buf) < 24)
return -1;
if (!drv->probe_from) {
wpa_printf(MSG_DEBUG, "%s: probe_from not set", __func__);
return -1;
}
pos = resp;
end = resp + sizeof(resp);
mgmt = wpabuf_head(buf);
/* reply: SCANRESP BSSID SSID IEs */
ret = os_snprintf(pos, end - pos, "SCANRESP " MACSTR " ",
MAC2STR(mgmt->bssid));
if (ret < 0 || ret >= end - pos)
return -1;
pos += ret;
ie = mgmt->u.probe_resp.variable;
ie_end = wpabuf_head_u8(buf) + wpabuf_len(buf);
if (ie_end - ie < 2 || ie[0] != WLAN_EID_SSID ||
ie + 2 + ie[1] > ie_end)
return -1;
pos += wpa_snprintf_hex(pos, end - pos, ie + 2, ie[1]);
ret = os_snprintf(pos, end - pos, " ");
if (ret < 0 || ret >= end - pos)
return -1;
pos += ret;
pos += wpa_snprintf_hex(pos, end - pos, ie, ie_end - ie);
sendto(drv->test_socket, resp, pos - resp, 0,
drv->probe_from, drv->probe_from_len);
return 0;
}
static void test_sd_request(void *ctx, int freq, const u8 *sa, u8 dialog_token,
u16 update_indic, const u8 *tlvs, size_t tlvs_len)
{
wpa_printf(MSG_DEBUG, "%s", __func__);
/* TODO */
}
static void test_sd_response(void *ctx, const u8 *sa, u16 update_indic,
const u8 *tlvs, size_t tlvs_len)
{
wpa_printf(MSG_DEBUG, "%s", __func__);
/* TODO */
}
static void test_prov_disc_req(void *ctx, const u8 *peer, u16 config_methods,
const u8 *dev_addr, const u8 *pri_dev_type,
const char *dev_name, u16 supp_config_methods,
u8 dev_capab, u8 group_capab,
const u8 *group_id, size_t group_id_len)
{
wpa_printf(MSG_DEBUG, "%s(peer=" MACSTR " config_methods=0x%x)",
__func__, MAC2STR(peer), config_methods);
/* TODO */
}
static void test_prov_disc_resp(void *ctx, const u8 *peer, u16 config_methods)
{
wpa_printf(MSG_DEBUG, "%s(peer=" MACSTR " config_methods=0x%x)",
__func__, MAC2STR(peer), config_methods);
/* TODO */
}
#endif /* CONFIG_P2P */
static int wpa_driver_test_init_p2p(struct wpa_driver_test_data *drv)
{
#ifdef CONFIG_P2P
struct p2p_config p2p;
unsigned int r;
int i;
os_memset(&p2p, 0, sizeof(p2p));
p2p.msg_ctx = drv->ctx;
p2p.cb_ctx = drv;
p2p.p2p_scan = test_p2p_scan;
p2p.send_action = test_send_action;
p2p.send_action_done = test_send_action_done;
p2p.go_neg_completed = test_go_neg_completed;
p2p.go_neg_req_rx = test_go_neg_req_rx;
p2p.dev_found = test_dev_found;
p2p.start_listen = test_start_listen;
p2p.stop_listen = test_stop_listen;
p2p.send_probe_resp = test_send_probe_resp;
p2p.sd_request = test_sd_request;
p2p.sd_response = test_sd_response;
p2p.prov_disc_req = test_prov_disc_req;
p2p.prov_disc_resp = test_prov_disc_resp;
os_memcpy(p2p.dev_addr, drv->own_addr, ETH_ALEN);
p2p.reg_class = 12; /* TODO: change depending on location */
/*
* Pick one of the social channels randomly as the listen
* channel.
*/
os_get_random((u8 *) &r, sizeof(r));
p2p.channel = 1 + (r % 3) * 5;
/* TODO: change depending on location */
p2p.op_reg_class = 12;
/*
* For initial tests, pick the operation channel randomly.
* TODO: Use scan results (etc.) to select the best channel.
*/
p2p.op_channel = 1 + r % 11;
os_memcpy(p2p.country, "US ", 3);
/* FIX: fetch available channels from the driver */
p2p.channels.reg_classes = 1;
p2p.channels.reg_class[0].reg_class = 12; /* US/12 = 2.4 GHz band */
p2p.channels.reg_class[0].channels = 11;
for (i = 0; i < 11; i++)
p2p.channels.reg_class[0].channel[i] = i + 1;
p2p.max_peers = 100;
drv->p2p = p2p_init(&p2p);
if (drv->p2p == NULL)
return -1;
return 0;
#else /* CONFIG_P2P */
wpa_printf(MSG_INFO, "driver_test: P2P support not included");
return -1;
#endif /* CONFIG_P2P */
}
const struct wpa_driver_ops wpa_driver_test_ops = {
"test",
"wpa_supplicant test driver",
@ -3302,14 +2680,4 @@ const struct wpa_driver_ops wpa_driver_test_ops = {
.remain_on_channel = wpa_driver_test_remain_on_channel,
.cancel_remain_on_channel = wpa_driver_test_cancel_remain_on_channel,
.probe_req_report = wpa_driver_test_probe_req_report,
#ifdef CONFIG_P2P
.p2p_find = wpa_driver_test_p2p_find,
.p2p_stop_find = wpa_driver_test_p2p_stop_find,
.p2p_listen = wpa_driver_test_p2p_listen,
.p2p_connect = wpa_driver_test_p2p_connect,
.wps_success_cb = wpa_driver_test_wps_success_cb,
.p2p_group_formation_failed =
wpa_driver_test_p2p_group_formation_failed,
.p2p_set_params = wpa_driver_test_p2p_set_params,
#endif /* CONFIG_P2P */
};

View File

@ -25,14 +25,32 @@ struct wpabuf * eap_tls_msg_alloc(EapType type, size_t payload_len,
return eap_msg_alloc(EAP_VENDOR_UNAUTH_TLS,
EAP_VENDOR_TYPE_UNAUTH_TLS, payload_len,
code, identifier);
else if (type == EAP_WFA_UNAUTH_TLS_TYPE)
return eap_msg_alloc(EAP_VENDOR_WFA_NEW,
EAP_VENDOR_WFA_UNAUTH_TLS, payload_len,
code, identifier);
return eap_msg_alloc(EAP_VENDOR_IETF, type, payload_len, code,
identifier);
}
#ifdef CONFIG_TLS_INTERNAL
static void eap_server_tls_log_cb(void *ctx, const char *msg)
{
struct eap_sm *sm = ctx;
eap_log_msg(sm, "TLS: %s", msg);
}
#endif /* CONFIG_TLS_INTERNAL */
int eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
int verify_peer)
{
if (sm->ssl_ctx == NULL) {
wpa_printf(MSG_ERROR, "TLS context not initialized - cannot use TLS-based EAP method");
return -1;
}
data->eap = sm;
data->phase2 = sm->init_phase2;
@ -43,6 +61,13 @@ int eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
return -1;
}
#ifdef CONFIG_TLS_INTERNAL
tls_connection_set_log_cb(data->conn, eap_server_tls_log_cb, sm);
#ifdef CONFIG_TESTING_OPTIONS
tls_connection_set_test_flags(data->conn, sm->tls_test_flags);
#endif /* CONFIG_TESTING_OPTIONS */
#endif /* CONFIG_TLS_INTERNAL */
if (tls_connection_set_verify(sm->ssl_ctx, data->conn, verify_peer)) {
wpa_printf(MSG_INFO, "SSL: Failed to configure verification "
"of TLS peer certificate");
@ -394,6 +419,10 @@ int eap_server_tls_process(struct eap_sm *sm, struct eap_ssl_data *data,
pos = eap_hdr_validate(EAP_VENDOR_UNAUTH_TLS,
EAP_VENDOR_TYPE_UNAUTH_TLS, respData,
&left);
else if (eap_type == EAP_WFA_UNAUTH_TLS_TYPE)
pos = eap_hdr_validate(EAP_VENDOR_WFA_NEW,
EAP_VENDOR_WFA_UNAUTH_TLS, respData,
&left);
else
pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, respData,
&left);

View File

@ -1,6 +1,6 @@
/*
* RADIUS Dynamic Authorization Server (DAS) (RFC 5176)
* Copyright (c) 2012, Jouni Malinen <j@w1.fi>
* Copyright (c) 2012-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@ -16,9 +16,6 @@
#include "radius_das.h"
extern int wpa_debug_level;
struct radius_das_data {
int sock;
u8 *shared_secret;
@ -41,11 +38,16 @@ static struct radius_msg * radius_das_disconnect(struct radius_das_data *das,
struct radius_msg *reply;
u8 allowed[] = {
RADIUS_ATTR_USER_NAME,
RADIUS_ATTR_NAS_IP_ADDRESS,
RADIUS_ATTR_CALLING_STATION_ID,
RADIUS_ATTR_NAS_IDENTIFIER,
RADIUS_ATTR_ACCT_SESSION_ID,
RADIUS_ATTR_EVENT_TIMESTAMP,
RADIUS_ATTR_MESSAGE_AUTHENTICATOR,
RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
#ifdef CONFIG_IPV6
RADIUS_ATTR_NAS_IPV6_ADDRESS,
#endif /* CONFIG_IPV6 */
0
};
int error = 405;
@ -70,6 +72,36 @@ static struct radius_msg * radius_das_disconnect(struct radius_das_data *das,
os_memset(&attrs, 0, sizeof(attrs));
if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_NAS_IP_ADDRESS,
&buf, &len, NULL) == 0) {
if (len != 4) {
wpa_printf(MSG_INFO, "DAS: Invalid NAS-IP-Address from %s:%d",
abuf, from_port);
error = 407;
goto fail;
}
attrs.nas_ip_addr = buf;
}
#ifdef CONFIG_IPV6
if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS,
&buf, &len, NULL) == 0) {
if (len != 16) {
wpa_printf(MSG_INFO, "DAS: Invalid NAS-IPv6-Address from %s:%d",
abuf, from_port);
error = 407;
goto fail;
}
attrs.nas_ipv6_addr = buf;
}
#endif /* CONFIG_IPV6 */
if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_NAS_IDENTIFIER,
&buf, &len, NULL) == 0) {
attrs.nas_identifier = buf;
attrs.nas_identifier_len = len;
}
if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CALLING_STATION_ID,
&buf, &len, NULL) == 0) {
if (len >= sizeof(tmp))
@ -284,7 +316,7 @@ static int radius_das_open_socket(int port)
s = socket(PF_INET, SOCK_DGRAM, 0);
if (s < 0) {
perror("socket");
wpa_printf(MSG_INFO, "RADIUS DAS: socket: %s", strerror(errno));
return -1;
}
@ -292,7 +324,7 @@ static int radius_das_open_socket(int port)
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
perror("bind");
wpa_printf(MSG_INFO, "RADIUS DAS: bind: %s", strerror(errno));
close(s);
return -1;
}

View File

@ -7,17 +7,28 @@
*/
#include "includes.h"
#include <assert.h>
#include "common.h"
#include "trace.h"
#include "list.h"
#include "eloop.h"
#if defined(CONFIG_ELOOP_POLL) && defined(CONFIG_ELOOP_EPOLL)
#error Do not define both of poll and epoll
#endif
#if !defined(CONFIG_ELOOP_POLL) && !defined(CONFIG_ELOOP_EPOLL)
#define CONFIG_ELOOP_SELECT
#endif
#ifdef CONFIG_ELOOP_POLL
#include <assert.h>
#include <poll.h>
#endif /* CONFIG_ELOOP_POLL */
#ifdef CONFIG_ELOOP_EPOLL
#include <sys/epoll.h>
#endif /* CONFIG_ELOOP_EPOLL */
struct eloop_sock {
int sock;
@ -31,7 +42,7 @@ struct eloop_sock {
struct eloop_timeout {
struct dl_list list;
struct os_time time;
struct os_reltime time;
void *eloop_data;
void *user_data;
eloop_timeout_handler handler;
@ -50,7 +61,11 @@ struct eloop_signal {
struct eloop_sock_table {
int count;
struct eloop_sock *table;
#ifdef CONFIG_ELOOP_EPOLL
eloop_event_type type;
#else /* CONFIG_ELOOP_EPOLL */
int changed;
#endif /* CONFIG_ELOOP_EPOLL */
};
struct eloop_data {
@ -63,6 +78,13 @@ struct eloop_data {
struct pollfd *pollfds;
struct pollfd **pollfds_map;
#endif /* CONFIG_ELOOP_POLL */
#ifdef CONFIG_ELOOP_EPOLL
int epollfd;
int epoll_max_event_num;
int epoll_max_fd;
struct eloop_sock *epoll_table;
struct epoll_event *epoll_events;
#endif /* CONFIG_ELOOP_EPOLL */
struct eloop_sock_table readers;
struct eloop_sock_table writers;
struct eloop_sock_table exceptions;
@ -75,7 +97,6 @@ struct eloop_data {
int pending_terminate;
int terminate;
int reader_table_changed;
};
static struct eloop_data eloop;
@ -128,6 +149,17 @@ int eloop_init(void)
{
os_memset(&eloop, 0, sizeof(eloop));
dl_list_init(&eloop.timeout);
#ifdef CONFIG_ELOOP_EPOLL
eloop.epollfd = epoll_create1(0);
if (eloop.epollfd < 0) {
wpa_printf(MSG_ERROR, "%s: epoll_create1 failed. %s\n",
__func__, strerror(errno));
return -1;
}
eloop.readers.type = EVENT_TYPE_READ;
eloop.writers.type = EVENT_TYPE_WRITE;
eloop.exceptions.type = EVENT_TYPE_EXCEPTION;
#endif /* CONFIG_ELOOP_EPOLL */
#ifdef WPA_TRACE
signal(SIGSEGV, eloop_sigsegv_handler);
#endif /* WPA_TRACE */
@ -139,6 +171,11 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
int sock, eloop_sock_handler handler,
void *eloop_data, void *user_data)
{
#ifdef CONFIG_ELOOP_EPOLL
struct eloop_sock *temp_table;
struct epoll_event ev, *temp_events;
int next;
#endif /* CONFIG_ELOOP_EPOLL */
struct eloop_sock *tmp;
int new_max_sock;
@ -174,6 +211,33 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
eloop.pollfds = n;
}
#endif /* CONFIG_ELOOP_POLL */
#ifdef CONFIG_ELOOP_EPOLL
if (new_max_sock >= eloop.epoll_max_fd) {
next = eloop.epoll_max_fd == 0 ? 16 : eloop.epoll_max_fd * 2;
temp_table = os_realloc_array(eloop.epoll_table, next,
sizeof(struct eloop_sock));
if (temp_table == NULL)
return -1;
eloop.epoll_max_fd = next;
eloop.epoll_table = temp_table;
}
if (eloop.count + 1 > eloop.epoll_max_event_num) {
next = eloop.epoll_max_event_num == 0 ? 8 :
eloop.epoll_max_event_num * 2;
temp_events = os_realloc_array(eloop.epoll_events, next,
sizeof(struct epoll_event));
if (temp_events == NULL) {
wpa_printf(MSG_ERROR, "%s: malloc for epoll failed. "
"%s\n", __func__, strerror(errno));
return -1;
}
eloop.epoll_max_event_num = next;
eloop.epoll_events = temp_events;
}
#endif /* CONFIG_ELOOP_EPOLL */
eloop_trace_sock_remove_ref(table);
tmp = os_realloc_array(table->table, table->count + 1,
@ -190,9 +254,38 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
table->table = tmp;
eloop.max_sock = new_max_sock;
eloop.count++;
#ifndef CONFIG_ELOOP_EPOLL
table->changed = 1;
#endif /* CONFIG_ELOOP_EPOLL */
eloop_trace_sock_add_ref(table);
#ifdef CONFIG_ELOOP_EPOLL
os_memset(&ev, 0, sizeof(ev));
switch (table->type) {
case EVENT_TYPE_READ:
ev.events = EPOLLIN;
break;
case EVENT_TYPE_WRITE:
ev.events = EPOLLOUT;
break;
/*
* Exceptions are always checked when using epoll, but I suppose it's
* possible that someone registered a socket *only* for exception
* handling.
*/
case EVENT_TYPE_EXCEPTION:
ev.events = EPOLLERR | EPOLLHUP;
break;
}
ev.data.fd = sock;
if (epoll_ctl(eloop.epollfd, EPOLL_CTL_ADD, sock, &ev) < 0) {
wpa_printf(MSG_ERROR, "%s: epoll_ctl(ADD) for fd=%d "
"failed. %s\n", __func__, sock, strerror(errno));
return -1;
}
os_memcpy(&eloop.epoll_table[sock], &table->table[table->count - 1],
sizeof(struct eloop_sock));
#endif /* CONFIG_ELOOP_EPOLL */
return 0;
}
@ -219,8 +312,18 @@ static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
}
table->count--;
eloop.count--;
#ifndef CONFIG_ELOOP_EPOLL
table->changed = 1;
#endif /* CONFIG_ELOOP_EPOLL */
eloop_trace_sock_add_ref(table);
#ifdef CONFIG_ELOOP_EPOLL
if (epoll_ctl(eloop.epollfd, EPOLL_CTL_DEL, sock, NULL) < 0) {
wpa_printf(MSG_ERROR, "%s: epoll_ctl(DEL) for fd=%d "
"failed. %s\n", __func__, sock, strerror(errno));
return;
}
os_memset(&eloop.epoll_table[sock], 0, sizeof(struct eloop_sock));
#endif /* CONFIG_ELOOP_EPOLL */
}
@ -362,7 +465,9 @@ static void eloop_sock_table_dispatch(struct eloop_sock_table *readers,
max_pollfd_map, POLLERR | POLLHUP);
}
#else /* CONFIG_ELOOP_POLL */
#endif /* CONFIG_ELOOP_POLL */
#ifdef CONFIG_ELOOP_SELECT
static void eloop_sock_table_set_fds(struct eloop_sock_table *table,
fd_set *fds)
@ -374,8 +479,10 @@ static void eloop_sock_table_set_fds(struct eloop_sock_table *table,
if (table->table == NULL)
return;
for (i = 0; i < table->count; i++)
for (i = 0; i < table->count; i++) {
assert(table->table[i].sock >= 0);
FD_SET(table->table[i].sock, fds);
}
}
@ -399,7 +506,24 @@ static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
}
}
#endif /* CONFIG_ELOOP_POLL */
#endif /* CONFIG_ELOOP_SELECT */
#ifdef CONFIG_ELOOP_EPOLL
static void eloop_sock_table_dispatch(struct epoll_event *events, int nfds)
{
struct eloop_sock *table;
int i;
for (i = 0; i < nfds; i++) {
table = &eloop.epoll_table[events[i].data.fd];
if (table->handler == NULL)
continue;
table->handler(table->sock, table->eloop_data,
table->user_data);
}
}
#endif /* CONFIG_ELOOP_EPOLL */
static void eloop_sock_table_destroy(struct eloop_sock_table *table)
@ -459,6 +583,7 @@ int eloop_register_sock(int sock, eloop_event_type type,
{
struct eloop_sock_table *table;
assert(sock >= 0);
table = eloop_get_sock_table(type);
return eloop_sock_table_add_sock(table, sock, handler,
eloop_data, user_data);
@ -484,7 +609,7 @@ int eloop_register_timeout(unsigned int secs, unsigned int usecs,
timeout = os_zalloc(sizeof(*timeout));
if (timeout == NULL)
return -1;
if (os_get_time(&timeout->time) < 0) {
if (os_get_reltime(&timeout->time) < 0) {
os_free(timeout);
return -1;
}
@ -514,7 +639,7 @@ int eloop_register_timeout(unsigned int secs, unsigned int usecs,
/* Maintain timeouts in order of increasing time */
dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
if (os_time_before(&timeout->time, &tmp->time)) {
if (os_reltime_before(&timeout->time, &tmp->time)) {
dl_list_add(tmp->list.prev, &timeout->list);
return 0;
}
@ -556,6 +681,33 @@ int eloop_cancel_timeout(eloop_timeout_handler handler,
}
int eloop_cancel_timeout_one(eloop_timeout_handler handler,
void *eloop_data, void *user_data,
struct os_reltime *remaining)
{
struct eloop_timeout *timeout, *prev;
int removed = 0;
struct os_reltime now;
os_get_reltime(&now);
remaining->sec = remaining->usec = 0;
dl_list_for_each_safe(timeout, prev, &eloop.timeout,
struct eloop_timeout, list) {
if (timeout->handler == handler &&
(timeout->eloop_data == eloop_data) &&
(timeout->user_data == user_data)) {
removed = 1;
if (os_reltime_before(&now, &timeout->time))
os_reltime_sub(&timeout->time, &now, remaining);
eloop_remove_timeout(timeout);
break;
}
}
return removed;
}
int eloop_is_timeout_registered(eloop_timeout_handler handler,
void *eloop_data, void *user_data)
{
@ -572,6 +724,70 @@ int eloop_is_timeout_registered(eloop_timeout_handler handler,
}
int eloop_deplete_timeout(unsigned int req_secs, unsigned int req_usecs,
eloop_timeout_handler handler, void *eloop_data,
void *user_data)
{
struct os_reltime now, requested, remaining;
struct eloop_timeout *tmp;
dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
if (tmp->handler == handler &&
tmp->eloop_data == eloop_data &&
tmp->user_data == user_data) {
requested.sec = req_secs;
requested.usec = req_usecs;
os_get_reltime(&now);
os_reltime_sub(&tmp->time, &now, &remaining);
if (os_reltime_before(&requested, &remaining)) {
eloop_cancel_timeout(handler, eloop_data,
user_data);
eloop_register_timeout(requested.sec,
requested.usec,
handler, eloop_data,
user_data);
return 1;
}
return 0;
}
}
return -1;
}
int eloop_replenish_timeout(unsigned int req_secs, unsigned int req_usecs,
eloop_timeout_handler handler, void *eloop_data,
void *user_data)
{
struct os_reltime now, requested, remaining;
struct eloop_timeout *tmp;
dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
if (tmp->handler == handler &&
tmp->eloop_data == eloop_data &&
tmp->user_data == user_data) {
requested.sec = req_secs;
requested.usec = req_usecs;
os_get_reltime(&now);
os_reltime_sub(&tmp->time, &now, &remaining);
if (os_reltime_before(&remaining, &requested)) {
eloop_cancel_timeout(handler, eloop_data,
user_data);
eloop_register_timeout(requested.sec,
requested.usec,
handler, eloop_data,
user_data);
return 1;
}
return 0;
}
}
return -1;
}
#ifndef CONFIG_NATIVE_WINDOWS
static void eloop_handle_alarm(int sig)
{
@ -682,20 +898,24 @@ void eloop_run(void)
#ifdef CONFIG_ELOOP_POLL
int num_poll_fds;
int timeout_ms = 0;
#else /* CONFIG_ELOOP_POLL */
#endif /* CONFIG_ELOOP_POLL */
#ifdef CONFIG_ELOOP_SELECT
fd_set *rfds, *wfds, *efds;
struct timeval _tv;
#endif /* CONFIG_ELOOP_POLL */
#endif /* CONFIG_ELOOP_SELECT */
#ifdef CONFIG_ELOOP_EPOLL
int timeout_ms = -1;
#endif /* CONFIG_ELOOP_EPOLL */
int res;
struct os_time tv, now;
struct os_reltime tv, now;
#ifndef CONFIG_ELOOP_POLL
#ifdef CONFIG_ELOOP_SELECT
rfds = os_malloc(sizeof(*rfds));
wfds = os_malloc(sizeof(*wfds));
efds = os_malloc(sizeof(*efds));
if (rfds == NULL || wfds == NULL || efds == NULL)
goto out;
#endif /* CONFIG_ELOOP_POLL */
#endif /* CONFIG_ELOOP_SELECT */
while (!eloop.terminate &&
(!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 ||
@ -704,17 +924,18 @@ void eloop_run(void)
timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
list);
if (timeout) {
os_get_time(&now);
if (os_time_before(&now, &timeout->time))
os_time_sub(&timeout->time, &now, &tv);
os_get_reltime(&now);
if (os_reltime_before(&now, &timeout->time))
os_reltime_sub(&timeout->time, &now, &tv);
else
tv.sec = tv.usec = 0;
#ifdef CONFIG_ELOOP_POLL
#if defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL)
timeout_ms = tv.sec * 1000 + tv.usec / 1000;
#else /* CONFIG_ELOOP_POLL */
#endif /* defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) */
#ifdef CONFIG_ELOOP_SELECT
_tv.tv_sec = tv.sec;
_tv.tv_usec = tv.usec;
#endif /* CONFIG_ELOOP_POLL */
#endif /* CONFIG_ELOOP_SELECT */
}
#ifdef CONFIG_ELOOP_POLL
@ -724,30 +945,44 @@ void eloop_run(void)
eloop.max_pollfd_map);
res = poll(eloop.pollfds, num_poll_fds,
timeout ? timeout_ms : -1);
if (res < 0 && errno != EINTR && errno != 0) {
perror("poll");
goto out;
}
#else /* CONFIG_ELOOP_POLL */
#endif /* CONFIG_ELOOP_POLL */
#ifdef CONFIG_ELOOP_SELECT
eloop_sock_table_set_fds(&eloop.readers, rfds);
eloop_sock_table_set_fds(&eloop.writers, wfds);
eloop_sock_table_set_fds(&eloop.exceptions, efds);
res = select(eloop.max_sock + 1, rfds, wfds, efds,
timeout ? &_tv : NULL);
#endif /* CONFIG_ELOOP_SELECT */
#ifdef CONFIG_ELOOP_EPOLL
if (eloop.count == 0) {
res = 0;
} else {
res = epoll_wait(eloop.epollfd, eloop.epoll_events,
eloop.count, timeout_ms);
}
#endif /* CONFIG_ELOOP_EPOLL */
if (res < 0 && errno != EINTR && errno != 0) {
perror("select");
wpa_printf(MSG_ERROR, "eloop: %s: %s",
#ifdef CONFIG_ELOOP_POLL
"poll"
#endif /* CONFIG_ELOOP_POLL */
#ifdef CONFIG_ELOOP_SELECT
"select"
#endif /* CONFIG_ELOOP_SELECT */
#ifdef CONFIG_ELOOP_EPOLL
"epoll"
#endif /* CONFIG_ELOOP_EPOLL */
, strerror(errno));
goto out;
}
#endif /* CONFIG_ELOOP_POLL */
eloop_process_pending_signals();
/* check if some registered timeouts have occurred */
timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
list);
if (timeout) {
os_get_time(&now);
if (!os_time_before(&now, &timeout->time)) {
os_get_reltime(&now);
if (!os_reltime_before(&now, &timeout->time)) {
void *eloop_data = timeout->eloop_data;
void *user_data = timeout->user_data;
eloop_timeout_handler handler =
@ -765,19 +1000,24 @@ void eloop_run(void)
eloop_sock_table_dispatch(&eloop.readers, &eloop.writers,
&eloop.exceptions, eloop.pollfds_map,
eloop.max_pollfd_map);
#else /* CONFIG_ELOOP_POLL */
#endif /* CONFIG_ELOOP_POLL */
#ifdef CONFIG_ELOOP_SELECT
eloop_sock_table_dispatch(&eloop.readers, rfds);
eloop_sock_table_dispatch(&eloop.writers, wfds);
eloop_sock_table_dispatch(&eloop.exceptions, efds);
#endif /* CONFIG_ELOOP_POLL */
#endif /* CONFIG_ELOOP_SELECT */
#ifdef CONFIG_ELOOP_EPOLL
eloop_sock_table_dispatch(eloop.epoll_events, res);
#endif /* CONFIG_ELOOP_EPOLL */
}
eloop.terminate = 0;
out:
#ifndef CONFIG_ELOOP_POLL
#ifdef CONFIG_ELOOP_SELECT
os_free(rfds);
os_free(wfds);
os_free(efds);
#endif /* CONFIG_ELOOP_POLL */
#endif /* CONFIG_ELOOP_SELECT */
return;
}
@ -791,9 +1031,9 @@ void eloop_terminate(void)
void eloop_destroy(void)
{
struct eloop_timeout *timeout, *prev;
struct os_time now;
struct os_reltime now;
os_get_time(&now);
os_get_reltime(&now);
dl_list_for_each_safe(timeout, prev, &eloop.timeout,
struct eloop_timeout, list) {
int sec, usec;
@ -821,6 +1061,11 @@ void eloop_destroy(void)
os_free(eloop.pollfds);
os_free(eloop.pollfds_map);
#endif /* CONFIG_ELOOP_POLL */
#ifdef CONFIG_ELOOP_EPOLL
os_free(eloop.epoll_table);
os_free(eloop.epoll_events);
close(eloop.epollfd);
#endif /* CONFIG_ELOOP_EPOLL */
}
@ -843,7 +1088,13 @@ void eloop_wait_for_read_sock(int sock)
pfd.events = POLLIN;
poll(&pfd, 1, -1);
#else /* CONFIG_ELOOP_POLL */
#endif /* CONFIG_ELOOP_POLL */
#if defined(CONFIG_ELOOP_SELECT) || defined(CONFIG_ELOOP_EPOLL)
/*
* We can use epoll() here. But epoll() requres 4 system calls.
* epoll_create1(), epoll_ctl() for ADD, epoll_wait, and close() for
* epoll fd. So select() is better for performance here.
*/
fd_set rfds;
if (sock < 0)
@ -852,5 +1103,9 @@ void eloop_wait_for_read_sock(int sock)
FD_ZERO(&rfds);
FD_SET(sock, &rfds);
select(sock + 1, &rfds, NULL, NULL, NULL);
#endif /* CONFIG_ELOOP_POLL */
#endif /* defined(CONFIG_ELOOP_SELECT) || defined(CONFIG_ELOOP_EPOLL) */
}
#ifdef CONFIG_ELOOP_SELECT
#undef CONFIG_ELOOP_SELECT
#endif /* CONFIG_ELOOP_SELECT */

View File

@ -1,395 +0,0 @@
/*
* Event loop - empty template (basic structure, but no OS specific operations)
* Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include "common.h"
#include "eloop.h"
struct eloop_sock {
int sock;
void *eloop_data;
void *user_data;
void (*handler)(int sock, void *eloop_ctx, void *sock_ctx);
};
struct eloop_timeout {
struct os_time time;
void *eloop_data;
void *user_data;
void (*handler)(void *eloop_ctx, void *sock_ctx);
struct eloop_timeout *next;
};
struct eloop_signal {
int sig;
void *user_data;
void (*handler)(int sig, void *eloop_ctx, void *signal_ctx);
int signaled;
};
struct eloop_data {
int max_sock, reader_count;
struct eloop_sock *readers;
struct eloop_timeout *timeout;
int signal_count;
struct eloop_signal *signals;
int signaled;
int pending_terminate;
int terminate;
int reader_table_changed;
};
static struct eloop_data eloop;
int eloop_init(void)
{
memset(&eloop, 0, sizeof(eloop));
return 0;
}
int eloop_register_read_sock(int sock,
void (*handler)(int sock, void *eloop_ctx,
void *sock_ctx),
void *eloop_data, void *user_data)
{
struct eloop_sock *tmp;
tmp = (struct eloop_sock *)
realloc(eloop.readers,
(eloop.reader_count + 1) * sizeof(struct eloop_sock));
if (tmp == NULL)
return -1;
tmp[eloop.reader_count].sock = sock;
tmp[eloop.reader_count].eloop_data = eloop_data;
tmp[eloop.reader_count].user_data = user_data;
tmp[eloop.reader_count].handler = handler;
eloop.reader_count++;
eloop.readers = tmp;
if (sock > eloop.max_sock)
eloop.max_sock = sock;
eloop.reader_table_changed = 1;
return 0;
}
void eloop_unregister_read_sock(int sock)
{
int i;
if (eloop.readers == NULL || eloop.reader_count == 0)
return;
for (i = 0; i < eloop.reader_count; i++) {
if (eloop.readers[i].sock == sock)
break;
}
if (i == eloop.reader_count)
return;
if (i != eloop.reader_count - 1) {
memmove(&eloop.readers[i], &eloop.readers[i + 1],
(eloop.reader_count - i - 1) *
sizeof(struct eloop_sock));
}
eloop.reader_count--;
eloop.reader_table_changed = 1;
}
int eloop_register_timeout(unsigned int secs, unsigned int usecs,
void (*handler)(void *eloop_ctx, void *timeout_ctx),
void *eloop_data, void *user_data)
{
struct eloop_timeout *timeout, *tmp, *prev;
timeout = (struct eloop_timeout *) malloc(sizeof(*timeout));
if (timeout == NULL)
return -1;
os_get_time(&timeout->time);
timeout->time.sec += secs;
timeout->time.usec += usecs;
while (timeout->time.usec >= 1000000) {
timeout->time.sec++;
timeout->time.usec -= 1000000;
}
timeout->eloop_data = eloop_data;
timeout->user_data = user_data;
timeout->handler = handler;
timeout->next = NULL;
if (eloop.timeout == NULL) {
eloop.timeout = timeout;
return 0;
}
prev = NULL;
tmp = eloop.timeout;
while (tmp != NULL) {
if (os_time_before(&timeout->time, &tmp->time))
break;
prev = tmp;
tmp = tmp->next;
}
if (prev == NULL) {
timeout->next = eloop.timeout;
eloop.timeout = timeout;
} else {
timeout->next = prev->next;
prev->next = timeout;
}
return 0;
}
int eloop_cancel_timeout(void (*handler)(void *eloop_ctx, void *sock_ctx),
void *eloop_data, void *user_data)
{
struct eloop_timeout *timeout, *prev, *next;
int removed = 0;
prev = NULL;
timeout = eloop.timeout;
while (timeout != NULL) {
next = timeout->next;
if (timeout->handler == handler &&
(timeout->eloop_data == eloop_data ||
eloop_data == ELOOP_ALL_CTX) &&
(timeout->user_data == user_data ||
user_data == ELOOP_ALL_CTX)) {
if (prev == NULL)
eloop.timeout = next;
else
prev->next = next;
free(timeout);
removed++;
} else
prev = timeout;
timeout = next;
}
return removed;
}
int eloop_is_timeout_registered(void (*handler)(void *eloop_ctx,
void *timeout_ctx),
void *eloop_data, void *user_data)
{
struct eloop_timeout *tmp;
tmp = eloop.timeout;
while (tmp != NULL) {
if (tmp->handler == handler &&
tmp->eloop_data == eloop_data &&
tmp->user_data == user_data)
return 1;
tmp = tmp->next;
}
return 0;
}
/* TODO: replace with suitable signal handler */
#if 0
static void eloop_handle_signal(int sig)
{
int i;
eloop.signaled++;
for (i = 0; i < eloop.signal_count; i++) {
if (eloop.signals[i].sig == sig) {
eloop.signals[i].signaled++;
break;
}
}
}
#endif
static void eloop_process_pending_signals(void)
{
int i;
if (eloop.signaled == 0)
return;
eloop.signaled = 0;
if (eloop.pending_terminate) {
eloop.pending_terminate = 0;
}
for (i = 0; i < eloop.signal_count; i++) {
if (eloop.signals[i].signaled) {
eloop.signals[i].signaled = 0;
eloop.signals[i].handler(eloop.signals[i].sig,
eloop.user_data,
eloop.signals[i].user_data);
}
}
}
int eloop_register_signal(int sig,
void (*handler)(int sig, void *eloop_ctx,
void *signal_ctx),
void *user_data)
{
struct eloop_signal *tmp;
tmp = (struct eloop_signal *)
realloc(eloop.signals,
(eloop.signal_count + 1) *
sizeof(struct eloop_signal));
if (tmp == NULL)
return -1;
tmp[eloop.signal_count].sig = sig;
tmp[eloop.signal_count].user_data = user_data;
tmp[eloop.signal_count].handler = handler;
tmp[eloop.signal_count].signaled = 0;
eloop.signal_count++;
eloop.signals = tmp;
/* TODO: register signal handler */
return 0;
}
int eloop_register_signal_terminate(void (*handler)(int sig, void *eloop_ctx,
void *signal_ctx),
void *user_data)
{
#if 0
/* TODO: for example */
int ret = eloop_register_signal(SIGINT, handler, user_data);
if (ret == 0)
ret = eloop_register_signal(SIGTERM, handler, user_data);
return ret;
#endif
return 0;
}
int eloop_register_signal_reconfig(void (*handler)(int sig, void *eloop_ctx,
void *signal_ctx),
void *user_data)
{
#if 0
/* TODO: for example */
return eloop_register_signal(SIGHUP, handler, user_data);
#endif
return 0;
}
void eloop_run(void)
{
int i;
struct os_time tv, now;
while (!eloop.terminate &&
(eloop.timeout || eloop.reader_count > 0)) {
if (eloop.timeout) {
os_get_time(&now);
if (os_time_before(&now, &eloop.timeout->time))
os_time_sub(&eloop.timeout->time, &now, &tv);
else
tv.sec = tv.usec = 0;
}
/*
* TODO: wait for any event (read socket ready, timeout (tv),
* signal
*/
os_sleep(1, 0); /* just a dummy wait for testing */
eloop_process_pending_signals();
/* check if some registered timeouts have occurred */
if (eloop.timeout) {
struct eloop_timeout *tmp;
os_get_time(&now);
if (!os_time_before(&now, &eloop.timeout->time)) {
tmp = eloop.timeout;
eloop.timeout = eloop.timeout->next;
tmp->handler(tmp->eloop_data,
tmp->user_data);
free(tmp);
}
}
eloop.reader_table_changed = 0;
for (i = 0; i < eloop.reader_count; i++) {
/*
* TODO: call each handler that has pending data to
* read
*/
if (0 /* TODO: eloop.readers[i].sock ready */) {
eloop.readers[i].handler(
eloop.readers[i].sock,
eloop.readers[i].eloop_data,
eloop.readers[i].user_data);
if (eloop.reader_table_changed)
break;
}
}
}
}
void eloop_terminate(void)
{
eloop.terminate = 1;
}
void eloop_destroy(void)
{
struct eloop_timeout *timeout, *prev;
timeout = eloop.timeout;
while (timeout != NULL) {
prev = timeout;
timeout = timeout->next;
free(prev);
}
free(eloop.readers);
free(eloop.signals);
}
int eloop_terminated(void)
{
return eloop.terminate;
}
void eloop_wait_for_read_sock(int sock)
{
/*
* TODO: wait for the file descriptor to have something available for
* reading
*/
}

View File

@ -23,6 +23,11 @@ struct os_time {
os_time_t usec;
};
struct os_reltime {
os_time_t sec;
os_time_t usec;
};
/**
* os_get_time - Get current time (sec, usec)
* @t: Pointer to buffer for the time
@ -30,21 +35,84 @@ struct os_time {
*/
int os_get_time(struct os_time *t);
/**
* os_get_reltime - Get relative time (sec, usec)
* @t: Pointer to buffer for the time
* Returns: 0 on success, -1 on failure
*/
int os_get_reltime(struct os_reltime *t);
/* Helper macros for handling struct os_time */
#define os_time_before(a, b) \
((a)->sec < (b)->sec || \
((a)->sec == (b)->sec && (a)->usec < (b)->usec))
/* Helpers for handling struct os_time */
static inline int os_time_before(struct os_time *a, struct os_time *b)
{
return (a->sec < b->sec) ||
(a->sec == b->sec && a->usec < b->usec);
}
static inline void os_time_sub(struct os_time *a, struct os_time *b,
struct os_time *res)
{
res->sec = a->sec - b->sec;
res->usec = a->usec - b->usec;
if (res->usec < 0) {
res->sec--;
res->usec += 1000000;
}
}
/* Helpers for handling struct os_reltime */
static inline int os_reltime_before(struct os_reltime *a,
struct os_reltime *b)
{
return (a->sec < b->sec) ||
(a->sec == b->sec && a->usec < b->usec);
}
static inline void os_reltime_sub(struct os_reltime *a, struct os_reltime *b,
struct os_reltime *res)
{
res->sec = a->sec - b->sec;
res->usec = a->usec - b->usec;
if (res->usec < 0) {
res->sec--;
res->usec += 1000000;
}
}
static inline void os_reltime_age(struct os_reltime *start,
struct os_reltime *age)
{
struct os_reltime now;
os_get_reltime(&now);
os_reltime_sub(&now, start, age);
}
static inline int os_reltime_expired(struct os_reltime *now,
struct os_reltime *ts,
os_time_t timeout_secs)
{
struct os_reltime age;
os_reltime_sub(now, ts, &age);
return (age.sec > timeout_secs) ||
(age.sec == timeout_secs && age.usec > 0);
}
static inline int os_reltime_initialized(struct os_reltime *t)
{
return t->sec != 0 || t->usec != 0;
}
#define os_time_sub(a, b, res) do { \
(res)->sec = (a)->sec - (b)->sec; \
(res)->usec = (a)->usec - (b)->usec; \
if ((res)->usec < 0) { \
(res)->sec--; \
(res)->usec += 1000000; \
} \
} while (0)
/**
* os_mktime - Convert broken-down time into seconds since 1970-01-01
@ -171,6 +239,13 @@ int os_unsetenv(const char *name);
*/
char * os_readfile(const char *name, size_t *len);
/**
* os_file_exists - Check whether the specified file exists
* @fname: Path and name of the file
* Returns: 1 if the file exists or 0 if not
*/
int os_file_exists(const char *fname);
/**
* os_zalloc - Allocate and zero memory
* @size: Number of bytes to allocate
@ -360,15 +435,6 @@ int os_strcmp(const char *s1, const char *s2);
*/
int os_strncmp(const char *s1, const char *s2, size_t n);
/**
* os_strncpy - Copy a string
* @dest: Destination
* @src: Source
* @n: Maximum number of characters to copy
* Returns: dest
*/
char * os_strncpy(char *dest, const char *src, size_t n);
/**
* os_strstr - Locate a substring
* @haystack: String (haystack) to search from
@ -465,9 +531,6 @@ char * os_strdup(const char *s);
#ifndef os_strncmp
#define os_strncmp(s1, s2, n) strncmp((s1), (s2), (n))
#endif
#ifndef os_strncpy
#define os_strncpy(d, s, n) strncpy((d), (s), (n))
#endif
#ifndef os_strrchr
#define os_strrchr(s, c) strrchr((s), (c))
#endif
@ -493,6 +556,21 @@ static inline void * os_realloc_array(void *ptr, size_t nmemb, size_t size)
return os_realloc(ptr, nmemb * size);
}
/**
* os_remove_in_array - Remove a member from an array by index
* @ptr: Pointer to the array
* @nmemb: Current member count of the array
* @size: The size per member of the array
* @idx: Index of the member to be removed
*/
static inline void os_remove_in_array(void *ptr, size_t nmemb, size_t size,
size_t idx)
{
if (idx < nmemb - 1)
os_memmove(((unsigned char *) ptr) + idx * size,
((unsigned char *) ptr) + (idx + 1) * size,
(nmemb - idx - 1) * size);
}
/**
* os_strlcpy - Copy a string with size bound and NUL-termination
@ -506,6 +584,32 @@ static inline void * os_realloc_array(void *ptr, size_t nmemb, size_t size)
*/
size_t os_strlcpy(char *dest, const char *src, size_t siz);
/**
* os_memcmp_const - Constant time memory comparison
* @a: First buffer to compare
* @b: Second buffer to compare
* @len: Number of octets to compare
* Returns: 0 if buffers are equal, non-zero if not
*
* This function is meant for comparing passwords or hash values where
* difference in execution time could provide external observer information
* about the location of the difference in the memory buffers. The return value
* does not behave like os_memcmp(), i.e., os_memcmp_const() cannot be used to
* sort items into a defined order. Unlike os_memcmp(), execution time of
* os_memcmp_const() does not depend on the contents of the compared memory
* buffers, but only on the total compared length.
*/
int os_memcmp_const(const void *a, const void *b, size_t len);
/**
* os_exec - Execute an external program
* @program: Path to the program
* @arg: Command line argument string
* @wait_completion: Whether to wait until the program execution completes
* Returns: 0 on success, -1 on error
*/
int os_exec(const char *program, const char *arg, int wait_completion);
#ifdef OS_REJECT_C_LIB_FUNCTIONS
#define malloc OS_DO_NOT_USE_malloc

View File

@ -1,5 +1,5 @@
/* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.5 2005/01/22 20:12:05 sam Exp $ */
/* $NetBSD: radiotap.h,v 1.3 2014/01/03 02:08:17 christos Exp $ */
/* $NetBSD: radiotap.h,v 1.4 2014/10/16 19:29:30 christos Exp $ */
/*-
* Copyright (c) 2003, 2004 David Young. All rights reserved.
@ -175,6 +175,14 @@ struct ieee80211_radiotap_header {
*
* Number of unicast retries a transmitted frame used.
*
* IEEE80211_RADIOTAP_MCS u8, u8, u8 unitless
*
* Contains a bitmap of known fields/flags, the flags, and
* the MCS index.
*
* IEEE80211_RADIOTAP_AMPDU_STATUS u32, u16, u8, u8 unitlesss
*
* Contains the AMPDU information for the subframe.
*/
enum ieee80211_radiotap_type {
IEEE80211_RADIOTAP_TSFT = 0,
@ -195,6 +203,13 @@ enum ieee80211_radiotap_type {
IEEE80211_RADIOTAP_TX_FLAGS = 15,
IEEE80211_RADIOTAP_RTS_RETRIES = 16,
IEEE80211_RADIOTAP_DATA_RETRIES = 17,
IEEE80211_RADIOTAP_MCS = 19,
IEEE80211_RADIOTAP_AMPDU_STATUS = 20,
/* valid in every it_present bitmap, even vendor namespaces */
IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29,
IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30,
IEEE80211_RADIOTAP_EXT = 31
};
@ -227,8 +242,10 @@ enum ieee80211_radiotap_type {
* 802.11 header and payload
* (to 32-bit boundary)
*/
#define IEEE80211_RADIOTAP_F_BADFCS 0x40 /* frame failed FCS check */
/* For IEEE80211_RADIOTAP_RX_FLAGS */
#define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001 /* frame failed crc check */
#define IEEE80211_RADIOTAP_F_RX_BADPLCP 0x0002 /* bad PLCP */
/* For IEEE80211_RADIOTAP_TX_FLAGS */
#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive
@ -237,4 +254,38 @@ enum ieee80211_radiotap_type {
#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */
#define IEEE80211_RADIOTAP_F_TX_NOACK 0x0008 /* don't expect an ACK */
/* For IEEE80211_RADIOTAP_AMPDU_STATUS */
#define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN 0x0001
#define IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN 0x0002
#define IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN 0x0004
#define IEEE80211_RADIOTAP_AMPDU_IS_LAST 0x0008
#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010
#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020
/* For IEEE80211_RADIOTAP_MCS */
#define IEEE80211_RADIOTAP_MCS_HAVE_BW 0x01
#define IEEE80211_RADIOTAP_MCS_HAVE_MCS 0x02
#define IEEE80211_RADIOTAP_MCS_HAVE_GI 0x04
#define IEEE80211_RADIOTAP_MCS_HAVE_FMT 0x08
#define IEEE80211_RADIOTAP_MCS_HAVE_FEC 0x10
#define IEEE80211_RADIOTAP_MCS_HAVE_STBC 0x20
#define IEEE80211_RADIOTAP_MCS_HAVE_NESS 0x40
#define IEEE80211_RADIOTAP_MCS_NESS_BIT1 0x80
#define IEEE80211_RADIOTAP_MCS_BW_MASK 0x03
#define IEEE80211_RADIOTAP_MCS_BW_20 0
#define IEEE80211_RADIOTAP_MCS_BW_40 1
#define IEEE80211_RADIOTAP_MCS_BW_20L 2
#define IEEE80211_RADIOTAP_MCS_BW_20U 3
#define IEEE80211_RADIOTAP_MCS_SGI 0x04
#define IEEE80211_RADIOTAP_MCS_FMT_GF 0x08
#define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10
#define IEEE80211_RADIOTAP_MCS_STBC_MASK 0x60
#define IEEE80211_RADIOTAP_MCS_STBC_SHIFT 5
#define IEEE80211_RADIOTAP_MCS_STBC_1 1
#define IEEE80211_RADIOTAP_MCS_STBC_2 2
#define IEEE80211_RADIOTAP_MCS_STBC_3 3
#define IEEE80211_RADIOTAP_MCS_NESS_BIT0 0x80
#endif /* IEEE80211_RADIOTAP_H */

File diff suppressed because it is too large Load Diff