#include <cstring>
#include <iostream>
+#include <mutex>
#include <mv_barcode.h>
#include <optional>
#include <string_view>
}
struct TestContents {
- int status;
+ bool succeeded;
+ int statusMC;
+ int statusGA;
+ int updateMCRet = -1;
+ int updateGARet = -1;
std::string path;
Buffer credentialRawId;
Buffer userId;
std::optional<LinkedData> linkedData;
bool negative;
+ std::mutex mutex;
+
void UpdateLinkedData(const wauthn_hybrid_linked_data_s *ld)
{
if (ld) {
if (ret) {
std::cout << "chsmack command failed\n"
<< "System() returned: " << ret << std::endl;
- contents.status = -1;
+ contents.succeeded = false;
return;
}
if (ret) {
std::cout << "launch_app command failed\n"
<< "System() returned: " << ret << std::endl;
- contents.status = -1;
+ contents.succeeded = false;
}
}
if (ret != MEDIA_VISION_ERROR_NONE) {
std::cout << "mv_barcode_generate_image failed\n"
<< "Error code: " << ret << std::endl;
- contents.status = -1;
+ contents.succeeded = false;
} else {
DisplayQR(contents);
}
auto testContents = static_cast<TestContents *>(data);
if (testContents->path.empty() || !qr_contents) {
std::cout << "qrcode_callback failed" << std::endl;
- testContents->status = false;
+ testContents->succeeded = false;
return;
}
else
void *data)
{
auto *testContents = static_cast<TestContents *>(data);
+ auto lock = std::lock_guard{testContents->mutex};
if (pubkey_cred == nullptr || result != WAUTHN_ERROR_NONE) {
std::cout << __FUNCTION__ << ": response_callback failed\n"
<< "Error code: " << result << std::endl;
- testContents->status = -1;
+ testContents->statusMC = -1;
+ testContents->succeeded = false;
return;
}
std::cerr << "MC: credentialRawId: " << LowercaseHexStringOf(testContents->credentialRawId)
<< std::endl;
testContents->transports = pubkey_cred->response->transports;
- testContents->status = 1;
+ testContents->statusMC = 1;
if (pubkey_cred->linked_device != nullptr)
testContents->UpdateLinkedData(pubkey_cred->linked_device);
+
+ std::cout << "MC: awaiting potential update messages.." << std::endl;
}
void GACallback(const wauthn_pubkey_credential_assertion_s *pubkey_cred,
void *data)
{
auto *testContents = static_cast<TestContents *>(data);
+ auto lock = std::unique_lock{testContents->mutex};
if (pubkey_cred == nullptr || result != WAUTHN_ERROR_NONE) {
std::cout << __FUNCTION__ << ": response_callback failed\n"
<< "Error code: " << result << std::endl;
- testContents->status = -1;
+ testContents->statusGA = -1;
+ testContents->succeeded = false;
return;
}
if (credentialRawId != testContents->credentialRawId) {
std::cerr << "Error: invalid credentialRawId in GA: "
<< LowercaseHexStringOf(credentialRawId) << std::endl;
- testContents->status = -1;
+ testContents->statusGA = -1;
return;
}
if (userHandle != testContents->userId) {
std::cerr << "Error: invalid userHandle in GA: " << LowercaseHexStringOf(userHandle)
<< std::endl;
- testContents->status = -1;
+ testContents->statusGA = -1;
return;
}
}
- testContents->status = 2;
+ testContents->statusGA = 1;
if (pubkey_cred->linked_device != nullptr)
testContents->UpdateLinkedData(pubkey_cred->linked_device);
+ std::cout << "GA: awaiting potential update messages.." << std::endl;
}
-void UpdateLinkedDataCallback(const wauthn_hybrid_linked_data_s *linked_data,
- wauthn_error_e result,
- void *data)
+void MCUpdateLinkedDataCallback(const wauthn_hybrid_linked_data_s *linked_data,
+ wauthn_error_e result,
+ void *data)
+{
+ auto *testContents = static_cast<TestContents *>(data);
+ auto lock = std::unique_lock{testContents->mutex};
+ if (result != WAUTHN_ERROR_NONE && result != WAUTHN_ERROR_NONE_AND_WAIT) {
+ std::cout << __FUNCTION__ << ": failed\n"
+ << "Error code: " << result << std::endl;
+ testContents->succeeded = false;
+ return;
+ }
+ if (testContents->statusMC == 1)
+ {
+ std::cout << "MC: UpdateLinkedDataCallback was called: " << result << std::endl;
+ testContents->statusMC = 2;
+ testContents->updateMCRet = result;
+ }
+ if (linked_data != nullptr)
+ testContents->UpdateLinkedData(linked_data);
+}
+void GAUpdateLinkedDataCallback(const wauthn_hybrid_linked_data_s *linked_data,
+ wauthn_error_e result,
+ void *data)
{
auto *testContents = static_cast<TestContents *>(data);
+ auto lock = std::unique_lock{testContents->mutex};
if (result != WAUTHN_ERROR_NONE && result != WAUTHN_ERROR_NONE_AND_WAIT) {
std::cout << __FUNCTION__ << ": failed\n"
<< "Error code: " << result << std::endl;
- testContents->status = -1;
+ testContents->succeeded = false;
return;
}
- if (testContents->status == 1)
- testContents->status = 10;
- else if (testContents->status == 2)
- testContents->status = 20;
+ if (testContents->statusGA == 1)
+ {
+ std::cout << "GA: UpdateLinkedDataCallback was called: " << result << std::endl;
+ testContents->statusGA = 2;
+ testContents->updateGARet = result;
+ }
if (linked_data != nullptr)
testContents->UpdateLinkedData(linked_data);
}
bool Test(struct TestContents &testContents)
{
/* MakeCredential */
+
+ std::cout << "START: Make Credential" << std::endl;
unsigned char clientDataJson[] = "{}";
wauthn_const_buffer_s clientDataJsonBuff;
clientDataJsonBuff.data = clientDataJson;
wauthn_mc_callbacks_s mcCallbacks;
mcCallbacks.qrcode_callback = DisplayQRCallback;
mcCallbacks.response_callback = MCCallback;
- mcCallbacks.linked_data_callback = UpdateLinkedDataCallback;
+ mcCallbacks.linked_data_callback = MCUpdateLinkedDataCallback;
mcCallbacks.user_data = &testContents;
int ret = wauthn_make_credential(&clientData, &mcOptions, &mcCallbacks);
+
std::cout << "ret: " << wauthn_error_to_string(ret) << std::endl;
+
int timeCount = 120;
- std::cout << "Waiting for 120 seconds.." << std::endl;
- while (testContents.status == 0 && timeCount != 0)
+ std::cout << "MC: Waiting Authenticate with mobile device for 120 seconds.." << std::endl;
+ while (testContents.statusMC == 0 && timeCount != 0) // exit after called Response CB
{
- std::cout << " " << timeCount;
sleep(1);
timeCount--;
}
- if (testContents.status != 1) {
+ if (testContents.statusMC != 1) {
return false;
}
- // Checking whether the update_linked_data callback is called or not
- // The callback would called 1 sec after called response callback
- // TODO: Need to be checked concurrently after webauthn-ble is updated
- sleep(2);
- if (testContents.status != 10) {
- return false;
- }
-
-
- /* GetAssertion */
- std::cout << "Step for Get Assertion" << std::endl;
+ std::cout << "START: Get Assertion" << std::endl;
+ auto lock = std::unique_lock{testContents.mutex};
wauthn_const_buffer_s credentialId = ToWauthnConstBuff(testContents.credentialRawId);
}
wauthn_pubkey_cred_request_options_s gaOptions;
+ std::memset(&gaOptions, 0, sizeof(gaOptions)); // For future compatibility.
gaOptions.timeout = 60000; // 60s
gaOptions.rpId = rpId;
gaOptions.user_verification = UVR_REQUIRED;
wauthn_ga_callbacks_s gaCallbacks;
gaCallbacks.qrcode_callback = DisplayQRCallback;
gaCallbacks.response_callback = GACallback;
- gaCallbacks.linked_data_callback = UpdateLinkedDataCallback;
+ gaCallbacks.linked_data_callback = GAUpdateLinkedDataCallback;
gaCallbacks.user_data = &testContents;
+ lock.unlock();
ret = wauthn_get_assertion(&clientData, &gaOptions, &gaCallbacks);
std::cout << "ret: " << wauthn_error_to_string(ret) << std::endl;
+
+
timeCount = 120;
- std::cout << "Waiting for 120 seconds.." << std::endl;
- while (testContents.status == 10 && timeCount != 0)
+ std::cout << "GA: Waiting Authenticate with mobile device for 120 seconds.." << std::endl;
+ while (testContents.statusGA == 0 && timeCount != 0) // exit after called Response CB
{
- std::cout << " " << timeCount;
sleep(1);
timeCount--;
}
- if (testContents.status != 2) {
- return false;
+ if (testContents.statusGA != 1) {
+ testContents.succeeded = false;
}
- // Checking whether the update_linked_data callback is called or not
- // The callback would called 1 sec after called response callback
- // TODO: Need to be checked concurrently after webauthn-ble is updated
- sleep(2);
- if (testContents.status != 20) {
- return false;
+
+ timeCount = 120;
+ std::cout << "Waiting UpdateLinkedDataCallbacks for 120 seconds.." << std::endl;
+ while (testContents.updateGARet != WAUTHN_ERROR_NONE && timeCount != 0)
+ {
+ sleep(1);
+ timeCount--;
+ }
+
+
+ std::cout << "MC: " << testContents.statusMC << ", GA: " << testContents.statusGA
+ << std::endl;
+ std::cout << "MCRet: " << testContents.updateMCRet << ", GARet: "
+ << testContents.updateGARet << std::endl;
+ if (testContents.statusMC != 2 || testContents.statusGA != 2) {
+ return testContents.succeeded = false;
}
- return true;
+ if (testContents.updateMCRet != WAUTHN_ERROR_NONE
+ || testContents.updateGARet != WAUTHN_ERROR_NONE)
+ {
+ return testContents.succeeded = false;
+ }
+ return testContents.succeeded;
}
} // anonymous namespace
int main(int argc, char *argv[])
{
- TestContents testContents = {0, "/tmp/webauthn-qrcode.png",
+ TestContents testContents = {true, 0, 0, -1, -1, "/tmp/webauthn-qrcode.png",
{}, {}, WAUTHN_TRANSPORT_NONE,
- std::nullopt, false};
+ std::nullopt, false, {}};
if (argc == 2)
{
}
if (system("/usr/bin/killall /usr/apps/org.tizen.image-viewer_common/bin/image-viewer")) {
- std::cout << "Cannot close org.tizen.image-viewer\n";
- ret = true;
+ std::cout << "Cannot close /usr/apps/org.tizen.image-viewer_common/bin/image-viewer"
+ << std::endl;
+ if(system("/usr/bin/killall /opt/usr/apps/org.tizen.image-viewer_common/bin/image-viewer")) {
+ std::cout << "Cannot close /opt/usr/apps/org.tizen.image-viewer_common/bin/image-viewer"
+ << std::endl;
+ ret = true;
+ }
}
return ret;