diff --git a/app/controllers/cardManager.py b/app/controllers/cardManager.py index 762a13b..fc0a71a 100644 --- a/app/controllers/cardManager.py +++ b/app/controllers/cardManager.py @@ -1,6 +1,7 @@ from fastapi import APIRouter, Depends, HTTPException, status from sqlmodel import Session, select from typing import List +from sqlalchemy.exc import NoResultFound from ..model.models import Card from ..services.database import engine, get_session, add_and_refresh @@ -26,13 +27,16 @@ def add_card(*, db: Session = Depends(get_session), group_id: int, admin: bool = @card_router.get("/delete") def del_card(*, db: Session = Depends(get_session), admin: bool = Depends(auth_is_admin)): key = DeleteCard() - # card = db.get(Card, card_id) - # if card is None: - # raise HTTPException(status_code=404, detail="Card not found") - # db.delete(card) - # db.commit() - # return {"message": "Card deleted successfully"} -##TBH not a big fan of having creation using group_id but deletion using card_id + print(key) + try: + card = db.exec(select(Card).where(Card.uuid == key)).one() + except NoResultFound: + print(f"The key:'{key}' was not found in db!") + raise HTTPException(status_code=500, detail="Key on card not found in DB. Please tell an admin about this. KEY={key}") + db.delete(card) + db.commit() + return {"message": "Card deleted successfully"} + @card_router.get("/{group_id}", response_model=List[Card]) def get_cards(*, db: Session = Depends(get_session), group_id: int, admin: bool = Depends(auth_is_admin)): cards = db.exec(select(Card).where(Card.group_id == group_id)).all() diff --git a/app/services/scanner.py b/app/services/scanner.py index 58be59a..af14cdd 100644 --- a/app/services/scanner.py +++ b/app/services/scanner.py @@ -44,34 +44,80 @@ def checkForKey(): def getCardService(timeout: int = 10): cardtype = AnyCardType() cardrequest = CardRequest(timeout=timeout, cardType=cardtype) - print("Please present DESfire tag...") - try: - cardservice = cardrequest.waitforcard() - except CardRequestTimeoutException: - logger.error("No tag detected within the timeout.") - raise Exception("No tag detected within the timeout.") + cardservice = cardrequest.waitforcard() + cardservice.connection.connect() return cardservice +def readFileOnCard(desfire: DESFire): + #create keys + #desfire = DESFire(PCSCDevice(cardservice.connection.component)) + aes_keysettings = KeySettings(key_type=DESFireKeyType.DF_KEY_AES) + keysettings = desfire.get_key_setting() + desKey = DESFireKey(keysettings, "00" * 8) + + # Get real UID + desfire.authenticate(0x0, desKey) + #To get the uid you have to auth with an empty (default) key + uid = desfire.get_real_uid() + applications = desfire.get_application_ids() + try: + assert len(applications) == 1 + assert applications[0] == get_list(MIFARE_APP_ID) + except AssertionError: + logger.error("No application found!") + time.sleep(4) + return + #Then use the key derivation with that uid, the appid, the sysid + diversification_data = [0x01] + uid + get_list(MIFARE_APP_ID) + get_list(MIFARE_SYS_ID) + read_div_key_bytes = diversify_key(get_list(MIFARE_ACL_READ_BASE_KEY), diversification_data, pad_to_32=False) + + #Log in with derived read key + logger.info("Start auth") + aes_app_read_key = DESFireKey(aes_keysettings, read_div_key_bytes) + desfire.select_application(MIFARE_APP_ID) + + desfire.authenticate(MIFARE_ACL_READ_BASE_KEY_ID, aes_app_read_key) + + logger.info("Read data") + file_data = desfire.get_file_settings(MIFARE_ENCRYPTED_FILE_ID) + rdata = desfire.read_file_data(MIFARE_ENCRYPTED_FILE_ID, file_data) + #convert list of int to str + rdata = to_hex_string(rdata).replace(" ", "").lower() + logger.info(f"Data on card: {rdata}") + return rdata + def DeleteCard(): try: checkForKey() from app.main import scanner as scannerThread scannerThread.stop() cardservice = getCardService(15) - cardservice.connection.connect() # Create Desfire object desfire = DESFire(PCSCDevice(cardservice.connection.component)) + rdata = readFileOnCard(desfire=desfire) + # Create Key objects - AES_NULL_KEY_DATA = "00" * 8 - aes_keysettings = KeySettings( - key_type=DESFireKeyType.DF_KEY_AES, - ) - key_settings = desfire.get_key_setting() - aes_null_key = DESFireKey(key_settings, AES_NULL_KEY_DATA) + aes_keysettings = KeySettings(key_type=DESFireKeyType.DF_KEY_AES) + des_keysettings = KeySettings(key_type=DESFireKeyType.DF_KEY_2K3DES) + desKey = DESFireKey(des_keysettings, "00" * 8) aes_master_key = DESFireKey(aes_keysettings, MIFARE_APP_MASTER_KEY) - desfire.authenticate(0x0, aes_null_key) + aes_null_key = DESFireKey(aes_keysettings, "00" * 16) + + desfire.select_application(0x0) + + try: + try: + logger.info("Auth1") + desfire.authenticate(0x0, desKey) + except: + logger.info("Auth2") + desfire.authenticate(0x0, aes_null_key) + except: + logger.info("Auth3") + desfire.authenticate(0x0, aes_master_key) + applications = desfire.get_application_ids() logger.debug(f"Applications: {applications}") if len(applications) == 0: @@ -79,13 +125,15 @@ def DeleteCard(): desfire.select_application(MIFARE_APP_ID) desfire.authenticate(0x0, aes_master_key) + try: desfire.delete_application(MIFARE_APP_ID) + logger.info("App deleted!") except Exception: pass scannerThread.start() - - except Exception as e: + return rdata + except(Exception, AssertionError) as e: logger.error(f"Error in deletion function: {e}", exc_info=True) raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Error: {e}") @@ -96,7 +144,6 @@ def WriteNewCard(): scannerThread.stop() cardservice = getCardService(20) - cardservice.connection.connect() desfire = DESFire(PCSCDevice(cardservice.connection.component)) @@ -104,8 +151,7 @@ def WriteNewCard(): aes_keysettings = KeySettings(key_type=DESFireKeyType.DF_KEY_AES) aes_null_key = DESFireKey(aes_keysettings, "00" * 16) aes_master_key = DESFireKey(aes_keysettings, MIFARE_APP_MASTER_KEY) - keysetting = desfire.get_key_setting() - desKey = DESFireKey(keysetting, "00" * 8) + desKey = DESFireKey(desfire.get_key_setting(), "00" * 8) # Authenticate with default DES key print("Authenticating with default DES key...") @@ -162,7 +208,7 @@ def WriteNewCard(): aes_file_write_key = DESFireKey(aes_keysettings, write_div_key_bytes) desfire.change_key(MIFARE_ACL_WRITE_BASE_KEY_ID, aes_null_key, aes_file_write_key, 0x1) - print("Create encrypted file containing UUID...") + print("Create encrypted file containing key...") file_settings = FileSettings( file_size=16, encryption=DESFireCommunicationMode.ENCRYPTED, @@ -173,16 +219,7 @@ def WriteNewCard(): file_type=DESFireFileType.MDFT_STANDARD_DATA_FILE, ) desfire.create_standard_file(MIFARE_ENCRYPTED_FILE_ID, file_settings) - - print("Read and verify file settings again...") file_data = desfire.get_file_settings(MIFARE_ENCRYPTED_FILE_ID) - assert file_data.file_size == 16 - assert file_data.encryption == DESFireCommunicationMode.ENCRYPTED - assert file_data.permissions is not None - assert file_data.permissions.read_access == MIFARE_ACL_READ_BASE_KEY_ID - assert file_data.permissions.write_access == MIFARE_ACL_WRITE_BASE_KEY_ID - assert file_data.file_type == DESFireFileType.MDFT_STANDARD_DATA_FILE - print(" - File created successfully.") print("Writing UID to encrypted file...") key = secrets.token_hex(16) @@ -226,7 +263,7 @@ class BackgroundScanner: try: card_content = self._read_card() if card_content: - logger.info(to_hex_string(card_content)) + logger.info(f"content: {card_content}") time.sleep(5) logger.debug("READY after success") #self._check_db(card_content) @@ -239,53 +276,17 @@ class BackgroundScanner: time.sleep(6) def _read_card(self): - cardtype = AnyCardType() - cardrequest = CardRequest(timeout=5, cardType=cardtype) + time.sleep(0.5) try: - cardservice = cardrequest.waitforcard() + cardservice = getCardService(3) except CardRequestTimeoutException: logger.debug("No tag detected within the timeout.") return - + # Create Desfire object + desfire = DESFire(PCSCDevice(cardservice.connection.component)) try: - cardservice.connection.connect() - - # Create Desfire object - desfire = DESFire(PCSCDevice(cardservice.connection.component)) - aes_keysettings = KeySettings( - key_type=DESFireKeyType.DF_KEY_AES, - ) - - # Get real UID - mk = DESFireKey(desfire.get_key_setting(), "00" * 8) - desfire.authenticate(0x0, mk) - #To get the uid you have to auth with an empty (default) key - uid = desfire.get_real_uid() - applications = desfire.get_application_ids() - try: - assert len(applications) == 1 - assert applications[0] == get_list(MIFARE_APP_ID) - except AssertionError: - logger.error("No application found!") - time.sleep(4) - return None - #Then use the key derivation with that uid, the appid, the sysid - diversification_data = [0x01] + uid + get_list(MIFARE_APP_ID) + get_list(MIFARE_SYS_ID) - read_div_key_bytes = diversify_key(get_list(MIFARE_ACL_READ_BASE_KEY), diversification_data, pad_to_32=False) - - #Log in with derived read key - logger.info("Start auth") - aes_app_read_key = DESFireKey(aes_keysettings, read_div_key_bytes) - desfire.select_application(MIFARE_APP_ID) - - desfire.authenticate(MIFARE_ACL_READ_BASE_KEY_ID, aes_app_read_key) - - logger.info("Read data") - file_data = desfire.get_file_settings(MIFARE_ENCRYPTED_FILE_ID) - logger.info(f"File settings: {file_data}") - rdata = desfire.read_file_data(MIFARE_ENCRYPTED_FILE_ID, file_data) + rdata = readFileOnCard(desfire=desfire) return rdata - except Exception as e: logger.error(f"something went wrong: {e}") time.sleep(5) \ No newline at end of file