diff options
author | Neels Hofmeyr <neels@hofmeyr.de> | 2021-06-10 00:48:15 +0200 |
---|---|---|
committer | Neels Hofmeyr <neels@hofmeyr.de> | 2021-06-21 00:36:46 +0200 |
commit | 4a9756c17ab16180c451296b66a8da9c0dfc6a35 (patch) | |
tree | 7898fd10edaf6ab2fc08c066b0bc5ca1d9e0f6ea | |
parent | vty: make function cmd_range_match() public (diff) | |
download | libosmocore-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.h | 20 | ||||
-rw-r--r-- | include/osmocom/gsm/gsm0808_utils.h | 2 | ||||
-rw-r--r-- | src/gsm/gsm0808.c | 34 | ||||
-rw-r--r-- | src/gsm/gsm0808_utils.c | 24 | ||||
-rw-r--r-- | src/gsm/libosmogsm.map | 3 |
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; |