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>