]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Plumb in milenage
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sat, 9 Dec 2017 07:30:49 +0000 (07:30 +0000)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sat, 9 Dec 2017 07:30:49 +0000 (07:30 +0000)
share/dictionary.freeradius.internal
src/modules/rlm_eap/lib/sim/sim_proto.h
src/modules/rlm_eap/lib/sim/vector.c

index d86e1f5bd1e71dc64f5200cc4406cb8445d8363b..8c6130d12eb76f968719e658df63b914584f8b9f 100644 (file)
@@ -373,21 +373,29 @@ $INCLUDE dictionary.ethernet
 #
 
 # The Ki for a specific SIM card.
-ATTRIBUTE      SIM-Ki                                  1200    octets
+ATTRIBUTE      SIM-Ki                                  1200    octets[16]
+ATTRIBUTE      SIM-OPc                                 1201    octets[16]
+ATTRIBUTE      SIM-AMF                                 1202    octets[2]
+ATTRIBUTE      SIM-SQN                                 1203    octets[4]
 
 # The IMSI number of a SIM.
-ATTRIBUTE      SIM-IMSI                                1201    string
+ATTRIBUTE      SIM-IMSI                                1204    string
 
 # The algorithm the SIM card uses (Milenage for UMTS, COMP128 for others)
-ATTRIBUTE      SIM-Algo-Version                        1202    integer
-ATTRIBUTE      SIM-Method-Hint                         1203    integer
+ATTRIBUTE      SIM-Algo-Version                        1205    integer
+VALUE          SIM-Algo-Version        Comp128v1               0
+VALUE          SIM-Algo-Version        Comp128v2               1
+VALUE          SIM-Algo-Version        Comp128v3               2
+VALUE          SIM-Algo-Version        Milenage                3
+
+ATTRIBUTE      SIM-Method-Hint                         1206    integer
 
 VALUE          SIM-Method-Hint         Unknown                 0
 VALUE          SIM-Method-Hint         SIM                     1
 VALUE          SIM-Method-Hint         AKA                     2
 VALUE          SIM-Method-Hint         AKA-Prime               3
 
-ATTRIBUTE      SIM-Identity-Type                       1204    integer
+ATTRIBUTE      SIM-Identity-Type                       1207    integer
 
 VALUE          SIM-Identity-Type       Unknown                 0
 VALUE          SIM-Identity-Type       Permanent               1
index 2db36aa192597381c7a5109f33e0400e7b419c1c..3127d7d5153977ca1afc0e3e5e56f834c2f5b999 100644 (file)
@@ -55,8 +55,10 @@ RCSIDH(sim_h, "$Id$")
 #define SIM_VECTOR_UMTS_XRES_MAX_SIZE  16
 #define SIM_VECTOR_UMTS_RES_MAX_SIZE   16
 
-
-
+#define SIM_MILENAGE_KI_SIZE           16
+#define SIM_MILENAGE_OPC_SIZE          16
+#define SIM_MILENAGE_AMF_SIZE          2
+#define SIM_MILENAGE_SQN_SIZE          6
 
 /** Round up - Only works if _mul is a power of 2 but avoids division
  */
@@ -128,7 +130,7 @@ typedef struct {
        uint8_t const   *network;                               //!< Network name (EAP-AKA-Prime only).
        size_t          network_len;                            //!< Length of the network name (EAP-AKA-Prime only).
 
-       uint64_t sqn;                                           //!< Sequence number
+       uint64_t        sqn;                                    //!< Sequence number
 
        /*
         *      The vectors we acquired during the challenge phase.
index c00dcb9ac1f2d05fa0d3a527f07b4c26106d5e7c..d335c63e7446c13886d43fe45a098c5f57505c98 100644 (file)
@@ -30,66 +30,94 @@ RCSID("$Id$")
 #include "eap_types.h"
 #include "sim_proto.h"
 #include "comp128.h"
+#include "milenage.h"
 
 #include <freeradius-devel/rad_assert.h>
 
 static int vector_gsm_from_ki(eap_session_t *eap_session, VALUE_PAIR *vps,
                              int idx, fr_sim_keys_t *keys)
 {
-       REQUEST *request = eap_session->request;
-       VALUE_PAIR *vp, *version;
-       int i;
+       REQUEST         *request = eap_session->request;
+       VALUE_PAIR      *ki, *version;
+       int             i;
 
        /*
         *      Generate a new RAND value, and derive Kc and SRES from Ki
         */
-       vp = fr_pair_find_by_child_num(vps, dict_sim_root, FR_SIM_KI, TAG_ANY);
-       if (!vp) {
-               RDEBUG3("No &control:SIM-KI found, not generating triplets locally");
+       ki = fr_pair_find_by_child_num(vps, fr_dict_root(fr_dict_internal), FR_SIM_KI, TAG_ANY);
+       if (!ki) {
+               RDEBUG3("No &control:SIM-Ki found, not generating triplets locally");
                return 1;
+       } else if (ki->vp_length != SIM_MILENAGE_KI_SIZE) {
+               REDEBUG("&control:SIM-Ki has incorrect length, expected 16 bytes got %zu bytes", ki->vp_length);
+               return -1;
        }
 
        /*
         *      Check to see if have a Ki for the IMSI, this allows us to generate the rest
         *      of the triplets.
         */
-       version = fr_pair_find_by_child_num(vps, dict_sim_root, FR_SIM_ALGO_VERSION, TAG_ANY);
+       version = fr_pair_find_by_child_num(vps, fr_dict_root(fr_dict_internal), FR_SIM_ALGO_VERSION, TAG_ANY);
        if (!version) {
-               RDEBUG3("No &control:SIM-ALGO-VERSION found, not generating triplets locally");
+               RDEBUG3("No &control:SIM-Algo-Version found, not generating triplets locally");
                return 1;
        }
 
-       for (i = 0; i < SIM_VECTOR_GSM_RAND_SIZE; i++) {
-               keys->gsm.vector[idx].rand[i] = fr_rand();
+       for (i = 0; i < SIM_VECTOR_GSM_RAND_SIZE; i += sizeof(uint32_t)) {
+               uint32_t rand = fr_rand();
+               memcpy(&keys->gsm.vector[idx].rand[i], &rand, sizeof(rand));
        }
 
        switch (version->vp_uint32) {
        case 1:
                comp128v1(keys->gsm.vector[idx].sres,
-                         keys->gsm.vector[idx].kc, vp->vp_octets,
+                         keys->gsm.vector[idx].kc,
+                         ki->vp_octets,
                          keys->gsm.vector[idx].rand);
                break;
 
        case 2:
                comp128v23(keys->gsm.vector[idx].sres,
                           keys->gsm.vector[idx].kc,
-                          vp->vp_octets,
+                          ki->vp_octets,
                           keys->gsm.vector[idx].rand, true);
                break;
 
        case 3:
                comp128v23(keys->gsm.vector[idx].sres,
                           keys->gsm.vector[idx].kc,
-                          vp->vp_octets,
+                          ki->vp_octets,
                           keys->gsm.vector[idx].rand, false);
                break;
 
        case 4:
-               REDEBUG("Milenage not supported (feel free to implement it)");
+       {
+               VALUE_PAIR *opc;
+
+               opc = fr_pair_find_by_child_num(vps, fr_dict_root(fr_dict_internal), FR_SIM_OPC, TAG_ANY);
+               if (!opc) {
+                       RDEBUG3("No &control:SIM-OPc not generating triplets locally");
+                       return 1;
+               }
+               else if (opc->vp_length != SIM_MILENAGE_OPC_SIZE) {
+                       REDEBUG("&control:SIM-OPc has incorrect length, expected %u bytes got %zu bytes",
+                               SIM_MILENAGE_OPC_SIZE, opc->vp_length);
+                       return -1;
+               }
+
+               if (milenage_gsm_generate(keys->gsm.vector[idx].sres,
+                                         keys->gsm.vector[idx].kc,
+                                         opc->vp_octets,
+                                         ki->vp_octets,
+                                         keys->gsm.vector[idx].rand) < 0) {
+                       RPEDEBUG2("Failed deriving GSM triplet");
+                       return -1;
+               }
+       }
                return 1;
 
        default:
-               REDEBUG("Unknown/unsupported algorithm Comp128-%i", version->vp_uint32);
+               REDEBUG("Unknown/unsupported algorithm %i", version->vp_uint32);
                return -1;
        }
        return 0;
@@ -332,75 +360,97 @@ int fr_sim_vector_gsm_from_attrs(eap_session_t *eap_session, VALUE_PAIR *vps,
        return 0;
 }
 
-#if 0
-static int vector_umts_from_ki(eap_session_t *eap_session, VALUE_PAIR *vps,
-                              fr_sim_keys_t *keys)
+static int vector_umts_from_ki(eap_session_t *eap_session, VALUE_PAIR *vps, fr_sim_keys_t *keys)
 {
-       REQUEST *request = eap_session->request;
-       VALUE_PAIR *vp, *version;
-       int i;
+       REQUEST         *request = eap_session->request;
+       VALUE_PAIR      *ki, *opc, *amf, *sqn, *version_vp;
+       uint8_t         amf_buff[SIM_MILENAGE_AMF_SIZE];
+       uint8_t const   *amf_p;
+       uint8_t         sqn_buff[SIM_MILENAGE_SQN_SIZE];
+       uint8_t const   *sqn_p;
+       uint32_t        version = 4;
 
-       /*
-        *      Generate a new RAND value, and derive Kc and SRES from Ki
-        */
-       vp = fr_pair_find_by_num(vps, 0, FR_SIM_KI, TAG_ANY);
-       if (!vp) {
-               RDEBUG3("No &control:aka-KI found, not generating triplets locally");
+       int             i;
+
+       ki = fr_pair_find_by_child_num(vps, fr_dict_root(fr_dict_internal), FR_SIM_KI, TAG_ANY);
+       if (!ki) {
+               RDEBUG3("No &control:SIM-Ki found, not generating triplets locally");
                return 1;
+       } else if (ki->vp_length != SIM_MILENAGE_KI_SIZE) {
+               REDEBUG("&control:SIM-Ki has incorrect length, expected %u bytes got %zu bytes",
+                       SIM_MILENAGE_KI_SIZE, ki->vp_length);
+               return -1;
        }
 
-       /*
-        *      Check to see if have a Ki for the IMSI, this allows us to generate the rest
-        *      of the triplets.
-        */
-       version = fr_pair_find_by_num(vps, 0, FR_SIM_ALGO_VERSION, TAG_ANY);
-       if (!version) {
-               RDEBUG3("No &control:SIM-ALGO-VERSION found, not generating triplets locally");
+       opc = fr_pair_find_by_child_num(vps, fr_dict_root(fr_dict_internal), FR_SIM_OPC, TAG_ANY);
+       if (!opc) {
+               RDEBUG3("No &control:SIM-OPc not generating  quintuplets locally");
                return 1;
+       } else if (opc->vp_length != SIM_MILENAGE_OPC_SIZE) {
+               REDEBUG("&control:SIM-OPc has incorrect length, expected %u bytes got %zu bytes",
+                       SIM_MILENAGE_OPC_SIZE, opc->vp_length);
+               return -1;
        }
 
-       for (i = 0; i < SIM_VECTOR_UMTS_RAND_SIZE; i++) {
-               keys->umts.vector.rand[i] = fr_rand();
+       amf = fr_pair_find_by_child_num(vps, fr_dict_root(fr_dict_internal), FR_SIM_AMF, TAG_ANY);
+       if (!amf) {
+               memset(&amf_buff, 0, sizeof(amf_buff));
+               amf_p = amf_buff;
+       } else if (amf->vp_length != SIM_MILENAGE_AMF_SIZE) {
+               REDEBUG("&control:SIM-AMF has incorrect length, expected %u bytes got %zu bytes",
+                       SIM_MILENAGE_AMF_SIZE, amf->vp_length);
+               return -1;
+       } else {
+               amf_p = amf->vp_octets;
        }
 
-       switch (version->vp_uint32) {
-       case 1:
-               comp128v1(keys->umts.vector.sres,
-                         keys->umts.vector.kc, vp->vp_octets,
-                         keys->umts.vector.rand);
-               break;
+       sqn = fr_pair_find_by_child_num(vps, fr_dict_root(fr_dict_internal), FR_SIM_SQN, TAG_ANY);
+       if (!sqn) {
+               memset(&sqn_buff, 0, sizeof(sqn_buff));
+               sqn_p = sqn_buff;
+       } else if (sqn->vp_length != SIM_MILENAGE_SQN_SIZE) {
+               REDEBUG("&control:SIM-SQN has incorrect length, expected %u bytes got %zu bytes",
+                       SIM_MILENAGE_SQN_SIZE, sqn->vp_length);
+               return -1;
+       } else {
+               sqn_p = sqn->vp_octets;
+       }
 
-       case 2:
-               comp128v23(keys->umts.vector.sres,
-                          keys->umts.vector.kc,
-                          vp->vp_octets,
-                          keys->umts.vector.rand, true);
-               break;
+       /*
+        *      We default to milenage
+        */
+       version_vp = fr_pair_find_by_num(vps, 0, FR_SIM_ALGO_VERSION, TAG_ANY);
+       if (version_vp) version = version_vp->vp_uint32;
 
-       case 3:
-               comp128v23(keys->umts.vector.sres,
-                          keys->umts.vector.kc,
-                          vp->vp_octets,
-                          keys->umts.vector.rand, false);
-               break;
+       for (i = 0; i < SIM_VECTOR_UMTS_RAND_SIZE; i += sizeof(uint32_t)) {
+               uint32_t rand = fr_rand();
+               memcpy(&keys->umts.vector.rand[i], &rand, sizeof(rand));
+       }
 
+       switch (version) {
        case 4:
-               REDEBUG("Milenage not supported (feel free to implement it)");
+               if (milenage_umts_generate(keys->umts.vector.autn,
+                                          keys->umts.vector.ik, keys->umts.vector.ck, keys->umts.vector.xres,
+                                          opc->vp_octets, amf_p, ki->vp_octets,
+                                          sqn_p, keys->umts.vector.rand) < 0) {
+                       RPEDEBUG2("Failed deriving UMTS Quintuplet");
+                       return -1;
+               }
+               keys->umts.vector.xres_len = 8;
                return 1;
 
+       case 1:
+       case 2:
+       case 3:
+               REDEBUG("Only Milenage can be used to generate quintuplets");
+               return -1;
+
        default:
-               REDEBUG("Unknown/unsupported algorithm Comp128-%i", version->vp_uint32);
+               REDEBUG("Unknown/unsupported algorithm %i", version);
                return -1;
        }
        return 0;
 }
-#else
-static int vector_umts_from_ki(UNUSED eap_session_t *eap_session, UNUSED VALUE_PAIR *vps,
-                              UNUSED fr_sim_keys_t *keys)
-{
-       return 1;
-}
-#endif
 
 /** Get one set of quintuplets from the request
  *