SGSN: 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
diff --git a/openbsc/src/gprs/gprs_llc.c b/openbsc/src/gprs/gprs_llc.c
index bc856e9..e6639ce 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 <openssl/rand.h>
@@ -346,9 +347,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;
@@ -409,7 +413,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];
@@ -567,6 +571,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 */
@@ -640,11 +645,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 */
@@ -669,7 +672,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: