--- include/osmocom/crypt/gprs_cipher.h | 8 ++++++-- src/gsm/gprs_cipher_core.c | 20 +++++++++++++++++--- src/gsm/libosmogsm.map | 1 + 3 files changed, 24 insertions(+), 5 deletions(-)
diff --git a/include/osmocom/crypt/gprs_cipher.h b/include/osmocom/crypt/gprs_cipher.h index 3051071..b6b8e93 100644 --- a/include/osmocom/crypt/gprs_cipher.h +++ b/include/osmocom/crypt/gprs_cipher.h @@ -10,6 +10,7 @@ enum gprs_ciph_algo { GPRS_ALGO_GEA1, GPRS_ALGO_GEA2, GPRS_ALGO_GEA3, + GPRS_ALGO_GEA4, _GPRS_ALGO_NUM };
@@ -28,7 +29,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); };
@@ -40,11 +41,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..450272b 100644 --- a/src/gsm/gprs_cipher_core.c +++ b/src/gsm/gprs_cipher_core.c @@ -26,8 +26,8 @@ #include <osmocom/core/utils.h> #include <osmocom/core/linuxlist.h> #include <osmocom/core/plugin.h> - #include <osmocom/crypt/gprs_cipher.h> +#include <osmocom/gsm/gea.h>
static LLIST_HEAD(gprs_ciphers);
@@ -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,18 @@ 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); }
+unsigned gprs_cipher_key_length(enum gprs_ciph_algo algo) +{ + switch (algo) { + case GPRS_ALGO_GEA0: return 0; + case GPRS_ALGO_GEA1: return 8; + case GPRS_ALGO_GEA2: return 8; + 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 3a4a643..3beb1e9 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -31,6 +31,7 @@ gprs_cipher_load; gprs_cipher_register; gprs_cipher_run; gprs_cipher_supported; +gprs_cipher_key_length; gprs_tlli_type; gprs_tmsi2tlli;
I've just realized that this patch missing explicit comment.
Old API assumed that GPRS key length is always 64 bit - ETSI TS 155.22 proves this assumption wrong. Thit patch removes this assumption. It also makes GPRS cipher API to match the style of GSM cipher API which does not make any assumptions on the key length.
cheers, Max.
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(-)
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;
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 :)
baseband-devel@lists.osmocom.org