<p>laforge <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/15202">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  pespin: Looks good to me, approved
  Jenkins Builder: Verified

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">TTCN-3 native function wrapper for SNOW-3G<br><br>Change-Id: I7fca69ea8b4aed48d5a64885b762ab85be71ef03<br>---<br>A mme/LTE_CryptoFunctionDefs.cc<br>A mme/LTE_CryptoFunctions.ttcn<br>A mme/key_derivation.c<br>A mme/key_derivation.h<br>M mme/regen_makefile.sh<br>5 files changed, 557 insertions(+), 2 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/mme/LTE_CryptoFunctionDefs.cc b/mme/LTE_CryptoFunctionDefs.cc</span><br><span>new file mode 100644</span><br><span>index 0000000..da2d521</span><br><span>--- /dev/null</span><br><span>+++ b/mme/LTE_CryptoFunctionDefs.cc</span><br><span>@@ -0,0 +1,189 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* Utility functions from ogslib imported to TTCN-3</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2019 Harald Welte <laforge@gnumonks.org></span><br><span style="color: hsl(120, 100%, 40%);">+ * All rights reserved.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Released under the terms of GNU General Public License, Version 2 or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * SPDX-License-Identifier: GPL-2.0-or-later</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%);">+#include <stdio.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <errno.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <Boolean.hh></span><br><span style="color: hsl(120, 100%, 40%);">+#include <Integer.hh></span><br><span style="color: hsl(120, 100%, 40%);">+#include <Octetstring.hh></span><br><span style="color: hsl(120, 100%, 40%);">+#include <Bitstring.hh></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "snow-3g.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "key_derivation.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+//#define DEBUG</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef DEBUG</span><br><span style="color: hsl(120, 100%, 40%);">+static __thread char hexd_buff[4096];</span><br><span style="color: hsl(120, 100%, 40%);">+static const char hex_chars[] = "0123456789abcdef";</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const char *_osmo_hexdump_buf(char *out_buf, size_t out_buf_size, const unsigned char *buf, int len, const char *delim,</span><br><span style="color: hsl(120, 100%, 40%);">+                             bool delim_after_last)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        int i;</span><br><span style="color: hsl(120, 100%, 40%);">+        char *cur = out_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+  size_t delim_len;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!out_buf || !out_buf_size)</span><br><span style="color: hsl(120, 100%, 40%);">+                return "";</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        delim = delim ? : "";</span><br><span style="color: hsl(120, 100%, 40%);">+       delim_len = strlen(delim);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  for (i = 0; i < len; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                const char *delimp = delim;</span><br><span style="color: hsl(120, 100%, 40%);">+           int len_remain = out_buf_size - (cur - out_buf) - 1;</span><br><span style="color: hsl(120, 100%, 40%);">+          if (len_remain < (2 + delim_len)</span><br><span style="color: hsl(120, 100%, 40%);">+               && !(!delim_after_last && i == (len - 1) && len_remain >= 2))</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%);">+              *cur++ = hex_chars[buf[i] >> 4];</span><br><span style="color: hsl(120, 100%, 40%);">+                *cur++ = hex_chars[buf[i] & 0xf];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               if (i == (len - 1) && !delim_after_last)</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%);">+              while (len_remain > 1 && *delimp) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        *cur++ = *delimp++;</span><br><span style="color: hsl(120, 100%, 40%);">+                   len_remain--;</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%);">+     *cur = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+  return out_buf;</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%);">+static char *_osmo_hexdump(const unsigned char *buf, int len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        _osmo_hexdump_buf(hexd_buff, sizeof(hexd_buff), buf, len, "", true);</span><br><span style="color: hsl(120, 100%, 40%);">+        return hexd_buff;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+namespace LTE__CryptoFunctions {</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%);">+/* f8.</span><br><span style="color: hsl(120, 100%, 40%);">+* Input key: 128 bit Confidentiality Key as OCT16.</span><br><span style="color: hsl(120, 100%, 40%);">+* Input count:32-bit Count, Frame dependent input as INTEGER.</span><br><span style="color: hsl(120, 100%, 40%);">+* Input bearer: 5-bit Bearer identity (in the LSB side) as BIT5.</span><br><span style="color: hsl(120, 100%, 40%);">+* Input is_dlwnlink: Direction of transmission.</span><br><span style="color: hsl(120, 100%, 40%);">+* Input data: length number of bits, input bit stream as OCTETSTRING.</span><br><span style="color: hsl(120, 100%, 40%);">+* Output data: Output bit stream. Assumes data is suitably memory</span><br><span style="color: hsl(120, 100%, 40%);">+* allocated.</span><br><span style="color: hsl(120, 100%, 40%);">+* Encrypts/decrypts blocks of data between 1 and 2^32 bits in length as</span><br><span style="color: hsl(120, 100%, 40%);">+* defined in Section 3.</span><br><span style="color: hsl(120, 100%, 40%);">+*/</span><br><span style="color: hsl(120, 100%, 40%);">+OCTETSTRING f__snow__3g__f8(const OCTETSTRING& key, const INTEGER& count, const INTEGER & bearer,</span><br><span style="color: hsl(120, 100%, 40%);">+                           const BOOLEAN& is_downlink, const OCTETSTRING& data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   TTCN_Buffer ttcn_buf_data(data);</span><br><span style="color: hsl(120, 100%, 40%);">+      TTCN_Buffer ttcn_buf_key(key);</span><br><span style="color: hsl(120, 100%, 40%);">+        uint32_t direction = (uint32_t)is_downlink;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ snow_3g_f8((u8 *)ttcn_buf_key.get_data(), (u32) count, (u32)bearer, direction,</span><br><span style="color: hsl(120, 100%, 40%);">+                   (u8 *)ttcn_buf_data.get_data(), ttcn_buf_data.get_len());</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        return OCTETSTRING(ttcn_buf_data.get_len(), ttcn_buf_data.get_data());</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%);">+/* f9.</span><br><span style="color: hsl(120, 100%, 40%);">+* Input key: 128 bit Integrity Key as OCT16.</span><br><span style="color: hsl(120, 100%, 40%);">+* Input count:32-bit Count, Frame dependent input as UINT32.</span><br><span style="color: hsl(120, 100%, 40%);">+* Input fresh: 32-bit Random number as UINT32.</span><br><span style="color: hsl(120, 100%, 40%);">+* Input is_downlink:1 Direction of transmission.</span><br><span style="color: hsl(120, 100%, 40%);">+* Input data: input bit stream.</span><br><span style="color: hsl(120, 100%, 40%);">+* Output : 32 bit block used as MAC</span><br><span style="color: hsl(120, 100%, 40%);">+* Generates 32-bit MAC using UIA2 algorithm as defined in Section 4.</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%);">+OCTETSTRING f__snow__3g__f9(const OCTETSTRING& key, const INTEGER& count, const INTEGER& fresh,</span><br><span style="color: hsl(120, 100%, 40%);">+                          const BOOLEAN& is_downlink, const OCTETSTRING& data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   TTCN_Buffer ttcn_buf_data(data);</span><br><span style="color: hsl(120, 100%, 40%);">+      TTCN_Buffer ttcn_buf_key(key);</span><br><span style="color: hsl(120, 100%, 40%);">+        uint32_t direction = (uint32_t)is_downlink;</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t tmp[4];</span><br><span style="color: hsl(120, 100%, 40%);">+       TTCN_Buffer ttcn_buf_mac;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef DEBUG</span><br><span style="color: hsl(120, 100%, 40%);">+     printf("F9: key=%s, count=%u, fresh=%u, direction=%u, ",</span><br><span style="color: hsl(120, 100%, 40%);">+            _osmo_hexdump((u8 *)ttcn_buf_key.get_data(), ttcn_buf_key.get_len()), (u32) count,</span><br><span style="color: hsl(120, 100%, 40%);">+            (u32) fresh, direction);</span><br><span style="color: hsl(120, 100%, 40%);">+      printf("data=%s -> ", _osmo_hexdump(ttcn_buf_data.get_data(), ttcn_buf_data.get_len()));</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+ snow_3g_f9((u8 *)ttcn_buf_key.get_data(), (u32) count, (u32) fresh, direction,</span><br><span style="color: hsl(120, 100%, 40%);">+                   (u8 *)ttcn_buf_data.get_data(), ttcn_buf_data.get_len()*8, tmp);</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef DEBUG</span><br><span style="color: hsl(120, 100%, 40%);">+     printf("%s\n", _osmo_hexdump(tmp, sizeof(tmp)));</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return OCTETSTRING(4, tmp);</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%);">+OCTETSTRING f__kdf__kasme(const OCTETSTRING& ck, const OCTETSTRING& ik, const OCTETSTRING& plmn_id,</span><br><span style="color: hsl(120, 100%, 40%);">+                       const OCTETSTRING& sqn, const OCTETSTRING& ak)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   TTCN_Buffer ttcn_buf_ck(ck);</span><br><span style="color: hsl(120, 100%, 40%);">+  TTCN_Buffer ttcn_buf_ik(ik);</span><br><span style="color: hsl(120, 100%, 40%);">+  TTCN_Buffer ttcn_buf_plmn_id(plmn_id);</span><br><span style="color: hsl(120, 100%, 40%);">+        TTCN_Buffer ttcn_buf_sqn(sqn);</span><br><span style="color: hsl(120, 100%, 40%);">+        TTCN_Buffer ttcn_buf_ak(ak);</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t kasme[32];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  hss_auc_kasme(ttcn_buf_ck.get_data(), ttcn_buf_ik.get_data(), ttcn_buf_plmn_id.get_data(),</span><br><span style="color: hsl(120, 100%, 40%);">+                    ttcn_buf_sqn.get_data(), ttcn_buf_ak.get_data(), kasme);</span><br><span style="color: hsl(120, 100%, 40%);">+      return OCTETSTRING(sizeof(kasme), kasme);</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%);">+OCTETSTRING f__kdf__nas__int(const INTEGER& alg_id, const OCTETSTRING &kasme)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      TTCN_Buffer ttcn_buf_kasme(kasme);</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t knas[16];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   mme_kdf_nas(MME_KDF_NAS_INT_ALG, (int)alg_id, (const u8*) ttcn_buf_kasme.get_data(), knas);</span><br><span style="color: hsl(120, 100%, 40%);">+   return OCTETSTRING(sizeof(knas), knas);</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%);">+OCTETSTRING f__kdf__nas__enc(const INTEGER& alg_id, const OCTETSTRING &kasme)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        TTCN_Buffer ttcn_buf_kasme(kasme);</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t knas[16];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   mme_kdf_nas(MME_KDF_NAS_ENC_ALG, (int)alg_id, (const u8*) ttcn_buf_kasme.get_data(), knas);</span><br><span style="color: hsl(120, 100%, 40%);">+   return OCTETSTRING(sizeof(knas), knas);</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 style="color: hsl(120, 100%, 40%);">+OCTETSTRING f__kdf__enb(const OCTETSTRING &kasme, const INTEGER &ul_count)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ TTCN_Buffer ttcn_buf_kasme(kasme);</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t kenb[32];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   mme_kdf_enb(ttcn_buf_kasme.get_data(), (int)ul_count, kenb);</span><br><span style="color: hsl(120, 100%, 40%);">+  return OCTETSTRING(sizeof(kenb), kenb);</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%);">+OCTETSTRING f__kdf__nh(const OCTETSTRING &kasme, const OCTETSTRING &sync_inp)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        TTCN_Buffer ttcn_buf_kasme(kasme);</span><br><span style="color: hsl(120, 100%, 40%);">+    TTCN_Buffer ttcn_buf_sync_inp(sync_inp);</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t kenb[32];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   mme_kdf_nh(ttcn_buf_kasme.get_data(), ttcn_buf_sync_inp.get_data(), kenb);</span><br><span style="color: hsl(120, 100%, 40%);">+    return OCTETSTRING(sizeof(kenb), kenb);</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 style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+} // namespace</span><br><span>diff --git a/mme/LTE_CryptoFunctions.ttcn b/mme/LTE_CryptoFunctions.ttcn</span><br><span>new file mode 100644</span><br><span>index 0000000..687caab</span><br><span>--- /dev/null</span><br><span>+++ b/mme/LTE_CryptoFunctions.ttcn</span><br><span>@@ -0,0 +1,263 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* Utility functions from ogslib imported to TTCN-3</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2019 Harald Welte <laforge@gnumonks.org></span><br><span style="color: hsl(120, 100%, 40%);">+ * All rights reserved.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Released under the terms of GNU General Public License, Version 2 or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * SPDX-License-Identifier: GPL-2.0-or-later</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%);">+module LTE_CryptoFunctions {</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+import from General_Types all;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+import from S1AP_Types all;</span><br><span style="color: hsl(120, 100%, 40%);">+import from S1AP_PDU_Descriptions all;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+import from NAS_EPS_Types all;</span><br><span style="color: hsl(120, 100%, 40%);">+import from NAS_Templates all;</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%);">+ * low-level API (external C/C++ code)</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%);">+external function f_snow_3g_f8(in OCT16 key, in integer count, in integer bearer,</span><br><span style="color: hsl(120, 100%, 40%);">+                          in boolean is_downlink, in octetstring data) return octetstring;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+external function f_snow_3g_f9(in OCT16 key, in integer count, in integer fresh,</span><br><span style="color: hsl(120, 100%, 40%);">+                          in boolean is_downlink, in octetstring data) return OCT4;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+external function f_kdf_kasme(in OCT16 ck, in OCT16 ik, in OCT3 plmn_id,</span><br><span style="color: hsl(120, 100%, 40%);">+                       in OCT6 sqn, in OCT6 ak) return OCT32;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+external function f_kdf_nas_int(in integer alg_id, in OCT32 kasme) return OCT32;</span><br><span style="color: hsl(120, 100%, 40%);">+external function f_kdf_nas_enc(in integer alg_id, in OCT32 kasme) return OCT32;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+external function f_kdf_enb(in OCT16 kasme, in integer ul_count) return OCT32;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+external function f_kdf_nh(in OCT16 kasme, in OCT32 sync_inp) return OCT32;</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%);">+ * mid-level API</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%);">+function f_nas_mac_calc(NAS_ALG_INT alg, octetstring k_nas_int, integer seq_nr,</span><br><span style="color: hsl(120, 100%, 40%);">+                           integer bearer, boolean is_downlink, octetstring data) return OCT4 {</span><br><span style="color: hsl(120, 100%, 40%);">+  select (alg) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case (NAS_ALG_IP_EIA0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              return '00000000'O;</span><br><span style="color: hsl(120, 100%, 40%);">+           }</span><br><span style="color: hsl(120, 100%, 40%);">+     case (NAS_ALG_IP_EIA1) {</span><br><span style="color: hsl(120, 100%, 40%);">+              return f_snow_3g_f9(k_nas_int, seq_nr, bearer, is_downlink, data);</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+     case else {</span><br><span style="color: hsl(120, 100%, 40%);">+           setverdict(fail, "Unsupported EIA: ", alg);</span><br><span style="color: hsl(120, 100%, 40%);">+         mtc.stop;</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 style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+function f_nas_encrypt(NAS_ALG_ENC alg, octetstring k_nas_enc, integer count,</span><br><span style="color: hsl(120, 100%, 40%);">+                 integer bearer, boolean is_downlink, inout octetstring data) {</span><br><span style="color: hsl(120, 100%, 40%);">+        select (alg) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case (NAS_ALG_ENC_EEA0) { }</span><br><span style="color: hsl(120, 100%, 40%);">+   case (NAS_ALG_ENC_EEA1) {</span><br><span style="color: hsl(120, 100%, 40%);">+             f_snow_3g_f8(k_nas_enc, count, bearer, is_downlink, data);</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+     case else {</span><br><span style="color: hsl(120, 100%, 40%);">+           setverdict(fail, "Unsupported EEA: ", alg);</span><br><span style="color: hsl(120, 100%, 40%);">+         mtc.stop;</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 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 style="color: hsl(120, 100%, 40%);">+ * high-level API (full NAS encapsulation/decapsulation)</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%);">+type record NAS_UE_State {</span><br><span style="color: hsl(120, 100%, 40%);">+     NAS_Role role,          /* ATS implements UE or MME role? */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        NAS_ALG_INT alg_int,    /* NAS Integrity Protection Algorithm */</span><br><span style="color: hsl(120, 100%, 40%);">+      octetstring k_nas_int,  /* NAS Integrity Protection Key */</span><br><span style="color: hsl(120, 100%, 40%);">+    NAS_ALG_ENC alg_enc,    /* NAS Encryption Algorithm */</span><br><span style="color: hsl(120, 100%, 40%);">+        octetstring k_nas_enc,  /* NAS Encryption Key */</span><br><span style="color: hsl(120, 100%, 40%);">+      integer rx_count,       /* frame counter (ATS rx side) */</span><br><span style="color: hsl(120, 100%, 40%);">+     integer tx_count        /* frame counter (ATS tx side) */</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%);">+template (value) NAS_UE_State t_NAS_UE_State(NAS_Role role) := {</span><br><span style="color: hsl(120, 100%, 40%);">+     role := role,</span><br><span style="color: hsl(120, 100%, 40%);">+ alg_int := NAS_ALG_IP_EIA0,</span><br><span style="color: hsl(120, 100%, 40%);">+   k_nas_int := ''O,</span><br><span style="color: hsl(120, 100%, 40%);">+     alg_enc := NAS_ALG_ENC_EEA0,</span><br><span style="color: hsl(120, 100%, 40%);">+  k_nas_enc := ''O,</span><br><span style="color: hsl(120, 100%, 40%);">+     rx_count := 0,</span><br><span style="color: hsl(120, 100%, 40%);">+        tx_count := 0</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%);">+type enumerated NAS_Role {</span><br><span style="color: hsl(120, 100%, 40%);">+       NAS_ROLE_UE,    /* ATS implements/emulates UE */</span><br><span style="color: hsl(120, 100%, 40%);">+      NAS_ROLE_MME    /* ATS implements/emulates MME */</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+type enumerated NAS_ALG_INT {</span><br><span style="color: hsl(120, 100%, 40%);">+  NAS_ALG_IP_EIA0,        /* no integrity protection */</span><br><span style="color: hsl(120, 100%, 40%);">+ NAS_ALG_IP_EIA1,        /* SNOW-3G F9 based */</span><br><span style="color: hsl(120, 100%, 40%);">+        NAS_ALG_IP_EIA2,        /* AES based */</span><br><span style="color: hsl(120, 100%, 40%);">+       NAS_ALG_IP_EIA3         /* ZUC */</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+type enumerated NAS_ALG_ENC {</span><br><span style="color: hsl(120, 100%, 40%);">+  NAS_ALG_ENC_EEA0,       /* no encryption */</span><br><span style="color: hsl(120, 100%, 40%);">+   NAS_ALG_ENC_EEA1,       /* SNOW-3G F8 based */</span><br><span style="color: hsl(120, 100%, 40%);">+        NAS_ALG_ENC_EEA2,       /* AES based */</span><br><span style="color: hsl(120, 100%, 40%);">+       NAS_ALG_ENC_EEA3        /* ZUC */</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%);">+/* port between individual per-connection components and this translator */</span><br><span style="color: hsl(120, 100%, 40%);">+type port S1AP_NAS_Conn_PT message {</span><br><span style="color: hsl(120, 100%, 40%);">+    inout S1AP_PDU, PDU_NAS_EPS;</span><br><span style="color: hsl(120, 100%, 40%);">+} with { extension "internal" };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* determine if a received (from the IUT) message is downlink or not */</span><br><span style="color: hsl(120, 100%, 40%);">+private function f_rx_is_downlink(in NAS_UE_State nus) return boolean</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (nus.role == NAS_ROLE_UE) {</span><br><span style="color: hsl(120, 100%, 40%);">+                return true;</span><br><span style="color: hsl(120, 100%, 40%);">+  } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              return false;</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 style="color: hsl(120, 100%, 40%);">+/* determine if a message transmitted to the IUT message is downlink or not */</span><br><span style="color: hsl(120, 100%, 40%);">+private function f_tx_is_downlink(in NAS_UE_State nus) return boolean</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      return not f_rx_is_downlink(nus);</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%);">+private function f_nas_check_ip(inout NAS_UE_State nus,</span><br><span style="color: hsl(120, 100%, 40%);">+                               in PDU_NAS_EPS_SecurityProtectedNASMessage secp_nas) return boolean</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        var octetstring data_with_seq := int2oct(secp_nas.sequenceNumber, 1) & secp_nas.nAS_Message;</span><br><span style="color: hsl(120, 100%, 40%);">+      var OCT4 exp_mac := f_nas_mac_calc(nus.alg_int, nus.k_nas_int, nus.rx_count, 0,</span><br><span style="color: hsl(120, 100%, 40%);">+                                          f_rx_is_downlink(nus), data_with_seq);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (exp_mac != secp_nas.messageAuthenticationCode) {</span><br><span style="color: hsl(120, 100%, 40%);">+          setverdict(fail, "Received NAS MAC ", secp_nas.messageAuthenticationCode,</span><br><span style="color: hsl(120, 100%, 40%);">+                      " doesn't match expected MAC ", exp_mac, ": ", secp_nas);</span><br><span style="color: hsl(120, 100%, 40%);">+          return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+     return true;</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%);">+/* try to decapsulate (MAC verify, decrypt) NAS message */</span><br><span style="color: hsl(120, 100%, 40%);">+function f_nas_try_decaps(inout NAS_UE_State nus, PDU_NAS_EPS nas) return PDU_NAS_EPS</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       var PDU_NAS_EPS_SecurityProtectedNASMessage secp_nas;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* transparently pass through any non-protected NAS */</span><br><span style="color: hsl(120, 100%, 40%);">+        if (not match(nas, tr_NAS_EMM_SecurityProtected)) {</span><br><span style="color: hsl(120, 100%, 40%);">+           return nas;</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%);">+   /* process any security-protected NAS */</span><br><span style="color: hsl(120, 100%, 40%);">+      secp_nas := nas.ePS_messages.ePS_MobilityManagement.pDU_NAS_EPS_SecurityProtectedNASMessage;</span><br><span style="color: hsl(120, 100%, 40%);">+  select (secp_nas.securityHeaderType) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case ('0011'B) { /* IP with new EPS security context */</span><br><span style="color: hsl(120, 100%, 40%);">+               nus.rx_count := 0;</span><br><span style="color: hsl(120, 100%, 40%);">+            nus.alg_int := NAS_ALG_IP_EIA1; /* FIXME: from decoded inner message! */</span><br><span style="color: hsl(120, 100%, 40%);">+              if (not f_nas_check_ip(nus, secp_nas)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      mtc.stop;</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+             return dec_PDU_NAS_EPS(secp_nas.nAS_Message);</span><br><span style="color: hsl(120, 100%, 40%);">+         }</span><br><span style="color: hsl(120, 100%, 40%);">+     case ('0001'B) { /* IP only */</span><br><span style="color: hsl(120, 100%, 40%);">+                if (not f_nas_check_ip(nus, secp_nas)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      mtc.stop;</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+             return dec_PDU_NAS_EPS(secp_nas.nAS_Message);</span><br><span style="color: hsl(120, 100%, 40%);">+         }</span><br><span style="color: hsl(120, 100%, 40%);">+     case ('0010'B) { /* IP + ciphered */</span><br><span style="color: hsl(120, 100%, 40%);">+          if (not f_nas_check_ip(nus, secp_nas)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      mtc.stop;</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+             f_nas_encrypt(nus.alg_enc, nus.k_nas_enc, nus.rx_count, 0,</span><br><span style="color: hsl(120, 100%, 40%);">+                          f_rx_is_downlink(nus), secp_nas.nAS_Message);</span><br><span style="color: hsl(120, 100%, 40%);">+           return dec_PDU_NAS_EPS(secp_nas.nAS_Message);</span><br><span style="color: hsl(120, 100%, 40%);">+         }</span><br><span style="color: hsl(120, 100%, 40%);">+     case ('0100'B) { /* IP + ciphered; new EPS security context */</span><br><span style="color: hsl(120, 100%, 40%);">+                nus.rx_count := 0;</span><br><span style="color: hsl(120, 100%, 40%);">+            if (not f_nas_check_ip(nus, secp_nas)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      mtc.stop;</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+             f_nas_encrypt(nus.alg_enc, nus.k_nas_enc, nus.rx_count, 0,</span><br><span style="color: hsl(120, 100%, 40%);">+                          f_rx_is_downlink(nus), secp_nas.nAS_Message);</span><br><span style="color: hsl(120, 100%, 40%);">+           return dec_PDU_NAS_EPS(secp_nas.nAS_Message);</span><br><span style="color: hsl(120, 100%, 40%);">+         }</span><br><span style="color: hsl(120, 100%, 40%);">+     //case ('0101'B) { /* IP + partially ciphered */ }</span><br><span style="color: hsl(120, 100%, 40%);">+    //case ('1100'B) { /* Service Request Message */ }</span><br><span style="color: hsl(120, 100%, 40%);">+    case else  {</span><br><span style="color: hsl(120, 100%, 40%);">+          setverdict(fail, "Implement SecHdrType for ", secp_nas);</span><br><span style="color: hsl(120, 100%, 40%);">+            mtc.stop;</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 style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+private function f_nas_determine_sec_hdr_t(boolean encrypt, boolean authenticate, boolean new_ctx)</span><br><span style="color: hsl(120, 100%, 40%);">+return BIT4</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    if (encrypt == false and authenticate == false and new_ctx == false) {</span><br><span style="color: hsl(120, 100%, 40%);">+                return '0000'B;</span><br><span style="color: hsl(120, 100%, 40%);">+       } else if (encrypt == false and authenticate == true and new_ctx == false) {</span><br><span style="color: hsl(120, 100%, 40%);">+          return '0001'B;</span><br><span style="color: hsl(120, 100%, 40%);">+       } else if (encrypt == false and authenticate == true and new_ctx == true) {</span><br><span style="color: hsl(120, 100%, 40%);">+           return '0011'B;</span><br><span style="color: hsl(120, 100%, 40%);">+       } else if (encrypt == true and authenticate == true and new_ctx == true) {</span><br><span style="color: hsl(120, 100%, 40%);">+            return '0100'B;</span><br><span style="color: hsl(120, 100%, 40%);">+       } else if (encrypt == true and authenticate == true and new_ctx == false) {</span><br><span style="color: hsl(120, 100%, 40%);">+           return '0010'B;</span><br><span style="color: hsl(120, 100%, 40%);">+       } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              setverdict(fail, "invalid sec_hdr conditions");</span><br><span style="color: hsl(120, 100%, 40%);">+             mtc.stop;</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 style="color: hsl(120, 100%, 40%);">+/* encapsulate a NAS message (encrypt, MAC) */</span><br><span style="color: hsl(120, 100%, 40%);">+function f_nas_encaps(inout NAS_UE_State nus, PDU_NAS_EPS nas_in, boolean new_ctx := false)</span><br><span style="color: hsl(120, 100%, 40%);">+return PDU_NAS_EPS</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    var boolean encrypt := false;</span><br><span style="color: hsl(120, 100%, 40%);">+ var boolean authenticate := false;</span><br><span style="color: hsl(120, 100%, 40%);">+    if (nus.alg_int != NAS_ALG_IP_EIA0) {</span><br><span style="color: hsl(120, 100%, 40%);">+         authenticate := true;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (nus.alg_enc != NAS_ALG_ENC_EEA0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                encrypt := true;</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%);">+   if (encrypt == false and authenticate == false) {</span><br><span style="color: hsl(120, 100%, 40%);">+             return nas_in;</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%);">+   if (new_ctx) {</span><br><span style="color: hsl(120, 100%, 40%);">+                nus.tx_count := 0;</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%);">+   var BIT4 sec_hdr_t := f_nas_determine_sec_hdr_t(encrypt, authenticate, new_ctx);</span><br><span style="color: hsl(120, 100%, 40%);">+      var octetstring nas_enc := enc_PDU_NAS_EPS(nas_in);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (encrypt) {</span><br><span style="color: hsl(120, 100%, 40%);">+                f_nas_encrypt(nus.alg_enc, nus.k_nas_enc, nus.tx_count, 0,</span><br><span style="color: hsl(120, 100%, 40%);">+                          f_tx_is_downlink(nus), nas_enc);</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+     var PDU_NAS_EPS nas_out;</span><br><span style="color: hsl(120, 100%, 40%);">+      nas_out := valueof(ts_NAS_EMM_SecurityProtected(sec_hdr_t, nus.tx_count, nas_enc));</span><br><span style="color: hsl(120, 100%, 40%);">+   if (authenticate) {</span><br><span style="color: hsl(120, 100%, 40%);">+           var OCT4 mac := f_nas_mac_calc(nus.alg_int, nus.k_nas_int, nus.tx_count, 0,</span><br><span style="color: hsl(120, 100%, 40%);">+                                           f_tx_is_downlink(nus), '00'O & nas_enc);</span><br><span style="color: hsl(120, 100%, 40%);">+          nas_out.ePS_messages.ePS_MobilityManagement.pDU_NAS_EPS_SecurityProtectedNASMessage.messageAuthenticationCode := mac;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+     return nas_out;</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%);">+} // namespace</span><br><span>diff --git a/mme/key_derivation.c b/mme/key_derivation.c</span><br><span>new file mode 100644</span><br><span>index 0000000..36e4c91</span><br><span>--- /dev/null</span><br><span>+++ b/mme/key_derivation.c</span><br><span>@@ -0,0 +1,82 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <arpa/inet.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <gnutls/crypto.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* From nextepc/src/mme/mme-kdf.c under AGPLv3+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void mme_kdf_nas(uint8_t algorithm_type_distinguishers,</span><br><span style="color: hsl(120, 100%, 40%);">+                 uint8_t algorithm_identity, const uint8_t *kasme, uint8_t *knas)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t s[7];</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t out[32];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    s[0] = 0x15; /* FC Value */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ s[1] = algorithm_type_distinguishers;</span><br><span style="color: hsl(120, 100%, 40%);">+ s[2] = 0x00;</span><br><span style="color: hsl(120, 100%, 40%);">+  s[3] = 0x01;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        s[4] = algorithm_identity;</span><br><span style="color: hsl(120, 100%, 40%);">+    s[5] = 0x00;</span><br><span style="color: hsl(120, 100%, 40%);">+  s[6] = 0x01;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        gnutls_hmac_fast(GNUTLS_MAC_SHA256, kasme, 32, s, 7, out);</span><br><span style="color: hsl(120, 100%, 40%);">+    memcpy(knas, out+16, 16);</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%);">+void mme_kdf_enb(const uint8_t *kasme, uint32_t ul_count, uint8_t *kenb)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t s[7];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       s[0] = 0x11; /* FC Value */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ul_count = htonl(ul_count);</span><br><span style="color: hsl(120, 100%, 40%);">+   memcpy(s+1, &ul_count, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      s[5] = 0x00;</span><br><span style="color: hsl(120, 100%, 40%);">+  s[6] = 0x04;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        gnutls_hmac_fast(GNUTLS_MAC_SHA256, kasme, 32, s, 7, kenb);</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%);">+void mme_kdf_nh(const uint8_t *kasme, const uint8_t *sync_input, uint8_t *kenb)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t s[35];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      s[0] = 0x12; /* FC Value */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ memcpy(s+1, sync_input, 32);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        s[33] = 0x00;</span><br><span style="color: hsl(120, 100%, 40%);">+ s[34] = 0x20;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       gnutls_hmac_fast(GNUTLS_MAC_SHA256, kasme, 32, s, 35, kenb);</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%);">+/* From nextepc/src/hss/hss-auc.c under AGPLv3+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define FC_VALUE 0x10</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void hss_auc_kasme(const uint8_t *ck, const uint8_t *ik, const uint8_t plmn_id[3],</span><br><span style="color: hsl(120, 100%, 40%);">+             const uint8_t *sqn,  const uint8_t *ak, uint8_t *kasme)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t s[14];</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t k[32];</span><br><span style="color: hsl(120, 100%, 40%);">+        int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(&k[0], ck, 16);</span><br><span style="color: hsl(120, 100%, 40%);">+    memcpy(&k[16], ik, 16);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ s[0] = FC_VALUE;</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(&s[1], plmn_id, 3);</span><br><span style="color: hsl(120, 100%, 40%);">+        s[4] = 0x00;</span><br><span style="color: hsl(120, 100%, 40%);">+  s[5] = 0x03;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        for (i = 0; i < 6; i++)</span><br><span style="color: hsl(120, 100%, 40%);">+            s[6+i] = sqn[i] ^ ak[i];</span><br><span style="color: hsl(120, 100%, 40%);">+      s[12] = 0x00;</span><br><span style="color: hsl(120, 100%, 40%);">+ s[13] = 0x06;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       gnutls_hmac_fast(GNUTLS_MAC_SHA256, k, 32, s, 14, kasme);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/mme/key_derivation.h b/mme/key_derivation.h</span><br><span>new file mode 100644</span><br><span>index 0000000..496f52b</span><br><span>--- /dev/null</span><br><span>+++ b/mme/key_derivation.h</span><br><span>@@ -0,0 +1,21 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma once</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define HSS_SQN_LEN 6</span><br><span style="color: hsl(120, 100%, 40%);">+#define HSS_AK_LEN 6</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void hss_auc_kasme(const uint8_t *ck, const uint8_t *ik,</span><br><span style="color: hsl(120, 100%, 40%);">+        const uint8_t plmn_id[3], const uint8_t *sqn,  const uint8_t *ak,</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t *kasme);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Algorithm Type Distinguishers */</span><br><span style="color: hsl(120, 100%, 40%);">+#define MME_KDF_NAS_ENC_ALG 0x01</span><br><span style="color: hsl(120, 100%, 40%);">+#define MME_KDF_NAS_INT_ALG 0x02</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void mme_kdf_nas(uint8_t algorithm_type_distinguishers,</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t algorithm_identity, const uint8_t *kasme, uint8_t *knas);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void mme_kdf_enb(const uint8_t *kasme, uint32_t ul_count, uint8_t *kenb);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void mme_kdf_nh(const uint8_t *kasme, const uint8_t *sync_input, uint8_t *kenb);</span><br><span>diff --git a/mme/regen_makefile.sh b/mme/regen_makefile.sh</span><br><span>index ee73658..4752302 100755</span><br><span>--- a/mme/regen_makefile.sh</span><br><span>+++ b/mme/regen_makefile.sh</span><br><span>@@ -1,9 +1,9 @@</span><br><span> #!/bin/sh</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-FILES="*.ttcn *.asn IPL4asp_PT.cc  IPL4asp_discovery.cc  Native_FunctionDefs.cc SGsAP_CodecPort_CtrlFunctDef.cc  TCCConversion.cc  TCCEncoding.cc  TCCInterface.cc  TELNETasp_PT.cc S1AP_EncDec.cc "</span><br><span style="color: hsl(120, 100%, 40%);">+FILES="*.ttcn *.asn *.c IPL4asp_PT.cc  IPL4asp_discovery.cc  Native_FunctionDefs.cc SGsAP_CodecPort_CtrlFunctDef.cc  TCCConversion.cc  TCCEncoding.cc  TCCInterface.cc  TELNETasp_PT.cc S1AP_EncDec.cc LTE_CryptoFunctionDefs.cc "</span><br><span> </span><br><span> export CPPFLAGS_TTCN3=""</span><br><span> </span><br><span> ../regen-makefile.sh MME_Tests.ttcn $FILES</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-sed -i -e 's/^LINUX_LIBS = -lxml2/LINUX_LIBS = -lxml2 -lfftranscode/' Makefile</span><br><span style="color: hsl(120, 100%, 40%);">+sed -i -e 's/^LINUX_LIBS = -lxml2/LINUX_LIBS = -lxml2 -lfftranscode -lgnutls/' Makefile</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/15202">change 15202</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-ttcn3-hacks/+/15202"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-ttcn3-hacks </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I7fca69ea8b4aed48d5a64885b762ab85be71ef03 </div>
<div style="display:none"> Gerrit-Change-Number: 15202 </div>
<div style="display:none"> Gerrit-PatchSet: 3 </div>
<div style="display:none"> Gerrit-Owner: laforge <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>