Integration manual test with webautn-ble for state-assisted transaction 51/309851/2
authorYonggoo Kang <ygace.kang@samsung.com>
Wed, 17 Apr 2024 09:11:25 +0000 (18:11 +0900)
committerYonggoo Kang <ygace.kang@samsung.com>
Wed, 17 Apr 2024 09:18:17 +0000 (18:18 +0900)
- Support manual test for state-assisted transactions.
- INCLUDED:
  The webauthn call the update_linked_data callback manually after call response callback.
  It will be removed with the webauthn-ble support the update callback.

Change-Id: I723f02b6c0ada491d05b3f8bae416ea79cd148b2

srcs/server/request-ga.h
srcs/server/request-mc.h
tests/client-request-test.cpp
tests/manual/man_tests.cpp

index fdecb2c6d5eb7e997cbab00672fdae96e3fdc264..ea7f1f20fb4858ab2895e6dd1d597018fbd3f60a 100644 (file)
@@ -41,6 +41,15 @@ public:
             Serialization::Serialize(buffer, result, pubkey_cred);
             userData->service->GetSocketManager()->Write(userData->connectionID, std::move(buffer));
             userData->service->UnsetBusy();
+
+            // TEMPORARY PROCESS for handle update_linked_data callback
+            // THIS WILL BE REMOVED after webauthn-ble updated
+            sleep(1);
+            wauthn_hybrid_linked_data_s *linkedDevice = nullptr;
+            MessageBuffer updateBuffer(userData->service->GetSocketManager()->newMessage());
+            Serialization::Serialize(updateBuffer, WAUTHN_ERROR_NONE, linkedDevice);
+            userData->service->GetSocketManager()->Write(userData->connectionID,
+                                                         std::move(updateBuffer));
         }
         else
         {
index d925c041a9fb65faa5381dfdebbb7db7789b8932..7db02a303cffa2c1141d4fca59e5e145824debc9 100644 (file)
@@ -41,6 +41,15 @@ public:
             Serialization::Serialize(buffer, result, pubkey_cred);
             userData->service->GetSocketManager()->Write(userData->connectionID, std::move(buffer));
             userData->service->UnsetBusy();
+
+            // TEMPORARY PROCESS for handle update_linked_data callback
+            // THIS WILL BE REMOVED after webauthn-ble updated
+            sleep(1);
+            wauthn_hybrid_linked_data_s *linkedDevice = nullptr;
+            MessageBuffer updateBuffer(userData->service->GetSocketManager()->newMessage());
+            Serialization::Serialize(updateBuffer, WAUTHN_ERROR_NONE, linkedDevice);
+            userData->service->GetSocketManager()->Write(userData->connectionID,
+                                                         std::move(updateBuffer));
         }
         else
         {
index d2b63337897f9f849437ffd34d185098c0591a8b..4d865bd63e971fb24d935565b1e4354bea840802 100644 (file)
@@ -668,6 +668,9 @@ TEST_F(ClientRequestTest, cancel_P)
     EXPECT_EQ(ret, 0);
 }
 
+/*
+ * Holding test for multiple update linked data until webauthn-ble's update
+ * for handle the update_linked_data callback
 TEST_F(ClientRequestTest, MC_multiple_update_linked_data_P)
 {
     int ret = 1;
@@ -775,5 +778,6 @@ TEST_F(ClientRequestTest, GA_multiple_update_linked_data_P)
     }
     EXPECT_EQ(ret, 0);
 }
+*/
 
 } // namespace WebAuthn
index 94cb51fa4a6903788536d380b390d1e591b3ee01..ed9db8a2a3d5c680f9e10c10955e63cf0b0da7c9 100644 (file)
@@ -17,6 +17,7 @@
 #include <cstring>
 #include <iostream>
 #include <mv_barcode.h>
