Example #1
0
    def generate_ec_key(self, key_slot, curve_name, timestamp=None):
        require_version(self.version, (5, 2, 0))
        """Requires Admin PIN verification."""
        if timestamp is None:
            timestamp = int(time.time())

        attributes = _format_ec_attributes(key_slot, curve_name)
        self._put_data(key_slot.key_id, attributes)
        resp = self._app.send_apdu(0, INS.GENERATE_ASYM, 0x80, 0x00, key_slot.crt)

        data = Tlv.parse_dict(Tlv.unpack(0x7F49, resp))
        pubkey_enc = data[0x86]

        self._put_data(key_slot.gen_time, struct.pack(">I", timestamp))
        # TODO: Calculate and write fingerprint

        if curve_name == "x25519":
            # Added in 2.0
            from cryptography.hazmat.primitives.asymmetric import x25519

            return x25519.X25519PublicKey.from_public_bytes(pubkey_enc)
        if curve_name == "ed25519":
            # Added in 2.6
            from cryptography.hazmat.primitives.asymmetric import ed25519

            return ed25519.Ed25519PublicKey.from_public_bytes(pubkey_enc)

        curve = getattr(ec, curve_name.upper())
        try:
            # Added in cryptography 2.5
            return ec.EllipticCurvePublicKey.from_encoded_point(curve(), pubkey_enc)
        except AttributeError:
            return ec.EllipticCurvePublicNumbers.from_encoded_point(
                curve(), pubkey_enc
            ).public_key(default_backend())
Example #2
0
        def test_read_write_certificate_as_object(self):
            with self.assertRaises(SystemExit):
                ykman_cli("piv", "read-object", hex(OBJECT_ID.AUTHENTICATION))

            cert = generate_self_signed_certificate()
            cert_bytes_der = cert.public_bytes(
                encoding=serialization.Encoding.DER)

            input_tlv = Tlv(0x70, cert_bytes_der) + Tlv(0x71, b"\0") + Tlv(
                0xFE, b"")

            ykman_cli(
                "piv",
                "write-object",
                hex(OBJECT_ID.AUTHENTICATION),
                "-",
                "-m",
                DEFAULT_MANAGEMENT_KEY,
                input=input_tlv,
            )

            output1 = ykman_cli.with_bytes_output(
                "piv", "read-object", hex(OBJECT_ID.AUTHENTICATION))
            output_cert_bytes = Tlv.parse_dict(output1)[0x70]
            self.assertEqual(output_cert_bytes, cert_bytes_der)

            output2 = ykman_cli.with_bytes_output(
                "piv",
                "export-certificate",
                hex(SLOT.AUTHENTICATION),
                "-",
                "--format",
                "DER",
            )
            self.assertEqual(output2, cert_bytes_der)
Example #3
0
 def __init__(self, raw_data: bytes = Tlv(0x80)):
     data = Tlv.parse_dict(Tlv(raw_data).value)
     self._flags = struct.unpack(">B",
                                 data[0x81])[0] if 0x81 in data else None
     self.salt = data.get(0x82)
     self.pin_timestamp = struct.unpack(
         ">I", data[0x83]) if 0x83 in data else None
Example #4
0
    def generate_rsa_key(self, key_slot, key_size, timestamp=None):
        """Requires Admin PIN verification."""
        if (4, 2, 0) <= self.version < (4, 3, 5):
            raise NotSupportedError(
                "RSA key generation not supported on this YubiKey")

        if timestamp is None:
            timestamp = int(time.time())

        neo = self.version < (4, 0, 0)
        if not neo:
            attributes = _format_rsa_attributes(key_size)
            self._put_data(key_slot.key_id, attributes)
        elif key_size != 2048:
            raise ValueError("Unsupported key size!")
        resp = self._app.send_apdu(0, INS.GENERATE_ASYM, 0x80, 0x00,
                                   key_slot.crt)

        data = Tlv.parse_dict(Tlv.unpack(0x7F49, resp))
        numbers = rsa.RSAPublicNumbers(bytes2int(data[0x82]),
                                       bytes2int(data[0x81]))

        self._put_data(key_slot.gen_time, struct.pack(">I", timestamp))
        # TODO: Calculate and write fingerprint

        return numbers.public_key(default_backend())
Example #5
0
 def parse(cls, data: bytes) -> "KdfData":
     fields = Tlv.parse_dict(data)
     return cls(
         _parse_int(fields, 0x81, KdfAlgorithm, KdfAlgorithm.NONE),
         _parse_int(fields, 0x82, HashAlgorithm),
         _parse_int(fields, 0x83),
         fields.get(0x84),
         fields.get(0x85),
         fields.get(0x86),
         fields.get(0x87),
         fields.get(0x88),
     )
    def test_read_write_certificate_as_object(self, ykman_cli):
        with pytest.raises(SystemExit):
            ykman_cli("piv", "objects", "export",
                      hex(OBJECT_ID.AUTHENTICATION), "-")

        cert = generate_self_signed_certificate()
        cert_bytes_der = cert.public_bytes(encoding=serialization.Encoding.DER)

        input_tlv = Tlv(0x70, cert_bytes_der) + Tlv(0x71, b"\0") + Tlv(
            0xFE, b"")

        ykman_cli(
            "piv",
            "objects",
            "import",
            hex(OBJECT_ID.AUTHENTICATION),
            "-",
            "-m",
            DEFAULT_MANAGEMENT_KEY,
            input=input_tlv,
        )

        output1 = ykman_cli("piv", "objects", "export",
                            hex(OBJECT_ID.AUTHENTICATION), "-").stdout_bytes
        output_cert_bytes = Tlv.parse_dict(output1)[0x70]
        assert output_cert_bytes == cert_bytes_der

        output2 = ykman_cli(
            "piv",
            "certificates",
            "export",
            hex(SLOT.AUTHENTICATION),
            "-",
            "--format",
            "DER",
        ).stdout_bytes
        assert output2 == cert_bytes_der
Example #7
0
    def generate_rsa_key(self, key_slot, key_size, timestamp=None):
        """Requires Admin PIN verification."""
        ensure_not_cve201715361_vulnerable_firmware_version(self.version)

        if timestamp is None:
            timestamp = int(time.time())

        neo = self.version < (4, 0, 0)
        if not neo:
            attributes = _format_rsa_attributes(key_size)
            self._put_data(key_slot.key_id, attributes)
        elif key_size != 2048:
            raise ValueError("Unsupported key size!")
        resp = self._app.send_apdu(0, INS.GENERATE_ASYM, 0x80, 0x00, key_slot.crt)

        data = Tlv.parse_dict(Tlv.unwrap(0x7F49, resp))
        numbers = rsa.RSAPublicNumbers(
            int_from_bytes(data[0x82], "big"), int_from_bytes(data[0x81], "big")
        )

        self._put_data(key_slot.gen_time, struct.pack(">I", timestamp))
        # TODO: Calculate and write fingerprint

        return numbers.public_key(default_backend())
Example #8
0
 def __init__(self, raw_data: bytes = Tlv(0x88)):
     data = Tlv.parse_dict(Tlv(raw_data).value)
     self.key = data.get(0x89)