This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
Hoernchen gerrit-no-reply at lists.osmocom.orgHoernchen has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-sgsn/+/24304 )
Change subject: add support for multiple encryption algorithms + a5/4
......................................................................
add support for multiple encryption algorithms + a5/4
config file syntax is backwards compatible
Change-Id: Ie6700c4e9d2df1eb5fde1b971e287b62668cc2de
Related: SYS#5324
---
M include/osmocom/sgsn/gprs_sgsn.h
M include/osmocom/sgsn/sgsn.h
M src/sgsn/gprs_gmm.c
M src/sgsn/gprs_llc.c
M src/sgsn/gprs_sgsn.c
M src/sgsn/sgsn_vty.c
6 files changed, 93 insertions(+), 31 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-sgsn refs/changes/04/24304/1
diff --git a/include/osmocom/sgsn/gprs_sgsn.h b/include/osmocom/sgsn/gprs_sgsn.h
index 289e0c4..c176494 100644
--- a/include/osmocom/sgsn/gprs_sgsn.h
+++ b/include/osmocom/sgsn/gprs_sgsn.h
@@ -175,6 +175,7 @@
/* Iu: CK, IK, KSI */
/* CKSN */
enum gprs_ciph_algo ciph_algo;
+ uint8_t ue_cipher_mask;
/* Auth & Ciphering Request reference from 3GPP TS 24.008 § 10.5.5.19: */
uint8_t ac_ref_nr_used;
diff --git a/include/osmocom/sgsn/sgsn.h b/include/osmocom/sgsn/sgsn.h
index b686c7c..5b29873 100644
--- a/include/osmocom/sgsn/sgsn.h
+++ b/include/osmocom/sgsn/sgsn.h
@@ -76,7 +76,7 @@
struct gprs_ns2_inst *nsi;
enum sgsn_auth_policy auth_policy;
- enum gprs_ciph_algo cipher;
+ uint8_t cipher_support_mask;
struct llist_head imsi_acl;
struct sockaddr_in gsup_server_addr;
diff --git a/src/sgsn/gprs_gmm.c b/src/sgsn/gprs_gmm.c
index edddd2d..4654709 100644
--- a/src/sgsn/gprs_gmm.c
+++ b/src/sgsn/gprs_gmm.c
@@ -445,6 +445,17 @@
return false;
}
+static enum gprs_ciph_algo gprs_ms_net_select_best_gea(uint8_t net_mask, uint8_t ms_mask) {
+ uint8_t common_mask = net_mask & ms_mask;
+ uint8_t r = 0;
+
+ while (common_mask >>= 1) {
+ r++;
+ }
+
+ return r;
+}
+
/* 3GPP TS 24.008 § 9.4.9: Authentication and Ciphering Request */
int gsm48_tx_gmm_auth_ciph_req(struct sgsn_mm_ctx *mm,
const struct osmo_auth_vector *vec,
@@ -1147,6 +1158,21 @@
}
+static uint8_t gprs_ms_net_cap_gea_mask(const uint8_t *ms_net_cap, uint8_t cap_len)
+{
+ uint8_t mask = (1 << GPRS_ALGO_GEA0);
+ mask |= (0x80 & ms_net_cap[0]) ? (1 << GPRS_ALGO_GEA1) : 0;
+
+ if(cap_len < 2)
+ return mask;
+
+ /* extended GEA bits start from 2nd bit of the next byte */
+ mask |= (0x40 & ms_net_cap[1]) ? (1 << GPRS_ALGO_GEA2) : 0;
+ mask |= (0x20 & ms_net_cap[1]) ? (1 << GPRS_ALGO_GEA3) : 0;
+ mask |= (0x10 & ms_net_cap[1]) ? (1 << GPRS_ALGO_GEA4) : 0;
+ return mask;
+}
+
/* 3GPP TS 24.008 § 9.4.1 Attach request */
static int gsm48_rx_gmm_att_req(struct sgsn_mm_ctx *ctx, struct msgb *msg,
struct gprs_llc_llme *llme)
@@ -1290,15 +1316,27 @@
ctx->ms_radio_access_capa.len);
ctx->ms_network_capa.len = msnc_len;
memcpy(ctx->ms_network_capa.buf, msnc, msnc_len);
- if (!gprs_ms_net_cap_gea_supported(ctx->ms_network_capa.buf, msnc_len,
- ctx->ciph_algo)) {
+
+ ctx->ue_cipher_mask = gprs_ms_net_cap_gea_mask(ctx->ms_network_capa.buf, msnc_len);
+
+ if (!(ctx->ue_cipher_mask & sgsn->cfg.cipher_support_mask)) {
reject_cause = GMM_CAUSE_PROTO_ERR_UNSPEC;
LOGMMCTXP(LOGL_NOTICE, ctx, "Rejecting ATTACH REQUEST with MI "
- "%s because MS do not support required %s "
- "encryption\n", mi_log_string,
- get_value_string(gprs_cipher_names,ctx->ciph_algo));
+ "%s because MS do not support required encryption, mask UE:0x%02x NW:0x%02x \n",
+ mi_log_string, ctx->ue_cipher_mask, sgsn->cfg.cipher_support_mask);
goto rejected;
}
+
+ /* just assume that everythig is fine if the phone offers a5/4:
+ * it requires a valid umts security context which we can only have after
+ * 1) IDENTITY REQUEST to know what to ask the HLR for
+ * 2) and AUTHENTICATION AND CIPHERING REQUEST
+ * ... but 2) already requires selecting a cipher mode.
+ * So let's just assume we will have the auth data required to make it work.
+ */
+
+ ctx->ciph_algo = gprs_ms_net_select_best_gea(ctx->ue_cipher_mask, sgsn->cfg.cipher_support_mask);
+
#ifdef PTMSI_ALLOC
/* Allocate a new P-TMSI (+ P-TMSI signature) and update TLLI */
ptmsi_update(ctx);
diff --git a/src/sgsn/gprs_llc.c b/src/sgsn/gprs_llc.c
index e357d16..73fb97f 100644
--- a/src/sgsn/gprs_llc.c
+++ b/src/sgsn/gprs_llc.c
@@ -42,6 +42,8 @@
#include <osmocom/sgsn/gprs_sndcp_comp.h>
#include <osmocom/sgsn/gprs_sndcp.h>
+#include <osmocom/crypt/kdf.h>
+
const struct value_string gprs_llc_llme_state_names[] = {
{ GPRS_LLMS_UNASSIGNED, "UNASSIGNED" },
{ GPRS_LLMS_ASSIGNED, "ASSIGNED" },
@@ -713,6 +715,7 @@
/* Compute the 'Input' Paraemeter */
uint32_t fcs_calc, iv = gprs_cipher_gen_input_ui(lle->llme->iov_ui, sapi,
nu, oc);
+
/* Compute gamma that we need to XOR with the data */
int r = gprs_cipher_run(cipher_out, crypt_len, lle->llme->algo,
lle->llme->kc, iv,
@@ -1042,8 +1045,13 @@
llme->algo = mm->ciph_algo;
if (llme->cksn != mm->auth_triplet.key_seq &&
mm->auth_triplet.key_seq != GSM_KEY_SEQ_INVAL) {
- memcpy(llme->kc, mm->auth_triplet.vec.kc,
- gprs_cipher_key_length(mm->ciph_algo));
+
+ /* gea4 needs kc128 */
+ if (mm->ciph_algo == GPRS_ALGO_GEA4)
+ osmo_kdf_kc128(mm->auth_triplet.vec.ck, mm->auth_triplet.vec.ik, llme->kc);
+ else
+ memcpy(llme->kc, mm->auth_triplet.vec.kc, gprs_cipher_key_length(mm->ciph_algo));
+
llme->cksn = mm->auth_triplet.key_seq;
}
} else
diff --git a/src/sgsn/gprs_sgsn.c b/src/sgsn/gprs_sgsn.c
index f744257..3441f54 100644
--- a/src/sgsn/gprs_sgsn.c
+++ b/src/sgsn/gprs_sgsn.c
@@ -293,11 +293,9 @@
memcpy(&ctx->ra, raid, sizeof(ctx->ra));
ctx->ran_type = MM_CTX_T_GERAN_Gb;
ctx->gb.tlli = tlli;
- ctx->ciph_algo = sgsn->cfg.cipher;
+ ctx->ciph_algo = GPRS_ALGO_GEA4; // overwritten on attach
osmo_fsm_inst_update_id_f(ctx->gb.mm_state_fsm, "%" PRIu32, tlli);
- LOGMMCTXP(LOGL_DEBUG, ctx, "Allocated with %s cipher.\n",
- get_value_string(gprs_cipher_names, ctx->ciph_algo));
return ctx;
}
diff --git a/src/sgsn/sgsn_vty.c b/src/sgsn/sgsn_vty.c
index 76d5202..533f9ca 100644
--- a/src/sgsn/sgsn_vty.c
+++ b/src/sgsn/sgsn_vty.c
@@ -206,6 +206,7 @@
struct apn_ctx *actx;
struct ares_addr_node *server;
struct sgsn_mme_ctx *mme;
+ int i;
vty_out(vty, "sgsn%s", VTY_NEWLINE);
@@ -236,10 +237,15 @@
for (server = sgsn->ares_servers; server; server = server->next)
vty_out(vty, " grx-dns-add %s%s", inet_ntoa(server->addr.addr4), VTY_NEWLINE);
- if (g_cfg->cipher != GPRS_ALGO_GEA0)
- vty_out(vty, " encryption %s%s",
- get_value_string(gprs_cipher_names, g_cfg->cipher),
- VTY_NEWLINE);
+ if (g_cfg->cipher_support_mask != 0) {
+ vty_out(vty, " encryption");
+
+ for (i = 0; i < 6; i++)
+ if (g_cfg->cipher_support_mask >> i & 1)
+ vty_out(vty, " %s", get_value_string(gprs_cipher_names, i));
+
+ vty_out(vty, "%s", VTY_NEWLINE);
+ }
if (g_cfg->sgsn_ipa_name)
vty_out(vty, " gsup ipa-name %s%s", g_cfg->sgsn_ipa_name, VTY_NEWLINE);
if (g_cfg->gsup_server_addr.sin_addr.s_addr)
@@ -723,27 +729,36 @@
}
DEFUN(cfg_encrypt, cfg_encrypt_cmd,
- "encryption (GEA0|GEA1|GEA2|GEA3|GEA4)",
- "Set encryption algorithm for SGSN\n"
- "Use GEA0 (no encryption)\n"
- "Use GEA1\nUse GEA2\nUse GEA3\nUse GEA4\n")
+ "encryption (GEA0-4) [GEA0-4] [GEA0-4] [GEA0-4] [GEA0-4]",
+ "Set encryption algorithm for SGSN\n"
+ "GEAn Algorithm Number\n"
+ "GEAn Algorithm Number\n"
+ "GEAn Algorithm Number\n"
+ "GEAn Algorithm Number\n"
+ "GEAn Algorithm Number\n")
{
- enum gprs_ciph_algo c = get_string_value(gprs_cipher_names, argv[0]);
- if (c != GPRS_ALGO_GEA0) {
- if (!gprs_cipher_supported(c)) {
- vty_out(vty, "%% cipher %s is unsupported in current version%s", argv[0], VTY_NEWLINE);
- return CMD_WARNING;
+ int i = argc;
+
+ g_cfg->cipher_support_mask = 0;
+
+ for (i = 0; i < argc; i++) {
+ enum gprs_ciph_algo c = get_string_value(gprs_cipher_names, argv[i]);
+ if (c != GPRS_ALGO_GEA0) {
+ if (!gprs_cipher_supported(c)) {
+ vty_out(vty, "%% cipher %s is unsupported in current version%s", argv[i], VTY_NEWLINE);
+ return CMD_ERR_INCOMPLETE;
+ }
+
+ if (!g_cfg->require_authentication) {
+ vty_out(vty, "%% unable to use encryption %s without authentication: please adjust auth-policy%s",
+ argv[i], VTY_NEWLINE);
+ return CMD_ERR_INCOMPLETE;
+ }
}
- if (!g_cfg->require_authentication) {
- vty_out(vty, "%% unable to use encryption %s without authentication: please adjust auth-policy%s",
- argv[0], VTY_NEWLINE);
- return CMD_WARNING;
- }
+ g_cfg->cipher_support_mask |= (1 << c);
}
- g_cfg->cipher = c;
-
return CMD_SUCCESS;
}
@@ -1692,6 +1707,8 @@
/* make sure sgsn_vty_init() was called before this */
OSMO_ASSERT(g_cfg);
+ g_cfg->cipher_support_mask = 1; // default to GEA0 support
+
rc = vty_read_config_file(config_file, NULL);
if (rc < 0) {
fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
--
To view, visit https://gerrit.osmocom.org/c/osmo-sgsn/+/24304
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-sgsn
Gerrit-Branch: master
Gerrit-Change-Id: Ie6700c4e9d2df1eb5fde1b971e287b62668cc2de
Gerrit-Change-Number: 24304
Gerrit-PatchSet: 1
Gerrit-Owner: Hoernchen <ewild at sysmocom.de>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20210519/46cd42e0/attachment.htm>