diff --git a/lib/S6a_crypt.py b/lib/S6a_crypt.py index c1ab38f..9070c15 100755 --- a/lib/S6a_crypt.py +++ b/lib/S6a_crypt.py @@ -66,7 +66,6 @@ def generate_eutran_vector(key, op_c, amf, sqn, plmn): CryptoLogger.debug("Successfully an S6a_crypt.generate_eutran_vector") return (rand, xres, autn, kasme) - def generate_maa_vector(key, op_c, amf, sqn, plmn): CryptoLogger.debug("Generating Multimedia Authentication Vector") key = key.encode('utf-8') @@ -112,6 +111,31 @@ def generate_maa_vector(key, op_c, amf, sqn, plmn): # print("ik: " + str(ik)) return (rand, autn, xres, ck, ik) +def generate_eap_aka_vector(key, op_c, amf, sqn, plmn): + CryptoLogger.debug("Generating EAP-AKA Vector") + key = key.encode('utf-8') + CryptoLogger.debug("Input K: " + str(key)) + key = binascii.unhexlify(key) + + op_c = op_c.encode('utf-8') + CryptoLogger.debug("Input OPc: " + str(op_c)) + op_c = binascii.unhexlify(op_c) + + amf = str(amf) + amf = amf.encode('utf-8') + amf = binascii.unhexlify(amf) + CryptoLogger.debug("Input AMF: " + str(amf)) + + sqn = int(sqn) + CryptoLogger.debug("Input SQN: " + str(sqn)) + + plmn = plmn.encode('utf-8') + plmn = binascii.unhexlify(plmn) + CryptoLogger.debug("Input PLMN: " + str(plmn)) + + crypto_obj = Milenage(amf) + + return crypto_obj.generate_eap_aka_vector(key, op_c, sqn, plmn) def generate_resync_s6a(key, op_c, amf, auts, rand): CryptoLogger.debug("Generating correct SQN value from AUTS") diff --git a/lib/database.py b/lib/database.py index 043da60..614eab2 100755 --- a/lib/database.py +++ b/lib/database.py @@ -1518,6 +1518,37 @@ def Get_Vectors_AuC(self, auc_id, action, **kwargs): self.Update_AuC(auc_id, sqn=key_data['sqn']+100) return vector_dict + elif action == "2g3g": + rand, autn, xres, ck, ik = S6a_crypt.generate_maa_vector(key_data['ki'], key_data['opc'], key_data['amf'], key_data['sqn'], kwargs['plmn']) + vector_list = [] + self.logTool.log(service='Database', level='debug', message="Generating " + str(kwargs['requested_vectors']) + " vectors for GSM use", redisClient=self.redisMessaging) + while kwargs['requested_vectors'] != 0: + self.logTool.log(service='Database', level='debug', message="RAND is: " + str(rand), redisClient=self.redisMessaging) + self.logTool.log(service='Database', level='debug', message="AUTN is: " + str(autn), redisClient=self.redisMessaging) + + vector_dict['rand'] = binascii.hexlify(rand).decode("utf-8") + vector_dict['autn'] = binascii.hexlify(autn).decode("utf-8") + vector_dict['xres'] = binascii.hexlify(xres).decode("utf-8") + vector_dict['ck'] = binascii.hexlify(ck).decode("utf-8") + vector_dict['ik'] = binascii.hexlify(ik).decode("utf-8") + + kwargs['requested_vectors'] = kwargs['requested_vectors'] - 1 + vector_list.append(vector_dict) + self.Update_AuC(auc_id, sqn=key_data['sqn']+100) + return vector_list + + elif action == "eap_aka": + rand, xres, autn, mac_a, ak = S6a_crypt.generate_eap_aka_vector(key_data['ki'], key_data['opc'], key_data['amf'], key_data['sqn'], kwargs['plmn']) + self.logTool.log(service='Database', level='debug', message="RAND is: " + str(rand), redisClient=self.redisMessaging) + self.logTool.log(service='Database', level='debug', message="AUTN is: " + str(autn), redisClient=self.redisMessaging) + vector_dict['rand'] = binascii.hexlify(rand).decode("utf-8") + vector_dict['autn'] = binascii.hexlify(autn).decode("utf-8") + vector_dict['xres'] = binascii.hexlify(xres).decode("utf-8") + vector_dict['mac'] = binascii.hexlify(mac_a).decode("utf-8") + vector_dict['ak'] = binascii.hexlify(ak).decode("utf-8") + self.Update_AuC(auc_id, sqn=key_data['sqn']+100) + return vector_dict + elif action == "Digest-MD5": self.logTool.log(service='Database', level='debug', message="Generating Digest-MD5 Auth vectors", redisClient=self.redisMessaging) self.logTool.log(service='Database', level='debug', message="key_data: " + str(key_data), redisClient=self.redisMessaging) @@ -1526,6 +1557,8 @@ def Get_Vectors_AuC(self, auc_id, action, **kwargs): vector_dict['nonce'] = nonce vector_dict['SIP_Authenticate'] = key_data['ki'] return vector_dict + else: + self.logTool.log(service='Database', level='error', message="Invalid action: " + str(action), redisClient=self.redisMessaging) def Get_APN(self, apn_id): self.logTool.log(service='Database', level='debug', message="Getting APN " + str(apn_id), redisClient=self.redisMessaging) diff --git a/lib/milenage.py b/lib/milenage.py index ef31daa..7524eb8 100644 --- a/lib/milenage.py +++ b/lib/milenage.py @@ -132,6 +132,35 @@ def generate_maa_vector(self, key, opc, sqn, plmn): return rand, xres, autn, ck, ik + def generate_eap_aka_vector(self, key, opc, sqn, plmn): + CryptoLogger.debug("Called milenage.generate_eap_aka_vector") + + CryptoLogger.debug("Generating SQN bytes") + CryptoLogger.debug("Current SQN value is " + str(sqn) + " and is " + str(len(str(sqn))) + " long") + sqn_bytes = bytearray.fromhex('{:012x}'.format(sqn)) + #With some inputs a space is added here. + #See https://stackoverflow.com/questions/57697983/how-do-i-interpret-spaces-in-python-byte-arrays + CryptoLogger.debug("Generated SQN bytes") + CryptoLogger.debug("SQN bytes is " + str(sqn_bytes)) + + CryptoLogger.debug("Generating rand") + rand = Milenage.generate_rand() + CryptoLogger.debug("Generated rand") + + CryptoLogger.debug("Generating f1") + mac_a, _ = Milenage.f1(key, sqn_bytes, rand, opc, self.amf) + CryptoLogger.debug("Generated f1") + + + CryptoLogger.debug("Generating f2") + xres, ak = Milenage.f2_f5(key, rand, opc) + CryptoLogger.debug("Generated f2") + + CryptoLogger.debug("Generate generate_autn") + autn = Milenage.generate_autn(sqn_bytes, ak, mac_a, self.amf) + + return rand, xres, autn, mac_a, ak + def generate_auts(self, key, opc, rand, sqn): """ Compute AUTS for re-synchronization using the formula diff --git a/services/apiService.py b/services/apiService.py index 2a0dae1..d32bcf6 100644 --- a/services/apiService.py +++ b/services/apiService.py @@ -100,19 +100,24 @@ APN_model = api.schema_model('APN JSON', databaseClient.Generate_JSON_Model_for_Flask(APN) ) + Serving_APN_model = api.schema_model('Serving APN JSON', databaseClient.Generate_JSON_Model_for_Flask(Serving_APN) ) + AUC_model = api.schema_model('AUC JSON', databaseClient.Generate_JSON_Model_for_Flask(AUC) ) + SUBSCRIBER_model = api.schema_model('SUBSCRIBER JSON', databaseClient.Generate_JSON_Model_for_Flask(SUBSCRIBER) ) + SUBSCRIBER_ROUTING_model = api.schema_model('SUBSCRIBER_ROUTING JSON', databaseClient.Generate_JSON_Model_for_Flask(SUBSCRIBER_ROUTING) ) + #Legacy support for sh_profile. sh_profile is deprecated as of v1.0.1. imsSubscriberModel = databaseClient.Generate_JSON_Model_for_Flask(TFT) imsSubscriberModel['sh_profile'] = fields.String(required=False, description=IMS_SUBSCRIBER.sh_profile.doc), @@ -120,18 +125,23 @@ IMS_SUBSCRIBER_model = api.schema_model('IMS_SUBSCRIBER JSON', databaseClient.Generate_JSON_Model_for_Flask(TFT) ) + TFT_model = api.schema_model('TFT JSON', databaseClient.Generate_JSON_Model_for_Flask(TFT) ) + CHARGING_RULE_model = api.schema_model('CHARGING_RULE JSON', databaseClient.Generate_JSON_Model_for_Flask(CHARGING_RULE) ) + EIR_model = api.schema_model('EIR JSON', databaseClient.Generate_JSON_Model_for_Flask(EIR) ) + IMSI_IMEI_HISTORY_model = api.schema_model('IMSI_IMEI_HISTORY JSON', databaseClient.Generate_JSON_Model_for_Flask(IMSI_IMEI_HISTORY) ) + SUBSCRIBER_ATTRIBUTES_model = api.schema_model('SUBSCRIBER_ATTRIBUTES JSON', databaseClient.Generate_JSON_Model_for_Flask(SUBSCRIBER_ATTRIBUTES) ) @@ -459,6 +469,40 @@ def get(self): print(E) return handle_exception(E) +@ns_auc.route('/eap_aka/plmn//imsi/') +class PyHSS_AUC_Get_EAP_AKA_Vectors(Resource): + def get(self, imsi, plmn): + '''Get EAP-AKA vectors for specified IMSI and PLMN''' + try: + #Get data from AuC + auc_data = databaseClient.Get_AuC(imsi=imsi) + print("Got AuC Data OK - Generating Vectors") + plmn = diameterClient.EncodePLMN(mcc=plmn[0:3], mnc=plmn[3:]) + print("Encoded PLMN into: " + str(plmn)) + vector_dict = databaseClient.Get_Vectors_AuC(auc_data['auc_id'], action='eap_aka', plmn=plmn) + print("Got Vectors: " + str(vector_dict)) + return vector_dict, 200 + except Exception as E: + print(E) + return handle_exception(E) + +@ns_auc.route('/aka/vector_count//imsi/') +class PyHSS_AUC_Get_AKA_Vectors(Resource): + def get(self, imsi, vector_count): + '''Get AKA vectors for specified IMSI and PLMN''' + try: + #Get data from AuC + auc_data = databaseClient.Get_AuC(imsi=imsi) + print("Got AuC Data OK - Generating " + str(vector_count) + " Vectors") + + plmn = diameterClient.EncodePLMN(mcc=config['hss']['MCC'], mnc=config['hss']['MNC']) + vector_dict = databaseClient.Get_Vectors_AuC(auc_data['auc_id'], action='2g3g', plmn=plmn, requested_vectors=int(vector_count)) + print("Got Vectors: " + str(vector_dict)) + return vector_dict, 200 + except Exception as E: + print(E) + return handle_exception(E) + @ns_subscriber.route('/') class PyHSS_SUBSCRIBER_Get(Resource): def get(self, subscriber_id):