EAP-SIM/AKA peer: IMSI privacy attribute
Extend IMSI privacy functionality to allow an attribute (in name=value format) to be added using the new imsi_privacy_attr parameter. Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
parent
1004fb7ee4
commit
5636991749
8 changed files with 87 additions and 9 deletions
|
@ -644,11 +644,12 @@ static struct wpabuf * eap_aka_synchronization_failure(
|
|||
#ifdef CRYPTO_RSA_OAEP_SHA256
|
||||
static struct wpabuf *
|
||||
eap_aka_encrypt_identity(struct crypto_rsa_key *imsi_privacy_key,
|
||||
const u8 *identity, size_t identity_len)
|
||||
const u8 *identity, size_t identity_len,
|
||||
const char *attr)
|
||||
{
|
||||
struct wpabuf *imsi_buf, *enc;
|
||||
char *b64;
|
||||
size_t b64_len;
|
||||
size_t b64_len, len;
|
||||
|
||||
wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Encrypt permanent identity",
|
||||
identity, identity_len);
|
||||
|
@ -666,7 +667,10 @@ eap_aka_encrypt_identity(struct crypto_rsa_key *imsi_privacy_key,
|
|||
if (!b64)
|
||||
return NULL;
|
||||
|
||||
enc = wpabuf_alloc(1 + b64_len);
|
||||
len = 1 + b64_len;
|
||||
if (attr)
|
||||
len += 1 + os_strlen(attr);
|
||||
enc = wpabuf_alloc(len);
|
||||
if (!enc) {
|
||||
os_free(b64);
|
||||
return NULL;
|
||||
|
@ -674,6 +678,10 @@ eap_aka_encrypt_identity(struct crypto_rsa_key *imsi_privacy_key,
|
|||
wpabuf_put_u8(enc, '\0');
|
||||
wpabuf_put_data(enc, b64, b64_len);
|
||||
os_free(b64);
|
||||
if (attr) {
|
||||
wpabuf_put_u8(enc, ',');
|
||||
wpabuf_put_str(enc, attr);
|
||||
}
|
||||
wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Encrypted permanent identity",
|
||||
wpabuf_head(enc), wpabuf_len(enc));
|
||||
|
||||
|
@ -717,9 +725,15 @@ static struct wpabuf * eap_aka_response_identity(struct eap_sm *sm,
|
|||
}
|
||||
#ifdef CRYPTO_RSA_OAEP_SHA256
|
||||
if (identity && data->imsi_privacy_key) {
|
||||
struct eap_peer_config *config;
|
||||
const char *attr = NULL;
|
||||
|
||||
config = eap_get_config(sm);
|
||||
if (config)
|
||||
attr = config->imsi_privacy_attr;
|
||||
enc_identity = eap_aka_encrypt_identity(
|
||||
data->imsi_privacy_key,
|
||||
identity, identity_len);
|
||||
identity, identity_len, attr);
|
||||
if (!enc_identity) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"EAP-AKA: Failed to encrypt permanent identity");
|
||||
|
|
|
@ -327,6 +327,16 @@ struct eap_peer_config {
|
|||
*/
|
||||
char *imsi_privacy_cert;
|
||||
|
||||
/**
|
||||
* imsi_privacy_attr - IMSI privacy attribute
|
||||
*
|
||||
* This field is used to help the EAP-SIM/AKA/AKA' server to identify
|
||||
* the used certificate (and as such, the matching private key). This
|
||||
* is set to an attribute in name=value format if the operator needs
|
||||
* this information.
|
||||
*/
|
||||
char *imsi_privacy_attr;
|
||||
|
||||
/**
|
||||
* machine_identity - EAP Identity for machine credential
|
||||
*
|
||||
|
|
|
@ -512,11 +512,12 @@ static struct wpabuf * eap_sim_client_error(struct eap_sim_data *data, u8 id,
|
|||
#ifdef CRYPTO_RSA_OAEP_SHA256
|
||||
static struct wpabuf *
|
||||
eap_sim_encrypt_identity(struct crypto_rsa_key *imsi_privacy_key,
|
||||
const u8 *identity, size_t identity_len)
|
||||
const u8 *identity, size_t identity_len,
|
||||
const char *attr)
|
||||
{
|
||||
struct wpabuf *imsi_buf, *enc;
|
||||
char *b64;
|
||||
size_t b64_len;
|
||||
size_t b64_len, len;
|
||||
|
||||
wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Encrypt permanent identity",
|
||||
identity, identity_len);
|
||||
|
@ -534,7 +535,10 @@ eap_sim_encrypt_identity(struct crypto_rsa_key *imsi_privacy_key,
|
|||
if (!b64)
|
||||
return NULL;
|
||||
|
||||
enc = wpabuf_alloc(1 + b64_len);
|
||||
len = 1 + b64_len;
|
||||
if (attr)
|
||||
len += 1 + os_strlen(attr);
|
||||
enc = wpabuf_alloc(len);
|
||||
if (!enc) {
|
||||
os_free(b64);
|
||||
return NULL;
|
||||
|
@ -542,6 +546,10 @@ eap_sim_encrypt_identity(struct crypto_rsa_key *imsi_privacy_key,
|
|||
wpabuf_put_u8(enc, '\0');
|
||||
wpabuf_put_data(enc, b64, b64_len);
|
||||
os_free(b64);
|
||||
if (attr) {
|
||||
wpabuf_put_u8(enc, ',');
|
||||
wpabuf_put_str(enc, attr);
|
||||
}
|
||||
wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Encrypted permanent identity",
|
||||
wpabuf_head(enc), wpabuf_len(enc));
|
||||
|
||||
|
@ -585,9 +593,15 @@ static struct wpabuf * eap_sim_response_start(struct eap_sm *sm,
|
|||
}
|
||||
#ifdef CRYPTO_RSA_OAEP_SHA256
|
||||
if (identity && data->imsi_privacy_key) {
|
||||
struct eap_peer_config *config;
|
||||
const char *attr = NULL;
|
||||
|
||||
config = eap_get_config(sm);
|
||||
if (config)
|
||||
attr = config->imsi_privacy_attr;
|
||||
enc_identity = eap_sim_encrypt_identity(
|
||||
data->imsi_privacy_key,
|
||||
identity, identity_len);
|
||||
identity, identity_len, attr);
|
||||
if (!enc_identity) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"EAP-SIM: Failed to encrypt permanent identity");
|
||||
|
|
|
@ -168,11 +168,16 @@ Credentials can be pre-configured for automatic network selection:
|
|||
# milenage: Milenage parameters for SIM/USIM simulator in <Ki>:<OPc>:<SQN>
|
||||
# format
|
||||
#
|
||||
# imsi_privacy_key: IMSI privacy key (PEM encoded X.509v3 certificate)
|
||||
# imsi_privacy_cert: IMSI privacy certificate (PEM encoded X.509v3 certificate)
|
||||
# This field is used with EAP-SIM/AKA/AKA' to encrypt the permanent
|
||||
# identity (IMSI) to improve privacy. The X.509v3 certificate needs to
|
||||
# include a 2048-bit RSA public key and this is from the operator who
|
||||
# authenticates the SIM/USIM.
|
||||
# imsi_privacy_attr: IMSI privacy attribute
|
||||
# This field is used to help the EAP-SIM/AKA/AKA' server to identify
|
||||
# the used certificate (and as such, the matching private key). This
|
||||
# is set to an attribute in name=value format if the operator needs
|
||||
# this information.
|
||||
#
|
||||
# domain_suffix_match: Constraint for server domain name
|
||||
# If set, this FQDN is used as a suffix match requirement for the AAA
|
||||
|
|
|
@ -2504,6 +2504,7 @@ static const struct parse_data ssid_fields[] = {
|
|||
{ INT(eapol_flags) },
|
||||
{ INTe(sim_num, sim_num) },
|
||||
{ STRe(imsi_privacy_cert, imsi_privacy_cert) },
|
||||
{ STRe(imsi_privacy_attr, imsi_privacy_attr) },
|
||||
{ STRe(openssl_ciphers, openssl_ciphers) },
|
||||
{ INTe(erp, erp) },
|
||||
#endif /* IEEE8021X_EAPOL */
|
||||
|
@ -2772,6 +2773,7 @@ static void eap_peer_config_free(struct eap_peer_config *eap)
|
|||
os_free(eap->anonymous_identity);
|
||||
os_free(eap->imsi_identity);
|
||||
os_free(eap->imsi_privacy_cert);
|
||||
os_free(eap->imsi_privacy_attr);
|
||||
os_free(eap->machine_identity);
|
||||
bin_clear_free(eap->password, eap->password_len);
|
||||
bin_clear_free(eap->machine_password, eap->machine_password_len);
|
||||
|
@ -2876,6 +2878,7 @@ void wpa_config_free_cred(struct wpa_cred *cred)
|
|||
os_free(cred->req_conn_capab_port);
|
||||
os_free(cred->req_conn_capab_proto);
|
||||
os_free(cred->imsi_privacy_cert);
|
||||
os_free(cred->imsi_privacy_attr);
|
||||
os_free(cred);
|
||||
}
|
||||
|
||||
|
@ -3917,6 +3920,12 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (os_strcmp(var, "imsi_privacy_attr") == 0) {
|
||||
os_free(cred->imsi_privacy_attr);
|
||||
cred->imsi_privacy_attr = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (line) {
|
||||
wpa_printf(MSG_ERROR, "Line %d: unknown cred field '%s'.",
|
||||
line, var);
|
||||
|
@ -4070,6 +4079,9 @@ char * wpa_config_get_cred_no_key(struct wpa_cred *cred, const char *var)
|
|||
if (os_strcmp(var, "imsi_privacy_cert") == 0)
|
||||
return alloc_strdup(cred->imsi_privacy_cert);
|
||||
|
||||
if (os_strcmp(var, "imsi_privacy_attr") == 0)
|
||||
return alloc_strdup(cred->imsi_privacy_attr);
|
||||
|
||||
if (os_strcmp(var, "milenage") == 0) {
|
||||
if (!(cred->milenage))
|
||||
return NULL;
|
||||
|
|
|
@ -190,6 +190,16 @@ struct wpa_cred {
|
|||
*/
|
||||
char *imsi_privacy_cert;
|
||||
|
||||
/**
|
||||
* imsi_privacy_attr - IMSI privacy attribute
|
||||
*
|
||||
* This field is used to help the EAP-SIM/AKA/AKA' server to identify
|
||||
* the used certificate (and as such, the matching private key). This
|
||||
* is set to an attribute in name=value format if the operator needs
|
||||
* this information.
|
||||
*/
|
||||
char *imsi_privacy_attr;
|
||||
|
||||
/**
|
||||
* engine - Use an engine for private key operations
|
||||
*/
|
||||
|
|
|
@ -1036,6 +1036,13 @@ static void wpa_config_write_cred(FILE *f, struct wpa_cred *cred)
|
|||
fprintf(f, "\tcert_id=\"%s\"\n", cred->cert_id);
|
||||
if (cred->ca_cert_id)
|
||||
fprintf(f, "\tca_cert_id=\"%s\"\n", cred->ca_cert_id);
|
||||
|
||||
if (cred->imsi_privacy_cert)
|
||||
fprintf(f, "\timsi_privacy_cert=\"%s\"\n",
|
||||
cred->imsi_privacy_cert);
|
||||
if (cred->imsi_privacy_attr)
|
||||
fprintf(f, "\timsi_privacy_attr=\"%s\"\n",
|
||||
cred->imsi_privacy_attr);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1071,6 +1071,12 @@ static int interworking_connect_3gpp(struct wpa_supplicant *wpa_s,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (cred->imsi_privacy_attr && cred->imsi_privacy_attr[0]) {
|
||||
if (wpa_config_set_quoted(ssid, "imsi_privacy_attr",
|
||||
cred->imsi_privacy_attr) < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
wpa_s->next_ssid = ssid;
|
||||
wpa_config_update_prio_list(wpa_s->conf);
|
||||
if (!only_add)
|
||||
|
|
Loading…
Reference in a new issue