<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>