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:
Jouni Malinen 2022-04-30 16:56:10 +03:00 committed by Jouni Malinen
parent 36b11bbcff
commit 21098e39fe
9 changed files with 181 additions and 7 deletions

View file

@ -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;

View file

@ -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);
}

View file

@ -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);