Add --exclude-credential option to manual test 66/313166/2
authorKrzysztof Malysa <k.malysa@samsung.com>
Wed, 19 Jun 2024 13:13:20 +0000 (15:13 +0200)
committerKrzysztof Malysa <k.malysa@samsung.com>
Fri, 21 Jun 2024 08:07:52 +0000 (10:07 +0200)
Change-Id: If560d8d79afce5a4c64050ee819ef43681e9253a

tests/man_tests.cpp

index 2e6045c6aa9237820bb3d3c7d38a9df0854bd58e..71832da9b62e8cd895ed07274fb8929c6c65c0e6 100644 (file)
@@ -20,6 +20,7 @@
 #include "to_wauthn_const_buff.h"
 #include "turn_bluetooth.h"
 
+#include <cctype>
 #include <cstring>
 #include <iostream>
 #include <mutex>
@@ -56,6 +57,7 @@ struct TestContents {
     Buffer credentialRawId;
     Buffer userId;
     unsigned transports = WAUTHN_TRANSPORT_NONE;
+    std::vector<Buffer> excludedCredentialsIds;
     std::optional<LinkedData> linkedData;
     bool seenLastMCUpdateCallback;
     bool seenLastGAUpdateCallback;
@@ -221,12 +223,30 @@ void TestMC(struct TestContents &testContents)
     pubkeyCredParams.params = params;
     pubkeyCredParams.size = sizeof(params) / sizeof(*params);
 
+    auto excluded_credentials_wcbs =
+        std::vector<wauthn_const_buffer_s>(testContents.excludedCredentialsIds.size());
+    auto excluded_credentials =
+        std::vector<wauthn_pubkey_cred_descriptor_s>(testContents.excludedCredentialsIds.size());
+    for (size_t i = 0; i < testContents.excludedCredentialsIds.size(); ++i) {
+        excluded_credentials_wcbs[i] = ToWauthnConstBuff(testContents.excludedCredentialsIds[i]);
+        excluded_credentials[i] = {
+            PCT_PUBLIC_KEY,
+            &excluded_credentials_wcbs[i],
+            testContents.transports,
+        };
+    }
+
+    wauthn_pubkey_cred_descriptors_s exclude_credentials;
+    exclude_credentials.descriptors = excluded_credentials.data();
+    exclude_credentials.size = excluded_credentials.size();
+
     wauthn_pubkey_cred_creation_options_s mcOptions;
     std::memset(&mcOptions, 0, sizeof(mcOptions));
     mcOptions.rp = &rp;
     mcOptions.user = &user;
     mcOptions.pubkey_cred_params = &pubkeyCredParams;
     mcOptions.timeout = 60000; // 60s
+    mcOptions.exclude_credentials = exclude_credentials.size > 0 ? &exclude_credentials : nullptr;
 
     wauthn_mc_callbacks_s mcCallbacks;
     mcCallbacks.qrcode_callback = DisplayQRCallback;
@@ -491,6 +511,45 @@ void GAUpdateLinkedDataCallback(const wauthn_hybrid_linked_data_s *linkedData,
                   << std::endl; // NOLINT(performance-avoid-endl)
 }
 
+void PrintHelp(char **argv)
+{
+    std::cout
+        << "Usage: " << (argv[0] ? argv[0] : "webauthn-ble-manual-tests")
+        << " [-n] [--exclude-credential CREDENTIAL_ID]\n"
+        << "\nOptions:\n"
+        << "  -n  Negative test -- with invalid QR code\n"
+        << "  --exclude-credential CREDENTIAL_ID  Send MakeCredential request with excludeList\n"
+           "                                      containing CREDENTIAL_ID. To exclude several\n"
+           "                                      credentials, specify this option multiple\n"
+           "                                      times. CREDENTIAL_ID must be a hex string. E.g.\n"
+           "                                      91ef2e74f47bd06a6c5c4053ab8de1f6845f460a3ded.\n";
+}
+
+std::optional<Buffer> HexStringToBuffer(std::string_view hexString)
+{
+    if (hexString.size() & 1) {
+        return std::nullopt;
+    }
+    Buffer res;
+    res.reserve(hexString.size() >> 1);
+    for (size_t i = 0; i < hexString.size(); i += 2) {
+        auto d1 = hexString[i];
+        auto d2 = hexString[i | 1];
+        if (!std::isxdigit(static_cast<unsigned char>(d1)) ||
+            !std::isxdigit(static_cast<unsigned char>(d2)))
+            return std::nullopt;
+        static constexpr auto toDec = [](char c) noexcept {
+            if ('0' <= c && c <= '9')
+                return c - '0';
+            if ('a' <= c && c <= 'f')
+                return c - 'a' + 10;
+            return c - 'A' + 10;
+        };
+        res.emplace_back((toDec(d1) << 4) | toDec(d2));
+    }
+    return res;
+}
+
 } // anonymous namespace
 
 int main(int argc, char *argv[])
@@ -502,19 +561,35 @@ int main(int argc, char *argv[])
                                  {},
                                  {},
                                  WAUTHN_TRANSPORT_NONE,
+                                 {},
                                  std::nullopt,
                                  false,
                                  false,
                                  {}};
 
-    if (argc > 2) {
-        std::cout << "Usage: " << (argv[0] ? argv[0] : "webauthn-ble-manual-tests") << " [-n]\n"
-                  << "\nOptions:\n"
-                  << "  -n  Negative test -- with invalid QR code\n";
-        return 3;
+    for (int i = 1; i < argc; ++i) {
+        auto arg = std::string_view{argv[i]};
+        if (arg == "-n")
+            testContents.negative = true;
+        else if (arg == "--exclude-credential") {
+            if (i + 1 == argc) {
+                std::cout << "--exclude-credential is missing CREDENTIAL_ID argument\n";
+                PrintHelp(argv);
+                return 3;
+            }
+            auto credentialId = HexStringToBuffer(argv[++i]);
+            if (!credentialId) {
+                std::cout << "CREDENTIAL_ID has to be a hex string\n";
+                PrintHelp(argv);
+                return 3;
+            }
+            testContents.excludedCredentialsIds.emplace_back(std::move(*credentialId));
+        } else {
+            std::cout << "Unrecognized option: " << arg << '\n';
+            PrintHelp(argv);
+            return 3;
+        }
     }
-    if (argc == 2 && std::string_view("-n") == argv[1])
-        testContents.negative = true;
 
     const int err = TurnBluetoothOn();
     if (err != BT_ERROR_NONE) {