---
src/gsm/a5.c | 43 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 43 insertions(+)
diff --git a/src/gsm/a5.c b/src/gsm/a5.c
index 93b22c7..5815aa7 100644
--- a/src/gsm/a5.c
+++ b/src/gsm/a5.c
@@ -39,6 +39,7 @@
#include <string.h>
#include <osmocom/core/bits.h>
#include <osmocom/gsm/a5.h>
+#include <osmocom/gsm/kasumi.h>
/*! \brief Main method to generate a A5/x cipher stream
* \param[in] n Which A5/x method to use
@@ -71,6 +72,10 @@ osmo_a5(int n, const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t
*ul)
osmo_a5_2(key, fn, dl, ul);
break;
+ case 3:
+ osmo_a5_3(key, fn, dl, ul);
+ break;
+
default:
/* a5/[4..7] not supported here/yet */
return -ENOTSUP;
@@ -368,4 +373,42 @@ osmo_a5_2(const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul)
}
}
+/* ------------------------------------------------------------------------ */
+/* A5/3 */
+/* ------------------------------------------------------------------------ */
+
+/*! \brief Generate a GSM A5/3 cipher stream
+ * \param[in] key 8 byte array for the key (as received from the SIM)
+ * \param[in] fn Frame number
+ * \param[out] dl Pointer to array of ubits to return Downlink cipher stream
+ * \param[out] ul Pointer to array of ubits to return Uplink cipher stream
+ *
+ * Either (or both) of dl/ul should be NULL if not needed.
+ *
+ * Implementation based on specifications from 3GPP TS 55.216, 3GPP TR 55.919 and ETSI TS
135 202
+ * with slight simplifications (CE hardcoded to 0).
+ */
+void
+osmo_a5_3(const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul)
+{
+ /* internal function require 128 bit key so we expand by concatenating supplied 64
bit key */
+ uint8_t i, ck[16], gamma[32], _key[8];
+ memcpy(_key, key, 8);
+ osmo_revbytes_buf(_key, 8); /* reverse key byte order to match the way it's
stored in SIM */
+ memcpy(ck, _key, 8);
+ memcpy(ck + 8, _key, 8);
+
+ uint32_t fn_count = osmo_a5_fn_count(fn); /* Frame count load */
+ if (dl) {
+ kgcore(0xF, 0, fn_count, 0, ck, gamma, 114);
+ osmo_pbit2ubit(dl, gamma, 114);
+ }
+ if (ul) {
+ kgcore(0xF, 0, fn_count, 0, ck, gamma, 228);
+ uint8_t uplink[15];
+ for(i = 0; i < 15; i++) uplink[i] = (gamma[i + 14] << 2) + (gamma[i + 15]
>> 6);
+ osmo_pbit2ubit(ul, uplink, 114);
+ }
+}
+
/*! @} */
--
1.7.10.4
--------------000004050908040808070403--