Ejemplo n.º 1
0
    def __init__(self, device):

        self.device = device

        self.id = None
        self.algorithm = None

        self._secret = BinaryDataType(self.device.pskc)
        self._counter = IntegerDataType(self.device.pskc)
        self._time_offset = IntegerDataType(self.device.pskc)
        self._time_interval = IntegerDataType(self.device.pskc)
        self._time_drift = IntegerDataType(self.device.pskc)

        self.issuer = None
        self.key_profile = None
        self.key_reference = None
        self.friendly_name = None
        self.key_userid = None

        self.algorithm_suite = None

        self.challenge_encoding = None
        self.challenge_min_length = None
        self.challenge_max_length = None
        self.challenge_check = None

        self.response_encoding = None
        self.response_length = None
        self.response_check = None

        self.policy = Policy(self)
Ejemplo n.º 2
0
    def __init__(self, device):

        self.device = device

        self.id = None
        self.algorithm = None

        self.issuer = None
        self.key_profile = None
        self.key_reference = None
        self.friendly_name = None
        self.key_userid = None

        self.algorithm_suite = None

        self.challenge_encoding = None
        self.challenge_min_length = None
        self.challenge_max_length = None
        self.challenge_check = None

        self.response_encoding = None
        self.response_length = None
        self.response_check = None

        self.policy = Policy(self)
Ejemplo n.º 3
0
    def __init__(self, pskc, key_package=None):

        self.pskc = pskc

        self.id = None
        self.algorithm = None

        self._secret = BinaryDataType(self)
        self._counter = IntegerDataType(self)
        self._time_offset = IntegerDataType(self)
        self._time_interval = IntegerDataType(self)
        self._time_drift = IntegerDataType(self)

        self.issuer = None
        self.key_profile = None
        self.key_reference = None
        self.friendly_name = None
        self.key_userid = None

        self.manufacturer = None
        self.serial = None
        self.model = None
        self.issue_no = None
        self.device_binding = None
        self.start_date = None
        self.expiry_date = None
        self.device_userid = None

        self.crypto_module = None

        self.algorithm_suite = None

        self.challenge_encoding = None
        self.challenge_min_length = None
        self.challenge_max_length = None
        self.challenge_check = None

        self.response_encoding = None
        self.response_length = None
        self.response_check = None

        self.policy = Policy(self)

        self.parse(key_package)
