Skip to content
Snippets Groups Projects
Verified Commit 2264b954 authored by Nik | Klampfradler's avatar Nik | Klampfradler
Browse files

Migrate to pylibsdm

parent c1b0dee3
No related branches found
No related tags found
1 merge request!14Draft: Resolve "Object / Person identification using SDM NFC cards"
Pipeline #134740 failed
from binascii import unhexlify
from typing import Optional
from django.core.exceptions import BadRequest
from django.http import HttpRequest
from libsdm import EncMode, InvalidMessage, decrypt_sun_message
from libsdm.derive import derive_tag_key, derive_undiversified_key
from libsdm.util import parse_parameters
from pylibsdm.backend.validate import ParamValidator
from aleksis.core.mixins import ExtensibleModel, ObjectAuthenticator
from aleksis.core.util.core_helpers import get_site_preferences
......@@ -17,48 +16,36 @@ class NfcSdmAuthenticator(ObjectAuthenticator):
"""Object authenticator using NFC SDM."""
name = "nfc_sdm"
require_lrp = False
def authenticate(self, request: HttpRequest, obj: ExtensibleModel):
def authenticate(self, request: HttpRequest, obj: Optional[ExtensibleModel]):
"""SUN decrypting authenticator"""
master_key = unhexlify(get_site_preferences()["kort__sdm_master_key"])
try:
param_mode, picc_enc_data, enc_file_data, sdmmac = parse_parameters(request.GET)
except ValueError as e:
raise BadRequest(**e.args)
file_read_key = unhexlify(get_site_preferences()["kort__sdm_file_read_key"])
meta_read_key = unhexlify(get_site_preferences()["kort__sdm_meta_read_key"])
try:
res = decrypt_sun_message(
param_mode=param_mode,
sdm_meta_read_key=derive_undiversified_key(master_key, 1),
sdm_file_read_key=lambda uid: derive_tag_key(master_key, uid, 2),
picc_enc_data=picc_enc_data,
sdmmac=sdmmac,
enc_file_data=enc_file_data,
)
except InvalidMessage:
raise BadRequest("Invalid SUN message or signature")
if self.require_lrp and res["encryption_mode"] != EncMode.LRP:
raise BadRequest("LRP required")
validator = ParamValidator(file_read_key, meta_read_key)
validator.parse_uri(request.build_absolute_uri())
# FIXME do tag tamper check here
if validator.uid is None or validator.read_ctr is None or not validator.cmac_valid:
raise BadRequest("Invalid SUN message or signature")
try:
card = Card.objects.get(chip_number__iexact=res["uid"].hex())
card = Card.objects.get(chip_number__iexact=validator.uid.hex())
except Card.DoesNotExist:
return False
if obj is None:
if self.object is None:
self.object = card.person
obj = card.person
else:
obj = self.object
if card.person != obj:
raise BadRequest("Card is not linked to identified object")
if card.last_read_counter >= res["read_ctr"]:
if card.last_read_counter >= validator.read_ctr:
raise BadRequest("Read counter went backwards, possible replay attack")
card.last_read_counter = res["read_ctr"]
card.last_read_counter = validator.read_ctr
card.save()
return True
class NfcSdmAuthenticatorRequireLrp(NfcSdmAuthenticator):
name = "nfc_sdm_lrp"
require_lrp = True
......@@ -11,11 +11,22 @@ kort = Section("kort", verbose_name=_("Student ID Cards"))
@site_preferences_registry.register
class SdmMasterKey(StringPreference):
"""SDM master key for NFC."""
class SdmFileReadKey(StringPreference):
"""SDM file read key for NFC."""
section = kort
name = "sdm_master_key"
name = "sdm_file_read_key"
default = hexlify(bytes(16))
verbose_name = _("SDM Master Key")
verbose_name = _("SDM file read key")
required = False
@site_preferences_registry.register
class SdmMetaReadKey(StringPreference):
"""SDM meta read key for NFC."""
section = kort
name = "sdm_meta_read_key"
default = hexlify(bytes(16))
verbose_name = _("SDM meta read key")
required = False
[tool.poetry]
name = "AlekSIS-App-Kort"
version = "0.2"
packages = [
{ include = "aleksis" }
]
packages = [{ include = "aleksis" }]
readme = "README.rst"
include = ["CHANGELOG.rst", "LICENCE.rst", "aleksis/**/*.mo"]
description = "AlekSIS (School Information System) — App Kort (manage student IDs)"
authors = ["Margarete Grassl <grasslma@katharineum.de>", "Jonathan Weth <dev@jonathanweth.de>"]
authors = [
"Margarete Grassl <grasslma@katharineum.de>",
"Jonathan Weth <dev@jonathanweth.de>",
]
license = "EUPL-1.2"
homepage = "https://aleksis.org"
repository = "https://edugit.org/AlekSIS/onboarding/AlekSIS-App-Kort"
classifiers = [
"Environment :: Web Environment",
"Intended Audience :: Education",
"Topic :: Education"
"Environment :: Web Environment",
"Intended Audience :: Education",
"Topic :: Education",
]
[[tool.poetry.source]]
......@@ -29,6 +30,7 @@ aleksis-core = "^3.0"
python-barcode = "^0.14.0"
django-formtools = "^2.3"
django-ace = "^1.0.12"
pylibsdm = "^1.0.0a0.dev2"
[tool.poetry.dev-dependencies]
aleksis-builddeps = "*"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment