Adding Authentication and Encryption to the Public Release
This work is currently hosted in openbts/features/a3a8 and subscriberRegistry/features/a3a8. Changes are required in both OpenBTS and sipauthserve.
The C2.8 commercial release currently supports A3/A8 authentication via a
SIP interface modeled on the IMS authentication exchange. This
procedure is similar to SIP digest authentication, but using the RAND as
a the nonce and an externally-supplied A3/A8 algorithm in place of MD5
or SHA2. An implementation of COMP128v1 is provided as an example A3/A8.
This capability was brought into the subscriberRegistry/features/a3a8 branch of the public release in r2583 and into the openbts/features/a3a8 in r2878. So at this point, these feature branches, together, support authentication for COMP128v1 SIMs. But as of r2878 they do not yet support encryption.
To add encryption to this system, we need to:
- Add code to sipauthserve to generate Kc when we run A3/A8 and send that Kc back to OpenBTS in the SIP 200 OK response in some kind of SIP header.
- Add code to SIPEngine to extract Kc from the 200 OK and store it in gTMSITable.
- Add code to GSML3RRMessages to encode the Ciphering Mod Command (GSM 04.08 9.1.9) and decode the Ciphering Mode Complete message (GSM 04.08 9.1.10).
- Add an XOR step to the L1 FEC encoder (GSM::L1Encoder) and decoder (GSM::L1Decoder) to apply the cipherstream.
- Add a cipherstream generator to the system somewhere. For
simplicity, the cipherstream generator should be continuously active,
and just generate a stream of 0s for Kc=0. The input to the generator
is the frame number and Kc. The output of the generator is a frame of
cipherstream bits. If we are smart, we will find a way to avoid calling
the generator twice in a row with the same parameters.
- Add methods to GSM::L1FEC and GSM::LogicalChannel to set Kc.
The total authentication/encryption process is:
- Generate a Kc in sipauthserver when we run A3/A8.
- Send that Kc back to OpenBTS in the SIP 200 OK response in some kind of SIP header or content.
- Store Kc locally in the TMSI table.
- When we start a new transaction, at some point early in that
transaction, the handset will identify itself by IMSI or TMSI. When
this happens, we start the ciphering process with the Ciphering Mode
Command message (GSM 04.08 9.1.9).
- Set the Kc on the L1 decoder part of the logical channel. Because GSM::L1FEC::writeHighSide() is blocking and synchronous, synchronization of the L1 Kc change with the outgoing frame stream should be simple.
- The L1 decoder watches for the first valid inbound frame with
ciphering turned on. When it arrives, the L1 decoder sets Kc on the
corresponding L1 encoder using the mSibling pointer. (See GSM 03.20 4.5.)
- Receive the Ciphering Mode Complete message (GSM 04.08 9.1.10).
(We need a new message flow diagram for this.)
This is all for a minimal first-cut implementation. For longer term,
scalable ciphering support, we will need other work as well, but we can
deal with that once this basic plan is in place. The phases of
- Get A3/A8 and ciphering working for LUR.
- Add ciphering to other transactions, using the Kc stored in the TMSI table, referenced by key sequence number.
- Add authentication and Kc generation to other transactions.
Kc is generated along with SRES and CKSN when comp128v1 (or any other A3/A8) is invoked in SubscriberRegistry?. Acquiring it is just a matter of adding a little extra string processing to sipauthserve.
Sending Kc and CKSN to OpenBTS
Kc and CKSN should be communicated to OpenBTS in the final 200 OK response from sipauthserve.
Use SIP 200 OK message with Authentication-Info header set to Kc, and cnonce value set to CKSN.
- This header is already use in IMS AKA protocol, RFC3310.
- Supported by oSIP library which is already used in OpenBTS: http://www.antisip.com/doc/osip2/group__oSIP__AUTH__INFO.html.
Available via following repositories:
- git clone git://github.com/zabbal/openbts-p2.8.git -b authenc
- git clone git://github.com/zabbal/subscriberRegistry.git -b authenc
Storing Kc and CKSN Locally in OpenBTS
When Kc and CKSN arrives in the 200 OK, they should be stored locally in
the TMSI table. When a channel is actually using Kc, the active Kc
value is also stored in the L1FEC for that channel. A Kc value of zero
will indicate that cihpering is off. Setting the Kc value on the L1FEC
results in immediate application of the new ciphering setting. The
actual Kc value should be kept in L1FEC, with accessor in the L1Encoder and L1Decoder classes and a passthrough accessor in LogicalChannel so that it can also be presented in the transaction table records.
Cipher Stream Generation
For licensing compatibility with both the public and commercial
releases, the A5/1 cipher stream generator needs to be under a
permissive (non-copyleft) license, like this one.
Maybe we can speed that up a little if nobody else has. The proper
place for cipherstream generation is in the lower parts of L1. See the
next section for details.
Cipher Stream Application
An earlier plan called for Kc to be in GSM::L1FEC and accessed from there by GSM::L1Encoder and GSM::L1Decoder.
that won't work, since we need to set Kc on uplink and downlink at
different times (GSM 03.30 4.5). So the encoder and decoder need
separate Kc values and the decoder needs to be able to control Kc on the
encoder. This would work just fine if we keep bool flags
indicating whether encryption has been enabled for particular direction
or not. The Kc value is common for both uplink and downlink and hence
should be stored in single place: GSM::L1FEC.
The best place to apply the downlink cipher stream is in XCCHL1Encoder::transmit() in GSM/GSML1FEC.cpp.
The best place to apply the uplink cipher stream is in TCHFACCHL1Decoder::processBurst() for TCH/F+FACCH and XCCHL1Decoder::processBurst() for everything else. Both of these are in GSM/GSML1FEC.cpp.
注：Adding Authentication and Encryption to the Public Release（原文出处，翻译整理仅供参考!）