SGSN: split GEA key management from TLLI
Move GEA key from TLLI assignment into separate function.
Change-Id: I8a0bc907072dc19cd9535a28b5252dc0f05357cc
Related: OS#1582
diff --git a/openbsc/src/gprs/gprs_gmm.c b/openbsc/src/gprs/gprs_gmm.c
index 7f10b07..492c766 100644
--- a/openbsc/src/gprs/gprs_gmm.c
+++ b/openbsc/src/gprs/gprs_gmm.c
@@ -976,8 +976,10 @@
ctx->gb.tlli_new = gprs_tmsi2tlli(ctx->p_tmsi, TLLI_LOCAL);
/* Inform LLC layer about new TLLI but keep old active */
- gprs_llgmm_assign(ctx->gb.llme, ctx->gb.tlli, ctx->gb.tlli_new,
- GPRS_ALGO_GEA0, NULL);
+ if (ctx->is_authenticated)
+ gprs_llme_copy_key(ctx, ctx->gb.llme);
+
+ gprs_llgmm_assign(ctx->gb.llme, ctx->gb.tlli, ctx->gb.tlli_new);
}
ctx->pending_req = GSM48_MT_GMM_ATTACH_REQ;
@@ -1276,8 +1278,7 @@
/* Inform LLC layer about new TLLI but keep old active */
gprs_llgmm_assign(mmctx->gb.llme, mmctx->gb.tlli,
- mmctx->gb.tlli_new, GPRS_ALGO_GEA0,
- NULL);
+ mmctx->gb.tlli_new);
}
/* Look at PDP Context Status IE and see if MS's view of
@@ -1412,9 +1413,9 @@
if (mmctx->ran_type == MM_CTX_T_GERAN_Gb) {
/* Unassign the old TLLI */
mmctx->gb.tlli = mmctx->gb.tlli_new;
+ gprs_llme_copy_key(mmctx, mmctx->gb.llme);
gprs_llgmm_assign(mmctx->gb.llme, 0xffffffff,
- mmctx->gb.tlli_new,
- GPRS_ALGO_GEA0, NULL);
+ mmctx->gb.tlli_new);
}
mmctx->mm_state = GMM_REGISTERED_NORMAL;
rc = 0;
@@ -1435,8 +1436,8 @@
if (mmctx->ran_type == MM_CTX_T_GERAN_Gb) {
/* Unassign the old TLLI */
mmctx->gb.tlli = mmctx->gb.tlli_new;
- gprs_llgmm_assign(mmctx->gb.llme, 0xffffffff, mmctx->gb.tlli_new,
- GPRS_ALGO_GEA0, NULL);
+ gprs_llgmm_assign(mmctx->gb.llme, 0xffffffff,
+ mmctx->gb.tlli_new);
}
mmctx->mm_state = GMM_REGISTERED_NORMAL;
rc = 0;
diff --git a/openbsc/src/gprs/gprs_llc.c b/openbsc/src/gprs/gprs_llc.c
index 64d22b3..b271e21 100644
--- a/openbsc/src/gprs/gprs_llc.c
+++ b/openbsc/src/gprs/gprs_llc.c
@@ -236,6 +236,7 @@
llme->old_tlli = 0xffffffff;
llme->state = GPRS_LLMS_UNASSIGNED;
llme->age_timestamp = GPRS_LLME_RESET_AGE;
+ llme->cksn = GSM_KEY_SEQ_INVAL;
for (i = 0; i < ARRAY_SIZE(llme->lle); i++)
lle_init(llme, i);
@@ -366,6 +367,8 @@
return -EFBIG;
}
+ gprs_llme_copy_key(mmctx, lle->llme);
+
/* Update LLE's (BVCI, NSEI) tuple */
lle->llme->bvci = msgb_bvci(msg);
lle->llme->nsei = msgb_nsei(msg);
@@ -687,18 +690,29 @@
return rc;
}
+/* Propagate crypto parameters MM -> LLME */
+void gprs_llme_copy_key(struct sgsn_mm_ctx *mm, struct gprs_llc_llme *llme)
+{
+ if (!mm)
+ return;
+ if (mm->ciph_algo != GPRS_ALGO_GEA0) {
+ 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));
+ llme->cksn = mm->auth_triplet.key_seq;
+ }
+ } else
+ llme->cksn = GSM_KEY_SEQ_INVAL;
+}
+
/* 04.64 Chapter 7.2.1.1 LLGMM-ASSIGN */
int gprs_llgmm_assign(struct gprs_llc_llme *llme,
- uint32_t old_tlli, uint32_t new_tlli,
- enum gprs_ciph_algo alg, const uint8_t *kc)
+ uint32_t old_tlli, uint32_t new_tlli)
{
unsigned int i;
- /* Update the crypto parameters */
- llme->algo = alg;
- if (alg != GPRS_ALGO_GEA0)
- memcpy(llme->kc, kc, sizeof(llme->kc));
-
if (old_tlli == 0xffffffff && new_tlli != 0xffffffff) {
/* TLLI Assignment 8.3.1 */
/* New TLLI shall be assigned and used when (re)transmitting LLC frames */
@@ -748,8 +762,7 @@
/* TLLI unassignment */
int gprs_llgmm_unassign(struct gprs_llc_llme *llme)
{
- return gprs_llgmm_assign(llme, llme->tlli, 0xffffffff, GPRS_ALGO_GEA0,
- NULL);
+ return gprs_llgmm_assign(llme, llme->tlli, 0xffffffff);
}
/* Chapter 7.2.1.2 LLGMM-RESET.req */
diff --git a/openbsc/src/gprs/gprs_sgsn.c b/openbsc/src/gprs/gprs_sgsn.c
index 98439de..711887e 100644
--- a/openbsc/src/gprs/gprs_sgsn.c
+++ b/openbsc/src/gprs/gprs_sgsn.c
@@ -244,7 +244,7 @@
if (llme) {
/* TLLI unassignment, must be called after sgsn_mm_ctx_free */
- gprs_llgmm_assign(llme, tlli, 0xffffffff, GPRS_ALGO_GEA0, NULL);
+ gprs_llgmm_assign(llme, tlli, 0xffffffff);
}
}