Cumulative patch from commit 681278246232029c334117bd6dc7e74c6b179f96
6812782 hlr_auc_gw: Allow Milenage RES length to be reduced
4839f7c wpa_cli: Fix a typo in usage text
a20a361 wpa_supplicant: Clear blacklist on connect
0144ecb Android: wpa_ctrl missing include for sys/stat.h
0bb20ef HS 2.0R2: Allow user to specify spp.xsd file location
97c9991 HS 2.0R2: Add more debugging messages to hs20-osu-client
93c2e60 HS 2.0R2 CA: Improve setup.sh and .conf for more flexibility
02e122a Reschedule scan from wpas_stop_pno if it was postponed
80fd9c3 EAP-PEAP server: Add support for negotiating vendor for Phase 2
a867082 EAP peer: Use 32-bit EAP method type for Phase 2 processing
56dfc49 Fix a typo in configuration parameter documentation
c4b45c6 TLS: Fix memory leaks on tls_connection_set_params() error paths
af85191 Make tls_connection_get_keyblock_size() internal to tls_*.c
94f1fe6 Remove master key extraction from tls_connection_get_keys()
fa0e715 Use tls_connection_prf() for all EAP TLS-based key derivation
df8191d Rename HT 20/40 coex variable to be more descriptive
1d0f42a EAP server: Add debug prints to help asleap testing
2c1cf90 Add wpa_snprintf_hex_sep()
5955cfa ms_funcs: Make challenge_hash() non-static
Change-Id: I0f3e5e5170a61e458949a675641946d95598dc5d
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/hostapd/hlr_auc_gw.c b/hostapd/hlr_auc_gw.c
index 42d59db..8afe457 100644
--- a/hostapd/hlr_auc_gw.c
+++ b/hostapd/hlr_auc_gw.c
@@ -87,6 +87,7 @@
u8 amf[2];
u8 sqn[6];
int set;
+ size_t res_len;
};
static struct milenage_parameters *milenage_db = NULL;
@@ -96,6 +97,7 @@
#define EAP_AKA_RAND_LEN 16
#define EAP_AKA_AUTN_LEN 16
#define EAP_AKA_AUTS_LEN 14
+#define EAP_AKA_RES_MIN_LEN 4
#define EAP_AKA_RES_MAX_LEN 16
#define EAP_AKA_IK_LEN 16
#define EAP_AKA_CK_LEN 16
@@ -124,7 +126,8 @@
" ki CHAR(32) NOT NULL,"
" opc CHAR(32) NOT NULL,"
" amf CHAR(4) NOT NULL,"
- " sqn CHAR(12) NOT NULL"
+ " sqn CHAR(12) NOT NULL,"
+ " res_len INTEGER"
");";
printf("Adding database table for milenage information\n");
@@ -190,6 +193,10 @@
printf("Invalid sqn value in database\n");
return -1;
}
+
+ if (os_strcmp(col[i], "res_len") == 0 && argv[i]) {
+ m->res_len = atoi(argv[i]);
+ }
}
return 0;
@@ -206,8 +213,7 @@
os_snprintf(db_tmp_milenage.imsi, sizeof(db_tmp_milenage.imsi),
"%llu", imsi);
os_snprintf(cmd, sizeof(cmd),
- "SELECT ki,opc,amf,sqn FROM milenage WHERE imsi=%llu;",
- imsi);
+ "SELECT * FROM milenage WHERE imsi=%llu;", imsi);
if (sqlite3_exec(sqlite_db, cmd, get_milenage_cb, &db_tmp_milenage,
NULL) != SQLITE_OK)
return NULL;
@@ -424,7 +430,7 @@
while (fgets(buf, sizeof(buf), f)) {
line++;
- /* Parse IMSI Ki OPc AMF SQN */
+ /* Parse IMSI Ki OPc AMF SQN [RES_len] */
buf[sizeof(buf) - 1] = '\0';
if (buf[0] == '#')
continue;
@@ -515,7 +521,19 @@
ret = -1;
break;
}
- pos = pos2 + 1;
+
+ if (pos2) {
+ pos = pos2 + 1;
+ m->res_len = atoi(pos);
+ if (m->res_len &&
+ (m->res_len < EAP_AKA_RES_MIN_LEN ||
+ m->res_len > EAP_AKA_RES_MAX_LEN)) {
+ printf("%s:%d - Invalid RES_len (%s)\n",
+ fname, line, pos);
+ ret = -1;
+ break;
+ }
+ }
m->next = milenage_db;
milenage_db = m;
@@ -798,6 +816,10 @@
}
milenage_generate(m->opc, m->amf, m->ki, m->sqn, _rand,
autn, ik, ck, res, &res_len);
+ if (m->res_len >= EAP_AKA_RES_MIN_LEN &&
+ m->res_len <= EAP_AKA_RES_MAX_LEN &&
+ m->res_len < res_len)
+ res_len = m->res_len;
} else {
printf("Unknown IMSI: %s\n", imsi);
#ifdef AKA_USE_FIXED_TEST_VALUES
diff --git a/hostapd/hlr_auc_gw.milenage_db b/hostapd/hlr_auc_gw.milenage_db
index ecd06d7..c156a29 100644
--- a/hostapd/hlr_auc_gw.milenage_db
+++ b/hostapd/hlr_auc_gw.milenage_db
@@ -5,8 +5,10 @@
# authentication. In case of GSM/EAP-SIM, AMF and SQN values are not used, but
# dummy values will need to be included in this file.
-# IMSI Ki OPc AMF SQN
+# IMSI Ki OPc AMF SQN [RES_len]
232010000000000 90dca4eda45b53cf0f12d7c9c3bc6a89 cb9cccc4b9258e6dca4760379fb82581 61df 000000000000
+# Example using truncated 32-bit RES instead of 64-bit default
+232010000000001 90dca4eda45b53cf0f12d7c9c3bc6a89 cb9cccc4b9258e6dca4760379fb82581 61df 000000000000 4
# These values are from Test Set 19 which has the AMF separation bit set to 1
# and as such, is suitable for EAP-AKA' test.
diff --git a/hs20/client/osu_client.c b/hs20/client/osu_client.c
index 649a884..5cd823e 100644
--- a/hs20/client/osu_client.c
+++ b/hs20/client/osu_client.c
@@ -25,6 +25,8 @@
#include "crypto/sha256.h"
#include "osu_client.h"
+const char *spp_xsd_fname = "spp.xsd";
+
void write_result(struct hs20_osu_client *ctx, const char *fmt, ...)
{
@@ -547,8 +549,9 @@
wpa_printf(MSG_INFO, "SP FQDN: %s", fqdn);
if (!server_dnsname_suffix_match(ctx, fqdn)) {
- wpa_printf(MSG_INFO, "FQDN '%s' for new PPS MO did not have suffix match with server's dNSName values",
- fqdn);
+ wpa_printf(MSG_INFO,
+ "FQDN '%s' for new PPS MO did not have suffix match with server's dNSName values, count: %d",
+ fqdn, (int) ctx->server_dnsname_count);
write_result(ctx, "FQDN '%s' for new PPS MO did not have suffix match with server's dNSName values",
fqdn);
free(fqdn);
@@ -2094,10 +2097,14 @@
}
ctx->no_reconnect = 1;
- if (methods & 0x02)
+ if (methods & 0x02) {
+ wpa_printf(MSG_DEBUG, "Calling cmd_prov from osu_connect");
res = cmd_prov(ctx, url);
- else if (methods & 0x01)
+ } else if (methods & 0x01) {
+ wpa_printf(MSG_DEBUG,
+ "Calling cmd_oma_dm_prov from osu_connect");
res = cmd_oma_dm_prov(ctx, url);
+ }
wpa_printf(MSG_INFO, "Remove OSU network connection");
write_summary(ctx, "Remove OSU network connection");
@@ -2290,12 +2297,19 @@
}
if (connect == 2) {
- if (last->methods & 0x02)
+ if (last->methods & 0x02) {
+ wpa_printf(MSG_DEBUG,
+ "Calling cmd_prov from cmd_osu_select");
ret = cmd_prov(ctx, last->url);
- else if (last->methods & 0x01)
+ } else if (last->methods & 0x01) {
+ wpa_printf(MSG_DEBUG,
+ "Calling cmd_oma_dm_prov from cmd_osu_select");
ret = cmd_oma_dm_prov(ctx, last->url);
- else
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "No supported OSU provisioning method");
ret = -1;
+ }
} else if (connect)
ret = osu_connect(ctx, last->bssid, last->osu_ssid,
last->url, last->methods,
@@ -2972,6 +2986,7 @@
" [-w<wpa_supplicant ctrl_iface dir>] "
"[-r<result file>] [-f<debug file>] \\\n"
" [-s<summary file>] \\\n"
+ " [-x<spp.xsd file name>] \\\n"
" <command> [arguments..]\n"
"commands:\n"
"- to_tnds <XML MO> <XML MO in TNDS format> [URN]\n"
@@ -3013,7 +3028,7 @@
return -1;
for (;;) {
- c = getopt(argc, argv, "df:hKNO:qr:s:S:tw:");
+ c = getopt(argc, argv, "df:hKNO:qr:s:S:tw:x:");
if (c < 0)
break;
switch (c) {
@@ -3051,6 +3066,9 @@
case 'w':
wpas_ctrl_path = optarg;
break;
+ case 'x':
+ spp_xsd_fname = optarg;
+ break;
case 'h':
default:
usage();
@@ -3125,6 +3143,7 @@
exit(0);
}
ctx.ca_fname = argv[optind + 2];
+ wpa_printf(MSG_DEBUG, "Calling cmd_prov from main");
cmd_prov(&ctx, argv[optind + 1]);
} else if (strcmp(argv[optind], "sim_prov") == 0) {
if (argc - optind < 2) {
diff --git a/hs20/client/spp_client.c b/hs20/client/spp_client.c
index 302a050..cc1a0bf 100644
--- a/hs20/client/spp_client.c
+++ b/hs20/client/spp_client.c
@@ -21,6 +21,8 @@
#include "osu_client.h"
+extern const char *spp_xsd_fname;
+
static int hs20_spp_update_response(struct hs20_osu_client *ctx,
const char *session_id,
const char *spp_status,
@@ -59,7 +61,7 @@
return -1;
}
- ret = xml_validate(xctx, node, "spp.xsd", &err);
+ ret = xml_validate(xctx, node, spp_xsd_fname, &err);
if (ret < 0) {
wpa_printf(MSG_INFO, "XML schema validation error(s)\n%s", err);
write_summary(ctx, "SPP XML schema validation failed");
@@ -952,7 +954,9 @@
return -1;
}
- wpa_printf(MSG_INFO, "Credential provisioning requested");
+ wpa_printf(MSG_INFO,
+ "Credential provisioning requested - URL: %s ca_fname: %s",
+ url, ctx->ca_fname ? ctx->ca_fname : "N/A");
os_free(ctx->server_url);
ctx->server_url = os_strdup(url);
diff --git a/hs20/server/ca/clean.sh b/hs20/server/ca/clean.sh
old mode 100644
new mode 100755
index c69a1f5..c72dcbd
--- a/hs20/server/ca/clean.sh
+++ b/hs20/server/ca/clean.sh
@@ -5,6 +5,9 @@
done
rm -f openssl.cnf.tmp
-rm -r demoCA
+if [ -d demoCA ]; then
+ rm -r demoCA
+fi
rm -f ca.pem logo.asn1 logo.der server.der ocsp-server-cache.der
+rm -f my-openssl.cnf my-openssl-root.cnf
#rm -r rootCA
diff --git a/hs20/server/ca/openssl-root.cnf b/hs20/server/ca/openssl-root.cnf
index 5b220fe..5bc50be 100644
--- a/hs20/server/ca/openssl-root.cnf
+++ b/hs20/server/ca/openssl-root.cnf
@@ -69,8 +69,8 @@
attributes = req_attributes
x509_extensions = v3_ca # The extentions to add to the self signed cert
-input_password = whatever
-output_password = whatever
+input_password = @PASSWORD@
+output_password = @PASSWORD@
string_mask = utf8only
diff --git a/hs20/server/ca/openssl.cnf b/hs20/server/ca/openssl.cnf
index a939f08..6141013 100644
--- a/hs20/server/ca/openssl.cnf
+++ b/hs20/server/ca/openssl.cnf
@@ -80,8 +80,8 @@
attributes = req_attributes
x509_extensions = v3_ca # The extentions to add to the self signed cert
-input_password = whatever
-output_password = whatever
+input_password = @PASSWORD@
+output_password = @PASSWORD@
string_mask = utf8only
@@ -95,7 +95,7 @@
localityName_default = Tuusula
0.organizationName = Organization Name (eg, company)
-0.organizationName_default = w1.fi
+0.organizationName_default = @DOMAIN@
##organizationalUnitName = Organizational Unit Name (eg, section)
#organizationalUnitName_default =
@@ -117,10 +117,10 @@
authorityKeyIdentifier=keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, cRLSign, keyCertSign
-authorityInfoAccess = OCSP;URI:http://osu.w1.fi:8888/
+authorityInfoAccess = OCSP;URI:@OCSP_URI@
# For SP intermediate CA
#subjectAltName=critical,otherName:1.3.6.1.4.1.40808.1.1.1;UTF8String:engExample OSU
-#nameConstraints=permitted;DNS:.w1.fi
+#nameConstraints=permitted;DNS:.@DOMAIN@
#1.3.6.1.5.5.7.1.12=ASN1:SEQUENCE:LogotypeExtn
[ v3_osu_server ]
@@ -150,16 +150,16 @@
#value2=SEQUENCE:HashAlgAndValueSHA1
[HashAlgAndValueSHA256]
hashAlg=SEQUENCE:sha256_alg
-hashValue=FORMAT:HEX,OCTETSTRING:4532f7ec36424381617c03c6ce87b55a51d6e7177ffafda243cebf280a68954d
+hashValue=FORMAT:HEX,OCTETSTRING:@LOGO_HASH256@
[HashAlgAndValueSHA1]
hashAlg=SEQUENCE:sha1_alg
-hashValue=FORMAT:HEX,OCTETSTRING:5e1d5085676eede6b02da14d31c523ec20ffba0b
+hashValue=FORMAT:HEX,OCTETSTRING:@LOGO_HASH1@
[sha256_alg]
algorithm=OID:sha256
[sha1_alg]
algorithm=OID:sha1
[URI]
-uri=IA5STRING:http://osu.w1.fi/w1fi_logo.png
+uri=IA5STRING:@LOGO_URI@
[LogotypeImageInfo]
# default value color(1), component optional
#type=IMP:0,INTEGER:1
@@ -184,7 +184,7 @@
basicConstraints=CA:FALSE
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
-authorityInfoAccess = OCSP;URI:http://osu.w1.fi:8888/
+authorityInfoAccess = OCSP;URI:@OCSP_URI@
#@ALTNAME@
extendedKeyUsage = clientAuth
@@ -194,7 +194,7 @@
basicConstraints=critical, CA:FALSE
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
-authorityInfoAccess = OCSP;URI:http://osu.w1.fi:8888/
+authorityInfoAccess = OCSP;URI:@OCSP_URI@
#@ALTNAME@
extendedKeyUsage = critical, serverAuth
keyUsage = critical, keyEncipherment
diff --git a/hs20/server/ca/setup.sh b/hs20/server/ca/setup.sh
old mode 100644
new mode 100755
index f61bf73..78abccc
--- a/hs20/server/ca/setup.sh
+++ b/hs20/server/ca/setup.sh
@@ -5,6 +5,67 @@
fi
export OPENSSL_CONF=$PWD/openssl.cnf
PASS=whatever
+if [ -z "$DOMAIN" ]; then
+ DOMAIN=w1.fi
+fi
+COMPANY=w1.fi
+OPER_ENG="engw1.fi TESTING USE"
+OPER_FI="finw1.fi TESTIKÄYTTÖ"
+CNR="Hotspot 2.0 Trust Root CA - 99"
+CNO="ocsp.$DOMAIN"
+CNV="osu-revoked.$DOMAIN"
+CNOC="osu-client.$DOMAIN"
+OSU_SERVER_HOSTNAME="osu.$DOMAIN"
+DEBUG=0
+OCSP_URI="http://$CNO:8888/"
+LOGO_URI="http://osu.w1.fi/w1fi_logo.png"
+LOGO_HASH256="4532f7ec36424381617c03c6ce87b55a51d6e7177ffafda243cebf280a68954d"
+LOGO_HASH1="5e1d5085676eede6b02da14d31c523ec20ffba0b"
+
+# Command line overrides
+USAGE=$( cat <<EOF
+Usage:\n
+# -c: Company name, used to generate Subject name CN for Intermediate CA\n
+# -C: Subject name CN of the Root CA ($CNR)\n
+# -D: Enable debugging (set -x, etc)\n
+# -g: Logo sha1 hash ($LOGO_HASH1)\n
+# -G: Logo sha256 hash ($LOGO_HASH256)\n
+# -h: Show this help message\n
+# -l: Logo URI ($LOGO_URI)\n
+# -m: Domain ($DOMAIN)\n
+# -o: Subject name CN for OSU-Client Server ($CNOC)\n
+# -O: Subject name CN for OCSP Server ($CNO)\n
+# -p: passphrase for private keys ($PASS)\n
+# -r: Operator-english ($OPER_ENG)\n
+# -R: Operator-finish ($OPER_FI)\n
+# -S: OSU Server name ($OSU_SERVER_HOSTNAME)\n
+# -u: OCSP-URI ($OCSP_URI)\n
+# -V: Subject name CN for OSU-Revoked Server ($CNV)\n
+EOF
+)
+
+while getopts "c:C:Dg:G:l:m:o:O:p:r:R:S:u:V:h" flag
+ do
+ case $flag in
+ c) COMPANY=$OPTARG;;
+ C) CNR=$OPTARG;;
+ D) DEBUG=1;;
+ g) LOGO_HASH1=$OPTARG;;
+ G) LOGO_HASH256=$OPTARG;;
+ h) echo -e $USAGE; exit 0;;
+ l) LOGO_URI=$OPTARG;;
+ m) DOMAIN=$OPTARG;;
+ o) CNOC=$OPTARG;;
+ O) CNO=$OPTARG;;
+ p) PASS=$OPTARG;;
+ r) OPER_ENG=$OPTARG;;
+ R) OPER_FI=$OPTARG;;
+ S) OSU_SERVER_HOSTNAME=$OPTARG;;
+ u) OCSP_URI=$OPTARG;;
+ V) CNV=$OPTARG;;
+ *) echo "Unknown flag: $flag"; echo -e $USAGE; exit 1;;
+ esac
+done
fail()
{
@@ -16,7 +77,25 @@
echo "---[ Root CA ]----------------------------------------------------------"
echo
-cat openssl-root.cnf | sed "s/#@CN@/commonName_default = Hotspot 2.0 Trust Root CA - 99/" > openssl.cnf.tmp
+if [ $DEBUG = 1 ]
+then
+ set -x
+fi
+
+# Set the passphrase and some other common config accordingly.
+cat openssl-root.cnf | sed "s/@PASSWORD@/$PASS/" \
+ > my-openssl-root.cnf
+
+cat openssl.cnf | sed "s/@PASSWORD@/$PASS/" |
+sed "s,@OCSP_URI@,$OCSP_URI," |
+sed "s,@LOGO_URI@,$LOGO_URI," |
+sed "s,@LOGO_HASH1@,$LOGO_HASH1," |
+sed "s,@LOGO_HASH256@,$LOGO_HASH256," |
+sed "s/@DOMAIN@/$DOMAIN/" \
+ > my-openssl.cnf
+
+
+cat my-openssl-root.cnf | sed "s/#@CN@/commonName_default = $CNR/" > openssl.cnf.tmp
mkdir -p rootCA/certs rootCA/crl rootCA/newcerts rootCA/private
touch rootCA/index.txt
if [ -e rootCA/private/cakey.pem ]; then
@@ -26,6 +105,8 @@
$OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:4096 -keyout rootCA/private/cakey.pem -out rootCA/careq.pem || fail "Failed to generate Root CA private key"
echo " * Sign Root CA certificate"
$OPENSSL ca -config openssl.cnf.tmp -md sha256 -create_serial -out rootCA/cacert.pem -days 10957 -batch -keyfile rootCA/private/cakey.pem -passin pass:$PASS -selfsign -extensions v3_ca -outdir rootCA/newcerts -infiles rootCA/careq.pem || fail "Failed to sign Root CA certificate"
+ $OPENSSL x509 -in rootCA/cacert.pem -out rootCA/cacert.der -outform DER || fail "Failed to create rootCA DER"
+ sha256sum rootCA/cacert.der > rootCA/cacert.fingerprint || fail "Failed to create rootCA fingerprint"
fi
if [ ! -e rootCA/crlnumber ]; then
echo 00 > rootCA/crlnumber
@@ -35,7 +116,7 @@
echo "---[ Intermediate CA ]--------------------------------------------------"
echo
-cat openssl.cnf | sed "s/#@CN@/commonName_default = w1.fi Hotspot 2.0 Intermediate CA/" > openssl.cnf.tmp
+cat my-openssl.cnf | sed "s/#@CN@/commonName_default = $COMPANY Hotspot 2.0 Intermediate CA/" > openssl.cnf.tmp
mkdir -p demoCA/certs demoCA/crl demoCA/newcerts demoCA/private
touch demoCA/index.txt
if [ -e demoCA/private/cakey.pem ]; then
@@ -47,6 +128,8 @@
$OPENSSL ca -config openssl.cnf.tmp -md sha256 -create_serial -out demoCA/cacert.pem -days 3652 -batch -keyfile rootCA/private/cakey.pem -cert rootCA/cacert.pem -passin pass:$PASS -extensions v3_ca -infiles demoCA/careq.pem || fail "Failed to sign Intermediate CA certificate"
# horrible from security view point, but for testing purposes since OCSP responder does not seem to support -passin
openssl rsa -in demoCA/private/cakey.pem -out demoCA/private/cakey-plain.pem -passin pass:$PASS
+ $OPENSSL x509 -in demoCA/cacert.pem -out demoCA/cacert.der -outform DER || fail "Failed to create demoCA DER."
+ sha256sum demoCA/cacert.der > demoCA/cacert.fingerprint || fail "Failed to create demoCA fingerprint"
fi
if [ ! -e demoCA/crlnumber ]; then
echo 00 > demoCA/crlnumber
@@ -56,45 +139,46 @@
echo "OCSP responder"
echo
-cat openssl.cnf | sed "s/#@CN@/commonName_default = ocsp.w1.fi/" > openssl.cnf.tmp
+cat my-openssl.cnf | sed "s/#@CN@/commonName_default = $CNO/" > openssl.cnf.tmp
$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -out ocsp.csr -keyout ocsp.key -extensions v3_OCSP
-$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -keyfile demoCA/private/cakey.pem -passin pass:$PASS -in ocsp.csr -out ocsp.pem -days 730 -extensions v3_OCSP
+$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -keyfile demoCA/private/cakey.pem -passin pass:$PASS -in ocsp.csr -out ocsp.pem -days 730 -extensions v3_OCSP || fail "Could not generate ocsp.pem"
echo
echo "---[ Server - to be revoked ] ------------------------------------------"
echo
-cat openssl.cnf | sed "s/#@CN@/commonName_default = osu-revoked.w1.fi/" > openssl.cnf.tmp
+cat my-openssl.cnf | sed "s/#@CN@/commonName_default = $CNV/" > openssl.cnf.tmp
$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -out server-revoked.csr -keyout server-revoked.key
$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -in server-revoked.csr -out server-revoked.pem -key $PASS -days 730 -extensions ext_server
$OPENSSL ca -revoke server-revoked.pem -key $PASS
echo
echo "---[ Server - with client ext key use ] ---------------------------------"
+echo "---[ Only used for negative-testing for OSU-client implementation ] -----"
echo
-cat openssl.cnf | sed "s/#@CN@/commonName_default = osu-client.w1.fi/" > openssl.cnf.tmp
-$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -out server-client.csr -keyout server-client.key
-$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -in server-client.csr -out server-client.pem -key $PASS -days 730 -extensions ext_client
+cat my-openssl.cnf | sed "s/#@CN@/commonName_default = $CNOC/" > openssl.cnf.tmp
+$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -out server-client.csr -keyout server-client.key || fail "Could not create server-client.key"
+$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -in server-client.csr -out server-client.pem -key $PASS -days 730 -extensions ext_client || fail "Could not create server-client.pem"
echo
echo "---[ User ]-------------------------------------------------------------"
echo
-cat openssl.cnf | sed "s/#@CN@/commonName_default = User/" > openssl.cnf.tmp
-$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -out user.csr -keyout user.key
-$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -in user.csr -out user.pem -key $PASS -days 730 -extensions ext_client
+cat my-openssl.cnf | sed "s/#@CN@/commonName_default = User/" > openssl.cnf.tmp
+$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -out user.csr -keyout user.key || fail "Could not create user.key"
+$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -in user.csr -out user.pem -key $PASS -days 730 -extensions ext_client || fail "Could not create user.pem"
echo
echo "---[ Server ]-----------------------------------------------------------"
echo
-ALT="DNS:osu.w1.fi"
-ALT="$ALT,otherName:1.3.6.1.4.1.40808.1.1.1;UTF8String:engw1.fi TESTING USE"
-ALT="$ALT,otherName:1.3.6.1.4.1.40808.1.1.1;UTF8String:finw1.fi TESTIKÄYTTÖ"
+ALT="DNS:$OSU_SERVER_HOSTNAME"
+ALT="$ALT,otherName:1.3.6.1.4.1.40808.1.1.1;UTF8String:$OPER_ENG"
+ALT="$ALT,otherName:1.3.6.1.4.1.40808.1.1.1;UTF8String:$OPER_FI"
-cat openssl.cnf |
- sed "s/#@CN@/commonName_default = osu.w1.fi/" |
+cat my-openssl.cnf |
+ sed "s/#@CN@/commonName_default = $OSU_SERVER_HOSTNAME/" |
sed "s/^##organizationalUnitName/organizationalUnitName/" |
sed "s/#@OU@/organizationalUnitName_default = Hotspot 2.0 Online Sign Up Server/" |
sed "s/#@ALTNAME@/subjectAltName=critical,$ALT/" \
@@ -113,7 +197,7 @@
echo "---[ CRL ]---------------------------------------------------------------"
echo
-$OPENSSL ca -config $PWD/openssl.cnf -gencrl -md sha256 -out demoCA/crl/crl.pem -passin pass:$PASS
+$OPENSSL ca -config $PWD/my-openssl.cnf -gencrl -md sha256 -out demoCA/crl/crl.pem -passin pass:$PASS
echo
echo "---[ Verify ]------------------------------------------------------------"
diff --git a/hs20/server/hs20-osu-server.txt b/hs20/server/hs20-osu-server.txt
index 80985f7..001d6f2 100644
--- a/hs20/server/hs20-osu-server.txt
+++ b/hs20/server/hs20-osu-server.txt
@@ -100,6 +100,21 @@
# the examples as-is for initial testing).
cp -r www /home/user/hs20-server
+# Build local keys and certs
+cd ca
+# Display help options.
+./setup.sh -h
+
+# Remove old keys, fill in appropriate values, and generate your keys.
+# For instance:
+./clean.sh
+rm -fr rootCA"
+old_hostname=myserver.local
+./setup.sh -C "Hotspot 2.0 Trust Root CA - CT" -d $old_hostname \
+ -I "Hotspot 2.0 Intermediate CA - CT" -o $old_hostname-osu-client \
+ -O $old_hostname-oscp -p lanforge -S $old_hostname \
+ -V $old_hostname-osu-revoked \
+ -m local -u http://$old_hostname:8888/
# Configure subscription policies
mkdir -p /home/user/hs20-server/spp/policy
@@ -156,6 +171,50 @@
./hostapd -B as-sql.conf
+OSEN RADIUS server configuration notes
+
+The OSEN RADIUS server config file should have the 'ocsp_stapling_response'
+configuration in it. For example:
+
+# hostapd-radius config for the radius used by the OSEN AP
+interface=eth0#0
+driver=none
+logger_syslog=-1
+logger_syslog_level=2
+logger_stdout=-1
+logger_stdout_level=2
+ctrl_interface=/var/run/hostapd
+ctrl_interface_group=0
+eap_server=1
+eap_user_file=/home/user/hs20-server/AS/hostapd-osen.eap_user
+server_id=ben-ota-2-osen
+radius_server_auth_port=1811
+radius_server_clients=/home/user/hs20-server/AS/hostap.radius_clients
+
+ca_cert=/home/user/hs20-server/ca/ca.pem
+server_cert=/home/user/hs20-server/ca/server.pem
+private_key=/home/user/hs20-server/ca/server.key
+private_key_passwd=whatever
+
+ocsp_stapling_response=/home/user/hs20-server/ca/ocsp-server-cache.der
+
+The /home/user/hs20-server/AS/hostapd-osen.eap_user file should look
+similar to this, and should coorelate with the osu_nai entry in
+the non-OSEN VAP config file. For instance:
+
+# cat hostapd-osen.eap_user
+# For OSEN authentication (Hotspot 2.0 Release 2)
+"osen@w1.fi" WFA-UNAUTH-TLS
+
+
+# Run OCSP server:
+cd /home/user/hs20-server/ca
+./ocsp-responder.sh&
+
+# Update cache (This should be run periodically)
+./ocsp-update-cache.sh
+
+
Configure web server
--------------------
@@ -172,6 +231,8 @@
</Directory>
Update SSL configuration to use the OSU server certificate/key.
+They keys and certs are called 'server.key' and 'server.pem' from
+ca/setup.sh.
Enable default-ssl site and restart Apache2:
sudo a2ensite default-ssl
diff --git a/src/ap/ieee802_11_ht.c b/src/ap/ieee802_11_ht.c
index 15edbe9..9dad8e3 100644
--- a/src/ap/ieee802_11_ht.c
+++ b/src/ap/ieee802_11_ht.c
@@ -209,7 +209,7 @@
struct hostapd_iface *iface = hapd->iface;
struct ieee80211_2040_bss_coex_ie *bc_ie;
struct ieee80211_2040_intol_chan_report *ic_report;
- int is_ht_allowed = 1;
+ int is_ht40_allowed = 1;
int i;
const u8 *start = (const u8 *) mgmt;
const u8 *data = start + IEEE80211_HDRLEN + 2;
@@ -242,7 +242,7 @@
HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"20 MHz BSS width request bit is set in BSS coexistence information field");
- is_ht_allowed = 0;
+ is_ht40_allowed = 0;
}
if (bc_ie->coex_param & WLAN_20_40_BSS_COEX_40MHZ_INTOL) {
@@ -250,7 +250,7 @@
HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"40 MHz intolerant bit is set in BSS coexistence information field");
- is_ht_allowed = 0;
+ is_ht40_allowed = 0;
}
if (start + len - data >= 3 &&
@@ -276,13 +276,13 @@
HOSTAPD_LEVEL_DEBUG,
"20_40_INTOLERANT channel %d reported",
chan);
- is_ht_allowed = 0;
+ is_ht40_allowed = 0;
}
}
- wpa_printf(MSG_DEBUG, "is_ht_allowed=%d num_sta_ht40_intolerant=%d",
- is_ht_allowed, iface->num_sta_ht40_intolerant);
+ wpa_printf(MSG_DEBUG, "is_ht40_allowed=%d num_sta_ht40_intolerant=%d",
+ is_ht40_allowed, iface->num_sta_ht40_intolerant);
- if (!is_ht_allowed &&
+ if (!is_ht40_allowed &&
(iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX)) {
if (iface->conf->secondary_channel) {
hostapd_logger(hapd, mgmt->sa,
diff --git a/src/common/wpa_ctrl.c b/src/common/wpa_ctrl.c
index ccaaf1b..82d4655 100644
--- a/src/common/wpa_ctrl.c
+++ b/src/common/wpa_ctrl.c
@@ -21,6 +21,7 @@
#ifdef ANDROID
#include <dirent.h>
+#include <sys/stat.h>
#include <cutils/sockets.h>
#include "private/android_filesystem_config.h"
#endif /* ANDROID */
diff --git a/src/crypto/ms_funcs.c b/src/crypto/ms_funcs.c
index 49a5c1c..5f57656 100644
--- a/src/crypto/ms_funcs.c
+++ b/src/crypto/ms_funcs.c
@@ -78,9 +78,8 @@
* @challenge: 8-octet Challenge (OUT)
* Returns: 0 on success, -1 on failure
*/
-static int challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge,
- const u8 *username, size_t username_len,
- u8 *challenge)
+int challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge,
+ const u8 *username, size_t username_len, u8 *challenge)
{
u8 hash[SHA1_MAC_LEN];
const unsigned char *addr[3];
diff --git a/src/crypto/ms_funcs.h b/src/crypto/ms_funcs.h
index bd9bfee..b5b5918 100644
--- a/src/crypto/ms_funcs.h
+++ b/src/crypto/ms_funcs.h
@@ -33,6 +33,8 @@
void challenge_response(const u8 *challenge, const u8 *password_hash,
u8 *response);
+int challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge,
+ const u8 *username, size_t username_len, u8 *challenge);
int nt_password_hash(const u8 *password, size_t password_len,
u8 *password_hash);
int hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash);
diff --git a/src/crypto/tls.h b/src/crypto/tls.h
index 9ae95a6..f9e2e10 100644
--- a/src/crypto/tls.h
+++ b/src/crypto/tls.h
@@ -12,8 +12,6 @@
struct tls_connection;
struct tls_keys {
- const u8 *master_key; /* TLS master secret */
- size_t master_key_len;
const u8 *client_random;
size_t client_random_len;
const u8 *server_random;
@@ -308,10 +306,10 @@
int verify_peer);
/**
- * tls_connection_get_keys - Get master key and random data from TLS connection
+ * tls_connection_get_keys - Get random data from TLS connection
* @tls_ctx: TLS context data from tls_init()
* @conn: Connection context data from tls_connection_init()
- * @keys: Structure of key/random data (filled on success)
+ * @keys: Structure of client/server random data (filled on success)
* Returns: 0 on success, -1 on failure
*/
int __must_check tls_connection_get_keys(void *tls_ctx,
@@ -325,6 +323,7 @@
* @label: Label (e.g., description of the key) for PRF
* @server_random_first: seed is 0 = client_random|server_random,
* 1 = server_random|client_random
+ * @skip_keyblock: Skip TLS key block from the beginning of PRF output
* @out: Buffer for output data from TLS-PRF
* @out_len: Length of the output buffer
* Returns: 0 on success, -1 on failure
@@ -342,6 +341,7 @@
struct tls_connection *conn,
const char *label,
int server_random_first,
+ int skip_keyblock,
u8 *out, size_t out_len);
/**
@@ -528,16 +528,6 @@
struct tls_connection *conn);
/**
- * tls_connection_get_keyblock_size - Get TLS key_block size
- * @tls_ctx: TLS context data from tls_init()
- * @conn: Connection context data from tls_connection_init()
- * Returns: Size of the key_block for the negotiated cipher suite or -1 on
- * failure
- */
-int tls_connection_get_keyblock_size(void *tls_ctx,
- struct tls_connection *conn);
-
-/**
* tls_capabilities - Get supported TLS capabilities
* @tls_ctx: TLS context data from tls_init()
* Returns: Bit field of supported TLS capabilities (TLS_CAPABILITY_*)
diff --git a/src/crypto/tls_gnutls.c b/src/crypto/tls_gnutls.c
index 65db6fc..c7f6464 100644
--- a/src/crypto/tls_gnutls.c
+++ b/src/crypto/tls_gnutls.c
@@ -747,9 +747,9 @@
int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
const char *label, int server_random_first,
- u8 *out, size_t out_len)
+ int skip_keyblock, u8 *out, size_t out_len)
{
- if (conn == NULL || conn->session == NULL)
+ if (conn == NULL || conn->session == NULL || skip_keyblock)
return -1;
return gnutls_prf(conn->session, os_strlen(label), label,
@@ -1476,14 +1476,6 @@
}
-int tls_connection_get_keyblock_size(void *tls_ctx,
- struct tls_connection *conn)
-{
- /* TODO */
- return -1;
-}
-
-
unsigned int tls_capabilities(void *tls_ctx)
{
return 0;
diff --git a/src/crypto/tls_internal.c b/src/crypto/tls_internal.c
index 0c955da..afd4695 100644
--- a/src/crypto/tls_internal.c
+++ b/src/crypto/tls_internal.c
@@ -192,26 +192,31 @@
if (params->subject_match) {
wpa_printf(MSG_INFO, "TLS: subject_match not supported");
+ tlsv1_cred_free(cred);
return -1;
}
if (params->altsubject_match) {
wpa_printf(MSG_INFO, "TLS: altsubject_match not supported");
+ tlsv1_cred_free(cred);
return -1;
}
if (params->suffix_match) {
wpa_printf(MSG_INFO, "TLS: suffix_match not supported");
+ tlsv1_cred_free(cred);
return -1;
}
if (params->domain_match) {
wpa_printf(MSG_INFO, "TLS: domain_match not supported");
+ tlsv1_cred_free(cred);
return -1;
}
if (params->openssl_ciphers) {
- wpa_printf(MSG_INFO, "GnuTLS: openssl_ciphers not supported");
+ wpa_printf(MSG_INFO, "TLS: openssl_ciphers not supported");
+ tlsv1_cred_free(cred);
return -1;
}
@@ -348,25 +353,57 @@
}
-int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
- const char *label, int server_random_first,
- u8 *out, size_t out_len)
+static int tls_get_keyblock_size(struct tls_connection *conn)
{
#ifdef CONFIG_TLS_INTERNAL_CLIENT
+ if (conn->client)
+ return tlsv1_client_get_keyblock_size(conn->client);
+#endif /* CONFIG_TLS_INTERNAL_CLIENT */
+#ifdef CONFIG_TLS_INTERNAL_SERVER
+ if (conn->server)
+ return tlsv1_server_get_keyblock_size(conn->server);
+#endif /* CONFIG_TLS_INTERNAL_SERVER */
+ return -1;
+}
+
+
+int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
+ const char *label, int server_random_first,
+ int skip_keyblock, u8 *out, size_t out_len)
+{
+ int ret = -1, skip = 0;
+ u8 *tmp_out = NULL;
+ u8 *_out = out;
+
+ if (skip_keyblock) {
+ skip = tls_get_keyblock_size(conn);
+ if (skip < 0)
+ return -1;
+ tmp_out = os_malloc(skip + out_len);
+ if (!tmp_out)
+ return -1;
+ _out = tmp_out;
+ }
+
+#ifdef CONFIG_TLS_INTERNAL_CLIENT
if (conn->client) {
- return tlsv1_client_prf(conn->client, label,
- server_random_first,
- out, out_len);
+ ret = tlsv1_client_prf(conn->client, label,
+ server_random_first,
+ _out, out_len);
}
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
#ifdef CONFIG_TLS_INTERNAL_SERVER
if (conn->server) {
- return tlsv1_server_prf(conn->server, label,
- server_random_first,
- out, out_len);
+ ret = tlsv1_server_prf(conn->server, label,
+ server_random_first,
+ _out, out_len);
}
#endif /* CONFIG_TLS_INTERNAL_SERVER */
- return -1;
+ if (ret == 0 && skip_keyblock)
+ os_memcpy(out, _out + skip, out_len);
+ bin_clear_free(tmp_out, skip);
+
+ return ret;
}
@@ -637,21 +674,6 @@
}
-int tls_connection_get_keyblock_size(void *tls_ctx,
- struct tls_connection *conn)
-{
-#ifdef CONFIG_TLS_INTERNAL_CLIENT
- if (conn->client)
- return tlsv1_client_get_keyblock_size(conn->client);
-#endif /* CONFIG_TLS_INTERNAL_CLIENT */
-#ifdef CONFIG_TLS_INTERNAL_SERVER
- if (conn->server)
- return tlsv1_server_get_keyblock_size(conn->server);
-#endif /* CONFIG_TLS_INTERNAL_SERVER */
- return -1;
-}
-
-
unsigned int tls_capabilities(void *tls_ctx)
{
return 0;
diff --git a/src/crypto/tls_none.c b/src/crypto/tls_none.c
index a6d210a..1b1ba56 100644
--- a/src/crypto/tls_none.c
+++ b/src/crypto/tls_none.c
@@ -87,7 +87,7 @@
int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
const char *label, int server_random_first,
- u8 *out, size_t out_len)
+ int skip_keyblock, u8 *out, size_t out_len)
{
return -1;
}
@@ -181,13 +181,6 @@
}
-int tls_connection_get_keyblock_size(void *tls_ctx,
- struct tls_connection *conn)
-{
- return -1;
-}
-
-
unsigned int tls_capabilities(void *tls_ctx)
{
return 0;
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index 52db8fc..935add5 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -26,6 +26,7 @@
#include "common.h"
#include "crypto.h"
+#include "sha1.h"
#include "tls.h"
#if defined(SSL_CTX_get_app_data) && defined(SSL_CTX_set_app_data)
@@ -2632,8 +2633,6 @@
return -1;
os_memset(keys, 0, sizeof(*keys));
- keys->master_key = ssl->session->master_key;
- keys->master_key_len = ssl->session->master_key_length;
keys->client_random = ssl->s3->client_random;
keys->client_random_len = SSL3_RANDOM_SIZE;
keys->server_random = ssl->s3->server_random;
@@ -2644,16 +2643,122 @@
}
+static int openssl_get_keyblock_size(SSL *ssl)
+{
+ const EVP_CIPHER *c;
+ const EVP_MD *h;
+ int md_size;
+
+ if (ssl->enc_read_ctx == NULL || ssl->enc_read_ctx->cipher == NULL ||
+ ssl->read_hash == NULL)
+ return -1;
+
+ c = ssl->enc_read_ctx->cipher;
+#if OPENSSL_VERSION_NUMBER >= 0x00909000L
+ h = EVP_MD_CTX_md(ssl->read_hash);
+#else
+ h = conn->ssl->read_hash;
+#endif
+ if (h)
+ md_size = EVP_MD_size(h);
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+ else if (ssl->s3)
+ md_size = ssl->s3->tmp.new_mac_secret_size;
+#endif
+ else
+ return -1;
+
+ wpa_printf(MSG_DEBUG, "OpenSSL: keyblock size: key_len=%d MD_size=%d "
+ "IV_len=%d", EVP_CIPHER_key_length(c), md_size,
+ EVP_CIPHER_iv_length(c));
+ return 2 * (EVP_CIPHER_key_length(c) +
+ md_size +
+ EVP_CIPHER_iv_length(c));
+}
+
+
+static int openssl_tls_prf(void *tls_ctx, struct tls_connection *conn,
+ const char *label, int server_random_first,
+ int skip_keyblock, u8 *out, size_t out_len)
+{
+#ifdef CONFIG_FIPS
+ wpa_printf(MSG_ERROR, "OpenSSL: TLS keys cannot be exported in FIPS "
+ "mode");
+ return -1;
+#else /* CONFIG_FIPS */
+ SSL *ssl;
+ u8 *rnd;
+ int ret = -1;
+ int skip = 0;
+ u8 *tmp_out = NULL;
+ u8 *_out = out;
+
+ /*
+ * TLS library did not support key generation, so get the needed TLS
+ * session parameters and use an internal implementation of TLS PRF to
+ * derive the key.
+ */
+
+ if (conn == NULL)
+ return -1;
+ ssl = conn->ssl;
+ if (ssl == NULL || ssl->s3 == NULL || ssl->session == NULL ||
+ ssl->s3->client_random == NULL || ssl->s3->server_random == NULL ||
+ ssl->session->master_key == NULL)
+ return -1;
+
+ if (skip_keyblock) {
+ skip = openssl_get_keyblock_size(ssl);
+ if (skip < 0)
+ return -1;
+ tmp_out = os_malloc(skip + out_len);
+ if (!tmp_out)
+ return -1;
+ _out = tmp_out;
+ }
+
+ rnd = os_malloc(2 * SSL3_RANDOM_SIZE);
+ if (rnd == NULL)
+ return -1;
+ if (server_random_first) {
+ os_memcpy(rnd, ssl->s3->server_random, SSL3_RANDOM_SIZE);
+ os_memcpy(rnd + SSL3_RANDOM_SIZE, ssl->s3->client_random,
+ SSL3_RANDOM_SIZE);
+ } else {
+ os_memcpy(rnd, ssl->s3->client_random, SSL3_RANDOM_SIZE);
+ os_memcpy(rnd + SSL3_RANDOM_SIZE, ssl->s3->server_random,
+ SSL3_RANDOM_SIZE);
+ }
+
+ /* TODO: TLSv1.2 may need another PRF. This could use something closer
+ * to SSL_export_keying_material() design. */
+ if (tls_prf_sha1_md5(ssl->session->master_key,
+ ssl->session->master_key_length,
+ label, rnd, 2 * SSL3_RANDOM_SIZE,
+ _out, skip + out_len) == 0)
+ ret = 0;
+ os_free(rnd);
+ if (ret == 0 && skip_keyblock)
+ os_memcpy(out, _out + skip, out_len);
+ bin_clear_free(tmp_out, skip);
+
+ return ret;
+#endif /* CONFIG_FIPS */
+}
+
+
int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
const char *label, int server_random_first,
- u8 *out, size_t out_len)
+ int skip_keyblock, u8 *out, size_t out_len)
{
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
SSL *ssl;
if (conn == NULL)
return -1;
- if (server_random_first)
- return -1;
+ if (server_random_first || skip_keyblock)
+ return openssl_tls_prf(tls_ctx, conn, label,
+ server_random_first, skip_keyblock,
+ out, out_len);
ssl = conn->ssl;
if (SSL_export_keying_material(ssl, out, out_len, label,
os_strlen(label), NULL, 0, 0) == 1) {
@@ -2661,7 +2766,8 @@
return 0;
}
#endif
- return -1;
+ return openssl_tls_prf(tls_ctx, conn, label, server_random_first,
+ skip_keyblock, out, out_len);
}
@@ -3514,43 +3620,6 @@
}
-int tls_connection_get_keyblock_size(void *tls_ctx,
- struct tls_connection *conn)
-{
- const EVP_CIPHER *c;
- const EVP_MD *h;
- int md_size;
-
- if (conn == NULL || conn->ssl == NULL ||
- conn->ssl->enc_read_ctx == NULL ||
- conn->ssl->enc_read_ctx->cipher == NULL ||
- conn->ssl->read_hash == NULL)
- return -1;
-
- c = conn->ssl->enc_read_ctx->cipher;
-#if OPENSSL_VERSION_NUMBER >= 0x00909000L
- h = EVP_MD_CTX_md(conn->ssl->read_hash);
-#else
- h = conn->ssl->read_hash;
-#endif
- if (h)
- md_size = EVP_MD_size(h);
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
- else if (conn->ssl->s3)
- md_size = conn->ssl->s3->tmp.new_mac_secret_size;
-#endif
- else
- return -1;
-
- wpa_printf(MSG_DEBUG, "OpenSSL: keyblock size: key_len=%d MD_size=%d "
- "IV_len=%d", EVP_CIPHER_key_length(c), md_size,
- EVP_CIPHER_iv_length(c));
- return 2 * (EVP_CIPHER_key_length(c) +
- md_size +
- EVP_CIPHER_iv_length(c));
-}
-
-
unsigned int tls_capabilities(void *tls_ctx)
{
return 0;
diff --git a/src/eap_common/eap_fast_common.c b/src/eap_common/eap_fast_common.c
index fceb1b0..151cc78 100644
--- a/src/eap_common/eap_fast_common.c
+++ b/src/eap_common/eap_fast_common.c
@@ -96,49 +96,18 @@
u8 * eap_fast_derive_key(void *ssl_ctx, struct tls_connection *conn,
const char *label, size_t len)
{
- struct tls_keys keys;
- u8 *rnd = NULL, *out;
- int block_size;
+ u8 *out;
- block_size = tls_connection_get_keyblock_size(ssl_ctx, conn);
- if (block_size < 0)
- return NULL;
-
- out = os_malloc(block_size + len);
+ out = os_malloc(len);
if (out == NULL)
return NULL;
- if (tls_connection_prf(ssl_ctx, conn, label, 1, out, block_size + len)
- == 0) {
- os_memmove(out, out + block_size, len);
- return out;
+ if (tls_connection_prf(ssl_ctx, conn, label, 1, 1, out, len)) {
+ os_free(out);
+ return NULL;
}
- if (tls_connection_get_keys(ssl_ctx, conn, &keys))
- goto fail;
-
- rnd = os_malloc(keys.client_random_len + keys.server_random_len);
- if (rnd == NULL)
- goto fail;
-
- os_memcpy(rnd, keys.server_random, keys.server_random_len);
- os_memcpy(rnd + keys.server_random_len, keys.client_random,
- keys.client_random_len);
-
- wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: master_secret for key "
- "expansion", keys.master_key, keys.master_key_len);
- if (tls_prf_sha1_md5(keys.master_key, keys.master_key_len,
- label, rnd, keys.client_random_len +
- keys.server_random_len, out, block_size + len))
- goto fail;
- os_free(rnd);
- os_memmove(out, out + block_size, len);
return out;
-
-fail:
- os_free(rnd);
- os_free(out);
- return NULL;
}
diff --git a/src/eap_peer/eap.c b/src/eap_peer/eap.c
index 35433f3..fc4af95 100644
--- a/src/eap_peer/eap.c
+++ b/src/eap_peer/eap.c
@@ -2400,7 +2400,7 @@
u32 eap_get_phase2_type(const char *name, int *vendor)
{
int v;
- u8 type = eap_peer_get_type(name, &v);
+ u32 type = eap_peer_get_type(name, &v);
if (eap_allowed_phase2_type(v, type)) {
*vendor = v;
return type;
diff --git a/src/eap_peer/eap_tls_common.c b/src/eap_peer/eap_tls_common.c
index 8710781..15c1bac 100644
--- a/src/eap_peer/eap_tls_common.c
+++ b/src/eap_peer/eap_tls_common.c
@@ -313,53 +313,19 @@
u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
const char *label, size_t len)
{
-#ifndef CONFIG_FIPS
- struct tls_keys keys;
-#endif /* CONFIG_FIPS */
- u8 *rnd = NULL, *out;
+ u8 *out;
out = os_malloc(len);
if (out == NULL)
return NULL;
- /* First, try to use TLS library function for PRF, if available. */
- if (tls_connection_prf(data->ssl_ctx, data->conn, label, 0, out, len)
- == 0)
- return out;
+ if (tls_connection_prf(data->ssl_ctx, data->conn, label, 0, 0,
+ out, len)) {
+ os_free(out);
+ return NULL;
+ }
-#ifndef CONFIG_FIPS
- /*
- * TLS library did not support key generation, so get the needed TLS
- * session parameters and use an internal implementation of TLS PRF to
- * derive the key.
- */
- if (tls_connection_get_keys(data->ssl_ctx, data->conn, &keys))
- goto fail;
-
- if (keys.client_random == NULL || keys.server_random == NULL ||
- keys.master_key == NULL)
- goto fail;
-
- rnd = os_malloc(keys.client_random_len + keys.server_random_len);
- if (rnd == NULL)
- goto fail;
- os_memcpy(rnd, keys.client_random, keys.client_random_len);
- os_memcpy(rnd + keys.client_random_len, keys.server_random,
- keys.server_random_len);
-
- if (tls_prf_sha1_md5(keys.master_key, keys.master_key_len,
- label, rnd, keys.client_random_len +
- keys.server_random_len, out, len))
- goto fail;
-
- os_free(rnd);
return out;
-
-fail:
-#endif /* CONFIG_FIPS */
- os_free(out);
- os_free(rnd);
- return NULL;
}
@@ -1032,7 +998,7 @@
{
char *start, *pos, *buf;
struct eap_method_type *methods = NULL, *_methods;
- u8 method;
+ u32 method;
size_t num_methods = 0, prefix_len;
if (config == NULL || config->phase2 == NULL)
diff --git a/src/eap_server/eap.h b/src/eap_server/eap.h
index 9de6cb6..b825e18 100644
--- a/src/eap_server/eap.h
+++ b/src/eap_server/eap.h
@@ -149,5 +149,8 @@
const u8 * eap_get_identity(struct eap_sm *sm, size_t *len);
struct eap_eapol_interface * eap_get_interface(struct eap_sm *sm);
void eap_server_clear_identity(struct eap_sm *sm);
+void eap_server_mschap_rx_callback(struct eap_sm *sm, const char *source,
+ const u8 *username, size_t username_len,
+ const u8 *challenge, const u8 *response);
#endif /* EAP_H */
diff --git a/src/eap_server/eap_server.c b/src/eap_server/eap_server.c
index bd919e5..693debe 100644
--- a/src/eap_server/eap_server.c
+++ b/src/eap_server/eap_server.c
@@ -1979,3 +1979,25 @@
os_free(sm->identity);
sm->identity = NULL;
}
+
+
+#ifdef CONFIG_TESTING_OPTIONS
+void eap_server_mschap_rx_callback(struct eap_sm *sm, const char *source,
+ const u8 *username, size_t username_len,
+ const u8 *challenge, const u8 *response)
+{
+ char hex_challenge[30], hex_response[90], user[100];
+
+ /* Print out Challenge and Response in format supported by asleap. */
+ if (username)
+ printf_encode(user, sizeof(user), username, username_len);
+ else
+ user[0] = '\0';
+ wpa_snprintf_hex_sep(hex_challenge, sizeof(hex_challenge),
+ challenge, sizeof(challenge), ':');
+ wpa_snprintf_hex_sep(hex_response, sizeof(hex_response), response, 24,
+ ':');
+ wpa_printf(MSG_DEBUG, "[%s/user=%s] asleap -C %s -R %s",
+ source, user, hex_challenge, hex_response);
+}
+#endif /* CONFIG_TESTING_OPTIONS */
diff --git a/src/eap_server/eap_server_mschapv2.c b/src/eap_server/eap_server_mschapv2.c
index 05848d2..98d74e0 100644
--- a/src/eap_server/eap_server_mschapv2.c
+++ b/src/eap_server/eap_server_mschapv2.c
@@ -360,6 +360,19 @@
}
}
+#ifdef CONFIG_TESTING_OPTIONS
+ {
+ u8 challenge[8];
+
+ if (challenge_hash(peer_challenge, data->auth_challenge,
+ username, username_len, challenge) == 0) {
+ eap_server_mschap_rx_callback(sm, "EAP-MSCHAPV2",
+ username, username_len,
+ challenge, nt_response);
+ }
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
+
if (username_len != user_len ||
os_memcmp(username, user, username_len) != 0) {
wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Mismatch in user names");
diff --git a/src/eap_server/eap_server_peap.c b/src/eap_server/eap_server_peap.c
index faa0fd2..3848f30 100644
--- a/src/eap_server/eap_server_peap.c
+++ b/src/eap_server/eap_server_peap.c
@@ -539,15 +539,14 @@
static int eap_peap_phase2_init(struct eap_sm *sm, struct eap_peap_data *data,
- EapType eap_type)
+ int vendor, EapType eap_type)
{
if (data->phase2_priv && data->phase2_method) {
data->phase2_method->reset(sm, data->phase2_priv);
data->phase2_method = NULL;
data->phase2_priv = NULL;
}
- data->phase2_method = eap_server_get_eap_method(EAP_VENDOR_IETF,
- eap_type);
+ data->phase2_method = eap_server_get_eap_method(vendor, eap_type);
if (!data->phase2_method)
return -1;
@@ -737,7 +736,7 @@
const u8 *soh_tlv = NULL;
size_t soh_tlv_len = 0;
int tlv_type, mandatory, tlv_len, vtlv_len;
- u8 next_type;
+ u32 next_type;
u32 vendor_id;
pos = eap_hdr_validate(EAP_VENDOR_MICROSOFT, 0x21, in_data, &left);
@@ -852,8 +851,9 @@
eap_peap_state(data, PHASE2_METHOD);
next_type = sm->user->methods[0].method;
sm->user_eap_method_index = 1;
- wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", next_type);
- eap_peap_phase2_init(sm, data, next_type);
+ wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP vendor %d type %d",
+ sm->user->methods[0].vendor, next_type);
+ eap_peap_phase2_init(sm, data, sm->user->methods[0].vendor, next_type);
}
#endif /* EAP_SERVER_TNC */
@@ -862,7 +862,8 @@
struct eap_peap_data *data,
struct wpabuf *in_data)
{
- u8 next_type = EAP_TYPE_NONE;
+ int next_vendor = EAP_VENDOR_IETF;
+ u32 next_type = EAP_TYPE_NONE;
const struct eap_hdr *hdr;
const u8 *pos;
size_t left;
@@ -894,17 +895,23 @@
"allowed types", pos + 1, left - 1);
eap_sm_process_nak(sm, pos + 1, left - 1);
if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
- sm->user->methods[sm->user_eap_method_index].method !=
- EAP_TYPE_NONE) {
+ (sm->user->methods[sm->user_eap_method_index].vendor !=
+ EAP_VENDOR_IETF ||
+ sm->user->methods[sm->user_eap_method_index].method !=
+ EAP_TYPE_NONE)) {
+ next_vendor = sm->user->methods[
+ sm->user_eap_method_index].vendor;
next_type = sm->user->methods[
sm->user_eap_method_index++].method;
- wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d",
- next_type);
+ wpa_printf(MSG_DEBUG,
+ "EAP-PEAP: try EAP vendor %d type 0x%x",
+ next_vendor, next_type);
} else {
eap_peap_req_failure(sm, data);
+ next_vendor = EAP_VENDOR_IETF;
next_type = EAP_TYPE_NONE;
}
- eap_peap_phase2_init(sm, data, next_type);
+ eap_peap_phase2_init(sm, data, next_vendor, next_type);
return;
}
@@ -929,8 +936,9 @@
if (!data->phase2_method->isSuccess(sm, data->phase2_priv)) {
wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method failed");
eap_peap_req_failure(sm, data);
+ next_vendor = EAP_VENDOR_IETF;
next_type = EAP_TYPE_NONE;
- eap_peap_phase2_init(sm, data, next_type);
+ eap_peap_phase2_init(sm, data, next_vendor, next_type);
return;
}
@@ -942,7 +950,8 @@
wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 getKey "
"failed");
eap_peap_req_failure(sm, data);
- eap_peap_phase2_init(sm, data, EAP_TYPE_NONE);
+ eap_peap_phase2_init(sm, data, EAP_VENDOR_IETF,
+ EAP_TYPE_NONE);
return;
}
}
@@ -957,6 +966,7 @@
"database",
sm->identity, sm->identity_len);
eap_peap_req_failure(sm, data);
+ next_vendor = EAP_VENDOR_IETF;
next_type = EAP_TYPE_NONE;
break;
}
@@ -967,18 +977,22 @@
eap_peap_state(data, PHASE2_SOH);
wpa_printf(MSG_DEBUG, "EAP-PEAP: Try to initialize "
"TNC (NAP SOH)");
+ next_vendor = EAP_VENDOR_IETF;
next_type = EAP_TYPE_NONE;
break;
}
#endif /* EAP_SERVER_TNC */
eap_peap_state(data, PHASE2_METHOD);
+ next_vendor = sm->user->methods[0].vendor;
next_type = sm->user->methods[0].method;
sm->user_eap_method_index = 1;
- wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", next_type);
+ wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP vendor %d type 0x%x",
+ next_vendor, next_type);
break;
case PHASE2_METHOD:
eap_peap_req_success(sm, data);
+ next_vendor = EAP_VENDOR_IETF;
next_type = EAP_TYPE_NONE;
break;
case FAILURE:
@@ -989,7 +1003,7 @@
break;
}
- eap_peap_phase2_init(sm, data, next_type);
+ eap_peap_phase2_init(sm, data, next_vendor, next_type);
}
@@ -1133,7 +1147,8 @@
break;
case PHASE2_START:
eap_peap_state(data, PHASE2_ID);
- eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY);
+ eap_peap_phase2_init(sm, data, EAP_VENDOR_IETF,
+ EAP_TYPE_IDENTITY);
break;
case PHASE1_ID2:
case PHASE2_ID:
diff --git a/src/eap_server/eap_server_tls_common.c b/src/eap_server/eap_server_tls_common.c
index 56916c4..23498c9 100644
--- a/src/eap_server/eap_server_tls_common.c
+++ b/src/eap_server/eap_server_tls_common.c
@@ -100,43 +100,19 @@
u8 * eap_server_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
char *label, size_t len)
{
- struct tls_keys keys;
- u8 *rnd = NULL, *out;
+ u8 *out;
out = os_malloc(len);
if (out == NULL)
return NULL;
- if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, out, len) ==
- 0)
- return out;
+ if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, 0,
+ out, len)) {
+ os_free(out);
+ return NULL;
+ }
- if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))
- goto fail;
-
- if (keys.client_random == NULL || keys.server_random == NULL ||
- keys.master_key == NULL)
- goto fail;
-
- rnd = os_malloc(keys.client_random_len + keys.server_random_len);
- if (rnd == NULL)
- goto fail;
- os_memcpy(rnd, keys.client_random, keys.client_random_len);
- os_memcpy(rnd + keys.client_random_len, keys.server_random,
- keys.server_random_len);
-
- if (tls_prf_sha1_md5(keys.master_key, keys.master_key_len,
- label, rnd, keys.client_random_len +
- keys.server_random_len, out, len))
- goto fail;
-
- os_free(rnd);
return out;
-
-fail:
- os_free(out);
- os_free(rnd);
- return NULL;
}
diff --git a/src/eap_server/eap_server_ttls.c b/src/eap_server/eap_server_ttls.c
index 12a31b0..31c67e8 100644
--- a/src/eap_server/eap_server_ttls.c
+++ b/src/eap_server/eap_server_ttls.c
@@ -618,6 +618,12 @@
return;
}
+#ifdef CONFIG_TESTING_OPTIONS
+ eap_server_mschap_rx_callback(sm, "TTLS-MSCHAP",
+ sm->identity, sm->identity_len,
+ challenge, response + 2 + 24);
+#endif /* CONFIG_TESTING_OPTIONS */
+
if (os_memcmp_const(challenge, chal, EAP_TTLS_MSCHAP_CHALLENGE_LEN)
!= 0 ||
response[0] != chal[EAP_TTLS_MSCHAP_CHALLENGE_LEN]) {
@@ -740,6 +746,18 @@
}
rx_resp = response + 2 + EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 8;
+#ifdef CONFIG_TESTING_OPTIONS
+ {
+ u8 challenge2[8];
+
+ if (challenge_hash(peer_challenge, auth_challenge,
+ username, username_len, challenge2) == 0) {
+ eap_server_mschap_rx_callback(sm, "TTLS-MSCHAPV2",
+ username, username_len,
+ challenge2, rx_resp);
+ }
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
if (os_memcmp_const(nt_response, rx_resp, 24) == 0) {
wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Correct "
"NT-Response");
diff --git a/src/tls/tlsv1_client.c b/src/tls/tlsv1_client.c
index facdd65..533286c 100644
--- a/src/tls/tlsv1_client.c
+++ b/src/tls/tlsv1_client.c
@@ -731,8 +731,6 @@
if (conn->state != SERVER_HELLO) {
keys->server_random = conn->server_random;
keys->server_random_len = TLS_RANDOM_LEN;
- keys->master_key = conn->master_secret;
- keys->master_key_len = TLS_MASTER_SECRET_LEN;
}
return 0;
diff --git a/src/tls/tlsv1_server.c b/src/tls/tlsv1_server.c
index 93ae488..4df756f 100644
--- a/src/tls/tlsv1_server.c
+++ b/src/tls/tlsv1_server.c
@@ -627,8 +627,6 @@
if (conn->state != SERVER_HELLO) {
keys->server_random = conn->server_random;
keys->server_random_len = TLS_RANDOM_LEN;
- keys->master_key = conn->master_secret;
- keys->master_key_len = TLS_MASTER_SECRET_LEN;
}
return 0;
diff --git a/src/utils/common.c b/src/utils/common.c
index 5fd795f..0bdc38d 100644
--- a/src/utils/common.c
+++ b/src/utils/common.c
@@ -277,6 +277,31 @@
return ret;
}
+
+int wpa_snprintf_hex_sep(char *buf, size_t buf_size, const u8 *data, size_t len,
+ char sep)
+{
+ size_t i;
+ char *pos = buf, *end = buf + buf_size;
+ int ret;
+
+ if (buf_size == 0)
+ return 0;
+
+ for (i = 0; i < len; i++) {
+ ret = os_snprintf(pos, end - pos, "%02x%c",
+ data[i], sep);
+ if (os_snprintf_error(end - pos, ret)) {
+ end[-1] = '\0';
+ return pos - buf;
+ }
+ pos += ret;
+ }
+ pos[-1] = '\0';
+ return pos - buf;
+}
+
+
static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data,
size_t len, int uppercase)
{
diff --git a/src/utils/common.h b/src/utils/common.h
index 576e8e7..a0eda4a 100644
--- a/src/utils/common.h
+++ b/src/utils/common.h
@@ -480,6 +480,8 @@
void inc_byte_array(u8 *counter, size_t len);
void wpa_get_ntp_timestamp(u8 *buf);
int wpa_scnprintf(char *buf, size_t size, const char *fmt, ...);
+int wpa_snprintf_hex_sep(char *buf, size_t buf_size, const u8 *data, size_t len,
+ char sep);
int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len);
int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data,
size_t len);
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 11946cd..fc70035 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -3168,6 +3168,7 @@
union wpa_event_data *data)
{
struct wpa_supplicant *wpa_s = ctx;
+ int resched;
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED &&
event != EVENT_INTERFACE_ENABLED &&
@@ -3734,6 +3735,7 @@
case EVENT_SCHED_SCAN_STOPPED:
wpa_s->pno = 0;
wpa_s->sched_scanning = 0;
+ resched = wpa_s->scanning;
wpa_supplicant_notify_scanning(wpa_s, 0);
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
@@ -3748,6 +3750,8 @@
} else if (wpa_s->pno_sched_pending) {
wpa_s->pno_sched_pending = 0;
wpas_start_pno(wpa_s);
+ } else if (resched) {
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
}
break;
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index 1a4579e..5fe4618 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -2976,7 +2976,7 @@
{ "get_capability", wpa_cli_cmd_get_capability, NULL,
cli_cmd_flag_none,
"<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
- "= get capabilies" },
+ "= get capabilities" },
{ "reconfigure", wpa_cli_cmd_reconfigure, NULL,
cli_cmd_flag_none,
"= force wpa_supplicant to re-read its configuration file" },
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index f690b91..2ba9c38 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -731,6 +731,7 @@
ssid && ssid->id_str ? ssid->id_str : "");
#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
wpas_clear_temp_disabled(wpa_s, ssid, 1);
+ wpa_blacklist_clear(wpa_s);
wpa_s->extra_blacklist_count = 0;
wpa_s->new_connection = 0;
wpa_drv_set_operstate(wpa_s, 1);
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 853b156..eb7434a 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -974,7 +974,7 @@
# tls_disable_session_ticket=0 - allow TLS Session Ticket extension to be used
# Note: If not set, this is automatically set to 1 for EAP-TLS/PEAP/TTLS
# as a workaround for broken authentication server implementations unless
-# EAP workarounds are disabled with eap_workarounds=0.
+# EAP workarounds are disabled with eap_workaround=0.
# For EAP-FAST, this must be set to 0 (or left unconfigured for the
# default value to be used automatically).
# tls_disable_tlsv1_1=1 - disable use of TLSv1.1 (a workaround for AAA servers