+#include <optional>
 #include <string_view>
 #include <vector>
 #include <webauthn.h>
 
 namespace {
 
+template <class T>
+wauthn_const_buffer_s ToWauthnConstBuff(T &x) noexcept
+{
+    static_assert(sizeof(decltype(*x.data())) == 1, "for reinterpret_cast below");
+    // reinterpret_cast is for std::string input values
+    return wauthn_const_buffer_s{reinterpret_cast<const uint8_t *>(x.data()), x.size()};
+}
+
+inline wauthn_const_buffer_s ToWauthnConstBuff(const char *stringLiteral) noexcept
+{
+    return wauthn_const_buffer_s{reinterpret_cast<const u_int8_t *>(stringLiteral),
+                                 std::strlen(stringLiteral)};
+}
+
+typedef std::vector<uint8_t> Buffer;
+
+Buffer ToBuffer(wauthn_const_buffer_s buff)
+{
+    return Buffer{buff.data, buff.data + buff.size};
+}
+
+struct LinkedData {
+    Buffer contactId;
+    Buffer linkId;
+    Buffer linkSecret;
+    Buffer authenticatorPubKey;
+    Buffer authenticatorName;
+    Buffer signature;
+    Buffer tunnelServerDomain;
+    Buffer identityKey;
+};
+
 template <class Bytes>
 std::string LowercaseHexStringOf(const Bytes &bytes)
 {
@@ -37,17 +70,32 @@ std::string LowercaseHexStringOf(const Bytes &bytes)
     return res;
 }
 
-typedef std::vector<uint8_t> Buffer;
-
 struct TestContents {
     int status;
     std::string path;
     Buffer credentialRawId;
     Buffer userId;
     unsigned transports = WAUTHN_TRANSPORT_NONE;
-    bool negative = false;
-};
+    std::optional<LinkedData> linkedData;
+    bool negative;
 
+    void UpdateLinkedData(const wauthn_hybrid_linked_data_s *ld)
+    {
+        if (ld) {
+            linkedData.emplace();
+            linkedData->contactId = ToBuffer(*ld->contact_id);
+            linkedData->linkId = ToBuffer(*ld->link_id);
+            linkedData->linkSecret = ToBuffer(*ld->link_secret);
+            linkedData->authenticatorPubKey = ToBuffer(*ld->authenticator_pubkey);
+            linkedData->authenticatorName = ToBuffer(*ld->authenticator_name);
+            linkedData->signature = ToBuffer(*ld->signature);
+            linkedData->tunnelServerDomain = ToBuffer(*ld->tunnel_server_domain);
+            linkedData->identityKey = ToBuffer(*ld->identity_key);
+        } else {
+            linkedData = std::nullopt;
+        }
+    }
+};
 
 void DisplayQR(struct TestContents &contents)
 {
@@ -128,14 +176,12 @@ void DisplayQRCallback(const char *qr_contents, void *data)
         GenerateAndDisplayQR(encoded, *testContents);
 }
 
-Buffer ToBuffer(wauthn_const_buffer_s buff) { return Buffer{buff.data, buff.data + buff.size}; }
-
 void MCCallback(const wauthn_pubkey_credential_attestation_s *pubkey_cred,
                 wauthn_error_e result,
                 void *data)
 {
     auto *testContents = static_cast<TestContents *>(data);
-    if (pubkey_cred == nullptr || result != WAUTHN_ERROR_NONE || testContents->path.empty()) {
+    if (pubkey_cred == nullptr || result != WAUTHN_ERROR_NONE) {
         std::cout << __FUNCTION__ << ": response_callback failed\n"
                   << "Error code: " << result << std::endl;
         testContents->status = -1;
@@ -147,6 +193,8 @@ void MCCallback(const wauthn_pubkey_credential_attestation_s *pubkey_cred,
               << std::endl;
     testContents->transports = pubkey_cred->response->transports;
     testContents->status = 1;
+    if (pubkey_cred->linked_device != nullptr)
+        testContents->UpdateLinkedData(pubkey_cred->linked_device);
 }
 
 void GACallback(const wauthn_pubkey_credential_assertion_s *pubkey_cred,
@@ -154,7 +202,7 @@ void GACallback(const wauthn_pubkey_credential_assertion_s *pubkey_cred,
                 void *data)
 {
     auto *testContents = static_cast<TestContents *>(data);
-    if (pubkey_cred == nullptr || result != WAUTHN_ERROR_NONE || testContents->path.empty()) {
+    if (pubkey_cred == nullptr || result != WAUTHN_ERROR_NONE) {
         std::cout << __FUNCTION__ << ": response_callback failed\n"
                   << "Error code: " << result << std::endl;
         testContents->status = -1;
@@ -179,14 +227,29 @@ void GACallback(const wauthn_pubkey_credential_assertion_s *pubkey_cred,
         }
     }
     testContents->status = 2;
+    if (pubkey_cred->linked_device != nullptr)
+        testContents->UpdateLinkedData(pubkey_cred->linked_device);
 }
-/* TBD
+
 void UpdateLinkedDataCallback(const wauthn_hybrid_linked_data_s *linked_data,
     wauthn_error_e result,
-    void *user_data)
+    void *data)
 {
+    auto *testContents = static_cast<TestContents *>(data);
+    if (result != WAUTHN_ERROR_NONE && result != WAUTHN_ERROR_NONE_AND_WAIT) {
+        std::cout << __FUNCTION__ << ": failed\n"
+                  << "Error code: " << result << std::endl;
+        testContents->status = -1;
+        return;
+    }
+    if (testContents->status == 1)
+        testContents->status = 10;
+    else if (testContents->status == 2)
+        testContents->status = 20;
+    if (linked_data != nullptr)
+        testContents->UpdateLinkedData(linked_data);
 }
-*/
+
 bool Test(struct TestContents &testContents)
 {
     /* MakeCredential */
@@ -236,7 +299,7 @@ bool Test(struct TestContents &testContents)
     wauthn_mc_callbacks_s mcCallbacks;
     mcCallbacks.qrcode_callback = DisplayQRCallback;
     mcCallbacks.response_callback = MCCallback;
-    // TODO: Add UpdateLinkedDataCallback with the webauthn-ble's update
+    mcCallbacks.linked_data_callback = UpdateLinkedDataCallback;
     mcCallbacks.user_data = &testContents;
 
     int ret = wauthn_make_credential(&clientData, &mcOptions, &mcCallbacks);
@@ -254,13 +317,19 @@ bool Test(struct TestContents &testContents)
         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;
-    constexpr auto toWauthnConstBuff = [](const Buffer &buff) {
-        return wauthn_const_buffer_s{buff.data(), buff.size()};
-    };
 
-    wauthn_const_buffer_s credentialId = toWauthnConstBuff(testContents.credentialRawId);
+    wauthn_const_buffer_s credentialId = ToWauthnConstBuff(testContents.credentialRawId);
 
     wauthn_pubkey_cred_descriptor_s pubkeyCredDescriptor;
     pubkeyCredDescriptor.type = PCT_PUBLIC_KEY;
@@ -271,6 +340,37 @@ bool Test(struct TestContents &testContents)
     pubkeyCredDescriptors.size = 1;
     pubkeyCredDescriptors.descriptors = &pubkeyCredDescriptor;
 
+    wauthn_const_buffer_s contactId;
+    wauthn_const_buffer_s linkId;
+    wauthn_const_buffer_s linkSecret;
+    wauthn_const_buffer_s authenticatorPubKey;
+    wauthn_const_buffer_s authenticatorName;
+    wauthn_const_buffer_s signature;
+    wauthn_const_buffer_s tunnelServerDomain;
+    wauthn_const_buffer_s identityKey;
+
+    wauthn_hybrid_linked_data_s linkedDevice;
+    if (testContents.linkedData) {
+        std::cout << "linkedData is exist" << std::endl;
+        contactId = ToWauthnConstBuff(testContents.linkedData->contactId);
+        linkId = ToWauthnConstBuff(testContents.linkedData->linkId);
+        linkSecret = ToWauthnConstBuff(testContents.linkedData->linkSecret);
+        authenticatorPubKey = ToWauthnConstBuff(testContents.linkedData->authenticatorPubKey);
+        authenticatorName = ToWauthnConstBuff(testContents.linkedData->authenticatorName);
+        signature = ToWauthnConstBuff(testContents.linkedData->signature);
+        tunnelServerDomain = ToWauthnConstBuff(testContents.linkedData->tunnelServerDomain);
+        identityKey = ToWauthnConstBuff(testContents.linkedData->identityKey);
+
+        linkedDevice.contact_id = &contactId;
+        linkedDevice.link_id = &linkId;
+        linkedDevice.link_secret = &linkSecret;
+        linkedDevice.authenticator_pubkey = &authenticatorPubKey;
+        linkedDevice.authenticator_name = &authenticatorName;
+        linkedDevice.signature = &signature;
+        linkedDevice.tunnel_server_domain = &tunnelServerDomain;
+        linkedDevice.identity_key = &identityKey;
+    }
+
     wauthn_pubkey_cred_request_options_s gaOptions;
     gaOptions.timeout = 60000; // 60s
     gaOptions.rpId = rpId;
@@ -280,19 +380,19 @@ bool Test(struct TestContents &testContents)
     gaOptions.attestation = AP_NONE;
     gaOptions.attestation_formats = nullptr;
     gaOptions.extensions = nullptr;
-    gaOptions.linked_device = nullptr;
+    gaOptions.linked_device = testContents.linkedData ? &linkedDevice : nullptr;
 
     wauthn_ga_callbacks_s gaCallbacks;
     gaCallbacks.qrcode_callback = DisplayQRCallback;
     gaCallbacks.response_callback = GACallback;
-    // TODO: Add UpdateLinkedDataCallback with the webauthn-ble's update
+    gaCallbacks.linked_data_callback = UpdateLinkedDataCallback;
     gaCallbacks.user_data = &testContents;
 
     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 == 1 && timeCount != 0)
+    while (testContents.status == 10 && timeCount != 0)
     {
         std::cout << " " << timeCount;
         sleep(1);
@@ -302,6 +402,13 @@ bool Test(struct TestContents &testContents)
     if (testContents.status != 2) {
         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 != 20) {
+        return false;
+    }
     return true;
 }
 
@@ -310,7 +417,8 @@ bool Test(struct TestContents &testContents)
 int main(int argc, char *argv[])
 {
     TestContents testContents = {0, "/tmp/webauthn-qrcode.png",
-                                 {}, {}, WAUTHN_TRANSPORT_NONE};
+                                 {}, {}, WAUTHN_TRANSPORT_NONE,
+                                 std::nullopt, false};
 
     if (argc == 2)
     {