diff --git a/tests/conftest.py b/tests/conftest.py
index 48631b2..dd0c9c8 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -1,3 +1,23 @@
+"""
+/*
+ * This file is part of the Pico Fido distribution (https://github.com/polhenarejos/pico-fido).
+ * Copyright (c) 2022 Pol Henarejos.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+"""
+
+
from http import client
from fido2.hid import CtapHidDevice
from fido2.client import Fido2Client, WindowsClient, UserInteraction, ClientError, _Ctap1ClientBackend
@@ -393,3 +413,30 @@ def AuthRes(device, RegRes, *args):
@pytest.fixture(scope="class")
def client_pin(resetdevice):
return ClientPin(resetdevice.client()._backend.ctap2)
+
+@pytest.fixture(scope="class")
+def ccid_card():
+ cardtype = AnyCardType()
+ try:
+ # request card insertion
+ cardrequest = CardRequest(timeout=10, cardType=cardtype)
+ card = cardrequest.waitforcard()
+
+ # connect to the card and perform a few transmits
+ card.connection.connect()
+ return card
+
+ except CardRequestTimeoutException:
+ print('time-out: no card inserted during last 10s')
+ return None
+
+@pytest.fixture(scope="class")
+def select_oath(ccid_card):
+ aid = [0xa0, 0x00, 0x00, 0x05, 0x27, 0x21, 0x01, 0x01]
+ resp = send_apdu(ccid_card, 0xA4, 0x04, 0x00, aid)
+ return ccid_card
+
+@pytest.fixture(scope="class")
+def reset_oath(select_oath):
+ send_apdu(select_oath, 0x04, p1=0, p2=0)
+ return select_oath
diff --git a/tests/pico-fido/test_oath.py b/tests/pico-fido/test_oath.py
new file mode 100644
index 0000000..9aa3815
--- /dev/null
+++ b/tests/pico-fido/test_oath.py
@@ -0,0 +1,90 @@
+"""
+/*
+ * This file is part of the Pico Fido distribution (https://github.com/polhenarejos/pico-fido).
+ * Copyright (c) 2022 Pol Henarejos.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+"""
+
+import pytest
+from utils import *
+
+INS_PUT = 0x01
+INS_DELETE = 0x02
+INS_SET_CODE = 0x03
+INS_RESET = 0x04
+INS_LIST = 0xa1
+INS_CALCULATE = 0xa2
+INS_VALIDATE = 0xa3
+INS_CALC_ALL = 0xa4
+INS_SEND_REMAINING = 0xa5
+
+RESP_MORE_DATA = 0x61
+
+TAG_NAME = 0x71
+TAG_NAME_LIST = 0x72
+TAG_KEY = 0x73
+TAG_CHALLENGE = 0x74
+TAG_RESPONSE = 0x75
+TAG_T_RESPONSE = 0x76
+TAG_NO_RESPONSE = 0x77
+TAG_PROPERTY = 0x78
+TAG_VERSION = 0x79
+TAG_IMF = 0x7a
+TAG_ALGO = 0x7b
+TAG_TOUCH_RESPONSE = 0x7c
+
+TYPE_MASK = 0xf0
+TYPE_HOTP = 0x10
+TYPE_TOTP = 0x20
+
+ALG_MASK = 0x0f
+ALG_SHA1 = 0x01
+ALG_SHA256 = 0x02
+
+PROP_ALWAYS_INC = 0x01
+PROP_REQUIRE_TOUCH = 0x02
+
+## Based on tests on https://github.com/Yubico/ykneo-oath/blob/master/test/test/pkgYkneoOathTest/YkneoOathTest.java
+
+def test_select_oath(select_oath):
+ pass
+
+def list_apdu(ccid_card):
+ resp = send_apdu(ccid_card, INS_LIST, p1=0, p2=0)
+ return resp
+
+name_kaka = [ord('k'), ord('a'), ord('k'), ord('a')]
+data_name = [TAG_NAME] + [len(name_kaka)] + name_kaka
+data_key = [TAG_KEY, 0x16, 0x21, 0x06, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b]
+data_chal = [TAG_CHALLENGE, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]
+
+def test_life(reset_oath):
+ data = data_name + data_key
+ resp = send_apdu(reset_oath, INS_PUT, p1=0, p2=0, data=list(data))
+ assert(len(resp) == 0)
+ resp = list_apdu(reset_oath)
+ exp = [TAG_NAME_LIST, 5, 0x21] + name_kaka
+ assert(resp == exp)
+
+ data = data_name + data_chal
+ resp = send_apdu(reset_oath, INS_CALCULATE, p1=0, p2=0, data=data)
+ exp = [TAG_RESPONSE, 0x15, 0x06, 0xb3, 0x99, 0xbd, 0xfc, 0x9d, 0x05, 0xd1, 0x2a, 0xc4, 0x35, 0xc4, 0xc8, 0xd6, 0xcb, 0xd2, 0x47, 0xc4, 0x0a, 0x30, 0xf1]
+ assert(resp == exp)
+
+ data = data_name
+ resp = send_apdu(reset_oath, INS_DELETE, p1=0, p2=0, data=data)
+ resp = list_apdu(reset_oath)
+ assert(len(resp) == 0)
+