EAP-SIM/AKA server: IMSI privacy
Add support for IMSI privacy in the EAP-SIM/AKA server implementation. If the new hostapd configuration parameter imsi_privacy_key is used to specify an RSA private key, that key will be used to decrypt encrypted permanent identity. Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
parent
36b11bbcff
commit
21098e39fe
9 changed files with 181 additions and 7 deletions
|
@ -809,6 +809,7 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
|
|||
os_free(conf->eap_fast_a_id);
|
||||
os_free(conf->eap_fast_a_id_info);
|
||||
os_free(conf->eap_sim_db);
|
||||
os_free(conf->imsi_privacy_key);
|
||||
os_free(conf->radius_server_clients);
|
||||
os_free(conf->radius);
|
||||
os_free(conf->radius_das_shared_secret);
|
||||
|
|
|
@ -443,6 +443,7 @@ struct hostapd_bss_config {
|
|||
int eap_teap_id;
|
||||
int eap_sim_aka_result_ind;
|
||||
int eap_sim_id;
|
||||
char *imsi_privacy_key;
|
||||
int tnc;
|
||||
int fragment_size;
|
||||
u16 pwd_group;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "crypto/crypto.h"
|
||||
#include "crypto/tls.h"
|
||||
#include "eap_server/eap.h"
|
||||
#include "eap_server/eap_sim_db.h"
|
||||
|
@ -209,6 +210,7 @@ static struct eap_config * authsrv_eap_config(struct hostapd_data *hapd)
|
|||
cfg->eap_teap_id = hapd->conf->eap_teap_id;
|
||||
cfg->eap_sim_aka_result_ind = hapd->conf->eap_sim_aka_result_ind;
|
||||
cfg->eap_sim_id = hapd->conf->eap_sim_id;
|
||||
cfg->imsi_privacy_key = hapd->imsi_privacy_key;
|
||||
cfg->tnc = hapd->conf->tnc;
|
||||
cfg->wps = hapd->wps;
|
||||
cfg->fragment_size = hapd->conf->fragment_size;
|
||||
|
@ -295,6 +297,22 @@ int authsrv_init(struct hostapd_data *hapd)
|
|||
}
|
||||
#endif /* EAP_TLS_FUNCS */
|
||||
|
||||
#ifdef CRYPTO_RSA_OAEP_SHA256
|
||||
crypto_rsa_key_free(hapd->imsi_privacy_key);
|
||||
hapd->imsi_privacy_key = NULL;
|
||||
if (hapd->conf->imsi_privacy_key) {
|
||||
hapd->imsi_privacy_key = crypto_rsa_key_read(
|
||||
hapd->conf->imsi_privacy_key, true);
|
||||
if (!hapd->imsi_privacy_key) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Failed to read/parse IMSI privacy key %s",
|
||||
hapd->conf->imsi_privacy_key);
|
||||
authsrv_deinit(hapd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif /* CRYPTO_RSA_OAEP_SHA256 */
|
||||
|
||||
#ifdef EAP_SIM_DB
|
||||
if (hapd->conf->eap_sim_db) {
|
||||
hapd->eap_sim_db_priv =
|
||||
|
@ -335,6 +353,11 @@ void authsrv_deinit(struct hostapd_data *hapd)
|
|||
hapd->radius_srv = NULL;
|
||||
#endif /* RADIUS_SERVER */
|
||||
|
||||
#ifdef CRYPTO_RSA_OAEP_SHA256
|
||||
crypto_rsa_key_free(hapd->imsi_privacy_key);
|
||||
hapd->imsi_privacy_key = NULL;
|
||||
#endif /* CRYPTO_RSA_OAEP_SHA256 */
|
||||
|
||||
#ifdef EAP_TLS_FUNCS
|
||||
if (hapd->ssl_ctx) {
|
||||
tls_deinit(hapd->ssl_ctx);
|
||||
|
|
|
@ -208,6 +208,7 @@ struct hostapd_data {
|
|||
|
||||
void *ssl_ctx;
|
||||
void *eap_sim_db_priv;
|
||||
struct crypto_rsa_key *imsi_privacy_key;
|
||||
struct radius_server_data *radius_srv;
|
||||
struct dl_list erp_keys; /* struct eap_server_erp_key */
|
||||
|
||||
|
|
|
@ -124,6 +124,9 @@ struct eap_config {
|
|||
* callback context.
|
||||
*/
|
||||
void *eap_sim_db_priv;
|
||||
|
||||
struct crypto_rsa_key *imsi_privacy_key;
|
||||
|
||||
bool backend_auth;
|
||||
int eap_server;
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "utils/base64.h"
|
||||
#include "crypto/sha256.h"
|
||||
#include "crypto/crypto.h"
|
||||
#include "crypto/random.h"
|
||||
|
@ -737,11 +738,8 @@ static void eap_aka_determine_identity(struct eap_sm *sm,
|
|||
sm->identity, sm->identity_len);
|
||||
|
||||
username = sim_get_username(sm->identity, sm->identity_len);
|
||||
if (username == NULL) {
|
||||
data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
|
||||
eap_aka_state(data, NOTIFICATION);
|
||||
return;
|
||||
}
|
||||
if (!username)
|
||||
goto fail;
|
||||
|
||||
if (eap_aka_check_identity_reauth(sm, data, username) > 0) {
|
||||
os_free(username);
|
||||
|
@ -785,16 +783,87 @@ static void eap_aka_determine_identity(struct eap_sm *sm,
|
|||
username);
|
||||
os_strlcpy(data->permanent, username, sizeof(data->permanent));
|
||||
os_free(username);
|
||||
#ifdef CRYPTO_RSA_OAEP_SHA256
|
||||
} else if (sm->identity_len > 1 && sm->identity[0] == '\0') {
|
||||
char *enc_id, *pos, *end;
|
||||
size_t enc_id_len;
|
||||
u8 *decoded_id;
|
||||
size_t decoded_id_len;
|
||||
struct wpabuf *enc, *dec;
|
||||
u8 *new_id;
|
||||
|
||||
os_free(username);
|
||||
if (!sm->cfg->imsi_privacy_key) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EAP-AKA: Received encrypted identity, but no IMSI privacy key configured to decrypt it");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
enc_id = (char *) &sm->identity[1];
|
||||
end = (char *) &sm->identity[sm->identity_len];
|
||||
for (pos = enc_id; pos < end; pos++) {
|
||||
if (*pos == ',')
|
||||
break;
|
||||
}
|
||||
enc_id_len = pos - enc_id;
|
||||
|
||||
wpa_hexdump_ascii(MSG_DEBUG,
|
||||
"EAP-AKA: Encrypted permanent identity",
|
||||
enc_id, enc_id_len);
|
||||
decoded_id = base64_decode(enc_id, enc_id_len, &decoded_id_len);
|
||||
if (!decoded_id) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EAP-AKA: Could not base64 decode encrypted identity");
|
||||
goto fail;
|
||||
}
|
||||
wpa_hexdump(MSG_DEBUG,
|
||||
"EAP-AKA: Decoded encrypted permanent identity",
|
||||
decoded_id, decoded_id_len);
|
||||
enc = wpabuf_alloc_copy(decoded_id, decoded_id_len);
|
||||
os_free(decoded_id);
|
||||
if (!enc)
|
||||
goto fail;
|
||||
dec = crypto_rsa_oaep_sha256_decrypt(sm->cfg->imsi_privacy_key,
|
||||
enc);
|
||||
wpabuf_free(enc);
|
||||
if (!dec) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EAP-AKA: Failed to decrypt encrypted identity");
|
||||
goto fail;
|
||||
}
|
||||
wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Decrypted permanent identity",
|
||||
wpabuf_head(dec), wpabuf_len(dec));
|
||||
username = sim_get_username(wpabuf_head(dec), wpabuf_len(dec));
|
||||
if (!username) {
|
||||
wpabuf_free(dec);
|
||||
goto fail;
|
||||
}
|
||||
new_id = os_memdup(wpabuf_head(dec), wpabuf_len(dec));
|
||||
if (!new_id) {
|
||||
wpabuf_free(dec);
|
||||
goto fail;
|
||||
}
|
||||
os_free(sm->identity);
|
||||
sm->identity = new_id;
|
||||
sm->identity_len = wpabuf_len(dec);
|
||||
wpabuf_free(dec);
|
||||
os_strlcpy(data->permanent, username, sizeof(data->permanent));
|
||||
os_free(username);
|
||||
#endif /* CRYPTO_RSA_OAEP_SHA256 */
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG, "EAP-AKA: Unrecognized username '%s'",
|
||||
username);
|
||||
os_free(username);
|
||||
data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
|
||||
eap_aka_state(data, NOTIFICATION);
|
||||
goto fail;
|
||||
return;
|
||||
}
|
||||
|
||||
eap_aka_fullauth(sm, data);
|
||||
return;
|
||||
|
||||
fail:
|
||||
data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
|
||||
eap_aka_state(data, NOTIFICATION);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "utils/base64.h"
|
||||
#include "crypto/crypto.h"
|
||||
#include "crypto/random.h"
|
||||
#include "eap_server/eap_i.h"
|
||||
#include "eap_common/eap_sim_common.h"
|
||||
|
@ -512,6 +514,73 @@ static void eap_sim_process_start(struct eap_sm *sm,
|
|||
username);
|
||||
os_strlcpy(data->permanent, username, sizeof(data->permanent));
|
||||
os_free(username);
|
||||
#ifdef CRYPTO_RSA_OAEP_SHA256
|
||||
} else if (sm->identity_len > 1 && sm->identity[0] == '\0') {
|
||||
char *enc_id, *pos, *end;
|
||||
size_t enc_id_len;
|
||||
u8 *decoded_id;
|
||||
size_t decoded_id_len;
|
||||
struct wpabuf *enc, *dec;
|
||||
u8 *new_id;
|
||||
|
||||
os_free(username);
|
||||
if (!sm->cfg->imsi_privacy_key) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EAP-SIM: Received encrypted identity, but no IMSI privacy key configured to decrypt it");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
enc_id = (char *) &sm->identity[1];
|
||||
end = (char *) &sm->identity[sm->identity_len];
|
||||
for (pos = enc_id; pos < end; pos++) {
|
||||
if (*pos == ',')
|
||||
break;
|
||||
}
|
||||
enc_id_len = pos - enc_id;
|
||||
|
||||
wpa_hexdump_ascii(MSG_DEBUG,
|
||||
"EAP-SIM: Encrypted permanent identity",
|
||||
enc_id, enc_id_len);
|
||||
decoded_id = base64_decode(enc_id, enc_id_len, &decoded_id_len);
|
||||
if (!decoded_id) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EAP-SIM: Could not base64 decode encrypted identity");
|
||||
goto failed;
|
||||
}
|
||||
wpa_hexdump(MSG_DEBUG,
|
||||
"EAP-SIM: Decoded encrypted permanent identity",
|
||||
decoded_id, decoded_id_len);
|
||||
enc = wpabuf_alloc_copy(decoded_id, decoded_id_len);
|
||||
os_free(decoded_id);
|
||||
if (!enc)
|
||||
goto failed;
|
||||
dec = crypto_rsa_oaep_sha256_decrypt(sm->cfg->imsi_privacy_key,
|
||||
enc);
|
||||
wpabuf_free(enc);
|
||||
if (!dec) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EAP-SIM: Failed to decrypt encrypted identity");
|
||||
goto failed;
|
||||
}
|
||||
wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Decrypted permanent identity",
|
||||
wpabuf_head(dec), wpabuf_len(dec));
|
||||
username = sim_get_username(wpabuf_head(dec), wpabuf_len(dec));
|
||||
if (!username) {
|
||||
wpabuf_free(dec);
|
||||
goto failed;
|
||||
}
|
||||
new_id = os_memdup(wpabuf_head(dec), wpabuf_len(dec));
|
||||
if (!new_id) {
|
||||
wpabuf_free(dec);
|
||||
goto failed;
|
||||
}
|
||||
os_free(sm->identity);
|
||||
sm->identity = new_id;
|
||||
sm->identity_len = wpabuf_len(dec);
|
||||
wpabuf_free(dec);
|
||||
os_strlcpy(data->permanent, username, sizeof(data->permanent));
|
||||
os_free(username);
|
||||
#endif /* CRYPTO_RSA_OAEP_SHA256 */
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG, "EAP-SIM: Unrecognized username '%s'",
|
||||
username);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue