FR_NAME_NUMBER const sim_state_table[] = {
{ "START", EAP_SIM_SERVER_START },
{ "CHALLENGE", EAP_SIM_SERVER_CHALLENGE },
+ { "REAUTHENTICATE", EAP_SIM_SERVER_REAUTHENTICATE },
{ "SUCCESS-NOTIFICATION", EAP_SIM_SERVER_SUCCESS_NOTIFICATION },
{ "SUCCESS", EAP_SIM_SERVER_SUCCESS },
{ "FAILURE-NOTIFICATION", EAP_SIM_SERVER_FAILURE_NOTIFICATION },
return 0;
}
+/** Send NONCE_S and re-key
+ *
+ */
static int eap_sim_send_reauthentication(eap_session_t *eap_session)
{
REQUEST *request = eap_session->request;
eap_sim_session_t *eap_sim_session = talloc_get_type_abort(eap_session->opaque, eap_sim_session_t);
- VALUE_PAIR **to_peer, *vp;
+ VALUE_PAIR **to_peer, *vp, *mk, *counter;
RADIUS_PACKET *packet;
- fr_sim_vector_src_t src = SIM_VECTOR_SRC_AUTO;
rad_assert(eap_session->request != NULL);
rad_assert(eap_session->request->reply);
- RDEBUG2("Acquiring GSM vector(s)");
- if ((fr_sim_vector_gsm_from_attrs(eap_session, request->control, 0, &eap_sim_session->keys, &src) != 0) ||
- (fr_sim_vector_gsm_from_attrs(eap_session, request->control, 1, &eap_sim_session->keys, &src) != 0) ||
- (fr_sim_vector_gsm_from_attrs(eap_session, request->control, 2, &eap_sim_session->keys, &src) != 0)) {
- REDEBUG("Failed retrieving SIM vectors");
- return RLM_MODULE_FAIL;
- }
-
- /*
- * All set, calculate keys!
- */
- fr_sim_crypto_kdf_0_gsm(&eap_sim_session->keys);
- if (RDEBUG_ENABLED3) fr_sim_crypto_keys_log(request, &eap_sim_session->keys);
-
- RDEBUG2("Sending SIM-Challenge");
- eap_session->this_round->request->code = FR_EAP_CODE_REQUEST;
-
/*
* to_peer is the data to the client
*/
to_peer = &packet->vps;
/*
- * Okay, we got the challenges! Put them into attributes.
+ * If any of the session resumption inputs (on our side)
+ * are missing or malformed, return an error code
+ * and the state machine will jump to the start state.
*/
- MEM(vp = fr_pair_afrom_child_num(packet, dict_sim_root, FR_EAP_SIM_RAND));
- fr_pair_value_memcpy(vp, eap_sim_session->keys.gsm.vector[0].rand, SIM_VECTOR_GSM_RAND_SIZE);
- fr_pair_add(to_peer, vp);
+ mk = fr_pair_find_by_child_num(request->control, dict_sim_root, FR_EAP_SIM_MK, TAG_ANY);
+ if (!mk) {
+ RWDEBUG2("Missing &control:EAP-SIM-MK, skipping session resumption");
+ return -1;
+ }
+ if (mk->vp_length != SIM_MK_SIZE) {
+ RWDEBUG("&control:EAP-SIM-MK has incorrect length, expected %u bytes got %zu bytes",
+ SIM_MK_SIZE, mk->vp_length);
+ return -1;
+ }
+ counter = fr_pair_find_by_child_num(request->control, dict_sim_root, FR_EAP_SIM_COUNTER, TAG_ANY);
+ if (!counter) {
+ RWDEBUG2("Missing &control:EAP-SIM-Counter, skipping session resumption");
+ return -1;
+ }
- MEM(vp = fr_pair_afrom_child_num(packet, dict_sim_root, FR_EAP_SIM_RAND));
- fr_pair_value_memcpy(vp, eap_sim_session->keys.gsm.vector[1].rand, SIM_VECTOR_GSM_RAND_SIZE);
- fr_pair_add(to_peer, vp);
+ /*
+ * All set, calculate keys!
+ */
+ fr_sim_crypto_keys_init_kdf_0_reauth(&eap_sim_session->keys, mk->vp_octets, counter->vp_uint16);
+ fr_sim_crypto_kdf_0_reauth(&eap_sim_session->keys);
+ if (RDEBUG_ENABLED3) fr_sim_crypto_keys_log(request, &eap_sim_session->keys);
- MEM(vp = fr_pair_afrom_child_num(packet, dict_sim_root, FR_EAP_SIM_RAND));
- fr_pair_value_memcpy(vp, eap_sim_session->keys.gsm.vector[2].rand, SIM_VECTOR_GSM_RAND_SIZE);
- fr_pair_add(to_peer, vp);
+ RDEBUG2("Sending SIM-Reauthentication");
+ eap_session->this_round->request->code = FR_EAP_CODE_REQUEST;
/*
* Set subtype to challenge.
*/
vp = fr_pair_afrom_child_num(packet, dict_sim_root, FR_EAP_SIM_SUBTYPE);
- vp->vp_uint16 = EAP_SIM_CHALLENGE;
+ vp->vp_uint16 = EAP_SIM_REAUTH;
+ fr_pair_replace(to_peer, vp);
+
+ /*
+ * Add nonce_s
+ */
+ MEM(vp = fr_pair_afrom_child_num(packet, dict_sim_root, FR_EAP_SIM_NONCE_S));
+ fr_pair_value_memcpy(vp, eap_sim_session->keys.reauth.nonce_s, sizeof(eap_sim_session->keys.reauth.nonce_s));
fr_pair_replace(to_peer, vp);
/*
/*
* Encode the packet
*/
- if (eap_sim_compose(eap_session,
- eap_sim_session->keys.gsm.nonce_mt, sizeof(eap_sim_session->keys.gsm.nonce_mt)) < 0) {
+ if (eap_sim_compose(eap_session, NULL, 0) < 0) {
fr_pair_list_free(&packet->vps);
return -1;
}
* Send our version list
*/
case EAP_SIM_SERVER_START:
+ start:
if (eap_sim_send_start(eap_session) < 0) {
notify_failure:
eap_sim_state_enter(eap_session, EAP_SIM_SERVER_FAILURE_NOTIFICATION);
if (eap_sim_send_challenge(eap_session) < 0) goto notify_failure;
break;
+ case EAP_SIM_SERVER_REAUTHENTICATE:
+ if (eap_sim_send_reauthentication(eap_session) < 0) goto start;
+ break;
+
/*
* Sent a protected success notification
*/