Skip to content

Commit

Permalink
Merge pull request #173 from nickvsnetworking/EAP_AKA_API
Browse files Browse the repository at this point in the history
Vectors via API
  • Loading branch information
nickvsnetworking authored Dec 2, 2023
2 parents 4a60f8a + b5fd292 commit 6899837
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 1 deletion.
26 changes: 25 additions & 1 deletion lib/S6a_crypt.py
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down Expand Up @@ -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")
Expand Down
33 changes: 33 additions & 0 deletions lib/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down
29 changes: 29 additions & 0 deletions lib/milenage.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
44 changes: 44 additions & 0 deletions services/apiService.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,38 +100,48 @@
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),

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)
)
Expand Down Expand Up @@ -459,6 +469,40 @@ def get(self):
print(E)
return handle_exception(E)

@ns_auc.route('/eap_aka/plmn/<string:plmn>/imsi/<string: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/<string:vector_count>/imsi/<string: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('/<string:subscriber_id>')
class PyHSS_SUBSCRIBER_Get(Resource):
def get(self, subscriber_id):
Expand Down

0 comments on commit 6899837

Please sign in to comment.