Add support for computing Kc and SRES from Ki and RAND for Comp128-1 (and possibly...
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Tue, 24 Sep 2013 11:49:23 +0000 (12:49 +0100)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Fri, 28 Mar 2014 16:11:05 +0000 (16:11 +0000)
share/dictionary.freeradius.internal
src/modules/rlm_eap/libeap/eap_sim.h
src/modules/rlm_eap/types/rlm_eap_sim/rlm_eap_sim.c

index abaf153..9b1203b 100644 (file)
@@ -280,6 +280,9 @@ ATTRIBUTE   EAP-Sim-KC1                             1212    octets
 ATTRIBUTE      EAP-Sim-KC2                             1213    octets
 ATTRIBUTE      EAP-Sim-KC3                             1214    octets
 
+ATTRIBUTE      EAP-Sim-Ki                              1215    octets
+ATTRIBUTE      EAP-Sim-Algo-Version                    1216    integer
+
 #
 #      Range:  1280 - 1535
 #              EAP-type specific attributes
index 68e2cb8..f255b2d 100644 (file)
@@ -52,6 +52,9 @@ RCSIDH(eap_sim_h, "$Id$")
 #define ATTRIBUTE_EAP_SIM_KC2     1213
 #define ATTRIBUTE_EAP_SIM_KC3     1214
 
+#define ATTRIBUTE_EAP_SIM_KI           1215
+#define ATTRIBUTE_EAP_SIM_ALGO_VERSION 1216
+
 enum eapsim_subtype {
   eapsim_start       = 10,
   eapsim_challenge   = 11,
index cd8b0d4..fbb9df8 100644 (file)
@@ -117,10 +117,87 @@ static int eap_sim_sendstart(eap_handler_t *handler)
 static int eap_sim_get_challenge(eap_handler_t *handler, VALUE_PAIR *vps, int idx, eap_sim_state_t *ess)
 {
        REQUEST *request = handler->request;
-       VALUE_PAIR *vp;
+       VALUE_PAIR *vp, *ki, *algo_version;
 
        rad_assert(idx >= 0 && idx < 3);
 
+       /*
+        *      Generate a new RAND value, and derive Kc and SRES from Ki
+        */
+       ki = pairfind(vps, ATTRIBUTE_EAP_SIM_KI, 0, TAG_ANY);
+       if (ki) {
+               int i;
+
+               /*
+                *      Check to see if have a Ki for the IMSI, this allows us to generate the rest
+                *      of the triplets.
+                */
+               algo_version = pairfind(vps, ATTRIBUTE_EAP_SIM_ALGO_VERSION, 0, TAG_ANY);
+               if (!algo_version) {
+                       REDEBUG("Found Ki, but missing EAP-Sim-Algo-Version");
+                       return 0;
+               }
+
+               for (i = 0; i < EAPSIM_RAND_SIZE; i++) {
+                       ess->keys.rand[idx][i] = fr_rand();
+               }
+
+               switch (algo_version->vp_integer) {
+                       case 1:
+                               comp128v1(ess->keys.sres[idx], ess->keys.Kc[idx], ki->vp_octets, ess->keys.rand[idx]);
+                               break;
+
+                       case 2:
+                               comp128v23(ess->keys.sres[idx], ess->keys.Kc[idx], ki->vp_octets, ess->keys.rand[idx],
+                                          true);
+                               break;
+
+                       case 3:
+                               comp128v23(ess->keys.sres[idx], ess->keys.Kc[idx], ki->vp_octets, ess->keys.rand[idx],
+                                          false);
+                               break;
+
+                       case 4:
+                               REDEBUG("Comp128-4 algorithm is not supported as details have not yet been published. "
+                                       "If you have details of this algorithm please contact the FreeRADIUS "
+                                       "maintainers");
+                               return 0;
+
+                       default:
+                               REDEBUG("Unknown/unsupported algorithm Comp128-%i", algo_version->vp_integer);
+               }
+
+               if (RDEBUG_ENABLED2) {
+                       char buffer[33];        /* 32 hexits (16 bytes) + 1 */
+                       char *p;
+
+                       RDEBUG2("Generated following triplets for round %i:", idx);
+
+                       p = buffer;
+                       for (i = 0; i < EAPSIM_RAND_SIZE; i++) {
+                               p += sprintf(p, "%02x", ess->keys.rand[idx][i]);
+                       }
+                       RDEBUG2("\tRAND : 0x%s", buffer);
+
+                       p = buffer;
+                       for (i = 0; i < EAPSIM_SRES_SIZE; i++) {
+                               p += sprintf(p, "%02x", ess->keys.sres[idx][i]);
+                       }
+                       RDEBUG2("\tSRES : 0x%s", buffer);
+
+                       p = buffer;
+                       for (i = 0; i < EAPSIM_Kc_SIZE; i++) {
+                               p += sprintf(p, "%02x", ess->keys.Kc[idx][i]);
+                       }
+                       RDEBUG2("\tKc   : 0x%s", buffer);
+               }
+               return 1;
+       }
+
+       /*
+        *      Use known RAND, SRES, and Kc values, these may of been pulled in from an AuC,
+        *      or created by sending challenges to the SIM directly.
+        */
        vp = pairfind(vps, ATTRIBUTE_EAP_SIM_RAND1 + idx, 0, TAG_ANY);
        if(!vp) {
                /* bad, we can't find stuff! */
@@ -373,12 +450,6 @@ static int eap_sim_initiate(UNUSED void *instance, eap_handler_t *handler)
 
        outvps = handler->request->reply->vps;
 
-       vp = pairfind(outvps, ATTRIBUTE_EAP_SIM_RAND1, 0, TAG_ANY);
-       if (!vp) {
-               RDEBUG2("Can't initiate EAP-SIM, no RAND1 attribute");
-               return 0;
-       }
-
        ess = talloc_zero(handler, eap_sim_state_t);
        if (!ess) {
                RDEBUG2("No space for EAP-SIM state");
@@ -394,7 +465,6 @@ static int eap_sim_initiate(UNUSED void *instance, eap_handler_t *handler)
        if ((eap_sim_get_challenge(handler, outvps, 0, ess) +
             eap_sim_get_challenge(handler, outvps, 1, ess) +
             eap_sim_get_challenge(handler, outvps, 2, ess)) != 3) {
-               RDEBUG2("Can't initiate EAP-SIM, missing attributes");
                return 0;
        }