<p>Hoernchen has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-msc/+/24633">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">[WIP] a5/4 support<br><br>Change-Id: I1b3136f0b2728013677b62647c033aade2933299<br>Related: SYS#5324<br>---<br>M include/osmocom/msc/msc_common.h<br>M include/osmocom/msc/ran_msg.h<br>M src/libmsc/msc_ho.c<br>M src/libmsc/ran_msg_a.c<br>4 files changed, 61 insertions(+), 7 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-msc refs/changes/33/24633/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/msc/msc_common.h b/include/osmocom/msc/msc_common.h</span><br><span>index 8a43e69..20f5d15 100644</span><br><span>--- a/include/osmocom/msc/msc_common.h</span><br><span>+++ b/include/osmocom/msc/msc_common.h</span><br><span>@@ -32,6 +32,7 @@</span><br><span>    uint8_t alg_id;</span><br><span>      uint8_t key_len;</span><br><span>     uint8_t key[MAX_A5_KEY_LEN];</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t kc128[MAX_A5_KEY_LEN];</span><br><span> };</span><br><span> </span><br><span> enum complete_layer3_type {</span><br><span>diff --git a/include/osmocom/msc/ran_msg.h b/include/osmocom/msc/ran_msg.h</span><br><span>index 1303ba3..772d1ec 100644</span><br><span>--- a/include/osmocom/msc/ran_msg.h</span><br><span>+++ b/include/osmocom/msc/ran_msg.h</span><br><span>@@ -118,6 +118,7 @@</span><br><span>                * alg_id == 1 means A5/0 i.e. no encryption, alg_id == 4 means A5/3.</span><br><span>                 * alg_id == 0 means no such IE was present. */</span><br><span>              struct geran_encr *chosen_encryption;</span><br><span style="color: hsl(120, 100%, 40%);">+         bool umts_aka;</span><br><span>       } geran;</span><br><span>     struct gsm0808_cell_id cell_id_serving;</span><br><span>      struct gsm0808_cell_id cell_id_target;</span><br><span>diff --git a/src/libmsc/msc_ho.c b/src/libmsc/msc_ho.c</span><br><span>index d89a24c..7a8db3f 100644</span><br><span>--- a/src/libmsc/msc_ho.c</span><br><span>+++ b/src/libmsc/msc_ho.c</span><br><span>@@ -392,6 +392,7 @@</span><br><span>                        .geran = {</span><br><span>                           .chosen_encryption = &msc_a->geran_encr,</span><br><span>                              .a5_encryption_mask = net->a5_encryption_mask,</span><br><span style="color: hsl(120, 100%, 40%);">+                             .umts_aka = vsub->sec_ctx == VLR_SEC_CTX_UMTS  ? true : false,</span><br><span>                    },</span><br><span>                   .bssap_cause = GSM0808_CAUSE_BETTER_CELL,</span><br><span>                    .current_channel_type_1_present = msc_a->ho.info.current_channel_type_1_present,</span><br><span>diff --git a/src/libmsc/ran_msg_a.c b/src/libmsc/ran_msg_a.c</span><br><span>index 4cce289..477e5d9 100644</span><br><span>--- a/src/libmsc/ran_msg_a.c</span><br><span>+++ b/src/libmsc/ran_msg_a.c</span><br><span>@@ -25,6 +25,7 @@</span><br><span> #include <osmocom/core/byteswap.h></span><br><span> </span><br><span> #include <osmocom/crypt/auth.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/crypt/kdf.h></span><br><span> </span><br><span> #include <osmocom/gsm/tlv.h></span><br><span> #include <osmocom/gsm/gsm0808.h></span><br><span>@@ -482,6 +483,7 @@</span><br><span>        const struct tlv_p_entry *ie_aoip_transp_addr = TLVP_GET(tp, GSM0808_IE_AOIP_TRASP_ADDR);</span><br><span>    const struct tlv_p_entry *ie_codec_list_msc_preferred = TLVP_GET(tp, GSM0808_IE_SPEECH_CODEC_LIST);</span><br><span>  const struct tlv_p_entry *ie_call_id = TLVP_GET(tp, GSM0808_IE_CALL_ID);</span><br><span style="color: hsl(120, 100%, 40%);">+      const struct tlv_p_entry *ie_kc128 = TLVP_GET(tp, GSM0808_IE_KC_128);</span><br><span>        const struct tlv_p_entry *ie_global_call_ref = TLVP_GET(tp, GSM0808_IE_GLOBAL_CALL_REF);</span><br><span> </span><br><span>         struct gsm0808_channel_type channel_type;</span><br><span>@@ -524,6 +526,16 @@</span><br><span>                     geran_encr.key_len = encr_info.key_len;</span><br><span>              }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+         if(r->geran.a5_encryption_mask & (1 << 4)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     if (ie_kc128) {</span><br><span style="color: hsl(120, 100%, 40%);">+                               memcpy(geran_encr.kc128, ie_kc128->val, 16);</span><br><span style="color: hsl(120, 100%, 40%);">+                       } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                              LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Failed to decode Encryption Information IE:"</span><br><span style="color: hsl(120, 100%, 40%);">+                                   " A5/4 supported, but missing kc128 IE!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                              return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+                       }</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>          r->geran.chosen_encryption = &geran_encr;</span><br><span>     }</span><br><span> </span><br><span>@@ -1019,13 +1031,16 @@</span><br><span>      case 3:</span><br><span>              *dst = GSM0808_ALG_ID_A5_3;</span><br><span>          return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     case 4:</span><br><span style="color: hsl(120, 100%, 40%);">+               *dst = GSM0808_ALG_ID_A5_4;</span><br><span style="color: hsl(120, 100%, 40%);">+           return 0;</span><br><span>    default:</span><br><span>             return -ENOTSUP;</span><br><span>     }</span><br><span> }</span><br><span> </span><br><span> static int make_encrypt_info_perm_algo(struct osmo_fsm_inst *fi, struct gsm0808_encrypt_info *ei,</span><br><span style="color: hsl(0, 100%, 40%);">-                                uint8_t a5_encryption_mask, const struct osmo_gsm48_classmark *cm)</span><br><span style="color: hsl(120, 100%, 40%);">+                                        uint8_t a5_encryption_mask, const struct osmo_gsm48_classmark *cm, bool umts_aka)</span><br><span> {</span><br><span>    int i;</span><br><span>       int j = 0;</span><br><span>@@ -1036,6 +1051,10 @@</span><br><span>          if (!(a5_encryption_mask & (1 << i)))</span><br><span>                      continue;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+         /* no a5/4 without umts aka */</span><br><span style="color: hsl(120, 100%, 40%);">+                if(i > 3 && !umts_aka)</span><br><span style="color: hsl(120, 100%, 40%);">+                     continue;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>          /* A5/n supported by MS? */</span><br><span>          supported = osmo_gsm48_classmark_supports_a5(cm, i);</span><br><span>                 if (supported != 1)</span><br><span>@@ -1056,13 +1075,17 @@</span><br><span>  */</span><br><span> osmo_static_assert(sizeof(((struct gsm0808_encrypt_info*)0)->key) >= sizeof(((struct osmo_auth_vector*)0)->kc),</span><br><span>                gsm0808_encrypt_info_key_fits_osmo_auth_vec_kc);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static struct msgb *ran_a_make_cipher_mode_command(struct osmo_fsm_inst *fi, const struct ran_cipher_mode_command *cm)</span><br><span> {</span><br><span>         struct gsm0808_encrypt_info ei = {};</span><br><span>         char buf[16 * 2 + 1];</span><br><span>        const uint8_t cipher_response_mode = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+       uint8_t kc128[16];</span><br><span style="color: hsl(120, 100%, 40%);">+    bool has_a54 = false;</span><br><span style="color: hsl(120, 100%, 40%);">+ int i;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      if (make_encrypt_info_perm_algo(fi, &ei, cm->geran.a5_encryption_mask, cm->classmark))</span><br><span style="color: hsl(120, 100%, 40%);">+      if (make_encrypt_info_perm_algo(fi, &ei, cm->geran.a5_encryption_mask, cm->classmark, cm->geran.umts_aka))</span><br><span>              return NULL;</span><br><span> </span><br><span>     if (ei.perm_algo_len == 0) {</span><br><span>@@ -1072,13 +1095,23 @@</span><br><span>               return NULL;</span><br><span>         }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ for( i= 0; i < ei.perm_algo_len; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+            has_a54 = ei.perm_algo[i] == GSM0808_ALG_ID_A5_4;</span><br><span style="color: hsl(120, 100%, 40%);">+             if (has_a54)</span><br><span style="color: hsl(120, 100%, 40%);">+                  break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  /* In case of UMTS AKA, the Kc for ciphering must be derived from the 3G auth</span><br><span>         * tokens.  vec->kc was calculated from the GSM algorithm and is not</span><br><span>       * necessarily a match for the UMTS AKA tokens. */</span><br><span style="color: hsl(0, 100%, 40%);">-      if (cm->geran.umts_aka)</span><br><span style="color: hsl(120, 100%, 40%);">+    if (cm->geran.umts_aka) {</span><br><span>                 osmo_auth_c3(ei.key, cm->vec->ck, cm->vec->ik);</span><br><span style="color: hsl(0, 100%, 40%);">-     else</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                /* unconditionally derive key if aka, due to HO req */</span><br><span style="color: hsl(120, 100%, 40%);">+                osmo_kdf_kc128(cm->vec->ck, cm->vec->ik, kc128);</span><br><span style="color: hsl(120, 100%, 40%);">+  } else {</span><br><span>             memcpy(ei.key, cm->vec->kc, sizeof(cm->vec->kc));</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span>    ei.key_len = sizeof(cm->vec->kc);</span><br><span> </span><br><span>  /* Store chosen GERAN key where the caller asked it to be stored.</span><br><span>@@ -1090,12 +1123,16 @@</span><br><span>          }</span><br><span>            memcpy(cm->geran.chosen_key->key, ei.key, ei.key_len);</span><br><span>                 cm->geran.chosen_key->key_len = ei.key_len;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           if (cm->geran.umts_aka)</span><br><span style="color: hsl(120, 100%, 40%);">+                    memcpy(cm->geran.chosen_key->kc128, kc128, 16);</span><br><span>        }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>      LOG_RAN_A_ENC(fi, LOGL_DEBUG, "Tx BSSMAP CIPHER MODE COMMAND to BSC, %u ciphers (%s) key %s\n",</span><br><span>                   ei.perm_algo_len, osmo_hexdump_nospc(ei.perm_algo, ei.perm_algo_len),</span><br><span>                        osmo_hexdump_buf(buf, sizeof(buf), ei.key, ei.key_len, NULL, false));</span><br><span style="color: hsl(0, 100%, 40%);">-    return gsm0808_create_cipher(&ei, cm->geran.retrieve_imeisv ? &cipher_response_mode : NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+       return gsm0808_create_cipher(&ei, has_a54 ? kc128 : NULL, cm->geran.retrieve_imeisv ? &cipher_response_mode : NULL);</span><br><span> }</span><br><span> </span><br><span> struct msgb *ran_a_make_handover_request(struct osmo_fsm_inst *log_fi, const struct ran_handover_request *n)</span><br><span>@@ -1120,6 +1157,9 @@</span><br><span>             .global_call_reference = n->global_call_reference,</span><br><span>                .global_call_reference_len = n->global_call_reference_len,</span><br><span>        };</span><br><span style="color: hsl(120, 100%, 40%);">+    bool has_a54_in_set = false;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t kc128[16];</span><br><span style="color: hsl(120, 100%, 40%);">+    int i;</span><br><span> </span><br><span>   if (!n->geran.channel_type) {</span><br><span>             LOG_RAN_A_ENC(log_fi, LOGL_ERROR, "Channel Type required for encoding Handover Request in BSSAP\n");</span><br><span>@@ -1128,7 +1168,15 @@</span><br><span>      r.channel_type = *n->geran.channel_type;</span><br><span> </span><br><span>      /* Encryption Information */</span><br><span style="color: hsl(0, 100%, 40%);">-    make_encrypt_info_perm_algo(log_fi, &r.encryption_information, n->geran.a5_encryption_mask, n->classmark);</span><br><span style="color: hsl(120, 100%, 40%);">+  make_encrypt_info_perm_algo(log_fi, &r.encryption_information, n->geran.a5_encryption_mask, n->classmark, n->geran.umts_aka);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* kc128 is only included if intersection offers a5/4 */</span><br><span style="color: hsl(120, 100%, 40%);">+      for( i= 0; i < r.encryption_information.perm_algo_len; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+              has_a54_in_set = r.encryption_information.perm_algo[i] == GSM0808_ALG_ID_A5_4;</span><br><span style="color: hsl(120, 100%, 40%);">+                if (has_a54_in_set)</span><br><span style="color: hsl(120, 100%, 40%);">+                   break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  if (n->geran.chosen_encryption && n->geran.chosen_encryption->key_len) {</span><br><span>            /* Prevent both source / destination buffer overrun / overflow */</span><br><span>            if (n->geran.chosen_encryption->key_len > sizeof(r.encryption_information.key)</span><br><span>@@ -1141,6 +1189,9 @@</span><br><span>                     n->geran.chosen_encryption->key, n->geran.chosen_encryption->key_len);</span><br><span>            r.encryption_information.key_len = n->geran.chosen_encryption->key_len;</span><br><span>                r.chosen_encryption_algorithm_serving = n->geran.chosen_encryption->alg_id;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (has_a54_in_set)</span><br><span style="color: hsl(120, 100%, 40%);">+            memcpy(kc128, n->geran.chosen_encryption->kc128, 16);</span><br><span>    }</span><br><span> </span><br><span>        if (n->classmark)</span><br><span>@@ -1156,7 +1207,7 @@</span><br><span>                 r.aoip_transport_layer = &ss;</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   return gsm0808_create_handover_request(&r);</span><br><span style="color: hsl(120, 100%, 40%);">+       return gsm0808_create_handover_request(&r, has_a54_in_set ? kc128 : NULL);</span><br><span> }</span><br><span> </span><br><span> static struct msgb *ran_a_make_handover_request_ack(struct osmo_fsm_inst *caller_fi, const struct ran_handover_request_ack *r)</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-msc/+/24633">change 24633</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/osmo-msc/+/24633"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-msc </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I1b3136f0b2728013677b62647c033aade2933299 </div>
<div style="display:none"> Gerrit-Change-Number: 24633 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Hoernchen <ewild@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>