libvlr: Allow 2G auth tuples to be re-used without going through AUTH

If the key_seq we get in the first messages matches the last_tuple, then
both we and the MS already know the key to use and we don't need the
AUTH REQUEST/RESPONSE cycle.

Security wise ... not so good, and so IMHO the 'auth required' option
in the MSC should always be set. But this allows to turn on ciphering on
a channel without doing any MM transaction, and so the MS doesn't turn
on the T3240 timer which allows to have a ciphered silent-call channel
that won't timeout.

Change-Id: Ief840a2ae7a0ffd2bf0bf726f209a79e3f787646
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
diff --git a/src/libvlr/vlr_access_req_fsm.c b/src/libvlr/vlr_access_req_fsm.c
index 3b40285..26db42c 100644
--- a/src/libvlr/vlr_access_req_fsm.c
+++ b/src/libvlr/vlr_access_req_fsm.c
@@ -67,6 +67,7 @@
 	struct osmo_location_area_id lai;
 	bool authentication_required;
 	bool ciphering_required;
+	uint8_t key_seq;
 	bool is_r99;
 	bool is_utran;
 	bool implicitly_accepted_parq_by_ciphering_cmd;
@@ -316,7 +317,8 @@
 	/* The cases where the authentication procedure should be used
 	 * are defined in 3GPP TS 33.102 */
 	/* For now we use a default value passed in to vlr_lu_fsm(). */
-	return par->authentication_required || par->ciphering_required;
+	return par->authentication_required ||
+		(par->ciphering_required && !auth_try_reuse_tuple(par->vsub, par->key_seq));
 }
 
 /* after the IMSI is known */
@@ -528,6 +530,7 @@
 		.out_state_mask = S(PR_ARQ_S_DONE) |
 				  S(PR_ARQ_S_WAIT_OBTAIN_IMSI) |
 				  S(PR_ARQ_S_WAIT_AUTH) |
+				  S(PR_ARQ_S_WAIT_CIPH) |
 				  S(PR_ARQ_S_WAIT_UPD_LOC_CHILD) |
 				  S(PR_ARQ_S_WAIT_SUB_PRES) |
 				  S(PR_ARQ_S_WAIT_TRACE_SUB) |
@@ -540,6 +543,7 @@
 		.in_event_mask = S(PR_ARQ_E_ID_IMSI),
 		.out_state_mask = S(PR_ARQ_S_DONE) |
 				  S(PR_ARQ_S_WAIT_AUTH) |
+				  S(PR_ARQ_S_WAIT_CIPH) |
 				  S(PR_ARQ_S_WAIT_UPD_LOC_CHILD) |
 				  S(PR_ARQ_S_WAIT_SUB_PRES) |
 				  S(PR_ARQ_S_WAIT_TRACE_SUB) |
@@ -637,6 +641,7 @@
 		 const struct osmo_location_area_id *lai,
 		 bool authentication_required,
 		 bool ciphering_required,
+		 uint8_t key_seq,
 		 bool is_r99, bool is_utran)
 {
 	struct osmo_fsm_inst *fi;
@@ -660,6 +665,7 @@
 	par->parent_event_data = parent_event_data;
 	par->authentication_required = authentication_required;
 	par->ciphering_required = ciphering_required;
+	par->key_seq = key_seq;
 	par->is_r99 = is_r99;
 	par->is_utran = is_utran;