Ejemplo n.º 4
0
class Key(object):
    """Representation of a single key from a PSKC file.

    Instances of this class provide the following properties:

      id: unique key identifier (should be constant between interchanges)
      algorithm: identifier of the PSKC algorithm profile (URI)
      secret: the secret key itself (binary form, automatically decrypted)
      counter: event counter for event-based OTP
      time_offset: time offset for time-based OTP algorithms (in intervals)
      time_interval: time interval for time-based OTP in seconds
      time_drift: device clock drift (negative means device is slow)
      issuer: party that issued the key
      key_profile: reference to pre-shared key profile information
      key_reference: reference to an external key
      friendly_name: human-readable name for the secret key
      key_userid: user distinguished name associated with the key
      manufacturer: name of the organisation that made the device
      serial: serial number of the device
      model: device model description
      issue_no: issue number per serial number
      device_binding: device (class) identifier for the key to be loaded upon
      start_date: key should not be used before this date
      expiry_date: key or device may expire after this date
      device_userid: user distinguished name associated with the device
      crypto_module: id of module to which keys are provisioned within device
      algorithm_suite: additional algorithm characteristics (e.g. used hash)
      challenge_encoding: format of the challenge for CR devices
      challenge_min_length: minimum accepted challenge length by device
      challenge_max_length: maximum size challenge accepted by the device
      challenge_check: whether the device will check an embedded check digit
      response_encoding: format of the response the device will generate
      response_length: the length of the response of the device
      response_check: whether the device appends a Luhn check digit
      policy: reference to policy information (see Policy class)
    """

    def __init__(self, pskc, key_package=None):

        self.pskc = pskc

        self.id = None
        self.algorithm = None

        self._secret = BinaryDataType(self)
        self._counter = IntegerDataType(self)
        self._time_offset = IntegerDataType(self)
        self._time_interval = IntegerDataType(self)
        self._time_drift = IntegerDataType(self)

        self.issuer = None
        self.key_profile = None
        self.key_reference = None
        self.friendly_name = None
        self.key_userid = None

        self.manufacturer = None
        self.serial = None
        self.model = None
        self.issue_no = None
        self.device_binding = None
        self.start_date = None
        self.expiry_date = None
        self.device_userid = None

        self.crypto_module = None

        self.algorithm_suite = None

        self.challenge_encoding = None
        self.challenge_min_length = None
        self.challenge_max_length = None
        self.challenge_check = None

        self.response_encoding = None
        self.response_length = None
        self.response_check = None

        self.policy = Policy(self)

        self.parse(key_package)

    def parse(self, key_package):
        """Read key information from the provided <KeyPackage> tree."""
        from pskc.xml import find, findtext, findtime, getint, getbool

        if key_package is None:
            return

        key = find(key_package, "pskc:Key")
        if key is not None:
            self.id = key.get("Id")
            self.algorithm = key.get("Algorithm")

        data = find(key_package, "pskc:Key/pskc:Data")
        if data is not None:
            self._secret.parse(find(data, "pskc:Secret"))
            self._counter.parse(find(data, "pskc:Counter"))
            self._time_offset.parse(find(data, "pskc:Time"))
            self._time_interval.parse(find(data, "pskc:TimeInterval"))
            self._time_drift.parse(find(data, "pskc:TimeDrift"))

        self.issuer = findtext(key_package, "pskc:Key/pskc:Issuer")
        self.key_profile = findtext(key_package, "pskc:Key/pskc:KeyProfileId")
        self.key_reference = findtext(key_package, "pskc:Key/pskc:KeyReference")
        self.friendly_name = findtext(key_package, "pskc:Key/pskc:FriendlyName")
        # TODO: support multi-language values of <FriendlyName>
        self.key_userid = findtext(key_package, "pskc:Key/pskc:UserId")

        self.manufacturer = findtext(key_package, "pskc:DeviceInfo/pskc:Manufacturer")
        self.serial = findtext(key_package, "pskc:DeviceInfo/pskc:SerialNo")
        self.model = findtext(key_package, "pskc:DeviceInfo/pskc:Model")
        self.issue_no = findtext(key_package, "pskc:DeviceInfo/pskc:IssueNo")
        self.device_binding = findtext(key_package, "pskc:DeviceInfo/pskc:DeviceBinding")
        self.start_date = findtime(key_package, "pskc:DeviceInfo/pskc:StartDate")
        self.expiry_date = findtime(key_package, "pskc:DeviceInfo/pskc:ExpiryDate")
        self.device_userid = findtext(key_package, "pskc:DeviceInfo/pskc:UserId")

        self.crypto_module = findtext(key_package, "pskc:CryptoModuleInfo/pskc:Id")

        self.algorithm_suite = findtext(key_package, "pskc:Key/pskc:AlgorithmParameters/pskc:Suite")

        challenge_format = find(key_package, "pskc:Key/pskc:AlgorithmParameters/pskc:ChallengeFormat")
        if challenge_format is not None:
            self.challenge_encoding = challenge_format.get("Encoding")
            self.challenge_min_length = getint(challenge_format, "Min")
            self.challenge_max_length = getint(challenge_format, "Max")
            self.challenge_check = getbool(challenge_format, "CheckDigits")

        response_format = find(key_package, "pskc:Key/pskc:AlgorithmParameters/pskc:ResponseFormat")
        if response_format is not None:
            self.response_encoding = response_format.get("Encoding")
            self.response_length = getint(response_format, "Length")
            self.response_check = getbool(response_format, "CheckDigits")

        self.policy.parse(find(key_package, "pskc:Key/pskc:Policy"))

    def make_xml(self, container):
        from pskc.xml import mk_elem

        key_package = mk_elem(container, "pskc:KeyPackage", empty=True)

        if any(
            x is not None
            for x in (
                self.manufacturer,
                self.serial,
                self.model,
                self.issue_no,
                self.device_binding,
                self.start_date,
                self.expiry_date,
                self.device_userid,
            )
        ):
            device_info = mk_elem(key_package, "pskc:DeviceInfo", empty=True)
            mk_elem(device_info, "pskc:Manufacturer", self.manufacturer)
            mk_elem(device_info, "pskc:SerialNo", self.serial)
            mk_elem(device_info, "pskc:Model", self.model)
            mk_elem(device_info, "pskc:IssueNo", self.issue_no)
            mk_elem(device_info, "pskc:DeviceBinding", self.device_binding)
            mk_elem(device_info, "pskc:StartDate", self.start_date)
            mk_elem(device_info, "pskc:ExpiryDate", self.expiry_date)
            mk_elem(device_info, "pskc:UserId", self.device_userid)

        if self.crypto_module is not None:
            crypto_module = mk_elem(key_package, "pskc:CryptoModuleInfo", empty=True)
            mk_elem(crypto_module, "pskc:Id", self.crypto_module)

        key = mk_elem(key_package, "pskc:Key", empty=True, Id=self.id, Algorithm=self.algorithm)
        mk_elem(key, "pskc:Issuer", self.issuer)

        if any((self.algorithm_suite, self.challenge_encoding, self.response_encoding, self.response_length)):
            parameters = mk_elem(key, "pskc:AlgorithmParameters", empty=True)
            mk_elem(parameters, "pskc:Suite", self.algorithm_suite)
            mk_elem(
                parameters,
                "pskc:ChallengeFormat",
                Encoding=self.challenge_encoding,
                Min=self.challenge_min_length,
                Max=self.challenge_max_length,
                CheckDigits=self.challenge_check,
            )
            mk_elem(
                parameters,
                "pskc:ResponseFormat",
                Encoding=self.response_encoding,
                Length=self.response_length,
                CheckDigits=self.response_check,
            )

        mk_elem(key, "pskc:KeyProfileId", self.key_profile)
        mk_elem(key, "pskc:KeyReference", self.key_reference)
        mk_elem(key, "pskc:FriendlyName", self.friendly_name)
        self._secret.make_xml(key, "pskc:Secret")
        self._counter.make_xml(key, "pskc:Counter")
        self._time_offset.make_xml(key, "pskc:Time")
        self._time_interval.make_xml(key, "pskc:TimeInterval")
        self._time_drift.make_xml(key, "pskc:TimeDrift")
        mk_elem(key, "pskc:UserId", self.key_userid)

        self.policy.make_xml(key)

    secret = property(
        fget=lambda self: self._secret.get_value(),
        fset=lambda self, x: self._secret.set_value(x),
        doc="The secret key itself.",
    )

    counter = property(
        fget=lambda self: self._counter.get_value(),
        fset=lambda self, x: self._counter.set_value(x),
        doc="An event counter for event-based OTP.",
    )

    time_offset = property(
        fget=lambda self: self._time_offset.get_value(),
        fset=lambda self, x: self._time_offset.set_value(x),
        doc="A time offset for time-based OTP (number of intervals).",
    )

    time_interval = property(
        fget=lambda self: self._time_interval.get_value(),
        fset=lambda self, x: self._time_interval.set_value(x),
        doc="A time interval in seconds.",
    )

    time_drift = property(
        fget=lambda self: self._time_drift.get_value(),
        fset=lambda self, x: self._time_drift.set_value(x),
        doc="Device clock drift value (number of time intervals).",
    )

    def check(self):
        """Check if all MACs in the message are valid."""
        if any(
            (
                self._secret.check(),
                self._counter.check(),
                self._time_offset.check(),
                self._time_interval.check(),
                self._time_drift.check(),
            )
        ):
            return True