def make_2g_vector(self, IMSI, RAND=None): """ return a 2G authentication vector "triplet": RAND [16 bytes], RES [4 bytes], Kc [8 bytes] or None if the IMSI is not defined in the db or ALG is invalid RAND can be passed as argument """ # lookup db for authentication Key and algorithm id for IMSI try: K_ALG_SQN_OP = self.db[IMSI] except KeyError: self._log('WNG', '[make_2g_vector] IMSI %s not present in AuC.db' % IMSI) return None if len(K_ALG_SQN_OP) == 4: K, ALG, SQN, OP = K_ALG_SQN_OP else: K, ALG, SQN = K_ALG_SQN_OP OP = None # if not RAND: RAND = genrand(16) # if ALG == 0: # Milenage, adapted to 2G if OP is not None: XRES, CK, IK, AK = self.Milenage.f2345(RAND, K, OP) else: XRES, CK, IK, AK = self.Milenage.f2345(RAND, K) RES, Kc = conv_102_C2(XRES), conv_102_C3(CK, IK) elif ALG == 4: # TUAK, adapted to 2G if OP is not None: # which is actually TOP, for TUAK XRES, CK, IK, AK = self.TUAK.f2345(RAND, K, OP) else: XRES, CK, IK, AK = self.TUAK.f2345(RAND, K) RES, Kc = conv_102_C2(XRES), conv_102_C3(CK, IK) else: # COMP128 if ALG == 1: RES, Kc = comp128v1(K, RAND) elif ALG == 2: RES, Kc = comp128v2(K, RAND) elif ALG == 3: RES, Kc = comp128v3(K, RAND) else: # invalid ALG return None # # return auth vector self._log('DBG', '[make_2g_vector] IMSI %s: RAND %s, RES %s, Kc %s'\ % (IMSI, hexlify(RAND).decode('ascii'), hexlify(RES).decode('ascii'), hexlify(Kc).decode('ascii'))) return RAND, RES, Kc
def make_3g_vector(self, IMSI, AMF=b'\0\0', RAND=None): ''' return a 3G authentication vector "quintuplet": RAND [16 bytes], XRES [8 bytes], AUTN [16 bytes], CK [16 bytes], IK [16 bytes] or None if the IMSI is not defined in the db or does not support Milenage RAND can be passed as argument ''' # lookup db for authentication Key and counter for IMSI try: K_ALG2_SQN_OP = self.db[IMSI] except: self._log('WNG', '[make_3g_vector] IMSI %s not present in AuC.db' % IMSI) return None # K, ALG2, SQN, OP = K_ALG2_SQN_OP # if SQN == -1: # Milenage not supported self._log( 'WNG', '[make_3g_vector] IMSI %s does not support Milenage' % IMSI) return None # # increment SQN counter in the db K_ALG2_SQN_OP[2] += 1 self._save_required = True # pack SQN from integer to a 48-bit buffer SQNb = b'\0\0' + pack('>I', SQN) # generate challenge if necessary if RAND is None: RAND = genrand(16) # compute Milenage functions if OP is not None: XRES, CK, IK, AK = self.Milenage.f2345(K, RAND, OP) MAC_A = self.Milenage.f1(K, RAND, SQNb, AMF, OP) AUTN = xor_buf(SQNb, AK) + AMF + MAC_A else: XRES, CK, IK, AK = self.Milenage.f2345(K, RAND) MAC_A = self.Milenage.f1(K, RAND, SQNb, AMF) AUTN = xor_buf(SQNb, AK) + AMF + MAC_A # return auth vector self._log('DBG', '[make_3g_vector] IMSI %s, SQN %i: RAND %s, XRES %s, AUTN %s, CK %s, IK %s'\ % (IMSI, SQN, hexlify(RAND).decode('ascii'), hexlify(XRES).decode('ascii'), hexlify(AUTN).decode('ascii'), hexlify(CK).decode('ascii'), hexlify(IK).decode('ascii'))) return RAND, XRES, AUTN, CK, IK
def make_2g_vector(self, IMSI, RAND=None): """ return a 2G authentication vector "triplet": RAND [16 bytes], RES [4 bytes], Kc [8 bytes] or None if the IMSI is not defined in the db or ALG2 is invalid RAND can be passed as argument """ # lookup db for authentication Key and algorithm id for IMSI try: K, ALG2, SQN, OP = self.db[IMSI] except KeyError: self._log('WNG', '[make_2g_vector] IMSI %s not present in AuC.db' % IMSI) return None # if not RAND: RAND = genrand(16) # if ALG2 == 0: if OP is not None: XRES, CK, IK, AK = self.Milenage.f2345(RAND, K, OP) else: XRES, CK, IK, AK = self.Milenage.f2345(RAND, K) RES, Ck = conv_C2(XRES), conv_C3(CK, IK) else: if ALG2 == 1: RES, Ck = comp128v1(K, RAND) elif ALG2 == 2: RES, Ck = comp128v2(K, RAND) elif ALG2 == 3: RES, Ck = comp128v3(K, RAND) else: return None # # return auth vector self._log('DBG', '[make_2g_vector] IMSI %s: RAND %s, RES %s, Kc %s'\ % (IMSI, hexlify(RAND).decode('ascii'), hexlify(RES).decode('ascii'), hexlify(Kc).decode('ascii'))) return RAND, RES, Kc
def make_4g_vector(self, IMSI, SN_ID, AMF=b'\x80\x00', RAND=None): """ return a 4G authentication vector "quadruplet": RAND [16 bytes], XRES [8 bytes], AUTN [16 bytes], KASME [32 bytes] or None if the IMSI is not defined in the db or does not support Milenage or SN_ID is invalid or not allowed SN_ID is the serving network identity, bcd-encoded buffer RAND can be passed as argument """ if not isinstance(SN_ID, bytes_types) or len(SN_ID) != 3: self._log( 'WNG', '[make_4g_vector] SN_ID invalid, %s' % hexlify(SN_ID).decode('ascii')) return None elif self.PLMN_FILTER is not None and SN_ID not in self.PLMN_FILTER: self._log( 'WNG', '[make_4g_vector] SN_ID not allowed, %s' % hexlify(SN_ID).decode('ascii')) return None # # lookup db for authentication Key and counter for IMSI try: K_ALG2_SQN_OP = self.db[IMSI] except: self._log('WNG', '[make_4g_vector] IMSI %s not present in AuC.db' % IMSI) return None # K, ALG2, SQN, OP = K_ALG2_SQN_OP # if SQN == -1: # Milenage not supported self._log( 'WNG', '[make_4g_vector] IMSI %s does not support Milenage' % IMSI) return None # # increment SQN counter in the db K_ALG2_SQN_OP[2] += 1 self._save_required = True # pack SQN from integer to a 48-bit buffer SQNb = b'\0\0' + pack('>I', SQN) # # generate challenge if RAND is None: RAND = genrand(16) # compute Milenage functions if OP is not None: XRES, CK, IK, AK = self.Milenage.f2345(K, RAND, OP) MAC_A = self.Milenage.f1(K, RAND, SQNb, AMF, OP) SQN_X_AK = xor_buf(SQNb, AK) AUTN = SQN_X_AK + AMF + MAC_A else: XRES, CK, IK, AK = self.Milenage.f2345(K, RAND) MAC_A = self.Milenage.f1(K, RAND, SQNb, AMF) SQN_X_AK = xor_buf(SQNb, AK) AUTN = SQN_X_AK + AMF + MAC_A # convert to LTE master key KASME = conv_A2(CK, IK, SN_ID, SQN_X_AK) # return auth vector self._log('DBG', '[make_4g_vector] IMSI %s, SQN %i, SN_ID %s: RAND %s, XRES %s, AUTN %s, KASME %s'\ % (IMSI, SQN, hexlify(SN_ID).decode('ascii'), hexlify(RAND).decode('ascii'), hexlify(XRES).decode('ascii'), hexlify(AUTN).decode('ascii'), hexlify(KASME).decode('ascii'))) return RAND, XRES, AUTN, KASME
def make_5g_vector(self, IMSI, SNName, AMF=b'\x80\x00', RAND=None): """ return a 5G authentication vector "quadruplet": RAND [16 bytes], XRES* [8 bytes], AUTN [16 bytes], KAUSF [32 bytes] or None if the IMSI is not defined in the db or does not support Milenage or TUAK or SNName is invalid or not allowed SNName is the serving network name, ascii-encoded bytes buffer RAND can be passed as argument """ if not isinstance(SNName, bytes_types) or not 32 <= len(SNName) <= 255: self._log('WNG', '[make_5g_vector] SNName invalid, %s' % SNName.decode('ascii')) return None elif self.PLMN_FILTER is not None: # extract MCC, MNC from SNName (e.g. "5G:mnc012.mcc345.3gppnetwork.org") snname_parts = SNName.split(':')[1].split('.') mcc, mnc = snname_parts[1][3:], snname_parts[0][3:] if mcc + mnc not in self.PLMN_FILTER: self._log('WNG', '[make_5g_vector] SNName not allowed, %s' % SNName.decode('ascii')) return None # # lookup db for authentication Key and counter for IMSI try: K_ALG_SQN_OP = self.db[IMSI] except Exception: self._log('WNG', '[make_5g_vector] IMSI %s not present in AuC.db' % IMSI) return None if len(K_ALG_SQN_OP) == 4: K, ALG, SQN, OP = K_ALG_SQN_OP else: K, ALG, SQN = K_ALG_SQN_OP OP = None # if ALG not in (0, 4): # Milenage / TUAK not supported self._log('WNG', '[make_4g_vector] IMSI %s does not support Milenage or TUAK' % IMSI) return None # # increment SQN counter in the db if SQN >= 0: K_ALG_SQN_OP[2] += 1 self._save_required = True # # pack SQN from integer to a 48-bit buffer SQNb = pack('>Q', SQN)[2:] # # generate challenge if RAND is None: RAND = genrand(16) # if ALG == 0: # compute Milenage functions if OP is not None: XRES, CK, IK, AK = self.Milenage.f2345( K, RAND, OP ) MAC_A = self.Milenage.f1( K, RAND, SQNb, AMF, OP ) else: XRES, CK, IK, AK = self.Milenage.f2345( K, RAND ) MAC_A = self.Milenage.f1( K, RAND, SQNb, AMF ) else: # ALG == 4, compute TUAK functions if OP is not None: XRES, CK, IK, AK = self.TUAK.f2345( K, RAND, OP ) MAC_A = self.TUAK.f1( K, RAND, SQNb, AMF, OP ) else: XRES, CK, IK, AK = self.TUAK.f2345( K, RAND ) MAC_A = self.TUAK.f1( K, RAND, SQNb, AMF ) # SQN_X_AK = xor_buf( SQNb, AK ) AUTN = SQN_X_AK + AMF + MAC_A # convert to AUSF master key KAUSF = conv_501_A2(CK, IK, SNName, SQN_X_AK) XRESstar = conv_501_A4(CK, IK, SNName, RAND, XRES) # # return auth vector self._log('DBG', '[make_4g_vector] IMSI %s, SQN %i, SNName %s: RAND %s, XRES* %s, AUTN %s, KASME %s'\ % (IMSI, SQN, hexlify(SNName).decode('ascii'), hexlify(RAND).decode('ascii'), hexlify(XRESstar).decode('ascii'), hexlify(AUTN).decode('ascii'), hexlify(KAUSF).decode('ascii'))) return RAND, XRESstar, AUTN, KAUSF