Implementing EAP-SIM at Home

What is EAP-SIM?

EAP-SIM is one of the authentication methods that can be used in an 802.1x or WPA Enterprise network. Specifically, it relies on the user’s SIM card to process a presented challenge. This has been used by some telcos to provide WiFi service without having to maintain a separate set of credentials. However, not all phones support EAP-SIM.

Phone displaying EAP-SIM as a WiFi authentication method

Since I’m already using a RADIUS setup at home, the use of EAP-SIM will eliminate the need to install my CA certs onto each device. But of course, there is still a fair bit of work to do…

Reading the SIM

I bought a cheap SIM card reader for under $4 from DX (my favourite shoppping site for nonsense like this). Unfortunately, the card reader was so cheap it could not work reliably.

Photo of SIM card reader PCB with SIM slot visible

There are generally 2 kinds of smart card readers: PC/SC and Phoenix-compatible. Smart cards use the same frame format as the RS-232, therefore with the correct crystal and baud rate combination, it is possible to read a smart card using a serial port. This is how Phoenix-compatible card readers work.

This cheap SIM card reader is a Phoenix-compatible reader, but uses the PL2303 serial-to-USB chip to expose a USB interface. The PL2303 chip on this reader was scratched off, which could indicate it may not be a genuine chip. I populated a couple of empty footprints on the PCB with capacitors but it still fails to be recognized sometimes. You can see the flux residue below:

Photo of component side of SIM card reader, after rework to add capacitors

It comes with a CD with Windows drivers and a Windows application. Needless to say, I threw away the box and CD. Instead, I found a nice Python framework called pySim that is able to communicate with both Phoenix-compatible readers and PC/SC readers.

EAP-SIM relies on the GSM authentication triplets for security. Given a random number RAND, the card computes an expected response SRES and a session key Kc using its secret Ki, which is never exposed. The AuC (authentication centre, or in this case the telco) also knows the Ki and is thus able to compute the same SRES and Kc values. The authentication triplet thus consists of RAND, SRES and Kc.

The “Run GSM Algorithm” APDU was already implemented in pySim (but not used), so I added the pySim-run-gsm.py script to run the algorithms and output a simtriplets file:

./pySim-run-gsm.py -n 3 >> /etc/raddb/simtriplets

The simtriplets file should look something like the following:

# IMSI         , RAND          , SRES   , Kc
525xxxx163xxxx0,db8844...38a327,1fxxxxe8,c52xxxxxxxxx1c44
525xxxx163xxxx0,e3d0eb...752fac,41xxxxd7,edfxxxxxxxxx72ba
525xxxx163xxxx0,914c4a...e82ba5,c0xxxx3a,284xxxxxxxxx9970

I added a delay every 5 iterations, just in case the card had some limit and locks us out. Earlier versions of the algorithm (COMP128v1) had a flaw that leaked the secret Ki through ciphertexts, so card manufacturers might throttle the number of runs to prevent such attacks.

FreeRADIUS Configuration

I’m using FreeRADIUS 2.1.12 on CentOS 6. The CentOS/RHEL package doesn’t ship with rlm_sim_files but that functionality can supposedly be added through existing modules. After reading the source file rlm_sim_files.c, I thought it could be easily added into the users file, like some examples I have seen. However, I kept getting the “can not initiate sim, no RAND1 attribute” error. I finally found out what was wrong when I saw this message:

Looking at the rlm_eap_sim module, the RAND attributes have to go into the *reply*, not the *check* items. Ugh.

See “man unlang” in 2.0 for putting attributes into the reply list. Don’t use the “users” file.

By putting the values in the users file, they get added to the control list, but the module expects the RAND attributes to be in the reply list. This StackOverflow answer best describes how the users file works, and in general, attribute-value pair (AVP) lists in FreeRADIUS.

Despite what Alan DeKok says, we can actually use the users file and the unlang module to make this work. This approach avoids us having to recompile FreeRADIUS with the rlm_sim_files module, though the users file might get unwiedly after a while.

First, add the single line below to users file based on the values you have extracted from your SIM card:

1525000116337555@wlan.mnc001.mcc525.3gppnetwork.org    EAP-Type := SIM,
    EAP-Sim-RAND1 := 0x888...3237, 
    EAP-Sim-SRES1 := 0x1fad1278, 
    EAP-Sim-KC1   := 0xc526921113891444, 
    EAP-Sim-RAND2 := 0xe3d...5acc, 
    EAP-Sim-SRES2 := 0x41bd49dd, 
    EAP-Sim-KC2   := 0xedfab114663372bb, 
    EAP-Sim-RAND3 := 0x914...db15, 
    EAP-Sim-SRES3 := 0xc010313a, 
    EAP-Sim-KC3   := 0x2846fffb5aab9970

