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/.
Max gerrit-no-reply at lists.osmocom.orgSGSN: encrypt/decrypt only necessary frames According to 3GPP TS 24.008 § 4.7.1.2 some GMM frames are not supposed to be ciphered. Propagate information about the necessity for encryption between MM <-> LLC to ensure only proper frames are encrypted/decrypted/dropped. Change-Id: I0358905e60d1b182f75caec81bfcc72bbbbb2aa1 Related: OS#1582 --- M openbsc/include/openbsc/gprs_gmm.h M openbsc/include/openbsc/gprs_llc.h M openbsc/src/gprs/gprs_gmm.c M openbsc/src/gprs/gprs_llc.c M openbsc/src/gprs/gprs_sndcp.c M openbsc/tests/sgsn/sgsn_test.c 6 files changed, 50 insertions(+), 34 deletions(-) git pull ssh://gerrit.osmocom.org:29418/openbsc refs/changes/70/470/2 diff --git a/openbsc/include/openbsc/gprs_gmm.h b/openbsc/include/openbsc/gprs_gmm.h index e0d8f77..58449cb 100644 --- a/openbsc/include/openbsc/gprs_gmm.h +++ b/openbsc/include/openbsc/gprs_gmm.h @@ -4,13 +4,16 @@ #include <osmocom/core/msgb.h> #include <openbsc/gprs_sgsn.h> +#include <stdbool.h> + int gsm48_tx_gsm_deact_pdp_req(struct sgsn_pdp_ctx *pdp, uint8_t sm_cause); int gsm48_tx_gsm_act_pdp_rej(struct sgsn_mm_ctx *mm, uint8_t tid, uint8_t cause, uint8_t pco_len, uint8_t *pco_v); int gsm48_tx_gsm_act_pdp_acc(struct sgsn_pdp_ctx *pdp); int gsm48_tx_gsm_deact_pdp_acc(struct sgsn_pdp_ctx *pdp); -int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme); +int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme, + bool drop_cipherable); int gsm0408_gprs_force_reattach(struct sgsn_mm_ctx *mmctx); int gsm0408_gprs_force_reattach_oldmsg(struct msgb *msg); void gsm0408_gprs_access_granted(struct sgsn_mm_ctx *mmctx); diff --git a/openbsc/include/openbsc/gprs_llc.h b/openbsc/include/openbsc/gprs_llc.h index c48beb8..73870af 100644 --- a/openbsc/include/openbsc/gprs_llc.h +++ b/openbsc/include/openbsc/gprs_llc.h @@ -2,6 +2,7 @@ #define _GPRS_LLC_H #include <stdint.h> +#include <stdbool.h> #include <openbsc/gprs_sgsn.h> /* Section 4.7 LLC Layer Structure */ @@ -211,7 +212,7 @@ /* LL-UNITDATA.req */ int gprs_llc_tx_ui(struct msgb *msg, uint8_t sapi, int command, - void *mmctx); + struct sgsn_mm_ctx *mmctx, bool encryptable); /* Chapter 7.2.1.2 LLGMM-RESET.req */ int gprs_llgmm_reset(struct gprs_llc_llme *llme); diff --git a/openbsc/src/gprs/gprs_gmm.c b/openbsc/src/gprs/gprs_gmm.c index 3df4e4a..e531bef 100644 --- a/openbsc/src/gprs/gprs_gmm.c +++ b/openbsc/src/gprs/gprs_gmm.c @@ -26,7 +26,7 @@ #include <string.h> #include <stdint.h> #include <errno.h> - +#include <stdbool.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> @@ -130,13 +130,13 @@ /* Send a message through the underlying layer */ static int gsm48_gmm_sendmsg(struct msgb *msg, int command, - struct sgsn_mm_ctx *mm) + struct sgsn_mm_ctx *mm, bool encryptable) { if (mm) rate_ctr_inc(&mm->ctrg->ctr[GMM_CTR_PKTS_SIG_OUT]); /* caller needs to provide TLLI, BVCI and NSEI */ - return gprs_llc_tx_ui(msg, GPRS_SAPI_GMM, command, mm); + return gprs_llc_tx_ui(msg, GPRS_SAPI_GMM, command, mm, encryptable); } /* copy identifiers from old message to new message, this @@ -194,7 +194,7 @@ } gh->data[0] = cause; - return gsm48_gmm_sendmsg(msg, 0, mmctx); + return gsm48_gmm_sendmsg(msg, 0, mmctx, true); } static int gsm48_tx_gmm_status(struct sgsn_mm_ctx *mmctx, uint8_t cause) @@ -232,7 +232,7 @@ msgb_tv_put(msg, GSM48_IE_GMM_CAUSE, cause); - return gsm48_gmm_sendmsg(msg, 0, mmctx); + return gsm48_gmm_sendmsg(msg, 0, mmctx, true); } static int gsm48_tx_gmm_detach_req(struct sgsn_mm_ctx *mmctx, @@ -328,7 +328,7 @@ /* Optional: MS-identity (combined attach) */ /* Optional: GMM cause (partial attach result for combined attach) */ - return gsm48_gmm_sendmsg(msg, 0, mm); + return gsm48_gmm_sendmsg(msg, 0, mm, true); } /* Chapter 9.4.5: Attach reject */ @@ -345,7 +345,7 @@ gh->msg_type = GSM48_MT_GMM_ATTACH_REJ; gh->data[0] = gmm_cause; - return gsm48_gmm_sendmsg(msg, 0, NULL); + return gsm48_gmm_sendmsg(msg, 0, NULL, false); } static int gsm48_tx_gmm_att_rej_oldmsg(const struct msgb *old_msg, uint8_t gmm_cause) @@ -377,7 +377,7 @@ gh->msg_type = GSM48_MT_GMM_DETACH_ACK; gh->data[0] = force_stby; - return gsm48_gmm_sendmsg(msg, 0, mm); + return gsm48_gmm_sendmsg(msg, 0, mm, true); } static int gsm48_tx_gmm_det_ack(struct sgsn_mm_ctx *mm, uint8_t force_stby) @@ -413,7 +413,7 @@ /* 10.5.5.9 ID type 2 + identity type and 10.5.5.7 'force to standby' IE */ gh->data[0] = id_type & 0xf; - return gsm48_gmm_sendmsg(msg, 1, mm); + return gsm48_gmm_sendmsg(msg, 1, mm, false); } /* Section 9.4.9: Authentication and Ciphering Request */ @@ -454,7 +454,7 @@ /* FIXME: make sure we don't send any other messages to the MS */ - return gsm48_gmm_sendmsg(msg, 1, mm); + return gsm48_gmm_sendmsg(msg, 1, mm, false); } /* Section 9.4.11: Authentication and Ciphering Reject */ @@ -471,7 +471,7 @@ gh->proto_discr = GSM48_PDISC_MM_GPRS; gh->msg_type = GSM48_MT_GMM_AUTH_CIPH_REJ; - return gsm48_gmm_sendmsg(msg, 0, mm); + return gsm48_gmm_sendmsg(msg, 0, mm, false); } /* Section 9.4.10: Authentication and Ciphering Response */ @@ -1078,7 +1078,7 @@ gprs_secs_to_tmr_floor(sgsn->cfg.timers.T3314)); /* Option: MS ID, ... */ - return gsm48_gmm_sendmsg(msg, 0, mm); + return gsm48_gmm_sendmsg(msg, 0, mm, true); } /* Chapter 9.4.17: Routing area update reject */ @@ -1098,7 +1098,7 @@ gh->data[1] = 0; /* ? */ /* Option: P-TMSI signature, allocated P-TMSI, MS ID, ... */ - return gsm48_gmm_sendmsg(msg, 0, NULL); + return gsm48_gmm_sendmsg(msg, 0, NULL, false); } static void process_ms_ctx_status(struct sgsn_mm_ctx *mmctx, @@ -1312,13 +1312,19 @@ /* GPRS Mobility Management */ static int gsm0408_rcv_gmm(struct sgsn_mm_ctx *mmctx, struct msgb *msg, - struct gprs_llc_llme *llme) + struct gprs_llc_llme *llme, bool drop_cipherable) { struct sgsn_signal_data sig_data; struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg); int rc; /* MMCTX can be NULL when called */ + if (drop_cipherable && gsm48_hdr_gmm_cipherable(gh)) { + LOGP(DMM, LOGL_NOTICE, "Dropping cleartext GMM %s which is " + "expected to be encrypted\n", + get_value_string(gprs_mt_gmm_names, gh->msg_type)); + return -EBADMSG; + } if (llme && !mmctx && gh->msg_type != GSM48_MT_GMM_ATTACH_REQ && @@ -1631,7 +1637,7 @@ /* Optional: Packet Flow Identifier */ - return gsm48_gmm_sendmsg(msg, 0, pdp->mm); + return gsm48_gmm_sendmsg(msg, 0, pdp->mm, true); } /* Section 9.5.3: Activate PDP Context reject */ @@ -1654,7 +1660,7 @@ if (pco_len && pco_v) msgb_tlv_put(msg, GSM48_IE_GSM_PROTO_CONF_OPT, pco_len, pco_v); - return gsm48_gmm_sendmsg(msg, 0, mm); + return gsm48_gmm_sendmsg(msg, 0, mm, true); } /* Section 9.5.8: Deactivate PDP Context Request */ @@ -1675,7 +1681,7 @@ msgb_v_put(msg, sm_cause); - return gsm48_gmm_sendmsg(msg, 0, mm); + return gsm48_gmm_sendmsg(msg, 0, mm, true); } int gsm48_tx_gsm_deact_pdp_req(struct sgsn_pdp_ctx *pdp, uint8_t sm_cause) { @@ -1699,7 +1705,7 @@ gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4); gh->msg_type = GSM48_MT_GSM_DEACT_PDP_ACK; - return gsm48_gmm_sendmsg(msg, 0, mm); + return gsm48_gmm_sendmsg(msg, 0, mm, true); } int gsm48_tx_gsm_deact_pdp_acc(struct sgsn_pdp_ctx *pdp) { @@ -2147,7 +2153,8 @@ } /* Main entry point for incoming 04.08 GPRS messages from Gb */ -int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme) +int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme, + bool drop_cipherable) { struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg); uint8_t pdisc = gsm48_hdr_pdisc(gh); @@ -2167,7 +2174,7 @@ switch (pdisc) { case GSM48_PDISC_MM_GPRS: - rc = gsm0408_rcv_gmm(mmctx, msg, llme); + rc = gsm0408_rcv_gmm(mmctx, msg, llme, drop_cipherable); break; case GSM48_PDISC_SM_GPRS: rc = gsm0408_rcv_gsm(mmctx, msg, llme); diff --git a/openbsc/src/gprs/gprs_llc.c b/openbsc/src/gprs/gprs_llc.c index 11e8358..c8ae6ea 100644 --- a/openbsc/src/gprs/gprs_llc.c +++ b/openbsc/src/gprs/gprs_llc.c @@ -21,6 +21,7 @@ #include <errno.h> #include <stdint.h> +#include <stdbool.h> #include <osmocom/core/msgb.h> #include <osmocom/core/linuxlist.h> @@ -344,9 +345,12 @@ return gprs_llc_tx_u(msg, lle->sapi, command, GPRS_LLC_U_XID, 1); } -/* Transmit a UI frame over the given SAPI */ +/* Transmit a UI frame over the given SAPI: + 'encryptable' indicates whether particular message can be encrypted according + to 3GPP TS 24.008 § 4.7.1.2 + */ int gprs_llc_tx_ui(struct msgb *msg, uint8_t sapi, int command, - void *mmctx) + struct sgsn_mm_ctx *mmctx, bool encryptable) { struct gprs_llc_lle *lle; uint8_t *fcs, *llch; @@ -407,7 +411,7 @@ fcs[2] = (fcs_calc >> 16) & 0xff; /* encrypt information field + FCS, if needed! */ - if (lle->llme->algo != GPRS_ALGO_GEA0) { + if (lle->llme->algo != GPRS_ALGO_GEA0 && encryptable) { uint32_t iov_ui = 0; /* FIXME: randomly select for TLLI */ uint16_t crypt_len = (fcs + 3) - (llch + 3); uint8_t cipher_out[GSM0464_CIPH_MAX_BLOCK]; @@ -565,6 +569,7 @@ struct gprs_llc_hdr *lh = (struct gprs_llc_hdr *) msgb_llch(msg); struct gprs_llc_hdr_parsed llhp; struct gprs_llc_lle *lle; + bool drop_cipherable = false; int rc = 0; /* Identifiers from DOWN: NSEI, BVCI, TLLI */ @@ -637,11 +642,9 @@ for (i = 0; i < crypt_len; i++) *(llhp.data + i) ^= cipher_out[i]; } else { - if (lle->llme->algo != GPRS_ALGO_GEA0) { - LOGP(DLLC, LOGL_NOTICE, "unencrypted frame for LLC " - "that is supposed to be encrypted. Dropping.\n"); - return 0; - } + if (lle->llme->algo != GPRS_ALGO_GEA0 && + lle->llme->cksn != GSM_KEY_SEQ_INVAL) + drop_cipherable = true; } /* We have to do the FCS check _after_ decryption */ @@ -666,7 +669,8 @@ switch (llhp.sapi) { case GPRS_SAPI_GMM: /* send LL_UNITDATA_IND to GMM */ - rc = gsm0408_gprs_rcvmsg_gb(msg, lle->llme); + rc = gsm0408_gprs_rcvmsg_gb(msg, lle->llme, + drop_cipherable); break; case GPRS_SAPI_SNDCP3: case GPRS_SAPI_SNDCP5: diff --git a/openbsc/src/gprs/gprs_sndcp.c b/openbsc/src/gprs/gprs_sndcp.c index 46d779b..75f95c9 100644 --- a/openbsc/src/gprs/gprs_sndcp.c +++ b/openbsc/src/gprs/gprs_sndcp.c @@ -22,6 +22,7 @@ #include <errno.h> #include <stdint.h> +#include <stdbool.h> #include <osmocom/core/msgb.h> #include <osmocom/core/linuxlist.h> @@ -417,7 +418,7 @@ /* set the MORE bit of the SNDCP header accordingly */ sch->more = more; - rc = gprs_llc_tx_ui(fmsg, lle->sapi, 0, fs->mmcontext); + rc = gprs_llc_tx_ui(fmsg, lle->sapi, 0, fs->mmcontext, true); /* abort in case of error, do not advance frag_nr / next_byte */ if (rc < 0) { msgb_free(fs->msg); @@ -498,7 +499,7 @@ sch->type = 1; sch->nsapi = nsapi; - return gprs_llc_tx_ui(msg, lle->sapi, 0, mmcontext); + return gprs_llc_tx_ui(msg, lle->sapi, 0, mmcontext, true); } /* Section 5.1.2.17 LL-UNITDATA.ind */ diff --git a/openbsc/tests/sgsn/sgsn_test.c b/openbsc/tests/sgsn/sgsn_test.c index 59e422c..ef07976 100644 --- a/openbsc/tests/sgsn/sgsn_test.c +++ b/openbsc/tests/sgsn/sgsn_test.c @@ -196,7 +196,7 @@ msg = create_msg(data, data_len); msgb_tlli(msg) = tlli; bssgp_create_cell_id(msgb_bcid(msg), bssgp_raid, 0); - gsm0408_gprs_rcvmsg_gb(msg, llme); + gsm0408_gprs_rcvmsg_gb(msg, llme, false); msgb_free(msg); } -- To view, visit https://gerrit.osmocom.org/470 To unsubscribe, visit https://gerrit.osmocom.org/settings Gerrit-MessageType: newpatchset Gerrit-Change-Id: I0358905e60d1b182f75caec81bfcc72bbbbb2aa1 Gerrit-PatchSet: 2 Gerrit-Project: openbsc Gerrit-Branch: master Gerrit-Owner: Max <msuraev at sysmocom.de>