aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeels Hofmeyr <neels@hofmeyr.de>2021-06-10 00:48:15 +0200
committerNeels Hofmeyr <neels@hofmeyr.de>2021-06-21 00:36:46 +0200
commit4a9756c17ab16180c451296b66a8da9c0dfc6a35 (patch)
tree7898fd10edaf6ab2fc08c066b0bc5ca1d9e0f6ea
parentvty: make function cmd_range_match() public (diff)
downloadlibosmocore-4a9756c17ab16180c451296b66a8da9c0dfc6a35.tar.xz
libosmocore-4a9756c17ab16180c451296b66a8da9c0dfc6a35.zip
add Kc128 to gsm0808 Create Ciphering Command
Prepare for A5/4 support in osmo-msc. Add new function gsm0808_create_cipher2() which takes a struct as argument instead of individual fields. This is akin to e.g. gsm0808_create_handover_request() below in the file, and allows backwards compatibly extending the argument list without needing a new function signature every time. Add struct gsm0808_cipher_mode_command, as argument list for gsm0808_create_cipher2(), with kc128 included. Encode the Kc128 IE in gsm0808_create_cipher2(). Implement gsm0808_create_cipher() by calling gsm0808_create_cipher2(). Change-Id: Ib3906085e0c6e5a496a9f755f0f786238a86ca34
-rw-r--r--include/osmocom/gsm/gsm0808.h20
-rw-r--r--include/osmocom/gsm/gsm0808_utils.h2
-rw-r--r--src/gsm/gsm0808.c34
-rw-r--r--src/gsm/gsm0808_utils.c24
-rw-r--r--src/gsm/libosmogsm.map3
5 files changed, 73 insertions, 10 deletions
diff --git a/include/osmocom/gsm/gsm0808.h b/include/osmocom/gsm/gsm0808.h
index dc3610fd..3e394601 100644
--- a/include/osmocom/gsm/gsm0808.h
+++ b/include/osmocom/gsm/gsm0808.h
@@ -54,6 +54,26 @@ struct msgb *gsm0808_create_clear_command2(uint8_t cause, bool csfb_ind);
struct msgb *gsm0808_create_clear_complete(void);
struct msgb *gsm0808_create_cipher(const struct gsm0808_encrypt_info *ei,
const uint8_t *cipher_response_mode);
+
+struct gsm0808_cipher_mode_command {
+ struct gsm0808_encrypt_info ei;
+
+ /*! 3GPP TS 48.008 3.2.2.34 Cipher Response Mode, optional IE */
+ bool cipher_response_mode_present;
+ /*! 3GPP TS 48.008 3.2.2.34 Cipher Response Mode:
+ * 0 - IMEISV must not be included by the Mobile Station;
+ * 1 - IMEISV must be included by the Mobile Station.
+ */
+ uint8_t cipher_response_mode;
+
+ bool kc128_present;
+ uint8_t kc128[16];
+
+ /* more items are defined in the spec and may be added later */
+ bool more_items; /*< always set this to false */
+};
+struct msgb *gsm0808_create_cipher2(const struct gsm0808_cipher_mode_command *cmc);
+
struct msgb *gsm0808_create_cipher_complete(struct msgb *layer3, uint8_t alg_id);
struct msgb *gsm0808_create_cipher_reject(enum gsm0808_cause cause);
struct msgb *gsm0808_create_cipher_reject_ext(enum gsm0808_cause_class class, uint8_t ext);
diff --git a/include/osmocom/gsm/gsm0808_utils.h b/include/osmocom/gsm/gsm0808_utils.h
index 76e90645..60e665bb 100644
--- a/include/osmocom/gsm/gsm0808_utils.h
+++ b/include/osmocom/gsm/gsm0808_utils.h
@@ -125,6 +125,8 @@ uint8_t gsm0808_enc_encrypt_info(struct msgb *msg,
const struct gsm0808_encrypt_info *ei);
int gsm0808_dec_encrypt_info(struct gsm0808_encrypt_info *ei,
const uint8_t *elem, uint8_t len);
+int gsm0808_enc_kc128(struct msgb *msg, const uint8_t *kc128);
+int gsm0808_dec_kc128(uint8_t *kc128, const uint8_t *elem, uint8_t len);
uint8_t gsm0808_enc_cell_id_list2(struct msgb *msg, const struct gsm0808_cell_id_list2 *cil);
uint8_t gsm0808_enc_cell_id_list(struct msgb *msg,
const struct gsm0808_cell_id_list *cil)
diff --git a/src/gsm/gsm0808.c b/src/gsm/gsm0808.c
index 3a39fd14..4f072f73 100644
--- a/src/gsm/gsm0808.c
+++ b/src/gsm/gsm0808.c
@@ -228,22 +228,32 @@ struct msgb *gsm0808_create_clear_command2(uint8_t cause, bool csfb_ind)
return msg;
}
-/*! Create BSSMAP Cipher Mode Command message
+/*! Superseded by gsm0808_create_cipher2() to include Kc128.
+ * Create BSSMAP Cipher Mode Command message (without Kc128).
* \param[in] ei Mandatory Encryption Information
+ * \param[in] kc128 optional kc128 key for A5/4
* \param[in] cipher_response_mode optional 1-byte Cipher Response Mode
* \returns callee-allocated msgb with BSSMAP Cipher Mode Command message */
struct msgb *gsm0808_create_cipher(const struct gsm0808_encrypt_info *ei,
const uint8_t *cipher_response_mode)
{
+ struct gsm0808_cipher_mode_command cmc = {
+ .ei = *ei,
+ .cipher_response_mode_present = (cipher_response_mode != NULL),
+ .cipher_response_mode = (cipher_response_mode ? *cipher_response_mode : 0),
+ };
+ return gsm0808_create_cipher2(&cmc);
+}
+
+/*! Create BSSMAP Cipher Mode Command message.
+ * \param[in] cmc Information to encode.
+ * \returns callee-allocated msgb with BSSMAP Cipher Mode Command message */
+struct msgb *gsm0808_create_cipher2(const struct gsm0808_cipher_mode_command *cmc)
+{
/* See also: 3GPP TS 48.008 3.2.1.30 CIPHER MODE COMMAND */
struct msgb *msg;
- /* Mandatory emelent! */
- OSMO_ASSERT(ei);
-
- msg =
- msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
- "cipher-mode-command");
+ msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "cipher-mode-command");
if (!msg)
return NULL;
@@ -251,12 +261,16 @@ struct msgb *gsm0808_create_cipher(const struct gsm0808_encrypt_info *ei,
msgb_v_put(msg, BSS_MAP_MSG_CIPHER_MODE_CMD);
/* Encryption Information 3.2.2.10 */
- gsm0808_enc_encrypt_info(msg, ei);
+ gsm0808_enc_encrypt_info(msg, &cmc->ei);
/* Cipher Response Mode 3.2.2.34 */
- if (cipher_response_mode)
+ if (cmc->cipher_response_mode_present)
msgb_tv_put(msg, GSM0808_IE_CIPHER_RESPONSE_MODE,
- *cipher_response_mode);
+ cmc->cipher_response_mode);
+
+ /* Kc128 3.2.2.109 */
+ if (cmc->kc128_present)
+ gsm0808_enc_kc128(msg, cmc->kc128);
/* pre-pend the header */
msg->l3h =
diff --git a/src/gsm/gsm0808_utils.c b/src/gsm/gsm0808_utils.c
index 94c9a796..b5b8431f 100644
--- a/src/gsm/gsm0808_utils.c
+++ b/src/gsm/gsm0808_utils.c
@@ -767,6 +767,30 @@ int gsm0808_dec_encrypt_info(struct gsm0808_encrypt_info *ei,
return (int)(elem - old_elem);
}
+/*! Encode TS 48.008 Kc128 IE.
+ * \param[out] msg Message Buffer to which IE is to be appended.
+ * \param[in] kc128 Pointer to 16 bytes of Kc128 key data.
+ * \returns number of bytes appended to msg */
+int gsm0808_enc_kc128(struct msgb *msg, const uint8_t *kc128)
+{
+ uint8_t *start = msg->tail;
+ msgb_tv_fixed_put(msg, GSM0808_IE_KC_128, 16, kc128);
+ return msg->tail - start;
+}
+
+/*! Decode TS 48.008 Kc128 IE.
+ * \param[out] kc128 Target buffer for received Kc128 key, 16 bytes long.
+ * \param[in] elem IE value to be decoded (without IE discriminator).
+ * \param[in] len Length of elem in bytes.
+ * \returns number of bytes parsed; negative on error */
+int gsm0808_dec_kc128(uint8_t *kc128, const uint8_t *elem, uint8_t len)
+{
+ if (len != 16)
+ return -EINVAL;
+ memcpy(kc128, elem, 16);
+ return len;
+}
+
/* Store individual Cell Identifier information in a CGI, without clearing the remaining ones.
* This is useful to supplement one CGI with information from more than one Cell Identifier,
* which in turn is useful to match Cell Identifiers of differing kinds to each other.
diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map
index 437599be..475ec02a 100644
--- a/src/gsm/libosmogsm.map
+++ b/src/gsm/libosmogsm.map
@@ -170,6 +170,7 @@ gsm0808_create_ass_compl2;
gsm0808_create_assignment_failure;
gsm0808_create_ass_fail;
gsm0808_create_cipher;
+gsm0808_create_cipher2;
gsm0808_create_cipher_complete;
gsm0808_create_cipher_reject;
gsm0808_create_cipher_reject_ext;
@@ -218,6 +219,8 @@ gsm0808_enc_channel_type;
gsm0808_dec_channel_type;
gsm0808_enc_encrypt_info;
gsm0808_dec_encrypt_info;
+gsm0808_enc_kc128;
+gsm0808_dec_kc128;
gsm0808_enc_cell_id_list;
gsm0808_enc_cell_id_list2;
gsm0808_dec_cell_id_list;