From 3c7656a481931f7d001119c5ec0a7b2b10bd2744 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Mon, 7 Mar 2022 15:38:59 +0100 Subject: [PATCH] Iu: add UEA encryption Add vty 'encryption uea 0 1 2', defaults to 'encryption uea 0' to yield previous behavior. If any UEA above 0 is enabled, include the UEA key in the Iu Security Mode Command. I noticed that only the code bit in st_iu_security_cmd_on_enter() affects the test. The same code in gsm48_gmm_authorize() seems to be dead code? But applying the patch there as well just to be safe. We cannot yet verify the chosen UEA to match a configured UEA level, because the iu_client.c does not send us message details with the RANAP_IU_EVENT_SECURITY_MODE_COMPLETE. Also we cannot yet send the set of configured UEA to the hNodeB, since, again, iu_client.c does not provide the proper API for it. The proper solution here is to completely dissolve iu_client.c and do all Iu handling in osmo-sgsn itself -- see OS#5487. Related: SYS#5516 Related: I1a7c3b156830058c43f15f55883ea301d2d01d5f (osmo-ttcn3-hacks) Change-Id: I27e8e0078c45426bf227bb44aac82a4875d18d0f --- include/osmocom/sgsn/sgsn.h | 1 + src/sgsn/gprs_gmm.c | 9 ++++++++- src/sgsn/gprs_gmm_attach.c | 11 ++++++++++- src/sgsn/gprs_ranap.c | 5 +++++ src/sgsn/sgsn_vty.c | 24 +++++++++++++++++++++++- tests/osmo-sgsn_test-nodes.vty | 1 + 6 files changed, 48 insertions(+), 3 deletions(-) diff --git a/include/osmocom/sgsn/sgsn.h b/include/osmocom/sgsn/sgsn.h index 8823dea18..1b34c2a5d 100644 --- a/include/osmocom/sgsn/sgsn.h +++ b/include/osmocom/sgsn/sgsn.h @@ -77,6 +77,7 @@ struct sgsn_config { enum sgsn_auth_policy auth_policy; uint8_t gea_encryption_mask; + uint8_t uea_encryption_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 dfe477cb8..c2bf7a398 100644 --- a/src/sgsn/gprs_gmm.c +++ b/src/sgsn/gprs_gmm.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -916,7 +917,13 @@ int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx) /* The MS is authorized */ #ifdef BUILD_IU if (ctx->ran_type == MM_CTX_T_UTRAN_Iu && !ctx->iu.ue_ctx->integrity_active) { - rc = ranap_iu_tx_sec_mode_cmd(ctx->iu.ue_ctx, &ctx->auth_triplet.vec, 0, ctx->iu.new_key); + /* Is any encryption above UEA0 enabled? */ + bool send_ck = sgsn->cfg.uea_encryption_mask > (1 << OSMO_UTRAN_UEA0); + LOGMMCTXP(LOGL_DEBUG, ctx, "Iu Security Mode Command: %s encryption key (UEA encryption mask = 0x%x)\n", + send_ck ? "sending" : "not sending", sgsn->cfg.uea_encryption_mask); + /* FIXME: we should send the set of allowed UEA, as in ranap_new_msg_sec_mod_cmd2(). However, this + * is not possible in the iu_client API. See OS#5487. */ + rc = ranap_iu_tx_sec_mode_cmd(ctx->iu.ue_ctx, &ctx->auth_triplet.vec, send_ck, ctx->iu.new_key); ctx->iu.new_key = 0; return rc; } diff --git a/src/sgsn/gprs_gmm_attach.c b/src/sgsn/gprs_gmm_attach.c index 629cc53fe..59417dfaa 100644 --- a/src/sgsn/gprs_gmm_attach.c +++ b/src/sgsn/gprs_gmm_attach.c @@ -1,4 +1,5 @@ #include +#include #include @@ -257,6 +258,7 @@ static void st_iu_security_cmd_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_ { #ifdef BUILD_IU struct sgsn_mm_ctx *ctx = fi->priv; + bool send_ck; /* TODO: shouldn't this set always? not only when the integrity_active? */ if (ctx->iu.ue_ctx->integrity_active) { @@ -264,7 +266,14 @@ static void st_iu_security_cmd_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_ return; } - ranap_iu_tx_sec_mode_cmd(ctx->iu.ue_ctx, &ctx->auth_triplet.vec, 0, ctx->iu.new_key); + /* Is any encryption above UEA0 enabled? */ + send_ck = sgsn->cfg.uea_encryption_mask > (1 << OSMO_UTRAN_UEA0); + LOGMMCTXP(LOGL_DEBUG, ctx, "Iu Security Mode Command: %s encryption key (UEA encryption mask = 0x%x)\n", + send_ck ? "sending" : "not sending", sgsn->cfg.uea_encryption_mask); + + /* FIXME: we should send the set of allowed UEA, as in ranap_new_msg_sec_mod_cmd2(). However, this + * is not possible in the iu_client API. See OS#5487. */ + ranap_iu_tx_sec_mode_cmd(ctx->iu.ue_ctx, &ctx->auth_triplet.vec, send_ck, ctx->iu.new_key); ctx->iu.new_key = 0; #endif } diff --git a/src/sgsn/gprs_ranap.c b/src/sgsn/gprs_ranap.c index ead20f776..ab3a968ae 100644 --- a/src/sgsn/gprs_ranap.c +++ b/src/sgsn/gprs_ranap.c @@ -145,6 +145,11 @@ int sgsn_ranap_iu_event(struct ranap_ue_conn_ctx *ctx, enum ranap_iu_event_type rc = 0; break; case RANAP_IU_EVENT_SECURITY_MODE_COMPLETE: + /* FIXME: verify that a permitted UEA level was chosen. Compare how osmo-msc does it in + * msc_a_ran_dec_from_msc_i(), case RAN_MSG_CIPHER_MODE_COMPLETE. + * We should dissolve iu_client.c, it was a design mistake when first implementing Iu support. osmo-msc + * has moved away from it a long time ago. + */ /* Continue authentication here */ mm->iu.ue_ctx->integrity_active = 1; ranap_iu_tx_common_id(mm->iu.ue_ctx, mm->imsi); diff --git a/src/sgsn/sgsn_vty.c b/src/sgsn/sgsn_vty.c index 56a2d78bd..a394c419c 100644 --- a/src/sgsn/sgsn_vty.c +++ b/src/sgsn/sgsn_vty.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -775,9 +776,11 @@ DEFUN_DEPRECATED(cfg_encrypt, cfg_encrypt_cmd, return CMD_SUCCESS; } +#define ENCRYPTION_STR "Set encryption algorithms for SGSN\n" + DEFUN(cfg_encrypt2, cfg_encrypt2_cmd, "encryption gea <0-4> [<0-4>] [<0-4>] [<0-4>] [<0-4>]", - "Set encryption algorithms for SGSN\n" + ENCRYPTION_STR "GPRS Encryption Algorithm\n" "GEAn Algorithm Number\n" "GEAn Algorithm Number\n" @@ -835,6 +838,23 @@ DEFUN(cfg_authentication, cfg_authentication_cmd, return CMD_SUCCESS; } +DEFUN(cfg_encryption_uea, cfg_encryption_uea_cmd, + "encryption uea <0-2> [<0-2>] [<0-2>]", + ENCRYPTION_STR + "UTRAN (3G) encryption algorithms to allow: 0 = UEA0 (no encryption), 1 = UEA1, 2 = UEA2.\n" + "UEAn Algorithm Number\n" + "UEAn Algorithm Number\n" + "UEAn Algorithm Number\n") +{ + unsigned int i; + + g_cfg->uea_encryption_mask = 0; + for (i = 0; i < argc; i++) + g_cfg->uea_encryption_mask |= (1 << atoi(argv[i])); + + return CMD_SUCCESS; +} + DEFUN(cfg_auth_policy, cfg_auth_policy_cmd, "auth-policy (accept-all|closed|acl-only|remote)", "Configure the Authorization policy of the SGSN. This setting determines which subscribers are" @@ -1732,6 +1752,7 @@ int sgsn_vty_init(struct sgsn_config *cfg) /* order matters here: ensure we attempt to parse our new command first! */ install_element(SGSN_NODE, &cfg_encrypt2_cmd); install_element(SGSN_NODE, &cfg_encrypt_cmd); + install_element(SGSN_NODE, &cfg_encryption_uea_cmd); install_element(SGSN_NODE, &cfg_gsup_ipa_name_cmd); install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd); @@ -1784,6 +1805,7 @@ int sgsn_parse_config(const char *config_file) OSMO_ASSERT(g_cfg); g_cfg->gea_encryption_mask = 0x1; /* support GEA0 by default unless specific encryption config exists */ + g_cfg->uea_encryption_mask = (1 << OSMO_UTRAN_UEA0); /* support UEA0 by default unless specific encryption config exists */ rc = vty_read_config_file(config_file, NULL); if (rc < 0) { diff --git a/tests/osmo-sgsn_test-nodes.vty b/tests/osmo-sgsn_test-nodes.vty index f2ed2dce7..7e2e3a3f2 100644 --- a/tests/osmo-sgsn_test-nodes.vty +++ b/tests/osmo-sgsn_test-nodes.vty @@ -36,6 +36,7 @@ OsmoSGSN(config-sgsn)# list auth-policy (accept-all|closed|acl-only|remote) authentication (optional|required) encryption gea <0-4> [<0-4>] [<0-4>] [<0-4>] [<0-4>] + encryption uea <0-2> [<0-2>] [<0-2>] gsup ipa-name NAME gsup remote-ip A.B.C.D gsup remote-port <0-65535>