Update internal GPRS cipher API to comply with ETSI TS 155.22

Submitted by Max on June 17, 2014, 9:16 a.m.

Details

Message ID 1402996618-7967-1-git-send-email-Max.Suraev@fairwaves.co
State New
Headers show

Commit Message

Max June 17, 2014, 9:16 a.m.
Signed-off-by: Max Suraev <Max.Suraev@fairwaves.co>
---
 TODO-RELEASE                        |  3 ++-
 include/osmocom/crypt/gprs_cipher.h |  8 ++++++--
 src/gsm/gprs_cipher_core.c          | 23 +++++++++++++++++++++--
 src/gsm/libosmogsm.map              |  1 +
 4 files changed, 30 insertions(+), 5 deletions(-)

Comments

Max June 17, 2014, 9:22 a.m.
To clarify - this patch does not change external API: it adds convenience function to
external API and it changes internal API used by developers implementing GPRS
ciphers. To the best of my knowledge the massive set of such devs amounts to only me
at the moment :)

Patch hide | download patch | download mbox

diff --git a/TODO-RELEASE b/TODO-RELEASE
index 43b1e8e..c7366ae 100644
--- a/TODO-RELEASE
+++ b/TODO-RELEASE
@@ -1 +1,2 @@ 
-#library	what		description / commit summary line
+#library	what			description / commit summary line
+libosmogsm	internal API update	Internal API for GPRS cipher implementors updated to accommodate for arbitrary key lengths
\ No newline at end of file
diff --git a/include/osmocom/crypt/gprs_cipher.h b/include/osmocom/crypt/gprs_cipher.h
index 940b07b..d6edefa 100644
--- a/include/osmocom/crypt/gprs_cipher.h
+++ b/include/osmocom/crypt/gprs_cipher.h
@@ -9,6 +9,7 @@  enum gprs_ciph_algo {
 	GPRS_ALGO_GEA1,
 	GPRS_ALGO_GEA2,
 	GPRS_ALGO_GEA3,
+	GPRS_ALGO_GEA4,
 	_GPRS_ALGO_NUM
 };
 
@@ -27,7 +28,7 @@  struct gprs_cipher_impl {
 	/* As specified in 04.64 Annex A.  Uses Kc, IV and direction
 	 * to generate the 1523 bytes cipher stream that need to be
 	 * XORed wit the plaintext for encrypt / ciphertext for decrypt */
-	int (*run)(uint8_t *out, uint16_t len, uint64_t kc, uint32_t iv,
+	int (*run)(uint8_t *out, uint16_t len, uint8_t *kc, uint32_t iv,
 		   enum gprs_cipher_direction direction);
 };
 
@@ -39,11 +40,14 @@  int gprs_cipher_load(const char *path);
 
 /* function to be called by core code */
 int gprs_cipher_run(uint8_t *out, uint16_t len, enum gprs_ciph_algo algo,
-		    uint64_t kc, uint32_t iv, enum gprs_cipher_direction dir);
+		    uint8_t *kc, uint32_t iv, enum gprs_cipher_direction dir);
 
 /* Do we have an implementation for this cipher? */
 int gprs_cipher_supported(enum gprs_ciph_algo algo);
 
+/* Return key length for supported cipher, in bytes */
+unsigned gprs_cipher_key_length(enum gprs_ciph_algo algo);
+
 /* GSM TS 04.64 / Section A.2.1 : Generation of 'input' */
 uint32_t gprs_cipher_gen_input_ui(uint32_t iov_ui, uint8_t sapi, uint32_t lfn, uint32_t oc);
 
diff --git a/src/gsm/gprs_cipher_core.c b/src/gsm/gprs_cipher_core.c
index b9a22a1..e4fac04 100644
--- a/src/gsm/gprs_cipher_core.c
+++ b/src/gsm/gprs_cipher_core.c
@@ -53,12 +53,14 @@  int gprs_cipher_register(struct gprs_cipher_impl *ciph)
 int gprs_cipher_load(const char *path)
 {
 	/* load all plugins available from path */
-	return osmo_plugin_load_all(path);
+	if (path)
+		return osmo_plugin_load_all(path);
+	return 0;
 }
 
 /* function to be called by core code */
 int gprs_cipher_run(uint8_t *out, uint16_t len, enum gprs_ciph_algo algo,
-		    uint64_t kc, uint32_t iv, enum gprs_cipher_direction dir)
+		    uint8_t *kc, uint32_t iv, enum gprs_cipher_direction dir)
 {
 	if (algo >= ARRAY_SIZE(selected_ciphers))
 		return -ERANGE;
@@ -73,6 +75,23 @@  int gprs_cipher_run(uint8_t *out, uint16_t len, enum gprs_ciph_algo algo,
 	return selected_ciphers[algo]->run(out, len, kc, iv, dir);
 }
 
+/*! \brief Obtain key lenght for given GPRS cipher
+ *  \param[in] algo Enum representive GPRS cipher
+ *  \returns unsigned integer key length for supported algorithms,
+ *  for GEA0 and unknown ciphers will return 0
+ */
+unsigned gprs_cipher_key_length(enum gprs_ciph_algo algo)
+{
+	switch (algo) {
+	case GPRS_ALGO_GEA0: return 0;
+	case GPRS_ALGO_GEA1:
+	case GPRS_ALGO_GEA2:
+	case GPRS_ALGO_GEA3: return 8;
+	case GPRS_ALGO_GEA4: return 16;
+	default: return 0;
+	}
+}
+
 int gprs_cipher_supported(enum gprs_ciph_algo algo)
 {
 	if (algo >= ARRAY_SIZE(selected_ciphers))
diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map
index cab4fc4..7808be6 100644
--- a/src/gsm/libosmogsm.map
+++ b/src/gsm/libosmogsm.map
@@ -32,6 +32,7 @@  gprs_cipher_load;
 gprs_cipher_register;
 gprs_cipher_run;
 gprs_cipher_supported;
+gprs_cipher_key_length;
 gprs_tlli_type;
 gprs_tmsi2tlli;