Skip to content

Commit

Permalink
OpenPGP: Check PIN lengths.
Browse files Browse the repository at this point in the history
  • Loading branch information
dainnilsson committed Jan 12, 2024
1 parent ccebc66 commit 5350f52
Showing 1 changed file with 23 additions and 9 deletions.
32 changes: 23 additions & 9 deletions yubikit/openpgp.py
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,7 @@ class Kdf(abc.ABC):
algorithm: ClassVar[int]

@abc.abstractmethod
def process(self, pin: str, pw: PW) -> bytes:
def process(self, pw: PW, pin: str) -> bytes:
"""Run the KDF on the input PIN."""

@classmethod
Expand Down Expand Up @@ -1147,11 +1147,14 @@ def set_pin_attempts(
)
logger.info("Number of PIN attempts has been changed")

def get_kdf(self):
def get_kdf(self) -> Kdf:
"""Get the Key Derivation Function data object."""
if EXTENDED_CAPABILITY_FLAGS.KDF not in self.extended_capabilities.flags:
return KdfNone()
return Kdf.parse(self.get_data(DO.KDF))
kdf: Kdf = KdfNone()
else:
kdf = Kdf.parse(self.get_data(DO.KDF))
logger.debug("Using KDF: {kdf}")
return kdf

def set_kdf(self, kdf: Kdf) -> None:
"""Set up a PIN Key Derivation Function.
Expand All @@ -1173,8 +1176,19 @@ def set_kdf(self, kdf: Kdf) -> None:
self.put_data(DO.KDF, kdf)
logger.info("KDF settings changed")

def _process_pin(self, kdf: Kdf, pw: PW, pin: str) -> bytes:
pin_bytes = kdf.process(pw, pin)
pin_len = len(pin_bytes)
min_len = 6 if pw is PW.USER else 8
max_len = self._app_data.discretionary.pw_status.get_max_len(pw)
if not (min_len <= pin_len <= max_len):
raise ValueError(
f"{pw.name} PIN length must be in the range {min_len}-{max_len}"
)
return pin_bytes

def _verify(self, pw: PW, pin: str, mode: int = 0) -> None:
pin_enc = self.get_kdf().process(pw, pin)
pin_enc = self._process_pin(self.get_kdf(), pw, pin)
try:
self.protocol.send_apdu(0, INS.VERIFY, 0, pw + mode, pin_enc)
except ApduError as e:
Expand Down Expand Up @@ -1225,7 +1239,7 @@ def _change(self, pw: PW, pin: str, new_pin: str) -> None:
INS.CHANGE_PIN,
0,
pw,
kdf.process(pw, pin) + kdf.process(pw, new_pin),
self._process_pin(kdf, pw, pin) + self._process_pin(kdf, pw, new_pin),
)
except ApduError as e:
if e.sw == SW.SECURITY_CONDITION_NOT_SATISFIED:
Expand Down Expand Up @@ -1262,7 +1276,7 @@ def set_reset_code(self, reset_code: str) -> None:
:param reset_code: The Reset Code for User PIN.
"""
logger.debug("Setting a new PIN Reset Code")
data = self.get_kdf().process(PW.RESET, reset_code)
data = self._process_pin(self.get_kdf(), PW.RESET, reset_code)
self.put_data(DO.RESETTING_CODE, data)
logger.info("New Reset Code has been set")

Expand All @@ -1277,10 +1291,10 @@ def reset_pin(self, new_pin: str, reset_code: Optional[str] = None) -> None:
logger.debug("Resetting User PIN")
p1 = 2
kdf = self.get_kdf()
data = kdf.process(PW.USER, new_pin)
data = self._process_pin(kdf, PW.USER, new_pin)
if reset_code:
logger.debug("Using Reset Code")
data = kdf.process(PW.RESET, reset_code) + data
data = self._process_pin(kdf, PW.RESET, reset_code) + data
p1 = 0

try:
Expand Down

0 comments on commit 5350f52

Please sign in to comment.