Note that the identity consists of the realm (the @wlan... part) described in section 4.2.1.5 of RFC 4186 and the username in the following section. wpa_supplicant follows the RFC and prefixes the IMSI with a 1 to indicate EAP-SIM (the code can be traced to a switch-case at the end of the eap_sm_imsi_identity function).

Next, add the following block to your authorize { ... } section, after the files directive to read your users file:

if (User-Name =~ /^[0-9]+/) {
  update reply {
    EAP-Sim-Rand1 := "%{control:EAP-Sim-Rand1}"
    EAP-Sim-Rand2 := "%{control:EAP-Sim-Rand2}"
    EAP-Sim-Rand3 := "%{control:EAP-Sim-Rand3}"
    EAP-Sim-SRES1 := "%{control:EAP-Sim-SRES1}"
    EAP-Sim-SRES2 := "%{control:EAP-Sim-SRES2}"
    EAP-Sim-SRES3 := "%{control:EAP-Sim-SRES3}"
    EAP-Sim-KC1   := "%{control:EAP-Sim-KC1}"
    EAP-Sim-KC2   := "%{control:EAP-Sim-KC2}"
    EAP-Sim-KC3   := "%{control:EAP-Sim-KC3}"
  }
}

This update block will copy the required variables over, provided there was a matching user (that begins with numbers).

A Better Alternative

The rlm_eap module only requires at maximum 3 triplets to be sent, and therefore the users file only contains 3 hardcoded triplets. If you are indeed the operator and know the SIM Ki, you can write a module that computes SRES and Kc dynamically. However, since I most definitely am not, the next best thing to do is to query a bunch of values from the SIM card and have a module randomly pick 3 each time. I wrote a Python module that does exactly that.

You will need to install the Python “module” into the site-packages directory so that FreeRADIUS can find it. Subsequently, add a module file that specifies the functions in the Python module:

pip install https://bitbucket.org/geekman/simtriplets/get/tip.tar.gz
curl https://bitbucket.org/geekman/simtriplets/simtriplets_module > /etc/raddb/modules/simtriplets

Add the line simtriplets at an appropriate location within the authorize { ... } block. For now, the location of the simtriplets “database” file is hardcoded to /etc/raddb/simtriplets. Until such time that FreeRADIUS implements some method of passing configuration values to the Python module, we are stuck with this.

That’s it. You should see the following output in the FreeRADIUS log:

Info: Loaded virtual server <default>
Info: Loaded virtual server inner-tunnel
Info: [simtriplets.py] instantiated simtriplets.py
Info: [simtriplets.py] loaded 2 IMSIs
Info: Ready to process requests.

To prevent cluttering up the logs, the simtriplets.py module is usually very quiet. It is therefore helpful to run radiusd -X to enable full debugging.

Security

Section 12.3 of RFC 4186 describes security concerns, such as mutual authentication and the leakage of SRES and Kc values. Before reading the RFC, I assumed that the EAP peer (mobile device) blindly transmits its computed SRES and Kc values to the server, in clear. This is, of course, an incorrect assumption.

During the EAP exchange, the server selects 2 or 3 RAND values and computes an AT_MAC value to be sent back together with the RAND values. Using the AT_MAC value, the peer is able to confirm that the server indeed knows the SRES and Kc values before it replies with its own calculated AT_MAC value that includes the SRES values – the raw SRES values are never sent in clear.

The EAP-SIM authentication method implemented this way provides sufficient security for my purposes.

References

Here are some additional documents you might want to read up on:

Advertisements

