Add function to check GMM encryptability

Check if particular GMM message can be encrypted according to 3GPP TS
24.008 ยง 4.7.1.2

Related: OS#1582
Change-Id: I7ad0e03c2c738d174dd6bc3453f332eeb8da1e7d
diff --git a/src/gsm/gsm48.c b/src/gsm/gsm48.c
index 8a46f76..b4740cf 100644
--- a/src/gsm/gsm48.c
+++ b/src/gsm/gsm48.c
@@ -35,6 +35,7 @@
 #include <osmocom/gsm/gsm_utils.h>
 #include <osmocom/gsm/protocol/gsm_04_08.h>
 #include <osmocom/gsm/protocol/gsm_08_58.h>
+#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
 
 const struct tlv_definition gsm48_att_tlvdef = {
 	.def = {
@@ -302,6 +303,30 @@
 	val = val / 10;
 }
 
+/*! \brief Checks is particular message is cipherable in A/Gb mode according to
+ *         3GPP TS 24.008 § 4.7.1.2
+ *  \param[in] hdr Message header
+ *  \return true if message can be encrypted, false otherwise
+ */
+bool gsm48_hdr_gmm_cipherable(const struct gsm48_hdr *hdr)
+{
+	switch(hdr->msg_type) {
+	case GSM48_MT_GMM_ATTACH_REQ:
+	case GSM48_MT_GMM_ATTACH_REJ:
+	case GSM48_MT_GMM_AUTH_CIPH_REQ:
+	case GSM48_MT_GMM_AUTH_CIPH_RESP:
+	case GSM48_MT_GMM_AUTH_CIPH_REJ:
+	case GSM48_MT_GMM_AUTH_CIPH_FAIL:
+	case GSM48_MT_GMM_ID_REQ:
+	case GSM48_MT_GMM_ID_RESP:
+	case GSM48_MT_GMM_RA_UPD_REQ:
+	case GSM48_MT_GMM_RA_UPD_REJ:
+		return false;
+	default:
+		return true;
+	}
+}
+
 /* Convert given mcc and mnc to BCD and write to *bcd_dst, which must be an
  * allocated buffer of (at least) 3 bytes length. */
 void gsm48_mcc_mnc_to_bcd(uint8_t *bcd_dst, uint16_t mcc, uint16_t mnc)