#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);
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;
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));
}
#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");
*/
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
*
#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);
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;
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));
}
#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");
# 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
{ 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 */
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);
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);
}
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);
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;
*/
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
*/
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);
}
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)