23 comments on “Implementing EAP-SIM at Home

  1. Bill says:

    This is a very helpful solution to the RAND1 error. Unfortunately in the Google search results this is site is bumped by all the sites with people asking about the error, and not getting a clear answer or explanation. Thank you, Bill

  2. Ciro says:

    Hi!, do you have any hints to integrate freeradius 2.1.1 with and actual HLR?

  3. rusutamu says:

    Hi darell tan ,
    Thank you for what you have posted here, it makes me able to configure eap-sim successfully.

  4. TekRADIUS enables you to use EAP-SIM authentication easily. Please see http://www.kaplansoft.com/tekradius/

  5. Jay says:

    @Yasin, Do you have a example of how TekRADIUS EAP-SIM configurations and also it’s integration to HLR since you mentioned that it’s easy.

  6. Devoss says:

    Hi Darell,

    Nice blog…Have few doubts in mind…
    How did you forward EAP authentication requests to Free RADIUS server? Are you using any switch to perform this forwarding task? What are the other equipment you used for testing this whole thing apart from SIM card reader, a SIM card, Windows machine(to get the auth vectors) from SIM reader through pySIM s/w, Free RADIUS or any AAA server.

    • darell tan says:

      Hi Devoss, I used a phone which has EAP-SIM support and a WiFi AP/router that can authenticate using a RADIUS server. The WiFi router connects to my FreeRADIUS server via a normal unmanaged switch. No other special equipment is necessary during normal operation, which is why I used the term “at home”. Hope that answers your question.

      • Devoss says:

        Hi Darell,

        Thank you for your quick reply. I got your answer. I also want to test the same at home. I have android mobile phone which supports EAP-SIM and of course a AAA server which can authenticate EAP-SIM and even a HLR simulator. Now, I want to test end to end(From mobile -> Wifi router -> AAA -> HLR). For this, I need Wifi router which can pass through to AAA server and a SIM card reader which can provide me authentication vectors. Regarding this SIM card reader, can you suggest any device or can I go ahead with above mentioned device. Objective is just to get the authentication vectors(Kc, SRES) from given RAND(s). For this, is there any simpler way to get them? I mean to ask like any software which I can install in my system and connect it thru card reader and can see them? Or I should use above mentioned programs(pySIM) to get them?

        • darell tan says:

          Hi Devoss, I don’t think there’s any “normal” SIM card software that will run the GSM algo for you. Most of them can only retrieve SMS and contacts from the SIM, which is what most users want.

          From the post, you would know that I do not recommend this particular reader. I would advise you to buy a better one. I’m not sure which other card readers are compatible, so you have to do your homework or buy it to try.

  7. Devoss says:

    Thank you Darell, Let me check for other sim card readers. Meanwhile may i know the problems of the above mentioned card reader?
    I hope the pySim software supports both Pc/Sc and phoenix compatible readers. Let me try n thank you…

  8. r00f says:

    very good and helpful post!

  9. Shashi says:

    Hi,

    I get following error after I use these instruction on ubuntu 12.04 LTS with the authorisation template added to /etc/freeradius/modules/files after files {} and SIM response added to /etc/freeradius/users at the end of file as below –
    1240029990182300@wlan.mnc002.mcc240.3gppnetwork.org
    EAP-Type := SIM,
    EAP-Sim-RAND1 := 0xffffffffffffffffffffffffffffffff,
    EAP-Sim-SRES1 := 0x5178b64e,
    EAP-Sim-KC1 := 0xe39ba8f9ed8b28e8,
    EAP-Sim-RAND2 := 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
    EAP-Sim-SRES2 := 0x1317f2d3,
    EAP-Sim-KC2 := 0xb00213842e0ac82a,
    EAP-Sim-RAND3 := 0x55555555555555555555555555555555,
    EAP-Sim-SRES3 := 0x39d0af85,
    EAP-Sim-KC3 := 0x4e4b9043043c2dec

    since the path for Ubuntu was different. I get following error. Please let me know if you can help –

    [eap] Request found, released from the list
    [eap] EAP NAK
    [eap] NAK asked for unsupported type SIM
    [eap] No common EAP types found.
    [eap] Failed in EAP select

    Detail log –
    —————-
    Listening on authentication address * port 1812
    Listening on accounting address * port 1813
    Listening on authentication address 127.0.0.1 port 18120 as server inner-tunnel
    Listening on proxy address * port 1814
    Ready to process requests.
    rad_recv: Access-Request packet from host 192.168.1.1 port 55596, id=0, length=215
    User-Name = “1240029990182300@wlan.mnc002.mcc240.3gppnetwork.org”
    NAS-IP-Address = 192.168.1.1
    Called-Station-Id = “14dda9f506b4”
    Calling-Station-Id = “00f46f2066fd”
    NAS-Identifier = “14dda9f506b4”
    NAS-Port = 59
    Framed-MTU = 1400
    NAS-Port-Type = Wireless-802.11
    EAP-Message = 0x02000038013132343030323939393031383233303040776c616e2e6d6e633030322e6d63633234302e336770706e6574776f726b2e6f7267
    Message-Authenticator = 0x456a0b53cd565688b89a7b4f5ea0eddf
    # Executing section authorize from file /etc/freeradius/sites-enabled/default
    +- entering group authorize {…}
    ++[preprocess] returns ok
    ++[chap] returns noop
    ++[mschap] returns noop
    ++[digest] returns noop
    [suffix] Looking up realm “wlan.mnc002.mcc240.3gppnetwork.org” for User-Name = “1240029990182300@wlan.mnc002.mcc240.3gppnetwork.org”
    [suffix] No such realm “wlan.mnc002.mcc240.3gppnetwork.org”
    ++[suffix] returns noop
    [eap] EAP packet type response id 0 length 56
    [eap] No EAP Start, assuming it’s an on-going EAP conversation
    ++[eap] returns updated
    [files] users: Matched entry 1240029990182300@wlan.mnc002.mcc240.3gppnetwork.org at line 205
    ++[files] returns ok
    ++[expiration] returns noop
    ++[logintime] returns noop
    [pap] WARNING! No “known good” password found for the user. Authentication may fail because of this.
    ++[pap] returns noop
    Found Auth-Type = EAP
    # Executing group from file /etc/freeradius/sites-enabled/default
    +- entering group authenticate {…}
    [eap] EAP Identity
    [eap] processing type md5
    rlm_eap_md5: Issuing Challenge
    ++[eap] returns handled
    Sending Access-Challenge of id 0 to 192.168.1.1 port 55596
    EAP-Message = 0x010100160410a0eaa0a3d6c1b0bfe288e4a594bc958a
    Message-Authenticator = 0x00000000000000000000000000000000
    State = 0x212b3fe1212a3b7bc3e39b6539db43c2
    Finished request 0.
    Going to the next request
    Waking up in 4.9 seconds.
    rad_recv: Access-Request packet from host 192.168.1.1 port 55596, id=0, length=183
    Cleaning up request 0 ID 0 with timestamp +81
    User-Name = “1240029990182300@wlan.mnc002.mcc240.3gppnetwork.org”
    NAS-IP-Address = 192.168.1.1
    Called-Station-Id = “14dda9f506b4”
    Calling-Station-Id = “00f46f2066fd”
    NAS-Identifier = “14dda9f506b4”
    NAS-Port = 59
    Framed-MTU = 1400
    State = 0x212b3fe1212a3b7bc3e39b6539db43c2
    NAS-Port-Type = Wireless-802.11
    EAP-Message = 0x020100060312
    Message-Authenticator = 0x1cb72589bd652b99e8f0b94be3aba45b
    # Executing section authorize from file /etc/freeradius/sites-enabled/default
    +- entering group authorize {…}
    ++[preprocess] returns ok
    ++[chap] returns noop
    ++[mschap] returns noop
    ++[digest] returns noop
    [suffix] Looking up realm “wlan.mnc002.mcc240.3gppnetwork.org” for User-Name = “1240029990182300@wlan.mnc002.mcc240.3gppnetwork.org”
    [suffix] No such realm “wlan.mnc002.mcc240.3gppnetwork.org”
    ++[suffix] returns noop
    [eap] EAP packet type response id 1 length 6
    [eap] No EAP Start, assuming it’s an on-going EAP conversation
    ++[eap] returns updated
    [files] users: Matched entry 1240029990182300@wlan.mnc002.mcc240.3gppnetwork.org at line 205
    ++[files] returns ok
    ++[expiration] returns noop
    ++[logintime] returns noop
    [pap] WARNING! No “known good” password found for the user. Authentication may fail because of this.
    ++[pap] returns noop
    Found Auth-Type = EAP
    # Executing group from file /etc/freeradius/sites-enabled/default
    +- entering group authenticate {…}
    [eap] Request found, released from the list
    [eap] EAP NAK
    [eap] NAK asked for unsupported type SIM
    [eap] No common EAP types found.
    [eap] Failed in EAP select
    ++[eap] returns invalid
    Failed to authenticate the user.
    Using Post-Auth-Type Reject
    # Executing group from file /etc/freeradius/sites-enabled/default
    +- entering group REJECT {…}
    [attr_filter.access_reject] expand: %{User-Name} -> 1240029990182300@wlan.mnc002.mcc240.3gppnetwork.org
    attr_filter: Matched entry DEFAULT at line 11
    ++[attr_filter.access_reject] returns updated
    Delaying reject of request 1 for 1 seconds
    Going to the next request
    Waking up in 0.9 seconds.
    Sending delayed reject for request 1

    • darell tan says:

      From this it looks like you did not enable EAP SIM support. I’m not using Ubuntu, but there should be an eap.conf file with an eap {...} section inside. You need to just add an empty sim { } section within that and it should work.

      [eap] EAP NAK
      [eap] NAK asked for unsupported type SIM
      [eap] No common EAP types found.
      [eap] Failed in EAP select
      • Samuel says:

        Hi I’m getting this same issue even though I added sim {} in eap.conf
        Note: I’m running in Ubuntu 14.04

        • darell tan says:

          When you start FreeRADIUS in debugging mode using radiusd -X, you should see the SIM modules being instantiated, something like this:

           Module: Linked to sub-module rlm_eap_sim
           Module: Instantiating eap-sim
          

          If you don’t see it, the module might not have been compiled in.

  10. Shashi says:

    You have written
    ————————-
    Next, add the following block to your authorize { … } section, after the files directive to read your users file:

    if (User-Name =~ /^[0-9]+/) {

    ————————-
    In which file do you want to add this?

    • darell tan says:

      I added this inside my sites-enabled file. The file should look like this:

      server SERVER_NAME {
        ...
      
        authorize {
          preprocess
      
          ...
      
          # this reads your user file with the EAP-Sim-RAND1 attributes
          files
      
          # put the block here
          if (User-Name =~ /^[0-9]+/) {
            update reply {
               ...
            }
          }
        }
      }
      
    • Shashi says:

      Thank you very much for the information Darell,

      Now I manage to setup the EAP-SIM successfully using CentOS 7 since I was getting error on Ubuntu even after adding sim{} as you have told but it definitely put to next level in authentication. The reason on failing on Ubuntu might be because I used the old freedadius with Ubuntu APT which was older than you have used. I used default because I faced too many problems with latest freeradius with dependent libraries.

      In addition to this nice article, for new users it can be good to add following instruction on cleanly installed CentOS.

      All commands are used by root terminal

      1. Install CentOS7

      2. Disable CentOS7 firewall
      systemctl status firewalld
      systemctl disable firewalld
      systemctl stop firewalld
      systemctl status firewalld

      3. Install freeradius on CentOS
      yum install freeradius freeradius-mysql freeradius-utils -y (there is problem with mysql-server)
      service radiusd stop

      4. Add the router IP address in /etc/raddb/clients.conf as below so that freeradius accept packets from the router –

      client 192.168.10.1/16 {
      secret = testing123
      shortname = private-network-2
      }

      NOTE: Use your own router IP Address instead of 192.168.10.1

      5. Add SIM{} in /etc/raddb/mods-available/eap in eap { before md5 {} as below so that radius also uses EAP-SIM –

      eap {
      . . .
      sim {
      }
      md5 {
      }
      . . .

      6. Add SIM data in /etc/raddb/users in the beginning as below in one line –

      1525000116337555@wlan.mnc001.mcc525.3gppnetwork.org EAP-Type := SIM, EAP-Sim-RAND1 := 0x888…3237, EAP-Sim-SRES1 := 0x1fad1278, EAP-Sim-KC1 := 0xc526921113891444, EAP-Sim-RAND2 := 0xe3d…5acc, EAP-Sim-SRES2 := 0x41bd49dd, EAP-Sim-KC2 := 0xedfab114663372bb, EAP-Sim-RAND3 := 0x914…db15, EAP-Sim-SRES3 := 0xc010313a, EAP-Sim-KC3 := 0x2846fffb5aab9970

      7. Add SIM reader template to /etc/raddb/sites-available/default –

      server SERVER_NAME {

      authorize {
      preprocess

      # this reads your user file with the EAP-Sim-RAND1 attributes
      files

      # put the block here
      if (User-Name =~ /^[0-9]+/) {
      update reply {

      }
      }
      }
      }

      8. Run Freeradius using and observe the output –

      radiusd -X

      9. Use the same SIM card from android phone and use EAP-SIM and success.

      And everyone should be able to use it using phone 🙂 I hope I did not miss something.

  11. abdelrahman says:

    can you tell me your opinion about Nexoos 660 Smart Combo as a sim card reader ??

    • darell tan says:

      I’ve looked at the documentation for this reader, and it seems to present itself as a PC/SC device. It even has Linux support, so I’m guessing you should have very little difficulty getting it to work. If you are on Windows, you can use something like asgm.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s