forked from Yubico/yubikey-manager
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5aed7e4
commit 9105104
Showing
13 changed files
with
833 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
[bandit] | ||
exclude: /test,/.tox | ||
exclude: /tests |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
[mypy] | ||
files = yubikit/,ykman/ | ||
|
||
[mypy-smartcard.*] | ||
ignore_missing_imports = True |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
from yubikit.core import TRANSPORT | ||
from ykman.device import is_fips_version | ||
from inspect import signature, Parameter, isgeneratorfunction | ||
from makefun import wraps | ||
|
||
import pytest | ||
|
||
|
||
def condition(check, message="Condition not satisfied"): | ||
def deco(func): | ||
sig = signature(func) | ||
if "info" not in sig.parameters: | ||
params = [Parameter("info", kind=Parameter.POSITIONAL_OR_KEYWORD)] | ||
params.extend(sig.parameters.values()) | ||
sig = sig.replace(parameters=params) | ||
|
||
if isgeneratorfunction(func): | ||
|
||
def wrapper(info, *args, **kwargs): | ||
if not check(info): | ||
pytest.skip(message) | ||
yield from func(*args, **kwargs) | ||
|
||
else: | ||
|
||
def wrapper(info, *args, **kwargs): | ||
if not check(info): | ||
pytest.skip(message) | ||
return func(*args, **kwargs) | ||
|
||
return wraps(func, new_sig=sig)(wrapper) | ||
|
||
return deco | ||
|
||
|
||
def register_condition(cond): | ||
setattr(condition, cond.__name__, cond) | ||
return cond | ||
|
||
|
||
@register_condition | ||
def capability(capability): | ||
return condition( | ||
lambda info: capability in info.config.enabled_capabilities[TRANSPORT.USB], | ||
"Requires %s" % capability, | ||
) | ||
|
||
|
||
@register_condition | ||
def min_version(major, minor=0, micro=0): | ||
if isinstance(major, tuple): | ||
version = major | ||
else: | ||
version = (major, minor, micro) | ||
return condition(lambda info: info.version >= version, "Version < %s" % (version,)) | ||
|
||
|
||
@register_condition | ||
def max_version(major, minor=0, micro=0): | ||
if isinstance(major, tuple): | ||
version = major | ||
else: | ||
version = (major, minor, micro) | ||
return condition(lambda info: info.version <= version, "Version > %s" % (version,)) | ||
|
||
|
||
@register_condition | ||
def fips(status=True): | ||
return condition( | ||
lambda info: is_fips_version(info.version), "Requires FIPS = %s" % status | ||
) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
from ykman.cli.__main__ import cli | ||
from ykman.cli.aliases import apply_aliases | ||
from click.testing import CliRunner | ||
from functools import partial | ||
import pytest | ||
|
||
|
||
@pytest.fixture(scope="module") | ||
def ykman_cli(info): | ||
return partial(ykman_cli_for_serial, info.serial) | ||
|
||
|
||
def ykman_cli_for_serial(serial, *argv, **kwargs): | ||
argv = apply_aliases(["ykman"] + [str(a) for a in argv]) | ||
runner = CliRunner() | ||
result = runner.invoke(cli, argv[1:], obj={}, **kwargs) | ||
if result.exit_code != 0: | ||
raise result.exception | ||
return result |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
from yubikit.core import Tlv | ||
from yubikit.piv import SLOT, OBJECT_ID | ||
from yubikit.management import CAPABILITY | ||
from cryptography.hazmat.primitives import serialization | ||
from ...util import generate_self_signed_certificate | ||
from .. import condition | ||
|
||
import pytest | ||
import contextlib | ||
import os | ||
import io | ||
|
||
|
||
DEFAULT_MANAGEMENT_KEY = "010203040506070801020304050607080102030405060708" | ||
|
||
|
||
@pytest.fixture(autouse=True) | ||
@condition.capability(CAPABILITY.PIV) | ||
def ensure_piv(ykman_cli): | ||
ykman_cli("piv", "reset", "-f") | ||
|
||
|
||
def test_piv_info(ykman_cli): | ||
ykman_cli("piv", "info") | ||
|
||
|
||
def test_write_read_preserves_ansi_escapes(ykman_cli): | ||
red = b"\x00\x1b[31m" | ||
blue = b"\x00\x1b[34m" | ||
reset = b"\x00\x1b[0m" | ||
data = ( | ||
b"Hello, " | ||
+ red | ||
+ b"red" | ||
+ reset | ||
+ b" and " | ||
+ blue | ||
+ b"blue" | ||
+ reset | ||
+ b" world!" | ||
) | ||
ykman_cli( | ||
"piv", | ||
"objects", | ||
"import", | ||
"-m", | ||
DEFAULT_MANAGEMENT_KEY, | ||
"0x5f0001", | ||
"-", | ||
input=data, | ||
) | ||
output_data = ykman_cli("piv", "objects", "export", "0x5f0001", "-").stdout_bytes | ||
assert data == output_data | ||
|
||
|
||
def test_read_write_read_is_noop(ykman_cli): | ||
data = os.urandom(32) | ||
|
||
ykman_cli( | ||
"piv", | ||
"objects", | ||
"import", | ||
hex(OBJECT_ID.AUTHENTICATION), | ||
"-", | ||
"-m", | ||
DEFAULT_MANAGEMENT_KEY, | ||
input=data, | ||
) | ||
|
||
output1 = ykman_cli( | ||
"piv", "objects", "export", hex(OBJECT_ID.AUTHENTICATION), "-" | ||
).stdout_bytes | ||
assert output1 == data | ||
|
||
ykman_cli( | ||
"piv", | ||
"objects", | ||
"import", | ||
hex(OBJECT_ID.AUTHENTICATION), | ||
"-", | ||
"-m", | ||
DEFAULT_MANAGEMENT_KEY, | ||
input=output1, | ||
) | ||
|
||
output2 = ykman_cli( | ||
"piv", "objects", "export", hex(OBJECT_ID.AUTHENTICATION), "-" | ||
).stdout_bytes | ||
assert output2 == data | ||
|
||
|
||
def test_read_write_aliases(ykman_cli): | ||
data = os.urandom(32) | ||
|
||
with io.StringIO() as buf: | ||
with contextlib.redirect_stderr(buf): | ||
ykman_cli( | ||
"piv", | ||
"write-object", | ||
hex(OBJECT_ID.AUTHENTICATION), | ||
"-", | ||
"-m", | ||
DEFAULT_MANAGEMENT_KEY, | ||
input=data, | ||
) | ||
|
||
output1 = ykman_cli( | ||
"piv", "read-object", hex(OBJECT_ID.AUTHENTICATION), "-" | ||
).stdout_bytes | ||
err = buf.getvalue() | ||
assert output1 == data | ||
assert "piv objects import" in err | ||
assert "piv objects export" in err | ||
|
||
|
||
def test_read_write_certificate_as_object(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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
from ykman.device import connect_to_device, list_all_devices | ||
from yubikit.core.otp import OtpConnection | ||
from yubikit.core.fido import FidoConnection | ||
from yubikit.core.smartcard import SmartCardConnection | ||
|
||
import pytest | ||
import os | ||
|
||
|
||
@pytest.fixture(scope="session") | ||
def _pid_info(): | ||
devices = list_all_devices() | ||
assert len(devices) == 1 | ||
dev, info = devices[0] | ||
assert info.serial == int(os.environ.get("DESTRUCTIVE_TEST_YUBIKEY_SERIALS")) | ||
return dev.pid, info | ||
|
||
|
||
@pytest.fixture(scope="session") | ||
def pid(_pid_info): | ||
return _pid_info[0] | ||
|
||
|
||
@pytest.fixture(scope="session") | ||
def info(_pid_info): | ||
return _pid_info[1] | ||
|
||
|
||
@pytest.fixture(scope="session") | ||
def key_type(pid): | ||
return pid.get_type() | ||
|
||
|
||
connection_scope = os.environ.get("CONNECTION_SCOPE", "module") | ||
|
||
|
||
@pytest.fixture(scope=connection_scope) | ||
def otp_connection(info): | ||
with connect_to_device(info.serial, [OtpConnection])[0] as c: | ||
yield c | ||
|
||
|
||
@pytest.fixture(scope=connection_scope) | ||
def fido_connection(info): | ||
with connect_to_device(info.serial, [FidoConnection])[0] as c: | ||
yield c | ||
|
||
|
||
@pytest.fixture(scope=connection_scope) | ||
def ccid_connection(info): | ||
with connect_to_device(info.serial, [SmartCardConnection])[0] as c: | ||
yield c |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from yubikit.core.smartcard import SmartCardProtocol, ApplicationNotAvailableError | ||
import pytest | ||
|
||
|
||
def test_select_wrong_app(ccid_connection): | ||
p = SmartCardProtocol(ccid_connection) | ||
with pytest.raises(ApplicationNotAvailableError): | ||
p.select(b"not_a_real_aid") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
from ykman.device import connect_to_device | ||
from yubikit.core.otp import OtpConnection | ||
from yubikit.core.fido import FidoConnection | ||
from yubikit.core.smartcard import SmartCardConnection | ||
from yubikit.management import USB_INTERFACE | ||
|
||
|
||
def try_connection(conn_type): | ||
with connect_to_device(None, [conn_type])[0]: | ||
return True | ||
|
||
|
||
def test_switch_interfaces(pid): | ||
interfaces = pid.get_interfaces() | ||
if USB_INTERFACE.FIDO in interfaces: | ||
assert try_connection(FidoConnection) | ||
if USB_INTERFACE.OTP in interfaces: | ||
assert try_connection(OtpConnection) | ||
if USB_INTERFACE.FIDO in interfaces: | ||
assert try_connection(FidoConnection) | ||
if USB_INTERFACE.CCID in interfaces: | ||
assert try_connection(SmartCardConnection) | ||
if USB_INTERFACE.OTP in interfaces: | ||
assert try_connection(OtpConnection) | ||
if USB_INTERFACE.CCID in interfaces: | ||
assert try_connection(SmartCardConnection) | ||
if USB_INTERFACE.FIDO in interfaces: | ||
assert try_connection(FidoConnection) |
Oops, something went wrong.