Reading done, writing almost
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from sqlmodel import Session, select
|
||||
from typing import List
|
||||
|
||||
@@ -6,12 +6,16 @@ from ..model.models import Card
|
||||
from ..services.database import engine, get_session, add_and_refresh
|
||||
from ..services.auth import auth_is_admin
|
||||
import uuid as gen_uuid
|
||||
from app.services.scanner import WriteNewCard
|
||||
|
||||
card_router = APIRouter(prefix="/cards", tags=["Card"])
|
||||
|
||||
def register_card(group_id: int):
|
||||
uuid = str(gen_uuid.uuid4()) #hier code für mifare registrierung
|
||||
card = Card(group_id=group_id, uuid=uuid)
|
||||
key = WriteNewCard()
|
||||
if key == None:
|
||||
print("No card registered. Check logs!")
|
||||
raise HTTPException(status.HTTP_417_EXPECTATION_FAILED, detail="No card registered. Check logs!")
|
||||
card = Card(group_id=group_id, uuid=key)
|
||||
return card
|
||||
|
||||
@card_router.post("/{group_id}", response_model=Card)
|
||||
|
||||
@@ -9,6 +9,7 @@ from .services.auth import token_router, create_first_user
|
||||
from app.services.scanner import BackgroundScanner
|
||||
|
||||
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
|
||||
scanner = BackgroundScanner(db=get_session())
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
@@ -16,10 +17,9 @@ async def lifespan(app: FastAPI):
|
||||
create_db_and_tables()
|
||||
create_first_user()
|
||||
print("Database created and tables initialized.")
|
||||
scanner = BackgroundScanner(db=get_session())
|
||||
scanner.start()
|
||||
yield
|
||||
scanner.stop()
|
||||
#scanner.stop()
|
||||
|
||||
app = FastAPI(lifespan=lifespan)
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import logging
|
||||
import threading
|
||||
import time
|
||||
import os
|
||||
import secrets
|
||||
|
||||
from typing import Optional
|
||||
from sqlmodel import Session
|
||||
@@ -15,6 +16,7 @@ from desfire import DESFire, DESFireKey, PCSCDevice, diversify_key, get_list, to
|
||||
from desfire.enums import DESFireCommunicationMode, DESFireFileType, DESFireKeySettings, DESFireKeyType
|
||||
from desfire.schemas import FilePermissions, FileSettings, KeySettings
|
||||
|
||||
|
||||
#ENV vars
|
||||
load_dotenv()
|
||||
MIFARE_APP_MASTER_KEY = os.getenv('MIFARE_APP_MASTER_KEY')
|
||||
@@ -34,7 +36,129 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
if MIFARE_APP_MASTER_KEY == None:
|
||||
logger.critical("NO MASTER KEY LOADED")
|
||||
exit(1)
|
||||
#exit(1)
|
||||
##ADD DELETING APP
|
||||
##
|
||||
|
||||
def WriteNewCard():
|
||||
try:
|
||||
from app.main import scanner as scannerThread
|
||||
scannerThread.stop()
|
||||
|
||||
cardtype = AnyCardType()
|
||||
cardrequest = CardRequest(timeout=10, cardType=cardtype)
|
||||
print("Please present DESfire tag...")
|
||||
try:
|
||||
cardservice = cardrequest.waitforcard()
|
||||
except CardRequestTimeoutException:
|
||||
logger.error("No tag detected within the timeout.")
|
||||
return None
|
||||
|
||||
cardservice.connection.connect()
|
||||
|
||||
# Create Desfire object
|
||||
desfire = DESFire(PCSCDevice(cardservice.connection.component))
|
||||
|
||||
# Create Key objects
|
||||
AES_NULL_KEY_DATA = "00" * 16
|
||||
aes_keysettings = KeySettings(
|
||||
key_type=DESFireKeyType.DF_KEY_AES,
|
||||
)
|
||||
aes_null_key = DESFireKey(aes_keysettings, AES_NULL_KEY_DATA)
|
||||
aes_master_key = DESFireKey(aes_keysettings, MIFARE_APP_MASTER_KEY)
|
||||
|
||||
# Authenticate with default DES key
|
||||
print("Authenticating with default DES key...")
|
||||
key_settings = desfire.get_key_setting()
|
||||
mk = DESFireKey(key_settings, "00" * 8)
|
||||
desfire.authenticate(0x0, mk)
|
||||
|
||||
#get uid
|
||||
uid = desfire.get_real_uid()
|
||||
|
||||
# Set default key
|
||||
print("Setting default key...")
|
||||
desfire.change_default_key(aes_master_key, 0x0)
|
||||
|
||||
# Create application
|
||||
print("Creating application...")
|
||||
app_settings = KeySettings(
|
||||
settings=[
|
||||
DESFireKeySettings.KS_ALLOW_CHANGE_MK,
|
||||
DESFireKeySettings.KS_LISTING_WITHOUT_MK,
|
||||
DESFireKeySettings.KS_CREATE_DELETE_WITHOUT_MK,
|
||||
DESFireKeySettings.KS_CONFIGURATION_CHANGEABLE,
|
||||
],
|
||||
key_type=DESFireKeyType.DF_KEY_AES,
|
||||
)
|
||||
desfire.create_application(MIFARE_APP_ID, app_settings, 4)
|
||||
|
||||
# Verify application creation
|
||||
applications = desfire.get_application_ids()
|
||||
assert len(applications) == 1
|
||||
assert applications[0] == get_list(MIFARE_APP_ID)
|
||||
print(" - Application created successfully.")
|
||||
|
||||
# Select application
|
||||
print("Selecting application...")
|
||||
desfire.select_application(MIFARE_APP_ID)
|
||||
#Auth again as 0key
|
||||
desfire.authenticate(0x0, mk)
|
||||
#change to master
|
||||
desfire.change_key(0x0, mk, aes_master_key, 0x1)
|
||||
|
||||
# Authenticate with AES key, as this has been set as the default key
|
||||
print("Authenticating with master key...")
|
||||
desfire.authenticate(0x0, aes_master_key)
|
||||
|
||||
#generate div data
|
||||
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)
|
||||
write_div_key_bytes = diversify_key(get_list(MIFARE_ACL_WRITE_BASE_KEY), diversification_data, pad_to_32=False)
|
||||
|
||||
print("Changing file read key...")
|
||||
aes_file_read_key = DESFireKey(aes_keysettings, read_div_key_bytes)
|
||||
desfire.change_key(MIFARE_ACL_READ_BASE_KEY_ID, aes_master_key, aes_file_read_key, 0x1)
|
||||
|
||||
print("Changing file write key...")
|
||||
aes_file_write_key = DESFireKey(aes_keysettings, write_div_key_bytes)
|
||||
desfire.change_key(MIFARE_ACL_WRITE_BASE_KEY_ID, aes_master_key, aes_file_write_key, 0x1)
|
||||
|
||||
print("Create encrypted file containing UUID...")
|
||||
file_settings = FileSettings(
|
||||
file_size=32,
|
||||
encryption=DESFireCommunicationMode.ENCRYPTED,
|
||||
permissions=FilePermissions(
|
||||
read_key=MIFARE_ACL_READ_BASE_KEY_ID,
|
||||
write_key=MIFARE_ACL_WRITE_BASE_KEY_ID,
|
||||
),
|
||||
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)
|
||||
desfire.write_file_data(MIFARE_ENCRYPTED_FILE_ID, 0x0, file_data.encryption, get_list(key))
|
||||
|
||||
print("Reading from encrypted file...")
|
||||
rdata = desfire.read_file_data(MIFARE_ENCRYPTED_FILE_ID, file_data)
|
||||
assert rdata == key
|
||||
print(" - Data written successfully.")
|
||||
return key
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error in write function: {e}", exc_info=True)
|
||||
|
||||
|
||||
class BackgroundScanner:
|
||||
def __init__(self, db):
|
||||
@@ -83,25 +207,45 @@ class BackgroundScanner:
|
||||
logger.debug("No tag detected within the timeout.")
|
||||
return
|
||||
|
||||
cardservice.connection.connect()
|
||||
# Create Desfire object
|
||||
desfire = DESFire(PCSCDevice(cardservice.connection.component))
|
||||
aes_keysettings = KeySettings(
|
||||
key_type=DESFireKeyType.DF_KEY_AES,
|
||||
)
|
||||
try:
|
||||
cardservice.connection.connect()
|
||||
|
||||
#Auth
|
||||
logger.info("Start auth")
|
||||
aes_app_mk = DESFireKey(aes_keysettings, MIFARE_APP_MASTER_KEY)
|
||||
# Create Desfire object
|
||||
desfire = DESFire(PCSCDevice(cardservice.connection.component))
|
||||
aes_keysettings = KeySettings(
|
||||
key_type=DESFireKeyType.DF_KEY_AES,
|
||||
)
|
||||
|
||||
apps = desfire.get_application_ids()
|
||||
logger.info(f"app id's are: {apps}")
|
||||
desfire.select_application(MIFARE_APP_ID)
|
||||
# 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=True)
|
||||
|
||||
#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(0x0, aes_app_mk)
|
||||
|
||||
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)
|
||||
return rdata
|
||||
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)
|
||||
return rdata
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"something went wrong: {e}")
|
||||
time.sleep(5)
|
||||
Reference in New Issue
Block a user