From e32cb5701fd874ea167616859601ee21d756735d Mon Sep 17 00:00:00 2001 From: Isaiah Inuwa Date: Mon, 3 Nov 2025 13:37:04 -0600 Subject: [PATCH] Begin updating Windows WebAuthn plugin to GA API --- apps/desktop/build.ps1 | 27 + apps/desktop/desktop_native/napi/index.d.ts | 2 + apps/desktop/desktop_native/napi/src/lib.rs | 2 + .../passkey_authenticator_internal/windows.rs | 2 +- .../desktop_native/rust-toolchain.toml | 2 +- .../experimental/PluginAuthenticatorImpl.cpp | 977 ------ .../PluginRegistrationManager.cpp | 126 - .../experimental/PluginRegistrationManager.h | 80 - .../experimental/pluginauthenticator.h | 239 -- .../include/pluginauthenticator.h | 263 ++ .../include/{experimental => }/webauthn.h | 3108 ++++++++--------- .../include/webauthnplugin.h | 588 ++++ .../src/assert.rs | 55 +- .../src/com_provider.rs | 8 +- .../src/com_registration.rs | 12 +- .../src/webauthn.rs | 81 +- apps/desktop/package.json | 1 + apps/desktop/sign.js | 16 + apps/desktop/src/autofill/preload.ts | 1 + .../services/desktop-autofill.service.ts | 5 +- apps/desktop/src/main.ts | 11 +- .../main/autofill/native-autofill.main.ts | 21 +- .../autofill/native-autofill.windows.main.ts | 12 +- .../services/electron-log.main.service.ts | 2 +- .../services/fido2/credential-id-utils.ts | 6 +- .../fido2/fido2-authenticator.service.ts | 30 +- 26 files changed, 2454 insertions(+), 3223 deletions(-) create mode 100644 apps/desktop/build.ps1 delete mode 100644 apps/desktop/desktop_native/windows_plugin_authenticator/include/experimental/PluginAuthenticatorImpl.cpp delete mode 100644 apps/desktop/desktop_native/windows_plugin_authenticator/include/experimental/PluginRegistrationManager.cpp delete mode 100644 apps/desktop/desktop_native/windows_plugin_authenticator/include/experimental/PluginRegistrationManager.h delete mode 100644 apps/desktop/desktop_native/windows_plugin_authenticator/include/experimental/pluginauthenticator.h create mode 100644 apps/desktop/desktop_native/windows_plugin_authenticator/include/pluginauthenticator.h rename apps/desktop/desktop_native/windows_plugin_authenticator/include/{experimental => }/webauthn.h (72%) create mode 100644 apps/desktop/desktop_native/windows_plugin_authenticator/include/webauthnplugin.h diff --git a/apps/desktop/build.ps1 b/apps/desktop/build.ps1 new file mode 100644 index 00000000000..63588f3ed0e --- /dev/null +++ b/apps/desktop/build.ps1 @@ -0,0 +1,27 @@ +$ErrorActionPreference = "Stop" +$PSNativeCommandUseErrorActionPreference = $true + +$env:ELECTRON_BUILDER_SIGN_CERT = "C:\temp\code-signing.pfx" +$env:ELECTRON_BUILDER_SIGN_CERT_PW = "1234" +$bwFolder = "$env:LOCALAPPDATA\Packages\bitwardendesktop_h4e712dmw3xyy" + +$package = Get-AppxPackage -name bitwardendesktop +$appx = .\dist\Bitwarden-2025.10.2-arm64.appx +$backupDataFile = C:\temp\bw-data.json +$comLogFile = C:\temp\bitwarden_com_debug.log + +# Build Appx +npm run build:dev && npm run pack:win:arm64 + +# Backup tokens +Copy-Item -Path "$bwFolder\LocalCache\Roaming\Bitwarden\data.json" -DestinationPath $backupDataFile + +# Reinstall Appx +Remove-AppxPackage $package && Add-AppxPackage $appx + +# Delete log files +Remove-Item -Path $comLogFile + +# Restore tokens +New-Item -Type Folder -Recurse -Path "$bwFolder\LocalCache\Roaming\Bitwarden\" +Copy-Item -Path $backupDataFile -DestinationPath "$bwFolder\LocalCache\Roaming\Bitwarden\data.json" diff --git a/apps/desktop/desktop_native/napi/index.d.ts b/apps/desktop/desktop_native/napi/index.d.ts index d5b8a8242fe..0307ee7e886 100644 --- a/apps/desktop/desktop_native/napi/index.d.ts +++ b/apps/desktop/desktop_native/napi/index.d.ts @@ -213,9 +213,11 @@ export declare namespace passkey_authenticator { requestJson: string } export interface SyncedCredential { + /** base64url-encoded credential ID. */ credentialId: string rpId: string userName: string + /** base64url-encoded user ID. */ userHandle: string } export interface PasskeySyncRequest { diff --git a/apps/desktop/desktop_native/napi/src/lib.rs b/apps/desktop/desktop_native/napi/src/lib.rs index 8635f6a4d69..8258ab06d92 100644 --- a/apps/desktop/desktop_native/napi/src/lib.rs +++ b/apps/desktop/desktop_native/napi/src/lib.rs @@ -943,9 +943,11 @@ pub mod passkey_authenticator { #[napi(object)] #[derive(serde::Serialize, serde::Deserialize)] pub struct SyncedCredential { + /// base64url-encoded credential ID. pub credential_id: String, // base64url encoded pub rp_id: String, pub user_name: String, + /// base64url-encoded user ID. pub user_handle: String, // base64url encoded } diff --git a/apps/desktop/desktop_native/napi/src/passkey_authenticator_internal/windows.rs b/apps/desktop/desktop_native/napi/src/passkey_authenticator_internal/windows.rs index a062658479b..7aa72174b97 100644 --- a/apps/desktop/desktop_native/napi/src/passkey_authenticator_internal/windows.rs +++ b/apps/desktop/desktop_native/napi/src/passkey_authenticator_internal/windows.rs @@ -56,7 +56,7 @@ pub async fn on_request( match serde_json::from_str(&result) { Ok(resp) => resp, Err(e) => windows_plugin_authenticator::PasskeyResponse::Error { - message: format!("JSON parse error: {}", e), + message: format!("JSON parse error: {}\nJSON: {}", e, &result), }, }; let _ = event.response_sender.send(response); diff --git a/apps/desktop/desktop_native/rust-toolchain.toml b/apps/desktop/desktop_native/rust-toolchain.toml index 898a61f3f4b..c1ab6b3240a 100644 --- a/apps/desktop/desktop_native/rust-toolchain.toml +++ b/apps/desktop/desktop_native/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "1.85.0" +channel = "1.87.0" components = [ "rustfmt", "clippy" ] profile = "minimal" diff --git a/apps/desktop/desktop_native/windows_plugin_authenticator/include/experimental/PluginAuthenticatorImpl.cpp b/apps/desktop/desktop_native/windows_plugin_authenticator/include/experimental/PluginAuthenticatorImpl.cpp deleted file mode 100644 index 21025834182..00000000000 --- a/apps/desktop/desktop_native/windows_plugin_authenticator/include/experimental/PluginAuthenticatorImpl.cpp +++ /dev/null @@ -1,977 +0,0 @@ -#include "pch.h" -#include "PluginAuthenticatorImpl.h" -#include -#include -#include -#include -#include -#include -#include -#include -namespace winrt -{ - using namespace winrt::Windows::Foundation; - using namespace winrt::Microsoft::UI::Windowing; - using namespace winrt::Microsoft::UI::Xaml; - using namespace winrt::Microsoft::UI::Xaml::Controls; - using namespace winrt::Microsoft::UI::Xaml::Navigation; - using namespace PasskeyManager; - using namespace PasskeyManager::implementation; - using namespace CborLite; -} - -namespace winrt::PasskeyManager::implementation -{ - static std::vector GetRequestSigningPubKey() - { - return wil::reg::get_value_binary(HKEY_CURRENT_USER, c_pluginRegistryPath, c_windowsPluginRequestSigningKeyRegKeyName, REG_BINARY); - } - - /* - * This function is used to verify the signature of a request buffer. - * The public key is part of response to plugin registration. - */ - static HRESULT VerifySignatureHelper( - std::vector& dataBuffer, - PBYTE pbKeyData, - DWORD cbKeyData, - PBYTE pbSignature, - DWORD cbSignature) - { - // Create key provider - wil::unique_ncrypt_prov hProvider; - wil::unique_ncrypt_key reqSigningKey; - - // Get the provider - RETURN_IF_FAILED(NCryptOpenStorageProvider(&hProvider, nullptr, 0)); - // Create a NCrypt key handle from the public key - RETURN_IF_FAILED(NCryptImportKey( - hProvider.get(), - NULL, - BCRYPT_ECCPUBLIC_BLOB, - NULL, - &reqSigningKey, - pbKeyData, - cbKeyData, 0)); - - // Verify the signature over the hash of dataBuffer using the hKey - DWORD objLenSize = 0; - DWORD bytesRead = 0; - RETURN_IF_NTSTATUS_FAILED(BCryptGetProperty( - BCRYPT_SHA256_ALG_HANDLE, - BCRYPT_OBJECT_LENGTH, - reinterpret_cast(&objLenSize), - sizeof(objLenSize), - &bytesRead, 0)); - - auto objLen = wil::make_unique_cotaskmem(objLenSize); - wil::unique_bcrypt_hash hashHandle; - RETURN_IF_NTSTATUS_FAILED(BCryptCreateHash( - BCRYPT_SHA256_ALG_HANDLE, - wil::out_param(hashHandle), - objLen.get(), - objLenSize, - nullptr, 0, 0)); - RETURN_IF_NTSTATUS_FAILED(BCryptHashData( - hashHandle.get(), - dataBuffer.data(), - static_cast(dataBuffer.size()), 0)); - - DWORD localHashByteCount = 0; - RETURN_IF_NTSTATUS_FAILED(BCryptGetProperty( - BCRYPT_SHA256_ALG_HANDLE, - BCRYPT_HASH_LENGTH, - reinterpret_cast(&localHashByteCount), - sizeof(localHashByteCount), - &bytesRead, 0)); - - auto localHashBuffer = wil::make_unique_cotaskmem(localHashByteCount); - RETURN_IF_NTSTATUS_FAILED(BCryptFinishHash(hashHandle.get(), localHashBuffer.get(), localHashByteCount, 0)); - RETURN_IF_WIN32_ERROR(NCryptVerifySignature( - reqSigningKey.get(), - nullptr, - localHashBuffer.get(), - localHashByteCount, - pbSignature, - cbSignature, 0)); - - return S_OK; - } - - HRESULT CheckHelloConsentCompleted() - { - winrt::com_ptr curApp = winrt::Microsoft::UI::Xaml::Application::Current().as(); - HANDLE handles[2] = { curApp->m_hVaultConsentComplete.get(), curApp->m_hVaultConsentFailed.get() }; - - DWORD cWait = ARRAYSIZE(handles); - DWORD hIndex = 0; - RETURN_IF_FAILED(CoWaitForMultipleHandles(COWAIT_DISPATCH_WINDOW_MESSAGES | COWAIT_DISPATCH_CALLS, INFINITE, cWait, handles, &hIndex)); - if (hIndex == 1) // Consent failed - { - RETURN_HR(E_FAIL); - } - return S_OK; - } - - HRESULT PerformUv( - winrt::com_ptr& curApp, - HWND hWnd, - wil::shared_hmodule webauthnDll, - GUID transactionId, - PluginOperationType operationType, - std::vector requestBuffer, - wil::shared_cotaskmem_string rpName, - wil::shared_cotaskmem_string userName) - { - curApp->SetPluginPerformOperationOptions(hWnd, operationType, rpName.get(), userName.get()); - - // Wait for the app main window to be ready. - DWORD hIndex = 0; - RETURN_IF_FAILED(CoWaitForMultipleHandles(COWAIT_DISPATCH_WINDOW_MESSAGES | COWAIT_DISPATCH_CALLS, INFINITE, 1, curApp->m_hWindowReady.addressof(), &hIndex)); - - // Trigger a Consent Verifier Dialog to simulate a Windows Hello unlock flow - // This is to demonstrate a vault unlock flow using Windows Hello and is not the recommended way to secure the vault - if (PluginCredentialManager::getInstance().GetVaultLock()) - { - curApp->GetDispatcherQueue().TryEnqueue([curApp]() - { - curApp->SimulateUnLockVaultUsingConsentVerifier(); - }); - RETURN_IF_FAILED(CheckHelloConsentCompleted()); - } - else - { - SetEvent(curApp->m_hVaultConsentComplete.get()); - } - - // Wait for user confirmation to proceed with the operation Create/Signin/Cancel button - // This is a mock up for plugin requiring UI. - { - HANDLE handles[2] = { curApp->m_hPluginProceedButtonEvent.get(), curApp->m_hPluginUserCancelEvent.get() }; - DWORD cWait = ARRAYSIZE(handles); - - RETURN_IF_FAILED(CoWaitForMultipleHandles(COWAIT_DISPATCH_WINDOW_MESSAGES | COWAIT_DISPATCH_CALLS, INFINITE, cWait, handles, &hIndex)); - if (hIndex == 1) // Cancel button clicked - { - // User cancelled the operation. NTE_USER_CANCELLED allows Windows to distinguish between user cancellation and other errors. - return NTE_USER_CANCELLED; - } - } - - // Skip user verification if the user has already performed a gesture to unlock the vault to avoid double prompting - if (PluginCredentialManager::getInstance().GetVaultLock()) - { - return S_OK; - } - - EXPERIMENTAL_WEBAUTHN_PLUGIN_PERFORM_UV pluginPerformUv{}; - pluginPerformUv.transactionId = &transactionId; - - if (curApp->m_silentMode) - { - // If the app did not display any UI, use the hwnd of the caller here. This was included in the request to the plugin. Refer: EXPERIMENTAL_PCWEBAUTHN_PLUGIN_OPERATION_REQUEST - pluginPerformUv.hwnd = hWnd; - } - else - { - // If the app displayed UI, use the hwnd of the app window here - pluginPerformUv.hwnd = curApp->GetNativeWindowHandle(); - } - - EXPERIMENTAL_PWEBAUTHN_PLUGIN_PERFORM_UV_RESPONSE pPluginPerformUvResponse = nullptr; - - auto webAuthNPluginPerformUv = GetProcAddressByFunctionDeclaration(webauthnDll.get(), EXPERIMENTAL_WebAuthNPluginPerformUv); - RETURN_HR_IF_NULL(E_NOTIMPL, webAuthNPluginPerformUv); - - // Step 1: Get the UV count - pluginPerformUv.type = EXPERIMENTAL_WEBAUTHN_PLUGIN_PERFORM_UV_OPERATION_TYPE::GetUvCount; - RETURN_IF_FAILED(webAuthNPluginPerformUv(&pluginPerformUv, &pPluginPerformUvResponse)); - - /* - * pPluginPerformUvResponse->pbResponse contains the UV count - * The UV count tracks the number of times the user has performed a gesture to unlock the vault - */ - - // Step 2: Get the public key - pluginPerformUv.type = EXPERIMENTAL_WEBAUTHN_PLUGIN_PERFORM_UV_OPERATION_TYPE::GetPubKey; - RETURN_IF_FAILED(webAuthNPluginPerformUv(&pluginPerformUv, &pPluginPerformUvResponse)); - - // stash public key in a new buffer for later use - DWORD cbPubData = pPluginPerformUvResponse->cbResponse; - wil::unique_hlocal_ptr ppbPubKeyData = wil::make_unique_hlocal(cbPubData); - memcpy_s(ppbPubKeyData.get(), cbPubData, pPluginPerformUvResponse->pbResponse, pPluginPerformUvResponse->cbResponse); - - // Step 3: Perform UV. This step uses a Windows Hello prompt to authenticate the user - pluginPerformUv.type = EXPERIMENTAL_WEBAUTHN_PLUGIN_PERFORM_UV_OPERATION_TYPE::PerformUv; - pluginPerformUv.pwszUsername = wil::make_cotaskmem_string(userName.get()).release(); - // pwszContext can be used to provide additional context to the user. This is displayed alongside the username in the Windows Hello passkey user verification dialog. - pluginPerformUv.pwszContext = wil::make_cotaskmem_string(L"Context String").release(); - RETURN_IF_FAILED(webAuthNPluginPerformUv(&pluginPerformUv, &pPluginPerformUvResponse)); - - // Verify the signature over the hash of requestBuffer using the hKey - auto signatureVerifyResult = VerifySignatureHelper( - requestBuffer, - ppbPubKeyData.get(), - cbPubData, - pPluginPerformUvResponse->pbResponse, - pPluginPerformUvResponse->cbResponse); - curApp->GetDispatcherQueue().TryEnqueue([curApp, signatureVerifyResult]() - { - if (FAILED(signatureVerifyResult)) - { - curApp->m_pluginOperationStatus.uvSignatureVerificationStatus = signatureVerifyResult; - } - }); - return S_OK; - } - - /* - * This function is used to create a simplified version of authenticator data for the webauthn authenticator operations. - * Refer: https://www.w3.org/TR/webauthn-3/#authenticator-data for more details. - */ - HRESULT CreateAuthenticatorData(wil::shared_ncrypt_key hKey, - DWORD cbRpId, - PBYTE pbRpId, - DWORD& pcbPackedAuthenticatorData, - wil::unique_hlocal_ptr& ppbpackedAuthenticatorData, - std::vector& vCredentialIdBuffer) - { - // Get the public key blob - DWORD cbPubKeyBlob = 0; - THROW_IF_FAILED(NCryptExportKey( - hKey.get(), - NULL, - BCRYPT_ECCPUBLIC_BLOB, - NULL, - NULL, - 0, - &cbPubKeyBlob, - 0)); - auto pbPubKeyBlob = std::make_unique(cbPubKeyBlob); - THROW_HR_IF(E_UNEXPECTED, pbPubKeyBlob == nullptr); - DWORD cbPubKeyBlobOutput = 0; - THROW_IF_FAILED(NCryptExportKey( - hKey.get(), - NULL, - BCRYPT_ECCPUBLIC_BLOB, - NULL, - pbPubKeyBlob.get(), - cbPubKeyBlob, - &cbPubKeyBlobOutput, - 0)); - - BCRYPT_ECCKEY_BLOB* pPubKeyBlobHeader = reinterpret_cast(pbPubKeyBlob.get()); - DWORD cbXCoord = pPubKeyBlobHeader->cbKey; - PBYTE pbXCoord = reinterpret_cast(&pPubKeyBlobHeader[1]); - DWORD cbYCoord = pPubKeyBlobHeader->cbKey; - PBYTE pbYCoord = pbXCoord + cbXCoord; - - // create byte span for x and y - std::span xCoord(pbXCoord, cbXCoord); - std::span yCoord(pbYCoord, cbYCoord); - - // CBOR encode the public key in this order: kty, alg, crv, x, y - std::vector buffer; - -#pragma warning(push) -#pragma warning(disable: 4293) - size_t bufferSize = CborLite::encodeMapSize(buffer, 5u); -#pragma warning(pop) - - // COSE CBOR encoding format. Refer to https://datatracker.ietf.org/doc/html/rfc9052#section-7 for more details. - const int8_t ktyIndex = 1; - const int8_t algIndex = 3; - const int8_t crvIndex = -1; - const int8_t xIndex = -2; - const int8_t yIndex = -3; - - // Example values for EC2 P-256 ES256 Keys. Refer to https://www.w3.org/TR/webauthn-3/#example-bdbd14cc - // Note that this sample authenticator only supports ES256 keys. - const int8_t kty = 2; // Key type is EC2 - const int8_t crv = 1; // Curve is P-256 - const int8_t alg = -7; // Algorithm is ES256 - - bufferSize += CborLite::encodeInteger(buffer, ktyIndex); - bufferSize += CborLite::encodeInteger(buffer, kty); - bufferSize += CborLite::encodeInteger(buffer, algIndex); - bufferSize += CborLite::encodeInteger(buffer, alg); - bufferSize += CborLite::encodeInteger(buffer, crvIndex); - bufferSize += CborLite::encodeInteger(buffer, crv); - bufferSize += CborLite::encodeInteger(buffer, xIndex); - bufferSize += CborLite::encodeBytes(buffer, xCoord); - bufferSize += CborLite::encodeInteger(buffer, yIndex); - bufferSize += CborLite::encodeBytes(buffer, yCoord); - - wil::unique_bcrypt_hash hashHandle; - THROW_IF_NTSTATUS_FAILED(BCryptCreateHash( - BCRYPT_SHA256_ALG_HANDLE, - &hashHandle, - nullptr, - 0, - nullptr, - 0, - 0)); - - THROW_IF_NTSTATUS_FAILED(BCryptHashData(hashHandle.get(), reinterpret_cast(pbXCoord), cbXCoord, 0)); - THROW_IF_NTSTATUS_FAILED(BCryptHashData(hashHandle.get(), reinterpret_cast(pbYCoord), cbYCoord, 0)); - - DWORD cbHash = 0; - DWORD bytesRead = 0; - THROW_IF_NTSTATUS_FAILED(BCryptGetProperty( - hashHandle.get(), - BCRYPT_HASH_LENGTH, - reinterpret_cast(&cbHash), - sizeof(cbHash), - &bytesRead, - 0)); - - wil::unique_hlocal_ptr pbCredentialId = wil::make_unique_hlocal(cbHash); - THROW_IF_NTSTATUS_FAILED(BCryptFinishHash(hashHandle.get(), pbCredentialId.get(), cbHash, 0)); - - // Close the key and hash handle - hKey.reset(); - hashHandle.reset(); - - com_ptr curApp = winrt::Microsoft::UI::Xaml::Application::Current().as(); - PluginOperationType operationType = PLUGIN_OPERATION_TYPE_MAKE_CREDENTIAL; - if (curApp && - curApp->m_pluginOperationOptions.operationType == PLUGIN_OPERATION_TYPE_GET_ASSERTION) - { - operationType = PLUGIN_OPERATION_TYPE_GET_ASSERTION; - } - - // Refer to learn about packing credential data https://www.w3.org/TR/webauthn-3/#sctn-authenticator-data - const DWORD rpidsha256Size = 32; // SHA256 hash of rpId - const DWORD flagsSize = 1; // flags - const DWORD signCountSize = 4; // signCount - DWORD cbPackedAuthenticatorData = rpidsha256Size + flagsSize + signCountSize; - - if (operationType == PLUGIN_OPERATION_TYPE_MAKE_CREDENTIAL) - { - cbPackedAuthenticatorData += sizeof(GUID); // aaGuid - cbPackedAuthenticatorData += sizeof(WORD); // credentialId length - cbPackedAuthenticatorData += cbHash; // credentialId - cbPackedAuthenticatorData += static_cast(buffer.size()); // public key - } - - std::vector vPackedAuthenticatorData(cbPackedAuthenticatorData); - auto writer = buffer_writer{ vPackedAuthenticatorData }; - - auto rgbRpIdHash = writer.reserve_space>(); // 32 bytes of rpIdHash which is SHA256 hash of rpName. https://www.w3.org/TR/webauthn-3/#sctn-authenticator-data - DWORD cbRpIdHash; - THROW_IF_WIN32_BOOL_FALSE(CryptHashCertificate2(BCRYPT_SHA256_ALGORITHM, - 0, - nullptr, - pbRpId, - cbRpId, - rgbRpIdHash->data(), - &cbRpIdHash)); - - // Flags uv, up, be, and at are set - if (operationType == PLUGIN_OPERATION_TYPE_GET_ASSERTION) - { - // Refer https://www.w3.org/TR/webauthn-3/#authdata-flags - *writer.reserve_space() = 0x1d; // credential data flags of size 1 byte - - *writer.reserve_space() = 0u; // Sign count of size 4 bytes is set to 0 - - vCredentialIdBuffer.assign(pbCredentialId.get(), pbCredentialId.get() + cbHash); - } - else - { - // Refer https://www.w3.org/TR/webauthn-3/#authdata-flags - *writer.reserve_space() = 0x5d; // credential data flags of size 1 byte - - *writer.reserve_space() = 0u; // Sign count of size 4 bytes is set to 0 - - *writer.reserve_space() = GUID_NULL; // aaGuid of size 16 bytes is set to 0 - - // Retrieve credential id - WORD cbCredentialId = static_cast(cbHash); - WORD cbCredentialIdBigEndian = _byteswap_ushort(cbCredentialId); - - *writer.reserve_space() = cbCredentialIdBigEndian; // Size of credential id in unsigned big endian of size 2 bytes - - writer.add(std::span(pbCredentialId.get(), cbHash)); // Set credential id - - vCredentialIdBuffer.assign(pbCredentialId.get(), pbCredentialId.get() + cbHash); - - writer.add(std::span(buffer.data(), buffer.size())); // Set CBOR encoded public key - } - - pcbPackedAuthenticatorData = static_cast(vPackedAuthenticatorData.size()); - ppbpackedAuthenticatorData = wil::make_unique_hlocal(pcbPackedAuthenticatorData); - memcpy_s(ppbpackedAuthenticatorData.get(), pcbPackedAuthenticatorData, vPackedAuthenticatorData.data(), pcbPackedAuthenticatorData); - - return S_OK; - } - - /* - * This function is invoked by the platform to request the plugin to handle a make credential operation. - * Refer: pluginauthenticator.h/pluginauthenticator.idl - */ - HRESULT STDMETHODCALLTYPE ContosoPlugin::EXPERIMENTAL_PluginMakeCredential( - /* [in] */ __RPC__in EXPERIMENTAL_PCWEBAUTHN_PLUGIN_OPERATION_REQUEST pPluginMakeCredentialRequest, - /* [out] */ __RPC__deref_out_opt EXPERIMENTAL_PWEBAUTHN_PLUGIN_OPERATION_RESPONSE* response) noexcept - { - try - { - SetEvent(App::s_pluginOpRequestRecievedEvent.get()); // indicate COM message received - DWORD hIndex = 0; - RETURN_IF_FAILED(CoWaitForMultipleHandles( // wait for app to be ready - COWAIT_DISPATCH_WINDOW_MESSAGES | COWAIT_DISPATCH_CALLS, - INFINITE, - 1, - App::s_hAppReadyForPluginOpEvent.addressof(), - &hIndex)); - com_ptr curApp = winrt::Microsoft::UI::Xaml::Application::Current().as(); - - wil::shared_hmodule webauthnDll(LoadLibraryExW(L"webauthn.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32)); - if (webauthnDll == nullptr) - { - return E_ABORT; - } - - wil::unique_cotaskmem_ptr pDecodedMakeCredentialRequest; - auto webauthnDecodeMakeCredentialRequest = GetProcAddressByFunctionDeclaration(webauthnDll.get(), EXPERIMENTAL_WebAuthNDecodeMakeCredentialRequest); - THROW_IF_FAILED(webauthnDecodeMakeCredentialRequest( - pPluginMakeCredentialRequest->cbEncodedRequest, - pPluginMakeCredentialRequest->pbEncodedRequest, - wil::out_param(pDecodedMakeCredentialRequest))); - auto rpName = wil::make_cotaskmem_string(pDecodedMakeCredentialRequest->pRpInformation->pwszName); - auto userName = wil::make_cotaskmem_string(pDecodedMakeCredentialRequest->pUserInformation->pwszName); - std::vector requestBuffer( - pPluginMakeCredentialRequest->pbEncodedRequest, - pPluginMakeCredentialRequest->pbEncodedRequest + pPluginMakeCredentialRequest->cbEncodedRequest); - - auto ppbPubKeyData = GetRequestSigningPubKey(); - HRESULT requestSignResult = E_FAIL; - if (!ppbPubKeyData.empty()) - { - requestSignResult = VerifySignatureHelper( - requestBuffer, - ppbPubKeyData.data(), - static_cast(ppbPubKeyData.size()), - pPluginMakeCredentialRequest->pbRequestSignature, - pPluginMakeCredentialRequest->cbRequestSignature); - } - { - std::lock_guard lock(curApp->m_pluginOperationOptionsMutex); - curApp->m_pluginOperationStatus.requestSignatureVerificationStatus = requestSignResult; - } - - THROW_IF_FAILED(PerformUv(curApp, - pPluginMakeCredentialRequest->hWnd, - webauthnDll, - pPluginMakeCredentialRequest->transactionId, - PLUGIN_OPERATION_TYPE_MAKE_CREDENTIAL, - requestBuffer, - std::move(rpName), - std::move(userName))); - - //create a persisted key using ncrypt - wil::unique_ncrypt_prov hProvider; - wil::unique_ncrypt_key hKey; - - // get the provider - THROW_IF_FAILED(NCryptOpenStorageProvider(&hProvider, nullptr, 0)); - - // get the user handle as a string - std::wstring keyNameStr = contosoplugin_key_domain; - std::wstringstream keyNameStream; - for (DWORD idx = 0; idx < pDecodedMakeCredentialRequest->pUserInformation->cbId; idx++) - { - keyNameStream << std::hex << std::setw(2) << std::setfill(L'0') << - static_cast(pDecodedMakeCredentialRequest->pUserInformation->pbId[idx]); - } - keyNameStr += keyNameStream.str(); - - // create the key - THROW_IF_FAILED(NCryptCreatePersistedKey( - hProvider.get(), - &hKey, - BCRYPT_ECDH_P256_ALGORITHM, - keyNameStr.c_str(), - 0, - NCRYPT_OVERWRITE_KEY_FLAG)); - - // set the export policy - DWORD exportPolicy = NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG; - THROW_IF_FAILED(NCryptSetProperty( - hKey.get(), - NCRYPT_EXPORT_POLICY_PROPERTY, - reinterpret_cast(&exportPolicy), - sizeof(exportPolicy), - NCRYPT_PERSIST_FLAG)); - - // allow both signing and encryption - DWORD keyUsage = NCRYPT_ALLOW_SIGNING_FLAG | NCRYPT_ALLOW_DECRYPT_FLAG; - THROW_IF_FAILED(NCryptSetProperty( - hKey.get(), - NCRYPT_KEY_USAGE_PROPERTY, - reinterpret_cast(&keyUsage), - sizeof(keyUsage), - NCRYPT_PERSIST_FLAG)); - HWND hWnd; - if (curApp->m_silentMode) - { - hWnd = curApp->m_pluginOperationOptions.hWnd; - } - else - { - hWnd = curApp->GetNativeWindowHandle(); - } - THROW_IF_FAILED(NCryptSetProperty( - hKey.get(), - NCRYPT_WINDOW_HANDLE_PROPERTY, - reinterpret_cast(&hWnd), - sizeof(HWND), - 0)); - - // finalize the key - THROW_IF_FAILED(NCryptFinalizeKey(hKey.get(), 0)); - - DWORD cbPackedAuthenticatorData = 0; - wil::unique_hlocal_ptr packedAuthenticatorData; - std::vector vCredentialIdBuffer; - THROW_IF_FAILED(CreateAuthenticatorData( - std::move(hKey), - pDecodedMakeCredentialRequest->cbRpId, - pDecodedMakeCredentialRequest->pbRpId, - cbPackedAuthenticatorData, - packedAuthenticatorData, - vCredentialIdBuffer)); - - auto operationResponse = wil::make_unique_cotaskmem(); - - WEBAUTHN_CREDENTIAL_ATTESTATION attestationResponse{}; - attestationResponse.dwVersion = WEBAUTHN_CREDENTIAL_ATTESTATION_CURRENT_VERSION; - attestationResponse.pwszFormatType = WEBAUTHN_ATTESTATION_TYPE_NONE; - attestationResponse.cbAttestation = 0; - attestationResponse.pbAttestation = nullptr; - attestationResponse.cbAuthenticatorData = 0; - attestationResponse.pbAuthenticatorData = nullptr; - - attestationResponse.pbAuthenticatorData = packedAuthenticatorData.get(); - attestationResponse.cbAuthenticatorData = cbPackedAuthenticatorData; - - DWORD cbAttestationBuffer = 0; - PBYTE pbattestationBuffer; - - auto webauthnEncodeMakeCredentialResponse = GetProcAddressByFunctionDeclaration(webauthnDll.get(), EXPERIMENTAL_WebAuthNEncodeMakeCredentialResponse); - THROW_IF_FAILED(webauthnEncodeMakeCredentialResponse( - &attestationResponse, - &cbAttestationBuffer, - &pbattestationBuffer)); - operationResponse->cbEncodedResponse = cbAttestationBuffer; - operationResponse->pbEncodedResponse = wil::make_unique_cotaskmem(cbAttestationBuffer).release(); - memcpy_s(operationResponse->pbEncodedResponse, - operationResponse->cbEncodedResponse, - pbattestationBuffer, - cbAttestationBuffer); - - *response = operationResponse.release(); - - WEBAUTHN_CREDENTIAL_DETAILS credentialDetails{}; - credentialDetails.dwVersion = WEBAUTHN_CREDENTIAL_DETAILS_CURRENT_VERSION; - credentialDetails.pUserInformation = const_cast(pDecodedMakeCredentialRequest->pUserInformation); - credentialDetails.pRpInformation = const_cast(pDecodedMakeCredentialRequest->pRpInformation); - credentialDetails.cbCredentialID = static_cast(vCredentialIdBuffer.size()); - credentialDetails.pbCredentialID = wil::make_unique_cotaskmem(vCredentialIdBuffer.size()).release(); - memcpy_s(credentialDetails.pbCredentialID, credentialDetails.cbCredentialID, vCredentialIdBuffer.data(), static_cast(vCredentialIdBuffer.size())); - if (!PluginCredentialManager::getInstance().SaveCredentialMetadataToMockDB(credentialDetails)) - { - std::lock_guard lock(curApp->m_pluginOperationOptionsMutex); - curApp->m_pluginOperationStatus.performOperationStatus = E_FAIL; - } - pDecodedMakeCredentialRequest.reset(); - SetEvent(App::s_hPluginOpCompletedEvent.get()); - return S_OK; - } - catch (...) - { - HRESULT hr = wil::ResultFromCaughtException(); - com_ptr curApp = winrt::Microsoft::UI::Xaml::Application::Current().as(); - if (curApp) - { - hr = winrt::to_hresult(); - std::lock_guard lock(curApp->m_pluginOperationOptionsMutex); - curApp->m_pluginOperationStatus.performOperationStatus = hr; - }; - SetEvent(App::s_hPluginOpCompletedEvent.get()); - return hr; - } - } - - /* - * This function is invoked by the platform to request the plugin to handle a get assertion operation. - * Refer: pluginauthenticator.h/pluginauthenticator.idl - */ - HRESULT STDMETHODCALLTYPE ContosoPlugin::EXPERIMENTAL_PluginGetAssertion( - /* [in] */ __RPC__in EXPERIMENTAL_PCWEBAUTHN_PLUGIN_OPERATION_REQUEST pPluginGetAssertionRequest, - /* [out] */ __RPC__deref_out_opt EXPERIMENTAL_PWEBAUTHN_PLUGIN_OPERATION_RESPONSE* response) noexcept - { - try - { - SetEvent(App::s_pluginOpRequestRecievedEvent.get()); - DWORD hIndex = 0; - RETURN_IF_FAILED(CoWaitForMultipleHandles( - COWAIT_DISPATCH_WINDOW_MESSAGES | COWAIT_DISPATCH_CALLS, - INFINITE, - 1, - App::s_hAppReadyForPluginOpEvent.addressof(), - &hIndex)); - com_ptr curApp = winrt::Microsoft::UI::Xaml::Application::Current().as(); - - wil::shared_hmodule webauthnDll(LoadLibraryExW(L"webauthn.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32)); - if (webauthnDll == nullptr) - { - return E_ABORT; - } - - wil::unique_cotaskmem_ptr pDecodedAssertionRequest; - // The EXPERIMENTAL_WebAuthNDecodeGetAssertionRequest function can be optionally used to decode the CBOR encoded request to a EXPERIMENTAL_WEBAUTHN_CTAPCBOR_GET_ASSERTION_REQUEST structure. - auto webauthnDecodeGetAssertionRequest = GetProcAddressByFunctionDeclaration(webauthnDll.get(), EXPERIMENTAL_WebAuthNDecodeGetAssertionRequest); - webauthnDecodeGetAssertionRequest(pPluginGetAssertionRequest->cbEncodedRequest, pPluginGetAssertionRequest->pbEncodedRequest, wil::out_param(pDecodedAssertionRequest)); - wil::shared_cotaskmem_string rpName = wil::make_cotaskmem_string(pDecodedAssertionRequest->pwszRpId); - //load the user handle - auto& credManager = PluginCredentialManager::getInstance(); - const WEBAUTHN_CREDENTIAL_DETAILS* selectedCredential{}; - // create a list of credentials - std::vector selectedCredentials; - - while (true) - { - Sleep(100); - if (credManager.IsLocalCredentialMetadataLoaded()) - { - credManager.GetLocalCredsByRpIdAndAllowList(pDecodedAssertionRequest->pwszRpId, - pDecodedAssertionRequest->CredentialList.ppCredentials, - pDecodedAssertionRequest->CredentialList.cCredentials, - selectedCredentials); - break; - } - } - - if (selectedCredentials.empty()) - { - { - std::lock_guard lock(curApp->m_pluginOperationOptionsMutex); - curApp->m_pluginOperationStatus.performOperationStatus = NTE_NOT_FOUND; - } - SetEvent(App::s_hPluginOpCompletedEvent.get()); - return NTE_NOT_FOUND; - } - else if (selectedCredentials.size() == 1 && credManager.GetSilentOperation()) - { - selectedCredential = selectedCredentials[0]; - } - else - { - curApp->SetMatchingCredentials(pDecodedAssertionRequest->pwszRpId, selectedCredentials, pPluginGetAssertionRequest->hWnd); - hIndex = 0; - RETURN_IF_FAILED(CoWaitForMultipleHandles(COWAIT_DISPATCH_WINDOW_MESSAGES | COWAIT_DISPATCH_CALLS, INFINITE, 1, curApp->m_hPluginCredentialSelected.addressof(), &hIndex)); - - { - std::lock_guard lock(curApp->m_pluginOperationOptionsMutex); - selectedCredential = curApp->m_pluginOperationOptions.selectedCredential; - } - - // Failed to select a credential - if (selectedCredential->cbCredentialID == 0 || - selectedCredential->pbCredentialID == nullptr || - selectedCredential->pUserInformation == nullptr || - selectedCredential->pUserInformation->pwszName == nullptr) - { - { - std::lock_guard lock(curApp->m_pluginOperationOptionsMutex); - curApp->m_pluginOperationStatus.performOperationStatus = NTE_NOT_FOUND; - } - SetEvent(App::s_hPluginOpCompletedEvent.get()); - return NTE_NOT_FOUND; - } - } - - wil::shared_cotaskmem_string userName = wil::make_cotaskmem_string(selectedCredential->pUserInformation->pwszName); - - std::vector requestBuffer( - pPluginGetAssertionRequest->pbEncodedRequest, - pPluginGetAssertionRequest->pbEncodedRequest + pPluginGetAssertionRequest->cbEncodedRequest); - - auto ppbPubKeyData = GetRequestSigningPubKey(); - HRESULT requestSignResult = E_FAIL; - if (!ppbPubKeyData.empty()) - { - requestSignResult = VerifySignatureHelper( - requestBuffer, - ppbPubKeyData.data(), - static_cast(ppbPubKeyData.size()), - pPluginGetAssertionRequest->pbRequestSignature, - pPluginGetAssertionRequest->cbRequestSignature); - } - - { - std::lock_guard lock(curApp->m_pluginOperationOptionsMutex); - curApp->m_pluginOperationStatus.requestSignatureVerificationStatus = requestSignResult; - } - - THROW_IF_FAILED(PerformUv(curApp, - pPluginGetAssertionRequest->hWnd, - webauthnDll, - pPluginGetAssertionRequest->transactionId, - PLUGIN_OPERATION_TYPE_GET_ASSERTION, - requestBuffer, - rpName, - userName)); - - // convert user handle to a string - std::wstring keyNameStr = contosoplugin_key_domain; - std::wstringstream keyNameStream; - for (DWORD idx = 0; idx < selectedCredential->pUserInformation->cbId; idx++) - { - keyNameStream << std::hex << std::setw(2) << std::setfill(L'0') << - static_cast(selectedCredential->pUserInformation->pbId[idx]); - } - keyNameStr += keyNameStream.str(); - - //open the key using ncrypt and sign the data - wil::unique_ncrypt_prov hProvider; - wil::shared_ncrypt_key hKey; - - // get the provider - THROW_IF_FAILED(NCryptOpenStorageProvider(&hProvider, nullptr, 0)); - - // open the key - THROW_IF_FAILED(NCryptOpenKey(hProvider.get(), &hKey, keyNameStr.c_str(), 0, 0)); - - // set hwnd property - wil::unique_hwnd hWnd; - if (curApp->m_silentMode) - { - hWnd.reset(curApp->m_pluginOperationOptions.hWnd); - } - else - { - hWnd.reset(curApp->GetNativeWindowHandle()); - } - THROW_IF_FAILED(NCryptSetProperty( - hKey.get(), - NCRYPT_WINDOW_HANDLE_PROPERTY, - (BYTE*)(hWnd.addressof()), - sizeof(HWND), - 0)); - - // create authenticator data - DWORD cbPackedAuthenticatorData = 0; - wil::unique_hlocal_ptr packedAuthenticatorData; - std::vector vCredentialIdBuffer; - THROW_IF_FAILED(CreateAuthenticatorData(hKey, - pDecodedAssertionRequest->cbRpId, - pDecodedAssertionRequest->pbRpId, - cbPackedAuthenticatorData, - packedAuthenticatorData, - vCredentialIdBuffer)); - - wil::unique_hlocal_ptr pbSignature = nullptr; - DWORD cbSignature = 0; - - { - wil::unique_bcrypt_hash hashHandle; - - - THROW_IF_NTSTATUS_FAILED(BCryptCreateHash( - BCRYPT_SHA256_ALG_HANDLE, - &hashHandle, - nullptr, - 0, - nullptr, - 0, - 0)); - - THROW_IF_NTSTATUS_FAILED(BCryptHashData(hashHandle.get(), const_cast(packedAuthenticatorData.get()), cbPackedAuthenticatorData, 0)); - THROW_IF_NTSTATUS_FAILED(BCryptHashData(hashHandle.get(), const_cast(pDecodedAssertionRequest->pbClientDataHash), pDecodedAssertionRequest->cbClientDataHash, 0)); - - DWORD bytesRead = 0; - DWORD cbSignatureBuffer = 0; - THROW_IF_NTSTATUS_FAILED(BCryptGetProperty( - hashHandle.get(), - BCRYPT_HASH_LENGTH, - reinterpret_cast(&cbSignatureBuffer), - sizeof(cbSignatureBuffer), - &bytesRead, - 0)); - - wil::unique_hlocal_ptr signatureBuffer = wil::make_unique_hlocal(cbSignatureBuffer); - THROW_HR_IF(E_UNEXPECTED, signatureBuffer == nullptr); - THROW_IF_NTSTATUS_FAILED(BCryptFinishHash(hashHandle.get(), signatureBuffer.get(), cbSignatureBuffer, 0)); - - // sign the data - THROW_IF_FAILED(NCryptSignHash(hKey.get(), nullptr, signatureBuffer.get(), cbSignatureBuffer, nullptr, 0, &cbSignature, 0)); - - pbSignature = wil::make_unique_hlocal(cbSignature); - THROW_HR_IF(E_UNEXPECTED, pbSignature == nullptr); - - THROW_IF_FAILED(NCryptSignHash(hKey.get(), nullptr, signatureBuffer.get(), cbSignatureBuffer, pbSignature.get(), cbSignature, &cbSignature, 0)); - signatureBuffer.reset(); - - auto encodeSignature = [](PBYTE signature, size_t signatureSize) - { - std::vector encodedSignature{}; - encodedSignature.push_back(0x02); // ASN integer tag - encodedSignature.push_back(static_cast(signatureSize)); // length of the signature - if (WI_IsFlagSet(signature[0], 0x80)) - { - encodedSignature[encodedSignature.size() - 1]++; - encodedSignature.push_back(0x00); // add a padding byte if the first byte has the high bit set - } - - encodedSignature.insert(encodedSignature.end(), signature, signature + signatureSize); - return encodedSignature; - }; - - auto signatureR = encodeSignature(pbSignature.get(), cbSignature / 2); - auto signatureS = encodeSignature(pbSignature.get() + cbSignature / 2, cbSignature / 2); - - std::vector encodedSignature{}; - encodedSignature.push_back(0x30); // ASN sequence tag - encodedSignature.push_back(static_cast(signatureR.size() + signatureS.size())); // length of the sequence - encodedSignature.insert(encodedSignature.end(), signatureR.begin(), signatureR.end()); - encodedSignature.insert(encodedSignature.end(), signatureS.begin(), signatureS.end()); - - cbSignature = static_cast(encodedSignature.size()); - pbSignature.reset(); - pbSignature = wil::make_unique_hlocal(cbSignature); - THROW_HR_IF(E_UNEXPECTED, pbSignature == nullptr); - memcpy_s(pbSignature.get(), cbSignature, encodedSignature.data(), static_cast(cbSignature)); - } - - // create the response - auto operationResponse = wil::make_unique_cotaskmem(); - - auto assertionResponse = wil::make_unique_cotaskmem(); - assertionResponse->dwVersion = WEBAUTHN_ASSERTION_CURRENT_VERSION; - - // [1] Credential (optional) - assertionResponse->Credential.dwVersion = WEBAUTHN_CREDENTIAL_CURRENT_VERSION; - assertionResponse->Credential.cbId = static_cast(vCredentialIdBuffer.size()); - assertionResponse->Credential.pbId = vCredentialIdBuffer.data(); - assertionResponse->Credential.pwszCredentialType = WEBAUTHN_CREDENTIAL_TYPE_PUBLIC_KEY; - - // [2] AuthenticatorData - assertionResponse->cbAuthenticatorData = cbPackedAuthenticatorData; - assertionResponse->pbAuthenticatorData = packedAuthenticatorData.get(); - - // [3] Signature - assertionResponse->cbSignature = cbSignature; - assertionResponse->pbSignature = pbSignature.get(); - - // [4] User (optional) - assertionResponse->cbUserId = selectedCredential->pUserInformation->cbId; - auto userIdBuffer = wil::make_unique_cotaskmem(selectedCredential->pUserInformation->cbId); - memcpy_s(userIdBuffer.get(), - selectedCredential->pUserInformation->cbId, - selectedCredential->pUserInformation->pbId, - selectedCredential->pUserInformation->cbId); - assertionResponse->pbUserId = userIdBuffer.get(); - WEBAUTHN_USER_ENTITY_INFORMATION userEntityInformation{}; - userEntityInformation.dwVersion = WEBAUTHN_USER_ENTITY_INFORMATION_CURRENT_VERSION; - userEntityInformation.cbId = assertionResponse->cbUserId; - userEntityInformation.pbId = assertionResponse->pbUserId; - - auto ctapGetAssertionResponse = wil::make_unique_cotaskmem(); - ctapGetAssertionResponse->WebAuthNAssertion = *(assertionResponse.get()); // [1] Credential, [2] AuthenticatorData, [3] Signature - ctapGetAssertionResponse->pUserInformation = &userEntityInformation; // [4] User - ctapGetAssertionResponse->dwNumberOfCredentials = 1; // [5] NumberOfCredentials - - DWORD cbAssertionBuffer = 0; - PBYTE pbAssertionBuffer; - - // The EXPERIMENTAL_WebAuthNEncodeGetAssertionResponse function can be optionally used to encode the - // EXPERIMENTAL_WEBAUTHN_CTAPCBOR_GET_ASSERTION_RESPONSE structure to a CBOR encoded response. - auto webAuthNEncodeGetAssertionResponse = GetProcAddressByFunctionDeclaration(webauthnDll.get(), EXPERIMENTAL_WebAuthNEncodeGetAssertionResponse); - THROW_IF_FAILED(webAuthNEncodeGetAssertionResponse( - (EXPERIMENTAL_PCWEBAUTHN_CTAPCBOR_GET_ASSERTION_RESPONSE)(ctapGetAssertionResponse.get()), - &cbAssertionBuffer, - &pbAssertionBuffer)); - - assertionResponse.reset(); - ctapGetAssertionResponse.reset(); - userIdBuffer.reset(); - packedAuthenticatorData.reset(); - pbSignature.reset(); - pDecodedAssertionRequest.reset(); - - operationResponse->cbEncodedResponse = cbAssertionBuffer; - // pbEncodedResponse must contain a CBOR encoded response as specified the FIDO CTAP. - // Refer: https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#message-encoding. - operationResponse->pbEncodedResponse = wil::make_unique_cotaskmem(cbAssertionBuffer).release(); - memcpy_s( - operationResponse->pbEncodedResponse, - operationResponse->cbEncodedResponse, - pbAssertionBuffer, - cbAssertionBuffer); - - *response = operationResponse.release(); - SetEvent(App::s_hPluginOpCompletedEvent.get()); - return S_OK; - } - catch (...) - { - HRESULT localHr = wil::ResultFromCaughtException(); - { - winrt::com_ptr curApp = winrt::Microsoft::UI::Xaml::Application::Current().as(); - std::lock_guard lock(curApp->m_pluginOperationOptionsMutex); - curApp->m_pluginOperationStatus.performOperationStatus = localHr; - } - SetEvent(App::s_hPluginOpCompletedEvent.get()); - return localHr; - } - } - - /* - * This function is invoked by the platform to request the plugin to cancel an ongoing operation. - */ - HRESULT STDMETHODCALLTYPE ContosoPlugin::EXPERIMENTAL_PluginCancelOperation( - /* [out] */ __RPC__in EXPERIMENTAL_PCWEBAUTHN_PLUGIN_CANCEL_OPERATION_REQUEST) - { - SetEvent(App::s_pluginOpRequestRecievedEvent.get()); - com_ptr curApp = winrt::Microsoft::UI::Xaml::Application::Current().as(); - curApp->GetDispatcherQueue().TryEnqueue([curApp]() - { - curApp->PluginCancelAction(); - }); - return S_OK; - } - - /* - * This is a sample implementation of a factory method that creates an instance of the Class that implements the EXPERIMENTAL_IPluginAuthenticator interface. - * Refer: pluginauthenticator.h/pluginauthenticator.idl for the interface definition. - */ - HRESULT __stdcall ContosoPluginFactory::CreateInstance( - ::IUnknown* outer, - GUID const& iid, - void** result) noexcept - { - *result = nullptr; - - if (outer) - { - return CLASS_E_NOAGGREGATION; - } - - try - { - return make()->QueryInterface(iid, result); - } - catch (...) - { - return winrt::to_hresult(); - } - } - - HRESULT __stdcall ContosoPluginFactory::LockServer(BOOL) noexcept - { - return S_OK; - } - -} diff --git a/apps/desktop/desktop_native/windows_plugin_authenticator/include/experimental/PluginRegistrationManager.cpp b/apps/desktop/desktop_native/windows_plugin_authenticator/include/experimental/PluginRegistrationManager.cpp deleted file mode 100644 index c5a5a52bfa5..00000000000 --- a/apps/desktop/desktop_native/windows_plugin_authenticator/include/experimental/PluginRegistrationManager.cpp +++ /dev/null @@ -1,126 +0,0 @@ -#include "pch.h" -#include "MainPage.xaml.h" -#include "PluginRegistrationManager.h" -#include - -namespace winrt::PasskeyManager::implementation { - PluginRegistrationManager::PluginRegistrationManager() : - m_pluginRegistered(false), - m_initialized(false), - m_pluginState(EXPERIMENTAL_PLUGIN_AUTHENTICATOR_STATE::PluginAuthenticatorState_Unknown) - { - Initialize(); - m_webAuthnDll.reset(LoadLibraryExW(L"webauthn.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32)); - } - - PluginRegistrationManager::~PluginRegistrationManager() - { - } - - HRESULT PluginRegistrationManager::Initialize() - { - HRESULT hr = RefreshPluginState(); - RETURN_HR_IF_EXPECTED(S_OK, RefreshPluginState() == NTE_NOT_FOUND); - RETURN_HR(hr); - } - - HRESULT PluginRegistrationManager::RegisterPlugin() - { - // Get the function pointer of WebAuthNPluginAddAuthenticator - auto webAuthNPluginAddAuthenticator = GetProcAddressByFunctionDeclaration( - m_webAuthnDll.get(), - EXPERIMENTAL_WebAuthNPluginAddAuthenticator); - RETURN_HR_IF_NULL(E_FAIL, webAuthNPluginAddAuthenticator); - - /* - * This section creates a sample authenticatorInfo blob to include in the registration - * request. This blob must CBOR encoded using the format defined - * in https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#authenticatorGetInfo - * - * 'AAGUID' maybe used to fetch information about the authenticator from the FIDO Metadata Service and other sources. - * Refer: https://fidoalliance.org/metadata/ - * - * 'extensions' field is used to perform feature detection on the authenticator - * and maybe used to determine if the authenticator is filtered out. - */ - std::string tempAaguidStr{ c_pluginAaguid }; - tempAaguidStr.erase(std::remove(tempAaguidStr.begin(), tempAaguidStr.end(), L'-'), tempAaguidStr.end()); - std::transform(tempAaguidStr.begin(), tempAaguidStr.end(), tempAaguidStr.begin(), [](unsigned char c) { return static_cast(std::toupper(c)); }); - // The following hex strings represent the encoding of - // {1: ["FIDO_2_0", "FIDO_2_1"], 2: ["prf", "hmac-secret"], 3: h'/* AAGUID */', 4: {"rk": true, "up": true, "uv": true}, - // 9: ["internal"], 10: [{"alg": -7, "type": "public-key"}]} - std::string authenticatorInfoStrPart1 = "A60182684649444F5F325F30684649444F5F325F310282637072666B686D61632D7365637265740350"; - std::string authenticatorInfoStrPart2 = "04A362726BF5627570F5627576F5098168696E7465726E616C0A81A263616C672664747970656A7075626C69632D6B6579"; - std::string fullAuthenticatorInfoStr = authenticatorInfoStrPart1 + tempAaguidStr + authenticatorInfoStrPart2; - std::vector authenticatorInfo = hexStringToBytes(fullAuthenticatorInfoStr); - - // Validate that c_pluginClsid is a valid CLSID - CLSID CLSID_ContosoPluginAuthenticator; - RETURN_IF_FAILED(CLSIDFromString(c_pluginClsid, &CLSID_ContosoPluginAuthenticator)); - - EXPERIMENTAL_WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS addOptions{}; - addOptions.pwszAuthenticatorName = c_pluginName; - addOptions.pwszPluginRpId = c_pluginRpId; - addOptions.pwszPluginClsId = c_pluginClsid; - addOptions.pbAuthenticatorInfo = authenticatorInfo.data(); - addOptions.cbAuthenticatorInfo = static_cast(authenticatorInfo.size()); - - EXPERIMENTAL_PWEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_RESPONSE addResponse; - RETURN_IF_FAILED(webAuthNPluginAddAuthenticator(&addOptions, &addResponse)); - - // The response from plugin contains the public key used to sign plugin operation requests. Stash it for later use. - wil::unique_hkey hKey; - RETURN_IF_WIN32_ERROR(RegCreateKeyEx( - HKEY_CURRENT_USER, - c_pluginRegistryPath, - 0, - nullptr, - REG_OPTION_NON_VOLATILE, - KEY_WRITE, - nullptr, - &hKey, - nullptr)); - - RETURN_IF_WIN32_ERROR(RegSetValueEx( - hKey.get(), - c_windowsPluginRequestSigningKeyRegKeyName, - 0, - REG_BINARY, - addResponse->pbOpSignPubKey, - addResponse->cbOpSignPubKey)); - return S_OK; - } - - HRESULT PluginRegistrationManager::UnregisterPlugin() - { - // Get the function pointer of WebAuthNPluginRemoveAuthenticator - auto webAuthNPluginRemoveAuthenticator = GetProcAddressByFunctionDeclaration( - m_webAuthnDll.get(), - EXPERIMENTAL_WebAuthNPluginRemoveAuthenticator); - RETURN_HR_IF_NULL(E_FAIL, webAuthNPluginRemoveAuthenticator); - - RETURN_HR(webAuthNPluginRemoveAuthenticator(c_pluginClsid)); - } - - HRESULT PluginRegistrationManager::RefreshPluginState() - { - // Reset the plugin state and registration status - m_pluginRegistered = false; - m_pluginState = EXPERIMENTAL_PLUGIN_AUTHENTICATOR_STATE::PluginAuthenticatorState_Unknown; - - // Get handle to EXPERIMENTAL_WebAuthNPluginGetAuthenticatorState which takes in a GUID and returns EXPERIMENTAL_PLUGIN_AUTHENTICATOR_STATE - auto webAuthNPluginGetAuthenticatorState = GetProcAddressByFunctionDeclaration( - m_webAuthnDll.get(), - EXPERIMENTAL_WebAuthNPluginGetAuthenticatorState); - RETURN_HR_IF_NULL(E_FAIL, webAuthNPluginGetAuthenticatorState); - - // Get the plugin state - EXPERIMENTAL_PLUGIN_AUTHENTICATOR_STATE localPluginState; - RETURN_IF_FAILED(webAuthNPluginGetAuthenticatorState(c_pluginClsid, &localPluginState)); - - // If the EXPERIMENTAL_WebAuthNPluginGetAuthenticatorState function succeeded, that indicates the plugin is registered and localPluginState is the valid plugin state - m_pluginRegistered = true; - m_pluginState = localPluginState; - return S_OK; - } -} \ No newline at end of file diff --git a/apps/desktop/desktop_native/windows_plugin_authenticator/include/experimental/PluginRegistrationManager.h b/apps/desktop/desktop_native/windows_plugin_authenticator/include/experimental/PluginRegistrationManager.h deleted file mode 100644 index df0d3b6949b..00000000000 --- a/apps/desktop/desktop_native/windows_plugin_authenticator/include/experimental/PluginRegistrationManager.h +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once -#include "pch.h" -#include -#include -#include -#include -#include - -constexpr wchar_t c_pluginName[] = L"Contoso Passkey Manager"; -constexpr wchar_t c_pluginRpId[] = L"contoso.com"; - -/* The AAGUID is a unique identifier for the FIDO authenticator model. -*'AAGUID' maybe used to fetch information about the authenticator from the FIDO Metadata Service and other sources. -* Refer: https://fidoalliance.org/metadata/ -*/ -constexpr char c_pluginAaguid[] = "########-####-####-####-############"; -static_assert(c_pluginAaguid[1] != '#', "Please replace the ##### above with your AAGUID or a value you generated by running guidgen"); - -/* Generate a GUID using guidgen and replace below and in Package.appxmanifest file */ -constexpr wchar_t c_pluginClsid[] = L"{########-####-####-####-############}"; -static_assert(c_pluginClsid[1] != '#', "Please replace the ##### above with a GUID you generated by running guidgen"); - - -constexpr wchar_t c_pluginSigningKeyName[] = L"TestAppPluginIdKey"; -constexpr wchar_t c_pluginRegistryPath[] = L"Software\\Contoso\\PasskeyManager"; -constexpr wchar_t c_windowsPluginRequestSigningKeyRegKeyName[] = L"RequestSigningKeyBlob"; -constexpr wchar_t c_windowsPluginVaultLockedRegKeyName[] = L"VaultLocked"; -constexpr wchar_t c_windowsPluginSilentOperationRegKeyName[] = L"SilentOperation"; -constexpr wchar_t c_windowsPluginDBUpdateInd[] = L"SilentOperation"; - -namespace winrt::PasskeyManager::implementation -{ - class PluginRegistrationManager - { - public: - static PluginRegistrationManager& getInstance() - { - static PluginRegistrationManager instance; - return instance; - } - - // Initialize function which calls GetPluginState to check if the plugin is already registered - HRESULT Initialize(); - - HRESULT RegisterPlugin(); - HRESULT UnregisterPlugin(); - - HRESULT RefreshPluginState(); - - bool IsPluginRegistered() const - { - return m_pluginRegistered; - } - - EXPERIMENTAL_PLUGIN_AUTHENTICATOR_STATE GetPluginState() const - { - return m_pluginState; - } - - private: - EXPERIMENTAL_PLUGIN_AUTHENTICATOR_STATE m_pluginState; - bool m_initialized = false; - bool m_pluginRegistered = false; - wil::unique_hmodule m_webAuthnDll; - - PluginRegistrationManager(); - ~PluginRegistrationManager(); - PluginRegistrationManager(const PluginRegistrationManager&) = delete; - PluginRegistrationManager& operator=(const PluginRegistrationManager&) = delete; - - void UpdatePasskeyOperationStatusText(hstring const& statusText) - { - com_ptr curApp = winrt::Microsoft::UI::Xaml::Application::Current().as(); - curApp->GetDispatcherQueue().TryEnqueue([curApp, statusText]() - { - curApp->m_window.Content().try_as().Content().try_as()->UpdatePasskeyOperationStatusText(statusText); - }); - } - }; -}; \ No newline at end of file diff --git a/apps/desktop/desktop_native/windows_plugin_authenticator/include/experimental/pluginauthenticator.h b/apps/desktop/desktop_native/windows_plugin_authenticator/include/experimental/pluginauthenticator.h deleted file mode 100644 index 3e5bfcb80c9..00000000000 --- a/apps/desktop/desktop_native/windows_plugin_authenticator/include/experimental/pluginauthenticator.h +++ /dev/null @@ -1,239 +0,0 @@ - - -/* this ALWAYS GENERATED file contains the definitions for the interfaces */ - - - /* File created by MIDL compiler version 8.01.0628 */ -/* @@MIDL_FILE_HEADING( ) */ - - - -/* verify that the version is high enough to compile this file*/ -#ifndef __REQUIRED_RPCNDR_H_VERSION__ -#define __REQUIRED_RPCNDR_H_VERSION__ 501 -#endif - -/* verify that the version is high enough to compile this file*/ -#ifndef __REQUIRED_RPCSAL_H_VERSION__ -#define __REQUIRED_RPCSAL_H_VERSION__ 100 -#endif - -#include "rpc.h" -#include "rpcndr.h" - -#ifndef __RPCNDR_H_VERSION__ -#error this stub requires an updated version of -#endif /* __RPCNDR_H_VERSION__ */ - -#ifndef COM_NO_WINDOWS_H -#include "windows.h" -#include "ole2.h" -#endif /*COM_NO_WINDOWS_H*/ - -#ifndef __pluginauthenticator_h__ -#define __pluginauthenticator_h__ - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -#pragma once -#endif - -#ifndef DECLSPEC_XFGVIRT -#if defined(_CONTROL_FLOW_GUARD_XFG) -#define DECLSPEC_XFGVIRT(base, func) __declspec(xfg_virtual(base, func)) -#else -#define DECLSPEC_XFGVIRT(base, func) -#endif -#endif - -/* Forward Declarations */ - -#ifndef __EXPERIMENTAL_IPluginAuthenticator_FWD_DEFINED__ -#define __EXPERIMENTAL_IPluginAuthenticator_FWD_DEFINED__ -typedef interface EXPERIMENTAL_IPluginAuthenticator EXPERIMENTAL_IPluginAuthenticator; - -#endif /* __EXPERIMENTAL_IPluginAuthenticator_FWD_DEFINED__ */ - - -/* header files for imported files */ -#include "oaidl.h" -#include "webauthn.h" - -#ifdef __cplusplus -extern "C"{ -#endif - - -/* interface __MIDL_itf_pluginauthenticator_0000_0000 */ -/* [local] */ - -typedef struct _EXPERIMENTAL_WEBAUTHN_PLUGIN_OPERATION_REQUEST - { - HWND hWnd; - GUID transactionId; - DWORD cbRequestSignature; - /* [size_is] */ byte *pbRequestSignature; - DWORD cbEncodedRequest; - /* [size_is] */ byte *pbEncodedRequest; - } EXPERIMENTAL_WEBAUTHN_PLUGIN_OPERATION_REQUEST; - -typedef struct _EXPERIMENTAL_WEBAUTHN_PLUGIN_OPERATION_REQUEST *EXPERIMENTAL_PWEBAUTHN_PLUGIN_OPERATION_REQUEST; - -typedef const EXPERIMENTAL_WEBAUTHN_PLUGIN_OPERATION_REQUEST *EXPERIMENTAL_PCWEBAUTHN_PLUGIN_OPERATION_REQUEST; - -typedef struct _EXPERIMENTAL_WEBAUTHN_PLUGIN_OPERATION_RESPONSE - { - DWORD cbEncodedResponse; - /* [size_is] */ byte *pbEncodedResponse; - } EXPERIMENTAL_WEBAUTHN_PLUGIN_OPERATION_RESPONSE; - -typedef struct _EXPERIMENTAL_WEBAUTHN_PLUGIN_OPERATION_RESPONSE *EXPERIMENTAL_PWEBAUTHN_PLUGIN_OPERATION_RESPONSE; - -typedef const EXPERIMENTAL_WEBAUTHN_PLUGIN_OPERATION_RESPONSE *EXPERIMENTAL_PCWEBAUTHN_PLUGIN_OPERATION_RESPONSE; - -typedef struct _EXPERIMENTAL_WEBAUTHN_PLUGIN_CANCEL_OPERATION_REQUEST - { - GUID transactionId; - DWORD cbRequestSignature; - /* [size_is] */ byte *pbRequestSignature; - } EXPERIMENTAL_WEBAUTHN_PLUGIN_CANCEL_OPERATION_REQUEST; - -typedef struct _EXPERIMENTAL_WEBAUTHN_PLUGIN_CANCEL_OPERATION_REQUEST *EXPERIMENTAL_PWEBAUTHN_PLUGIN_CANCEL_OPERATION_REQUEST; - -typedef const EXPERIMENTAL_WEBAUTHN_PLUGIN_CANCEL_OPERATION_REQUEST *EXPERIMENTAL_PCWEBAUTHN_PLUGIN_CANCEL_OPERATION_REQUEST; - - - -extern RPC_IF_HANDLE __MIDL_itf_pluginauthenticator_0000_0000_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_pluginauthenticator_0000_0000_v0_0_s_ifspec; - -#ifndef __EXPERIMENTAL_IPluginAuthenticator_INTERFACE_DEFINED__ -#define __EXPERIMENTAL_IPluginAuthenticator_INTERFACE_DEFINED__ - -/* interface EXPERIMENTAL_IPluginAuthenticator */ -/* [unique][version][uuid][object] */ - - -EXTERN_C const IID IID_EXPERIMENTAL_IPluginAuthenticator; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("e6466e9a-b2f3-47c5-b88d-89bc14a8d998") - EXPERIMENTAL_IPluginAuthenticator : public IUnknown - { - public: - virtual HRESULT STDMETHODCALLTYPE EXPERIMENTAL_PluginMakeCredential( - /* [in] */ __RPC__in EXPERIMENTAL_PCWEBAUTHN_PLUGIN_OPERATION_REQUEST request, - /* [out] */ __RPC__deref_out_opt EXPERIMENTAL_PWEBAUTHN_PLUGIN_OPERATION_RESPONSE *response) = 0; - - virtual HRESULT STDMETHODCALLTYPE EXPERIMENTAL_PluginGetAssertion( - /* [in] */ __RPC__in EXPERIMENTAL_PCWEBAUTHN_PLUGIN_OPERATION_REQUEST request, - /* [out] */ __RPC__deref_out_opt EXPERIMENTAL_PWEBAUTHN_PLUGIN_OPERATION_RESPONSE *response) = 0; - - virtual HRESULT STDMETHODCALLTYPE EXPERIMENTAL_PluginCancelOperation( - /* [in] */ __RPC__in EXPERIMENTAL_PCWEBAUTHN_PLUGIN_CANCEL_OPERATION_REQUEST request) = 0; - - }; - - -#else /* C style interface */ - - typedef struct EXPERIMENTAL_IPluginAuthenticatorVtbl - { - BEGIN_INTERFACE - - DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - __RPC__in EXPERIMENTAL_IPluginAuthenticator * This, - /* [in] */ __RPC__in REFIID riid, - /* [annotation][iid_is][out] */ - _COM_Outptr_ void **ppvObject); - - DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( - __RPC__in EXPERIMENTAL_IPluginAuthenticator * This); - - DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( - __RPC__in EXPERIMENTAL_IPluginAuthenticator * This); - - DECLSPEC_XFGVIRT(EXPERIMENTAL_IPluginAuthenticator, EXPERIMENTAL_PluginMakeCredential) - HRESULT ( STDMETHODCALLTYPE *EXPERIMENTAL_PluginMakeCredential )( - __RPC__in EXPERIMENTAL_IPluginAuthenticator * This, - /* [in] */ __RPC__in EXPERIMENTAL_PCWEBAUTHN_PLUGIN_OPERATION_REQUEST request, - /* [out] */ __RPC__deref_out_opt EXPERIMENTAL_PWEBAUTHN_PLUGIN_OPERATION_RESPONSE *response); - - DECLSPEC_XFGVIRT(EXPERIMENTAL_IPluginAuthenticator, EXPERIMENTAL_PluginGetAssertion) - HRESULT ( STDMETHODCALLTYPE *EXPERIMENTAL_PluginGetAssertion )( - __RPC__in EXPERIMENTAL_IPluginAuthenticator * This, - /* [in] */ __RPC__in EXPERIMENTAL_PCWEBAUTHN_PLUGIN_OPERATION_REQUEST request, - /* [out] */ __RPC__deref_out_opt EXPERIMENTAL_PWEBAUTHN_PLUGIN_OPERATION_RESPONSE *response); - - DECLSPEC_XFGVIRT(EXPERIMENTAL_IPluginAuthenticator, EXPERIMENTAL_PluginCancelOperation) - HRESULT ( STDMETHODCALLTYPE *EXPERIMENTAL_PluginCancelOperation )( - __RPC__in EXPERIMENTAL_IPluginAuthenticator * This, - /* [in] */ __RPC__in EXPERIMENTAL_PCWEBAUTHN_PLUGIN_CANCEL_OPERATION_REQUEST request); - - END_INTERFACE - } EXPERIMENTAL_IPluginAuthenticatorVtbl; - - interface EXPERIMENTAL_IPluginAuthenticator - { - CONST_VTBL struct EXPERIMENTAL_IPluginAuthenticatorVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define EXPERIMENTAL_IPluginAuthenticator_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) - -#define EXPERIMENTAL_IPluginAuthenticator_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) - -#define EXPERIMENTAL_IPluginAuthenticator_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) - - -#define EXPERIMENTAL_IPluginAuthenticator_EXPERIMENTAL_PluginMakeCredential(This,request,response) \ - ( (This)->lpVtbl -> EXPERIMENTAL_PluginMakeCredential(This,request,response) ) - -#define EXPERIMENTAL_IPluginAuthenticator_EXPERIMENTAL_PluginGetAssertion(This,request,response) \ - ( (This)->lpVtbl -> EXPERIMENTAL_PluginGetAssertion(This,request,response) ) - -#define EXPERIMENTAL_IPluginAuthenticator_EXPERIMENTAL_PluginCancelOperation(This,request) \ - ( (This)->lpVtbl -> EXPERIMENTAL_PluginCancelOperation(This,request) ) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - - -#endif /* __EXPERIMENTAL_IPluginAuthenticator_INTERFACE_DEFINED__ */ - - -/* Additional Prototypes for ALL interfaces */ - -unsigned long __RPC_USER HWND_UserSize( __RPC__in unsigned long *, unsigned long , __RPC__in HWND * ); -unsigned char * __RPC_USER HWND_UserMarshal( __RPC__in unsigned long *, __RPC__inout_xcount(0) unsigned char *, __RPC__in HWND * ); -unsigned char * __RPC_USER HWND_UserUnmarshal(__RPC__in unsigned long *, __RPC__in_xcount(0) unsigned char *, __RPC__out HWND * ); -void __RPC_USER HWND_UserFree( __RPC__in unsigned long *, __RPC__in HWND * ); - -unsigned long __RPC_USER HWND_UserSize64( __RPC__in unsigned long *, unsigned long , __RPC__in HWND * ); -unsigned char * __RPC_USER HWND_UserMarshal64( __RPC__in unsigned long *, __RPC__inout_xcount(0) unsigned char *, __RPC__in HWND * ); -unsigned char * __RPC_USER HWND_UserUnmarshal64(__RPC__in unsigned long *, __RPC__in_xcount(0) unsigned char *, __RPC__out HWND * ); -void __RPC_USER HWND_UserFree64( __RPC__in unsigned long *, __RPC__in HWND * ); - -/* end of Additional Prototypes */ - -#ifdef __cplusplus -} -#endif - -#endif - - diff --git a/apps/desktop/desktop_native/windows_plugin_authenticator/include/pluginauthenticator.h b/apps/desktop/desktop_native/windows_plugin_authenticator/include/pluginauthenticator.h new file mode 100644 index 00000000000..edb3ffd4f00 --- /dev/null +++ b/apps/desktop/desktop_native/windows_plugin_authenticator/include/pluginauthenticator.h @@ -0,0 +1,263 @@ + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 8.01.0628 */ +/* @@MIDL_FILE_HEADING( ) */ + + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 501 +#endif + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCSAL_H_VERSION__ +#define __REQUIRED_RPCSAL_H_VERSION__ 100 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif /* __RPCNDR_H_VERSION__ */ + +#ifndef COM_NO_WINDOWS_H +#include "windows.h" +#include "ole2.h" +#endif /*COM_NO_WINDOWS_H*/ + +#ifndef __pluginauthenticator_h__ +#define __pluginauthenticator_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +#ifndef DECLSPEC_XFGVIRT +#if defined(_CONTROL_FLOW_GUARD_XFG) +#define DECLSPEC_XFGVIRT(base, func) __declspec(xfg_virtual(base, func)) +#else +#define DECLSPEC_XFGVIRT(base, func) +#endif +#endif + +/* Forward Declarations */ + +#ifndef __IPluginAuthenticator_FWD_DEFINED__ +#define __IPluginAuthenticator_FWD_DEFINED__ +typedef interface IPluginAuthenticator IPluginAuthenticator; + +#endif /* __IPluginAuthenticator_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "oaidl.h" + +#ifdef __cplusplus +extern "C"{ +#endif + + +/* interface __MIDL_itf_pluginauthenticator_0000_0000 */ +/* [local] */ + +typedef +enum _WEBAUTHN_PLUGIN_REQUEST_TYPE + { + WEBAUTHN_PLUGIN_REQUEST_TYPE_CTAP2_CBOR = 0x1 + } WEBAUTHN_PLUGIN_REQUEST_TYPE; + +typedef struct _WEBAUTHN_PLUGIN_OPERATION_REQUEST + { + HWND hWnd; + GUID transactionId; + DWORD cbRequestSignature; + /* [size_is] */ byte *pbRequestSignature; + WEBAUTHN_PLUGIN_REQUEST_TYPE requestType; + DWORD cbEncodedRequest; + /* [size_is] */ byte *pbEncodedRequest; + } WEBAUTHN_PLUGIN_OPERATION_REQUEST; + +typedef struct _WEBAUTHN_PLUGIN_OPERATION_REQUEST *PWEBAUTHN_PLUGIN_OPERATION_REQUEST; + +typedef const WEBAUTHN_PLUGIN_OPERATION_REQUEST *PCWEBAUTHN_PLUGIN_OPERATION_REQUEST; + +typedef struct _WEBAUTHN_PLUGIN_OPERATION_RESPONSE + { + DWORD cbEncodedResponse; + /* [size_is] */ byte *pbEncodedResponse; + } WEBAUTHN_PLUGIN_OPERATION_RESPONSE; + +typedef struct _WEBAUTHN_PLUGIN_OPERATION_RESPONSE *PWEBAUTHN_PLUGIN_OPERATION_RESPONSE; + +typedef const WEBAUTHN_PLUGIN_OPERATION_RESPONSE *PCWEBAUTHN_PLUGIN_OPERATION_RESPONSE; + +typedef struct _WEBAUTHN_PLUGIN_CANCEL_OPERATION_REQUEST + { + GUID transactionId; + DWORD cbRequestSignature; + /* [size_is] */ byte *pbRequestSignature; + } WEBAUTHN_PLUGIN_CANCEL_OPERATION_REQUEST; + +typedef struct _WEBAUTHN_PLUGIN_CANCEL_OPERATION_REQUEST *PWEBAUTHN_PLUGIN_CANCEL_OPERATION_REQUEST; + +typedef const WEBAUTHN_PLUGIN_CANCEL_OPERATION_REQUEST *PCWEBAUTHN_PLUGIN_CANCEL_OPERATION_REQUEST; + +typedef +enum _PLUGIN_LOCK_STATUS + { + PluginLocked = 0, + PluginUnlocked = ( PluginLocked + 1 ) + } PLUGIN_LOCK_STATUS; + + + +extern RPC_IF_HANDLE __MIDL_itf_pluginauthenticator_0000_0000_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_pluginauthenticator_0000_0000_v0_0_s_ifspec; + +#ifndef __IPluginAuthenticator_INTERFACE_DEFINED__ +#define __IPluginAuthenticator_INTERFACE_DEFINED__ + +/* interface IPluginAuthenticator */ +/* [ref][version][uuid][object] */ + + +EXTERN_C const IID IID_IPluginAuthenticator; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("d26bcf6f-b54c-43ff-9f06-d5bf148625f7") + IPluginAuthenticator : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE MakeCredential( + /* [in] */ __RPC__in PCWEBAUTHN_PLUGIN_OPERATION_REQUEST request, + /* [retval][out] */ __RPC__out PWEBAUTHN_PLUGIN_OPERATION_RESPONSE response) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAssertion( + /* [in] */ __RPC__in PCWEBAUTHN_PLUGIN_OPERATION_REQUEST request, + /* [retval][out] */ __RPC__out PWEBAUTHN_PLUGIN_OPERATION_RESPONSE response) = 0; + + virtual HRESULT STDMETHODCALLTYPE CancelOperation( + /* [in] */ __RPC__in PCWEBAUTHN_PLUGIN_CANCEL_OPERATION_REQUEST request) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetLockStatus( + /* [retval][out] */ __RPC__out PLUGIN_LOCK_STATUS *lockStatus) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IPluginAuthenticatorVtbl + { + BEGIN_INTERFACE + + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in IPluginAuthenticator * This, + /* [in] */ __RPC__in REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + DECLSPEC_XFGVIRT(IUnknown, AddRef) + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in IPluginAuthenticator * This); + + DECLSPEC_XFGVIRT(IUnknown, Release) + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in IPluginAuthenticator * This); + + DECLSPEC_XFGVIRT(IPluginAuthenticator, MakeCredential) + HRESULT ( STDMETHODCALLTYPE *MakeCredential )( + __RPC__in IPluginAuthenticator * This, + /* [in] */ __RPC__in PCWEBAUTHN_PLUGIN_OPERATION_REQUEST request, + /* [retval][out] */ __RPC__out PWEBAUTHN_PLUGIN_OPERATION_RESPONSE response); + + DECLSPEC_XFGVIRT(IPluginAuthenticator, GetAssertion) + HRESULT ( STDMETHODCALLTYPE *GetAssertion )( + __RPC__in IPluginAuthenticator * This, + /* [in] */ __RPC__in PCWEBAUTHN_PLUGIN_OPERATION_REQUEST request, + /* [retval][out] */ __RPC__out PWEBAUTHN_PLUGIN_OPERATION_RESPONSE response); + + DECLSPEC_XFGVIRT(IPluginAuthenticator, CancelOperation) + HRESULT ( STDMETHODCALLTYPE *CancelOperation )( + __RPC__in IPluginAuthenticator * This, + /* [in] */ __RPC__in PCWEBAUTHN_PLUGIN_CANCEL_OPERATION_REQUEST request); + + DECLSPEC_XFGVIRT(IPluginAuthenticator, GetLockStatus) + HRESULT ( STDMETHODCALLTYPE *GetLockStatus )( + __RPC__in IPluginAuthenticator * This, + /* [retval][out] */ __RPC__out PLUGIN_LOCK_STATUS *lockStatus); + + END_INTERFACE + } IPluginAuthenticatorVtbl; + + interface IPluginAuthenticator + { + CONST_VTBL struct IPluginAuthenticatorVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IPluginAuthenticator_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IPluginAuthenticator_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IPluginAuthenticator_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IPluginAuthenticator_MakeCredential(This,request,response) \ + ( (This)->lpVtbl -> MakeCredential(This,request,response) ) + +#define IPluginAuthenticator_GetAssertion(This,request,response) \ + ( (This)->lpVtbl -> GetAssertion(This,request,response) ) + +#define IPluginAuthenticator_CancelOperation(This,request) \ + ( (This)->lpVtbl -> CancelOperation(This,request) ) + +#define IPluginAuthenticator_GetLockStatus(This,lockStatus) \ + ( (This)->lpVtbl -> GetLockStatus(This,lockStatus) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IPluginAuthenticator_INTERFACE_DEFINED__ */ + + +/* Additional Prototypes for ALL interfaces */ + +unsigned long __RPC_USER HWND_UserSize( __RPC__in unsigned long *, unsigned long , __RPC__in HWND * ); +unsigned char * __RPC_USER HWND_UserMarshal( __RPC__in unsigned long *, __RPC__inout_xcount(0) unsigned char *, __RPC__in HWND * ); +unsigned char * __RPC_USER HWND_UserUnmarshal(__RPC__in unsigned long *, __RPC__in_xcount(0) unsigned char *, __RPC__out HWND * ); +void __RPC_USER HWND_UserFree( __RPC__in unsigned long *, __RPC__in HWND * ); + +unsigned long __RPC_USER HWND_UserSize64( __RPC__in unsigned long *, unsigned long , __RPC__in HWND * ); +unsigned char * __RPC_USER HWND_UserMarshal64( __RPC__in unsigned long *, __RPC__inout_xcount(0) unsigned char *, __RPC__in HWND * ); +unsigned char * __RPC_USER HWND_UserUnmarshal64(__RPC__in unsigned long *, __RPC__in_xcount(0) unsigned char *, __RPC__out HWND * ); +void __RPC_USER HWND_UserFree64( __RPC__in unsigned long *, __RPC__in HWND * ); + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/apps/desktop/desktop_native/windows_plugin_authenticator/include/experimental/webauthn.h b/apps/desktop/desktop_native/windows_plugin_authenticator/include/webauthn.h similarity index 72% rename from apps/desktop/desktop_native/windows_plugin_authenticator/include/experimental/webauthn.h rename to apps/desktop/desktop_native/windows_plugin_authenticator/include/webauthn.h index 2f50e771bed..b5eaca30f1c 100644 --- a/apps/desktop/desktop_native/windows_plugin_authenticator/include/experimental/webauthn.h +++ b/apps/desktop/desktop_native/windows_plugin_authenticator/include/webauthn.h @@ -1,1727 +1,1381 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#ifndef __WEBAUTHN_H_ -#define __WEBAUTHN_H_ - -#pragma once - -#include - -#pragma region Desktop Family or OneCore Family -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM) - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef WINAPI -#define WINAPI __stdcall -#endif - -#ifndef INITGUID -#define INITGUID -#include -#undef INITGUID -#else -#include -#endif - -//+------------------------------------------------------------------------------------------ -// API Version Information. -// Caller should check for WebAuthNGetApiVersionNumber to check the presence of relevant APIs -// and features for their usage. -//------------------------------------------------------------------------------------------- - -#define WEBAUTHN_API_VERSION_1 1 -// WEBAUTHN_API_VERSION_1 : Baseline Version -// Data Structures and their sub versions: -// - WEBAUTHN_RP_ENTITY_INFORMATION : 1 -// - WEBAUTHN_USER_ENTITY_INFORMATION : 1 -// - WEBAUTHN_CLIENT_DATA : 1 -// - WEBAUTHN_COSE_CREDENTIAL_PARAMETER : 1 -// - WEBAUTHN_COSE_CREDENTIAL_PARAMETERS : Not Applicable -// - WEBAUTHN_CREDENTIAL : 1 -// - WEBAUTHN_CREDENTIALS : Not Applicable -// - WEBAUTHN_CREDENTIAL_EX : 1 -// - WEBAUTHN_CREDENTIAL_LIST : Not Applicable -// - WEBAUTHN_EXTENSION : Not Applicable -// - WEBAUTHN_EXTENSIONS : Not Applicable -// - WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS : 3 -// - WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS : 4 -// - WEBAUTHN_COMMON_ATTESTATION : 1 -// - WEBAUTHN_CREDENTIAL_ATTESTATION : 3 -// - WEBAUTHN_ASSERTION : 1 -// Extensions: -// - WEBAUTHN_EXTENSIONS_IDENTIFIER_HMAC_SECRET -// APIs: -// - WebAuthNGetApiVersionNumber -// - WebAuthNIsUserVerifyingPlatformAuthenticatorAvailable -// - WebAuthNAuthenticatorMakeCredential -// - WebAuthNAuthenticatorGetAssertion -// - WebAuthNFreeCredentialAttestation -// - WebAuthNFreeAssertion -// - WebAuthNGetCancellationId -// - WebAuthNCancelCurrentOperation -// - WebAuthNGetErrorName -// - WebAuthNGetW3CExceptionDOMError -// Transports: -// - WEBAUTHN_CTAP_TRANSPORT_USB -// - WEBAUTHN_CTAP_TRANSPORT_NFC -// - WEBAUTHN_CTAP_TRANSPORT_BLE -// - WEBAUTHN_CTAP_TRANSPORT_INTERNAL - -#define WEBAUTHN_API_VERSION_2 2 -// WEBAUTHN_API_VERSION_2 : Delta From WEBAUTHN_API_VERSION_1 -// Added Extensions: -// - WEBAUTHN_EXTENSIONS_IDENTIFIER_CRED_PROTECT -// - -#define WEBAUTHN_API_VERSION_3 3 -// WEBAUTHN_API_VERSION_3 : Delta From WEBAUTHN_API_VERSION_2 -// Data Structures and their sub versions: -// - WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS : 4 -// - WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS : 5 -// - WEBAUTHN_CREDENTIAL_ATTESTATION : 4 -// - WEBAUTHN_ASSERTION : 2 -// Added Extensions: -// - WEBAUTHN_EXTENSIONS_IDENTIFIER_CRED_BLOB -// - WEBAUTHN_EXTENSIONS_IDENTIFIER_MIN_PIN_LENGTH -// - -#define WEBAUTHN_API_VERSION_4 4 -// WEBAUTHN_API_VERSION_4 : Delta From WEBAUTHN_API_VERSION_3 -// Data Structures and their sub versions: -// - WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS : 5 -// - WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS : 6 -// - WEBAUTHN_ASSERTION : 3 -// - WEBAUTHN_CREDENTIAL_DETAILS : 1 -// APIs: -// - WebAuthNGetPlatformCredentialList -// - WebAuthNFreePlatformCredentialList -// - WebAuthNDeletePlatformCredential -// - -#define WEBAUTHN_API_VERSION_5 5 -// WEBAUTHN_API_VERSION_5 : Delta From WEBAUTHN_API_VERSION_4 -// Data Structures and their sub versions: -// - WEBAUTHN_CREDENTIAL_DETAILS : 2 -// Extension Changes: -// - Enabled LARGE_BLOB Support -// - -#define WEBAUTHN_API_VERSION_6 6 -// WEBAUTHN_API_VERSION_6 : Delta From WEBAUTHN_API_VERSION_5 -// Data Structures and their sub versions: -// - WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS : 6 -// - WEBAUTHN_CREDENTIAL_ATTESTATION : 5 -// - WEBAUTHN_ASSERTION : 4 -// Transports: -// - WEBAUTHN_CTAP_TRANSPORT_HYBRID - -#define WEBAUTHN_API_VERSION_7 7 -// WEBAUTHN_API_VERSION_7 : Delta From WEBAUTHN_API_VERSION_6 -// Data Structures and their sub versions: -// - WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS : 7 -// - WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS : 7 -// - WEBAUTHN_CREDENTIAL_ATTESTATION : 6 -// - WEBAUTHN_ASSERTION : 5 - -#define WEBAUTHN_API_VERSION_8 8 -// WEBAUTHN_API_VERSION_8 : Delta From WEBAUTHN_API_VERSION_7 -// Data Structures and their sub versions: -// - WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS : 8 -// - WEBAUTHN_CREDENTIAL_DETAILS : 3 -// - WEBAUTHN_CREDENTIAL_ATTESTATION : 7 -// - WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS : 8 - -#define WEBAUTHN_API_CURRENT_VERSION WEBAUTHN_API_VERSION_8 - -//+------------------------------------------------------------------------------------------ -// Information about an RP Entity -//------------------------------------------------------------------------------------------- - -#define WEBAUTHN_RP_ENTITY_INFORMATION_CURRENT_VERSION 1 - -typedef struct _WEBAUTHN_RP_ENTITY_INFORMATION { - // Version of this structure, to allow for modifications in the future. - // This field is required and should be set to CURRENT_VERSION above. - DWORD dwVersion; - - // Identifier for the RP. This field is required. - PCWSTR pwszId; - - // Contains the friendly name of the Relying Party, such as "Acme Corporation", "Widgets Inc" or "Awesome Site". - // This field is required. - PCWSTR pwszName; - - // Optional URL pointing to RP's logo. - PCWSTR pwszIcon; -} WEBAUTHN_RP_ENTITY_INFORMATION, *PWEBAUTHN_RP_ENTITY_INFORMATION; -typedef const WEBAUTHN_RP_ENTITY_INFORMATION *PCWEBAUTHN_RP_ENTITY_INFORMATION; - -//+------------------------------------------------------------------------------------------ -// Information about an User Entity -//------------------------------------------------------------------------------------------- -#define WEBAUTHN_MAX_USER_ID_LENGTH 64 - -#define WEBAUTHN_USER_ENTITY_INFORMATION_CURRENT_VERSION 1 - -typedef struct _WEBAUTHN_USER_ENTITY_INFORMATION { - // Version of this structure, to allow for modifications in the future. - // This field is required and should be set to CURRENT_VERSION above. - DWORD dwVersion; - - // Identifier for the User. This field is required. - DWORD cbId; - _Field_size_bytes_(cbId) - PBYTE pbId; - - // Contains a detailed name for this account, such as "john.p.smith@example.com". - PCWSTR pwszName; - - // Optional URL that can be used to retrieve an image containing the user's current avatar, - // or a data URI that contains the image data. - PCWSTR pwszIcon; - - // For User: Contains the friendly name associated with the user account by the Relying Party, such as "John P. Smith". - PCWSTR pwszDisplayName; -} WEBAUTHN_USER_ENTITY_INFORMATION, *PWEBAUTHN_USER_ENTITY_INFORMATION; -typedef const WEBAUTHN_USER_ENTITY_INFORMATION *PCWEBAUTHN_USER_ENTITY_INFORMATION; - -//+------------------------------------------------------------------------------------------ -// Information about client data. -//------------------------------------------------------------------------------------------- - -#define WEBAUTHN_HASH_ALGORITHM_SHA_256 L"SHA-256" -#define WEBAUTHN_HASH_ALGORITHM_SHA_384 L"SHA-384" -#define WEBAUTHN_HASH_ALGORITHM_SHA_512 L"SHA-512" - -#define WEBAUTHN_CLIENT_DATA_CURRENT_VERSION 1 - -typedef struct _WEBAUTHN_CLIENT_DATA { - // Version of this structure, to allow for modifications in the future. - // This field is required and should be set to CURRENT_VERSION above. - DWORD dwVersion; - - // Size of the pbClientDataJSON field. - DWORD cbClientDataJSON; - // UTF-8 encoded JSON serialization of the client data. - _Field_size_bytes_(cbClientDataJSON) - PBYTE pbClientDataJSON; - - // Hash algorithm ID used to hash the pbClientDataJSON field. - LPCWSTR pwszHashAlgId; -} WEBAUTHN_CLIENT_DATA, *PWEBAUTHN_CLIENT_DATA; -typedef const WEBAUTHN_CLIENT_DATA *PCWEBAUTHN_CLIENT_DATA; - -//+------------------------------------------------------------------------------------------ -// Information about credential parameters. -//------------------------------------------------------------------------------------------- - -#define WEBAUTHN_CREDENTIAL_TYPE_PUBLIC_KEY L"public-key" - -#define WEBAUTHN_COSE_ALGORITHM_ECDSA_P256_WITH_SHA256 -7 -#define WEBAUTHN_COSE_ALGORITHM_ECDSA_P384_WITH_SHA384 -35 -#define WEBAUTHN_COSE_ALGORITHM_ECDSA_P521_WITH_SHA512 -36 - -#define WEBAUTHN_COSE_ALGORITHM_RSASSA_PKCS1_V1_5_WITH_SHA256 -257 -#define WEBAUTHN_COSE_ALGORITHM_RSASSA_PKCS1_V1_5_WITH_SHA384 -258 -#define WEBAUTHN_COSE_ALGORITHM_RSASSA_PKCS1_V1_5_WITH_SHA512 -259 - -#define WEBAUTHN_COSE_ALGORITHM_RSA_PSS_WITH_SHA256 -37 -#define WEBAUTHN_COSE_ALGORITHM_RSA_PSS_WITH_SHA384 -38 -#define WEBAUTHN_COSE_ALGORITHM_RSA_PSS_WITH_SHA512 -39 - -#define WEBAUTHN_COSE_CREDENTIAL_PARAMETER_CURRENT_VERSION 1 - -typedef struct _WEBAUTHN_COSE_CREDENTIAL_PARAMETER { - // Version of this structure, to allow for modifications in the future. - DWORD dwVersion; - - // Well-known credential type specifying a credential to create. - LPCWSTR pwszCredentialType; - - // Well-known COSE algorithm specifying the algorithm to use for the credential. - LONG lAlg; -} WEBAUTHN_COSE_CREDENTIAL_PARAMETER, *PWEBAUTHN_COSE_CREDENTIAL_PARAMETER; -typedef const WEBAUTHN_COSE_CREDENTIAL_PARAMETER *PCWEBAUTHN_COSE_CREDENTIAL_PARAMETER; - -typedef struct _WEBAUTHN_COSE_CREDENTIAL_PARAMETERS { - DWORD cCredentialParameters; - _Field_size_(cCredentialParameters) - PWEBAUTHN_COSE_CREDENTIAL_PARAMETER pCredentialParameters; -} WEBAUTHN_COSE_CREDENTIAL_PARAMETERS, *PWEBAUTHN_COSE_CREDENTIAL_PARAMETERS; -typedef const WEBAUTHN_COSE_CREDENTIAL_PARAMETERS *PCWEBAUTHN_COSE_CREDENTIAL_PARAMETERS; - -//+------------------------------------------------------------------------------------------ -// Information about credential. -//------------------------------------------------------------------------------------------- -#define WEBAUTHN_CREDENTIAL_CURRENT_VERSION 1 - -typedef struct _WEBAUTHN_CREDENTIAL { - // Version of this structure, to allow for modifications in the future. - DWORD dwVersion; - - // Size of pbID. - DWORD cbId; - // Unique ID for this particular credential. - _Field_size_bytes_(cbId) - PBYTE pbId; - - // Well-known credential type specifying what this particular credential is. - LPCWSTR pwszCredentialType; -} WEBAUTHN_CREDENTIAL, *PWEBAUTHN_CREDENTIAL; -typedef const WEBAUTHN_CREDENTIAL *PCWEBAUTHN_CREDENTIAL; - -typedef struct _WEBAUTHN_CREDENTIALS { - DWORD cCredentials; - _Field_size_(cCredentials) - PWEBAUTHN_CREDENTIAL pCredentials; -} WEBAUTHN_CREDENTIALS, *PWEBAUTHN_CREDENTIALS; -typedef const WEBAUTHN_CREDENTIALS *PCWEBAUTHN_CREDENTIALS; - -//+------------------------------------------------------------------------------------------ -// Information about credential with extra information, such as, dwTransports -//------------------------------------------------------------------------------------------- - -#define WEBAUTHN_CTAP_TRANSPORT_USB 0x00000001 -#define WEBAUTHN_CTAP_TRANSPORT_NFC 0x00000002 -#define WEBAUTHN_CTAP_TRANSPORT_BLE 0x00000004 -#define WEBAUTHN_CTAP_TRANSPORT_TEST 0x00000008 -#define WEBAUTHN_CTAP_TRANSPORT_INTERNAL 0x00000010 -#define WEBAUTHN_CTAP_TRANSPORT_HYBRID 0x00000020 -#define WEBAUTHN_CTAP_TRANSPORT_FLAGS_MASK 0x0000003F - -#define WEBAUTHN_CREDENTIAL_EX_CURRENT_VERSION 1 - -typedef struct _WEBAUTHN_CREDENTIAL_EX { - // Version of this structure, to allow for modifications in the future. - DWORD dwVersion; - - // Size of pbID. - DWORD cbId; - // Unique ID for this particular credential. - _Field_size_bytes_(cbId) - PBYTE pbId; - - // Well-known credential type specifying what this particular credential is. - LPCWSTR pwszCredentialType; - - // Transports. 0 implies no transport restrictions. - DWORD dwTransports; -} WEBAUTHN_CREDENTIAL_EX, *PWEBAUTHN_CREDENTIAL_EX; -typedef const WEBAUTHN_CREDENTIAL_EX *PCWEBAUTHN_CREDENTIAL_EX; - -//+------------------------------------------------------------------------------------------ -// Information about credential list with extra information -//------------------------------------------------------------------------------------------- - -typedef struct _WEBAUTHN_CREDENTIAL_LIST { - DWORD cCredentials; - _Field_size_(cCredentials) - PWEBAUTHN_CREDENTIAL_EX *ppCredentials; -} WEBAUTHN_CREDENTIAL_LIST, *PWEBAUTHN_CREDENTIAL_LIST; -typedef const WEBAUTHN_CREDENTIAL_LIST *PCWEBAUTHN_CREDENTIAL_LIST; - -//+------------------------------------------------------------------------------------------ -// Information about linked devices -//------------------------------------------------------------------------------------------- - -#define CTAPCBOR_HYBRID_STORAGE_LINKED_DATA_VERSION_1 1 -#define CTAPCBOR_HYBRID_STORAGE_LINKED_DATA_CURRENT_VERSION CTAPCBOR_HYBRID_STORAGE_LINKED_DATA_VERSION_1 - -typedef struct _CTAPCBOR_HYBRID_STORAGE_LINKED_DATA -{ - // Version - DWORD dwVersion; - - // Contact Id - DWORD cbContactId; - _Field_size_bytes_(cbContactId) - PBYTE pbContactId; - - // Link Id - DWORD cbLinkId; - _Field_size_bytes_(cbLinkId) - PBYTE pbLinkId; - - // Link secret - DWORD cbLinkSecret; - _Field_size_bytes_(cbLinkSecret) - PBYTE pbLinkSecret; - - // Authenticator Public Key - DWORD cbPublicKey; - _Field_size_bytes_(cbPublicKey) - PBYTE pbPublicKey; - - // Authenticator Name - PCWSTR pwszAuthenticatorName; - - // Tunnel server domain - WORD wEncodedTunnelServerDomain; -} CTAPCBOR_HYBRID_STORAGE_LINKED_DATA, *PCTAPCBOR_HYBRID_STORAGE_LINKED_DATA; -typedef const CTAPCBOR_HYBRID_STORAGE_LINKED_DATA *PCCTAPCBOR_HYBRID_STORAGE_LINKED_DATA; - -//+------------------------------------------------------------------------------------------ -// Credential Information for WebAuthNGetPlatformCredentialList API -//------------------------------------------------------------------------------------------- - -#define WEBAUTHN_CREDENTIAL_DETAILS_VERSION_1 1 -#define WEBAUTHN_CREDENTIAL_DETAILS_VERSION_2 2 -#define WEBAUTHN_CREDENTIAL_DETAILS_VERSION_3 3 -#define WEBAUTHN_CREDENTIAL_DETAILS_CURRENT_VERSION WEBAUTHN_CREDENTIAL_DETAILS_VERSION_3 - -typedef struct _WEBAUTHN_CREDENTIAL_DETAILS { - // Version of this structure, to allow for modifications in the future. - DWORD dwVersion; - - // Size of pbCredentialID. - DWORD cbCredentialID; - _Field_size_bytes_(cbCredentialID) - PBYTE pbCredentialID; - - // RP Info - PWEBAUTHN_RP_ENTITY_INFORMATION pRpInformation; - - // User Info - PWEBAUTHN_USER_ENTITY_INFORMATION pUserInformation; - - // Removable or not. - BOOL bRemovable; - - // - // The following fields have been added in WEBAUTHN_CREDENTIAL_DETAILS_VERSION_2 - // - - // Backed Up or not. - BOOL bBackedUp; - - // - // The following fields have been added in WEBAUTHN_CREDENTIAL_DETAILS_VERSION_3 - // - PCWSTR pwszAuthenticatorName; - - // The logo is expected to be in the svg format - DWORD cbAuthenticatorLogo; - _Field_size_bytes_(cbAuthenticatorLogo) - PBYTE pbAuthenticatorLogo; - - // ThirdPartyPayment Credential or not. - BOOL bThirdPartyPayment; - -} WEBAUTHN_CREDENTIAL_DETAILS, *PWEBAUTHN_CREDENTIAL_DETAILS; -typedef const WEBAUTHN_CREDENTIAL_DETAILS *PCWEBAUTHN_CREDENTIAL_DETAILS; - -typedef struct _WEBAUTHN_CREDENTIAL_DETAILS_LIST { - DWORD cCredentialDetails; - _Field_size_(cCredentialDetails) - PWEBAUTHN_CREDENTIAL_DETAILS *ppCredentialDetails; -} WEBAUTHN_CREDENTIAL_DETAILS_LIST, *PWEBAUTHN_CREDENTIAL_DETAILS_LIST; -typedef const WEBAUTHN_CREDENTIAL_DETAILS_LIST *PCWEBAUTHN_CREDENTIAL_DETAILS_LIST; - -#define WEBAUTHN_GET_CREDENTIALS_OPTIONS_VERSION_1 1 -#define WEBAUTHN_GET_CREDENTIALS_OPTIONS_CURRENT_VERSION WEBAUTHN_GET_CREDENTIALS_OPTIONS_VERSION_1 - -typedef struct _WEBAUTHN_GET_CREDENTIALS_OPTIONS { - // Version of this structure, to allow for modifications in the future. - DWORD dwVersion; - - // Optional. - LPCWSTR pwszRpId; - - // Optional. BrowserInPrivate Mode. Defaulting to FALSE. - BOOL bBrowserInPrivateMode; -} WEBAUTHN_GET_CREDENTIALS_OPTIONS, *PWEBAUTHN_GET_CREDENTIALS_OPTIONS; -typedef const WEBAUTHN_GET_CREDENTIALS_OPTIONS *PCWEBAUTHN_GET_CREDENTIALS_OPTIONS; - -//+------------------------------------------------------------------------------------------ -// PRF values. -//------------------------------------------------------------------------------------------- - -#define WEBAUTHN_CTAP_ONE_HMAC_SECRET_LENGTH 32 - -// SALT values below by default are converted into RAW Hmac-Secret values as per PRF extension. -// - SHA-256(UTF8Encode("WebAuthn PRF") || 0x00 || Value) -// -// Set WEBAUTHN_AUTHENTICATOR_HMAC_SECRET_VALUES_FLAG in dwFlags in WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS, -// if caller wants to provide RAW Hmac-Secret SALT values directly. In that case, -// values if provided MUST be of WEBAUTHN_CTAP_ONE_HMAC_SECRET_LENGTH size. - -typedef struct _WEBAUTHN_HMAC_SECRET_SALT { - // Size of pbFirst. - DWORD cbFirst; - _Field_size_bytes_(cbFirst) - PBYTE pbFirst; // Required - - // Size of pbSecond. - DWORD cbSecond; - _Field_size_bytes_(cbSecond) - PBYTE pbSecond; -} WEBAUTHN_HMAC_SECRET_SALT, *PWEBAUTHN_HMAC_SECRET_SALT; -typedef const WEBAUTHN_HMAC_SECRET_SALT *PCWEBAUTHN_HMAC_SECRET_SALT; - -typedef struct _WEBAUTHN_CRED_WITH_HMAC_SECRET_SALT { - // Size of pbCredID. - DWORD cbCredID; - _Field_size_bytes_(cbCredID) - PBYTE pbCredID; // Required - - // PRF Values for above credential - PWEBAUTHN_HMAC_SECRET_SALT pHmacSecretSalt; // Required -} WEBAUTHN_CRED_WITH_HMAC_SECRET_SALT, *PWEBAUTHN_CRED_WITH_HMAC_SECRET_SALT; -typedef const WEBAUTHN_CRED_WITH_HMAC_SECRET_SALT *PCWEBAUTHN_CRED_WITH_HMAC_SECRET_SALT; - -typedef struct _WEBAUTHN_HMAC_SECRET_SALT_VALUES { - PWEBAUTHN_HMAC_SECRET_SALT pGlobalHmacSalt; - - DWORD cCredWithHmacSecretSaltList; - _Field_size_(cCredWithHmacSecretSaltList) - PWEBAUTHN_CRED_WITH_HMAC_SECRET_SALT pCredWithHmacSecretSaltList; -} WEBAUTHN_HMAC_SECRET_SALT_VALUES, *PWEBAUTHN_HMAC_SECRET_SALT_VALUES; -typedef const WEBAUTHN_HMAC_SECRET_SALT_VALUES *PCWEBAUTHN_HMAC_SECRET_SALT_VALUES; - -//+------------------------------------------------------------------------------------------ -// Hmac-Secret extension -//------------------------------------------------------------------------------------------- - -#define WEBAUTHN_EXTENSIONS_IDENTIFIER_HMAC_SECRET L"hmac-secret" -// Below type definitions is for WEBAUTHN_EXTENSIONS_IDENTIFIER_HMAC_SECRET -// MakeCredential Input Type: BOOL. -// - pvExtension must point to a BOOL with the value TRUE. -// - cbExtension must contain the sizeof(BOOL). -// MakeCredential Output Type: BOOL. -// - pvExtension will point to a BOOL with the value TRUE if credential -// was successfully created with HMAC_SECRET. -// - cbExtension will contain the sizeof(BOOL). -// GetAssertion Input Type: Not Supported -// GetAssertion Output Type: Not Supported - -//+------------------------------------------------------------------------------------------ -// credProtect extension -//------------------------------------------------------------------------------------------- - -#define WEBAUTHN_USER_VERIFICATION_ANY 0 -#define WEBAUTHN_USER_VERIFICATION_OPTIONAL 1 -#define WEBAUTHN_USER_VERIFICATION_OPTIONAL_WITH_CREDENTIAL_ID_LIST 2 -#define WEBAUTHN_USER_VERIFICATION_REQUIRED 3 - -typedef struct _WEBAUTHN_CRED_PROTECT_EXTENSION_IN { - // One of the above WEBAUTHN_USER_VERIFICATION_* values - DWORD dwCredProtect; - // Set the following to TRUE to require authenticator support for the credProtect extension - BOOL bRequireCredProtect; -} WEBAUTHN_CRED_PROTECT_EXTENSION_IN, *PWEBAUTHN_CRED_PROTECT_EXTENSION_IN; -typedef const WEBAUTHN_CRED_PROTECT_EXTENSION_IN *PCWEBAUTHN_CRED_PROTECT_EXTENSION_IN; - - -#define WEBAUTHN_EXTENSIONS_IDENTIFIER_CRED_PROTECT L"credProtect" -// Below type definitions is for WEBAUTHN_EXTENSIONS_IDENTIFIER_CRED_PROTECT -// MakeCredential Input Type: WEBAUTHN_CRED_PROTECT_EXTENSION_IN. -// - pvExtension must point to a WEBAUTHN_CRED_PROTECT_EXTENSION_IN struct -// - cbExtension will contain the sizeof(WEBAUTHN_CRED_PROTECT_EXTENSION_IN). -// MakeCredential Output Type: DWORD. -// - pvExtension will point to a DWORD with one of the above WEBAUTHN_USER_VERIFICATION_* values -// if credential was successfully created with CRED_PROTECT. -// - cbExtension will contain the sizeof(DWORD). -// GetAssertion Input Type: Not Supported -// GetAssertion Output Type: Not Supported - -//+------------------------------------------------------------------------------------------ -// credBlob extension -//------------------------------------------------------------------------------------------- - -typedef struct _WEBAUTHN_CRED_BLOB_EXTENSION { - // Size of pbCredBlob. - DWORD cbCredBlob; - _Field_size_bytes_(cbCredBlob) - PBYTE pbCredBlob; -} WEBAUTHN_CRED_BLOB_EXTENSION, *PWEBAUTHN_CRED_BLOB_EXTENSION; -typedef const WEBAUTHN_CRED_BLOB_EXTENSION *PCWEBAUTHN_CRED_BLOB_EXTENSION; - - -#define WEBAUTHN_EXTENSIONS_IDENTIFIER_CRED_BLOB L"credBlob" -// Below type definitions is for WEBAUTHN_EXTENSIONS_IDENTIFIER_CRED_BLOB -// MakeCredential Input Type: WEBAUTHN_CRED_BLOB_EXTENSION. -// - pvExtension must point to a WEBAUTHN_CRED_BLOB_EXTENSION struct -// - cbExtension must contain the sizeof(WEBAUTHN_CRED_BLOB_EXTENSION). -// MakeCredential Output Type: BOOL. -// - pvExtension will point to a BOOL with the value TRUE if credBlob was successfully created -// - cbExtension will contain the sizeof(BOOL). -// GetAssertion Input Type: BOOL. -// - pvExtension must point to a BOOL with the value TRUE to request the credBlob. -// - cbExtension must contain the sizeof(BOOL). -// GetAssertion Output Type: WEBAUTHN_CRED_BLOB_EXTENSION. -// - pvExtension will point to a WEBAUTHN_CRED_BLOB_EXTENSION struct if the authenticator -// returns the credBlob in the signed extensions -// - cbExtension will contain the sizeof(WEBAUTHN_CRED_BLOB_EXTENSION). - -//+------------------------------------------------------------------------------------------ -// minPinLength extension -//------------------------------------------------------------------------------------------- - -#define WEBAUTHN_EXTENSIONS_IDENTIFIER_MIN_PIN_LENGTH L"minPinLength" -// Below type definitions is for WEBAUTHN_EXTENSIONS_IDENTIFIER_MIN_PIN_LENGTH -// MakeCredential Input Type: BOOL. -// - pvExtension must point to a BOOL with the value TRUE to request the minPinLength. -// - cbExtension must contain the sizeof(BOOL). -// MakeCredential Output Type: DWORD. -// - pvExtension will point to a DWORD with the minimum pin length if returned by the authenticator -// - cbExtension will contain the sizeof(DWORD). -// GetAssertion Input Type: Not Supported -// GetAssertion Output Type: Not Supported - -//+------------------------------------------------------------------------------------------ -// Information about Extensions. -//------------------------------------------------------------------------------------------- -typedef struct _WEBAUTHN_EXTENSION { - LPCWSTR pwszExtensionIdentifier; - DWORD cbExtension; - PVOID pvExtension; -} WEBAUTHN_EXTENSION, *PWEBAUTHN_EXTENSION; -typedef const WEBAUTHN_EXTENSION *PCWEBAUTHN_EXTENSION; - -typedef struct _WEBAUTHN_EXTENSIONS { - DWORD cExtensions; - _Field_size_(cExtensions) - PWEBAUTHN_EXTENSION pExtensions; -} WEBAUTHN_EXTENSIONS, *PWEBAUTHN_EXTENSIONS; -typedef const WEBAUTHN_EXTENSIONS *PCWEBAUTHN_EXTENSIONS; - -//+------------------------------------------------------------------------------------------ -// Options. -//------------------------------------------------------------------------------------------- - -#define WEBAUTHN_AUTHENTICATOR_ATTACHMENT_ANY 0 -#define WEBAUTHN_AUTHENTICATOR_ATTACHMENT_PLATFORM 1 -#define WEBAUTHN_AUTHENTICATOR_ATTACHMENT_CROSS_PLATFORM 2 -#define WEBAUTHN_AUTHENTICATOR_ATTACHMENT_CROSS_PLATFORM_U2F_V2 3 - -#define WEBAUTHN_USER_VERIFICATION_REQUIREMENT_ANY 0 -#define WEBAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED 1 -#define WEBAUTHN_USER_VERIFICATION_REQUIREMENT_PREFERRED 2 -#define WEBAUTHN_USER_VERIFICATION_REQUIREMENT_DISCOURAGED 3 - -#define WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_ANY 0 -#define WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_NONE 1 -#define WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_INDIRECT 2 -#define WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT 3 - -#define WEBAUTHN_ENTERPRISE_ATTESTATION_NONE 0 -#define WEBAUTHN_ENTERPRISE_ATTESTATION_VENDOR_FACILITATED 1 -#define WEBAUTHN_ENTERPRISE_ATTESTATION_PLATFORM_MANAGED 2 - -#define WEBAUTHN_LARGE_BLOB_SUPPORT_NONE 0 -#define WEBAUTHN_LARGE_BLOB_SUPPORT_REQUIRED 1 -#define WEBAUTHN_LARGE_BLOB_SUPPORT_PREFERRED 2 - -#define WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_1 1 -#define WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_2 2 -#define WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_3 3 -#define WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_4 4 -#define WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_5 5 -#define WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_6 6 -#define WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_7 7 -#define WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_8 8 -#define WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_CURRENT_VERSION WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_8 - -typedef struct _WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS { - // Version of this structure, to allow for modifications in the future. - DWORD dwVersion; - - // Time that the operation is expected to complete within. - // This is used as guidance, and can be overridden by the platform. - DWORD dwTimeoutMilliseconds; - - // Credentials used for exclusion. - WEBAUTHN_CREDENTIALS CredentialList; - - // Optional extensions to parse when performing the operation. - WEBAUTHN_EXTENSIONS Extensions; - - // Optional. Platform vs Cross-Platform Authenticators. - DWORD dwAuthenticatorAttachment; - - // Optional. Require key to be resident or not. Defaulting to FALSE. - BOOL bRequireResidentKey; - - // User Verification Requirement. - DWORD dwUserVerificationRequirement; - - // Attestation Conveyance Preference. - DWORD dwAttestationConveyancePreference; - - // Reserved for future Use - DWORD dwFlags; - - // - // The following fields have been added in WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_2 - // - - // Cancellation Id - Optional - See WebAuthNGetCancellationId - GUID *pCancellationId; - - // - // The following fields have been added in WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_3 - // - - // Exclude Credential List. If present, "CredentialList" will be ignored. - PWEBAUTHN_CREDENTIAL_LIST pExcludeCredentialList; - - // - // The following fields have been added in WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_4 - // - - // Enterprise Attestation - DWORD dwEnterpriseAttestation; - - // Large Blob Support: none, required or preferred - // - // NTE_INVALID_PARAMETER when large blob required or preferred and - // bRequireResidentKey isn't set to TRUE - DWORD dwLargeBlobSupport; - - // Optional. Prefer key to be resident. Defaulting to FALSE. When TRUE, - // overrides the above bRequireResidentKey. - BOOL bPreferResidentKey; - - // - // The following fields have been added in WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_5 - // - - // Optional. BrowserInPrivate Mode. Defaulting to FALSE. - BOOL bBrowserInPrivateMode; - - // - // The following fields have been added in WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_6 - // - - // Enable PRF - BOOL bEnablePrf; - - // - // The following fields have been added in WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_7 - // - - // Optional. Linked Device Connection Info. - PCTAPCBOR_HYBRID_STORAGE_LINKED_DATA pLinkedDevice; - - // Size of pbJsonExt - DWORD cbJsonExt; - _Field_size_bytes_(cbJsonExt) - PBYTE pbJsonExt; - - // - // The following fields have been added in WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_8 - // - - // PRF extension "eval" values which will be converted into HMAC-SECRET values according to WebAuthn Spec. - // Set WEBAUTHN_AUTHENTICATOR_HMAC_SECRET_VALUES_FLAG in dwFlags above, if caller wants to provide RAW Hmac-Secret SALT values directly. - // In that case, values provided MUST be of WEBAUTHN_CTAP_ONE_HMAC_SECRET_LENGTH size. - PWEBAUTHN_HMAC_SECRET_SALT pPRFGlobalEval; - - // PublicKeyCredentialHints (https://w3c.github.io/webauthn/#enum-hints) - DWORD cCredentialHints; - _Field_size_(cCredentialHints) - LPCWSTR *ppwszCredentialHints; - - // Enable ThirdPartyPayment - BOOL bThirdPartyPayment; - -} WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS, *PWEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS; -typedef const WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS *PCWEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS; - -#define WEBAUTHN_CRED_LARGE_BLOB_OPERATION_NONE 0 -#define WEBAUTHN_CRED_LARGE_BLOB_OPERATION_GET 1 -#define WEBAUTHN_CRED_LARGE_BLOB_OPERATION_SET 2 -#define WEBAUTHN_CRED_LARGE_BLOB_OPERATION_DELETE 3 - -#define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_1 1 -#define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_2 2 -#define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_3 3 -#define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_4 4 -#define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_5 5 -#define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_6 6 -#define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_7 7 -#define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_8 8 -#define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_CURRENT_VERSION WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_8 - -/* - Information about flags. -*/ - -#define WEBAUTHN_AUTHENTICATOR_HMAC_SECRET_VALUES_FLAG 0x00100000 - -typedef struct _WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS { - // Version of this structure, to allow for modifications in the future. - DWORD dwVersion; - - // Time that the operation is expected to complete within. - // This is used as guidance, and can be overridden by the platform. - DWORD dwTimeoutMilliseconds; - - // Allowed Credentials List. - WEBAUTHN_CREDENTIALS CredentialList; - - // Optional extensions to parse when performing the operation. - WEBAUTHN_EXTENSIONS Extensions; - - // Optional. Platform vs Cross-Platform Authenticators. - DWORD dwAuthenticatorAttachment; - - // User Verification Requirement. - DWORD dwUserVerificationRequirement; - - // Flags - DWORD dwFlags; - - // - // The following fields have been added in WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_2 - // - - // Optional identifier for the U2F AppId. Converted to UTF8 before being hashed. Not lower cased. - PCWSTR pwszU2fAppId; - - // If the following is non-NULL, then, set to TRUE if the above pwszU2fAppid was used instead of - // PCWSTR pwszRpId; - BOOL *pbU2fAppId; - - // - // The following fields have been added in WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_3 - // - - // Cancellation Id - Optional - See WebAuthNGetCancellationId - GUID *pCancellationId; - - // - // The following fields have been added in WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_4 - // - - // Allow Credential List. If present, "CredentialList" will be ignored. - PWEBAUTHN_CREDENTIAL_LIST pAllowCredentialList; - - // - // The following fields have been added in WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_5 - // - - DWORD dwCredLargeBlobOperation; - - // Size of pbCredLargeBlob - DWORD cbCredLargeBlob; - _Field_size_bytes_(cbCredLargeBlob) - PBYTE pbCredLargeBlob; - - // - // The following fields have been added in WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_6 - // - - // PRF values which will be converted into HMAC-SECRET values according to WebAuthn Spec. - PWEBAUTHN_HMAC_SECRET_SALT_VALUES pHmacSecretSaltValues; - - // Optional. BrowserInPrivate Mode. Defaulting to FALSE. - BOOL bBrowserInPrivateMode; - - // - // The following fields have been added in WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_7 - // - - // Optional. Linked Device Connection Info. - PCTAPCBOR_HYBRID_STORAGE_LINKED_DATA pLinkedDevice; - - // Optional. Allowlist MUST contain 1 credential applicable for Hybrid transport. - BOOL bAutoFill; - - // Size of pbJsonExt - DWORD cbJsonExt; - _Field_size_bytes_(cbJsonExt) - PBYTE pbJsonExt; - - // - // The following fields have been added in WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_8 - // - - // PublicKeyCredentialHints (https://w3c.github.io/webauthn/#enum-hints) - DWORD cCredentialHints; - _Field_size_(cCredentialHints) - LPCWSTR *ppwszCredentialHints; - -} WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS, *PWEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS; -typedef const WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS *PCWEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS; - - -//+------------------------------------------------------------------------------------------ -// Attestation Info. -// -//------------------------------------------------------------------------------------------- -#define WEBAUTHN_ATTESTATION_DECODE_NONE 0 -#define WEBAUTHN_ATTESTATION_DECODE_COMMON 1 -// WEBAUTHN_ATTESTATION_DECODE_COMMON supports format types -// L"packed" -// L"fido-u2f" - -#define WEBAUTHN_ATTESTATION_VER_TPM_2_0 L"2.0" - -typedef struct _WEBAUTHN_X5C { - // Length of X.509 encoded certificate - DWORD cbData; - // X.509 encoded certificate bytes - _Field_size_bytes_(cbData) - PBYTE pbData; -} WEBAUTHN_X5C, *PWEBAUTHN_X5C; - -// Supports either Self or Full Basic Attestation - -// Note, new fields will be added to the following data structure to -// support additional attestation format types, such as, TPM. -// When fields are added, the dwVersion will be incremented. -// -// Therefore, your code must make the following check: -// "if (dwVersion >= WEBAUTHN_COMMON_ATTESTATION_CURRENT_VERSION)" - -#define WEBAUTHN_COMMON_ATTESTATION_CURRENT_VERSION 1 - -typedef struct _WEBAUTHN_COMMON_ATTESTATION { - // Version of this structure, to allow for modifications in the future. - DWORD dwVersion; - - // Hash and Padding Algorithm - // - // The following won't be set for "fido-u2f" which assumes "ES256". - PCWSTR pwszAlg; - LONG lAlg; // COSE algorithm - - // Signature that was generated for this attestation. - DWORD cbSignature; - _Field_size_bytes_(cbSignature) - PBYTE pbSignature; - - // Following is set for Full Basic Attestation. If not, set then, this is Self Attestation. - // Array of X.509 DER encoded certificates. The first certificate is the signer, leaf certificate. - DWORD cX5c; - _Field_size_(cX5c) - PWEBAUTHN_X5C pX5c; - - // Following are also set for tpm - PCWSTR pwszVer; // L"2.0" - DWORD cbCertInfo; - _Field_size_bytes_(cbCertInfo) - PBYTE pbCertInfo; - DWORD cbPubArea; - _Field_size_bytes_(cbPubArea) - PBYTE pbPubArea; -} WEBAUTHN_COMMON_ATTESTATION, *PWEBAUTHN_COMMON_ATTESTATION; -typedef const WEBAUTHN_COMMON_ATTESTATION *PCWEBAUTHN_COMMON_ATTESTATION; - -#define WEBAUTHN_ATTESTATION_TYPE_PACKED L"packed" -#define WEBAUTHN_ATTESTATION_TYPE_U2F L"fido-u2f" -#define WEBAUTHN_ATTESTATION_TYPE_TPM L"tpm" -#define WEBAUTHN_ATTESTATION_TYPE_NONE L"none" - -#define WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_1 1 -#define WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_2 2 -#define WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_3 3 -#define WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_4 4 -#define WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_5 5 -#define WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_6 6 -#define WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_7 7 -#define WEBAUTHN_CREDENTIAL_ATTESTATION_CURRENT_VERSION WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_7 - -typedef struct _WEBAUTHN_CREDENTIAL_ATTESTATION { - // Version of this structure, to allow for modifications in the future. - DWORD dwVersion; - - // Attestation format type - PCWSTR pwszFormatType; - - // Size of cbAuthenticatorData. - DWORD cbAuthenticatorData; - // Authenticator data that was created for this credential. - _Field_size_bytes_(cbAuthenticatorData) - PBYTE pbAuthenticatorData; - - // Size of CBOR encoded attestation information - //0 => encoded as CBOR null value. - DWORD cbAttestation; - //Encoded CBOR attestation information - _Field_size_bytes_(cbAttestation) - PBYTE pbAttestation; - - DWORD dwAttestationDecodeType; - // Following depends on the dwAttestationDecodeType - // WEBAUTHN_ATTESTATION_DECODE_NONE - // NULL - not able to decode the CBOR attestation information - // WEBAUTHN_ATTESTATION_DECODE_COMMON - // PWEBAUTHN_COMMON_ATTESTATION; - PVOID pvAttestationDecode; - - // The CBOR encoded Attestation Object to be returned to the RP. - DWORD cbAttestationObject; - _Field_size_bytes_(cbAttestationObject) - PBYTE pbAttestationObject; - - // The CredentialId bytes extracted from the Authenticator Data. - // Used by Edge to return to the RP. - DWORD cbCredentialId; - _Field_size_bytes_(cbCredentialId) - PBYTE pbCredentialId; - - // - // Following fields have been added in WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_2 - // - - WEBAUTHN_EXTENSIONS Extensions; - - // - // Following fields have been added in WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_3 - // - - // One of the WEBAUTHN_CTAP_TRANSPORT_* bits will be set corresponding to - // the transport that was used. - DWORD dwUsedTransport; - - // - // Following fields have been added in WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_4 - // - - BOOL bEpAtt; - BOOL bLargeBlobSupported; - BOOL bResidentKey; - - // - // Following fields have been added in WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_5 - // - - BOOL bPrfEnabled; - - // - // Following fields have been added in WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_6 - // - - DWORD cbUnsignedExtensionOutputs; - _Field_size_bytes_(cbUnsignedExtensionOutputs) - PBYTE pbUnsignedExtensionOutputs; - - // - // Following fields have been added in WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_7 - // - - PWEBAUTHN_HMAC_SECRET_SALT pHmacSecret; - - // ThirdPartyPayment Credential or not. - BOOL bThirdPartyPayment; - -} WEBAUTHN_CREDENTIAL_ATTESTATION, *PWEBAUTHN_CREDENTIAL_ATTESTATION; -typedef const WEBAUTHN_CREDENTIAL_ATTESTATION *PCWEBAUTHN_CREDENTIAL_ATTESTATION; - - -//+------------------------------------------------------------------------------------------ -// authenticatorGetAssertion output. -//------------------------------------------------------------------------------------------- - -#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_NONE 0 -#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_SUCCESS 1 -#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_NOT_SUPPORTED 2 -#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_INVALID_DATA 3 -#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_INVALID_PARAMETER 4 -#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_NOT_FOUND 5 -#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_MULTIPLE_CREDENTIALS 6 -#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_LACK_OF_SPACE 7 -#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_PLATFORM_ERROR 8 -#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_AUTHENTICATOR_ERROR 9 - -#define WEBAUTHN_ASSERTION_VERSION_1 1 -#define WEBAUTHN_ASSERTION_VERSION_2 2 -#define WEBAUTHN_ASSERTION_VERSION_3 3 -#define WEBAUTHN_ASSERTION_VERSION_4 4 -#define WEBAUTHN_ASSERTION_VERSION_5 5 -#define WEBAUTHN_ASSERTION_CURRENT_VERSION WEBAUTHN_ASSERTION_VERSION_5 - -typedef struct _WEBAUTHN_ASSERTION { - // Version of this structure, to allow for modifications in the future. - DWORD dwVersion; - - // Size of cbAuthenticatorData. - DWORD cbAuthenticatorData; - // Authenticator data that was created for this assertion. - _Field_size_bytes_(cbAuthenticatorData) - PBYTE pbAuthenticatorData; - - // Size of pbSignature. - DWORD cbSignature; - // Signature that was generated for this assertion. - _Field_size_bytes_(cbSignature) - PBYTE pbSignature; - - // Credential that was used for this assertion. - WEBAUTHN_CREDENTIAL Credential; - - // Size of User Id - DWORD cbUserId; - // UserId - _Field_size_bytes_(cbUserId) - PBYTE pbUserId; - - // - // Following fields have been added in WEBAUTHN_ASSERTION_VERSION_2 - // - - WEBAUTHN_EXTENSIONS Extensions; - - // Size of pbCredLargeBlob - DWORD cbCredLargeBlob; - _Field_size_bytes_(cbCredLargeBlob) - PBYTE pbCredLargeBlob; - - DWORD dwCredLargeBlobStatus; - - // - // Following fields have been added in WEBAUTHN_ASSERTION_VERSION_3 - // - - PWEBAUTHN_HMAC_SECRET_SALT pHmacSecret; - - // - // Following fields have been added in WEBAUTHN_ASSERTION_VERSION_4 - // - - // One of the WEBAUTHN_CTAP_TRANSPORT_* bits will be set corresponding to - // the transport that was used. - DWORD dwUsedTransport; - - // - // Following fields have been added in WEBAUTHN_ASSERTION_VERSION_5 - // - - DWORD cbUnsignedExtensionOutputs; - _Field_size_bytes_(cbUnsignedExtensionOutputs) - PBYTE pbUnsignedExtensionOutputs; -} WEBAUTHN_ASSERTION, *PWEBAUTHN_ASSERTION; -typedef const WEBAUTHN_ASSERTION *PCWEBAUTHN_ASSERTION; - -//+------------------------------------------------------------------------------------------ -// APIs. -//------------------------------------------------------------------------------------------- - -DWORD -WINAPI -WebAuthNGetApiVersionNumber(); - -HRESULT -WINAPI -WebAuthNIsUserVerifyingPlatformAuthenticatorAvailable( - _Out_ BOOL *pbIsUserVerifyingPlatformAuthenticatorAvailable); - - -HRESULT -WINAPI -WebAuthNAuthenticatorMakeCredential( - _In_ HWND hWnd, - _In_ PCWEBAUTHN_RP_ENTITY_INFORMATION pRpInformation, - _In_ PCWEBAUTHN_USER_ENTITY_INFORMATION pUserInformation, - _In_ PCWEBAUTHN_COSE_CREDENTIAL_PARAMETERS pPubKeyCredParams, - _In_ PCWEBAUTHN_CLIENT_DATA pWebAuthNClientData, - _In_opt_ PCWEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS pWebAuthNMakeCredentialOptions, - _Outptr_result_maybenull_ PWEBAUTHN_CREDENTIAL_ATTESTATION *ppWebAuthNCredentialAttestation); - - -HRESULT -WINAPI -WebAuthNAuthenticatorGetAssertion( - _In_ HWND hWnd, - _In_ LPCWSTR pwszRpId, - _In_ PCWEBAUTHN_CLIENT_DATA pWebAuthNClientData, - _In_opt_ PCWEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS pWebAuthNGetAssertionOptions, - _Outptr_result_maybenull_ PWEBAUTHN_ASSERTION *ppWebAuthNAssertion); - -void -WINAPI -WebAuthNFreeCredentialAttestation( - _In_opt_ PWEBAUTHN_CREDENTIAL_ATTESTATION pWebAuthNCredentialAttestation); - -void -WINAPI -WebAuthNFreeAssertion( - _In_ PWEBAUTHN_ASSERTION pWebAuthNAssertion); - -HRESULT -WINAPI -WebAuthNGetCancellationId( - _Out_ GUID* pCancellationId); - -HRESULT -WINAPI -WebAuthNCancelCurrentOperation( - _In_ const GUID* pCancellationId); - -// Returns NTE_NOT_FOUND when credentials are not found. -HRESULT -WINAPI -WebAuthNGetPlatformCredentialList( - _In_ PCWEBAUTHN_GET_CREDENTIALS_OPTIONS pGetCredentialsOptions, - _Outptr_result_maybenull_ PWEBAUTHN_CREDENTIAL_DETAILS_LIST *ppCredentialDetailsList); - -void -WINAPI -WebAuthNFreePlatformCredentialList( - _In_ PWEBAUTHN_CREDENTIAL_DETAILS_LIST pCredentialDetailsList); - -HRESULT -WINAPI -WebAuthNDeletePlatformCredential( - _In_ DWORD cbCredentialId, - _In_reads_bytes_(cbCredentialId) const BYTE *pbCredentialId - ); - -// -// Returns the following Error Names: -// L"Success" - S_OK -// L"InvalidStateError" - NTE_EXISTS -// L"ConstraintError" - HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), -// NTE_NOT_SUPPORTED, -// NTE_TOKEN_KEYSET_STORAGE_FULL -// L"NotSupportedError" - NTE_INVALID_PARAMETER -// L"NotAllowedError" - NTE_DEVICE_NOT_FOUND, -// NTE_NOT_FOUND, -// HRESULT_FROM_WIN32(ERROR_CANCELLED), -// NTE_USER_CANCELLED, -// HRESULT_FROM_WIN32(ERROR_TIMEOUT) -// L"UnknownError" - All other hr values -// -PCWSTR -WINAPI -WebAuthNGetErrorName( - _In_ HRESULT hr); - -HRESULT -WINAPI -WebAuthNGetW3CExceptionDOMError( - _In_ HRESULT hr); - -typedef enum _EXPERIMENTAL_PLUGIN_AUTHENTICATOR_STATE -{ - PluginAuthenticatorState_Unknown = 0, - PluginAuthenticatorState_Disabled, - PluginAuthenticatorState_Enabled -} EXPERIMENTAL_PLUGIN_AUTHENTICATOR_STATE; - -// -// Plugin Authenticator API: WebAuthNPluginGetAuthenticatorState: Get Plugin Authenticator State -// -HRESULT -WINAPI -EXPERIMENTAL_WebAuthNPluginGetAuthenticatorState( - _In_ LPCWSTR pwszPluginClsId, - _Out_ EXPERIMENTAL_PLUGIN_AUTHENTICATOR_STATE* pluginAuthenticatorState -); - -// -// Plugin Authenticator API: WebAuthNAddPluginAuthenticator: Add Plugin Authenticator -// - -typedef struct _EXPERIMENTAL_WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS { - // Authenticator Name - LPCWSTR pwszAuthenticatorName; - - // Plugin COM ClsId - LPCWSTR pwszPluginClsId; - - // Plugin RPID (Optional. Required for a nested WebAuthN call originating from a plugin) - LPCWSTR pwszPluginRpId; - - // Plugin Authenticator Logo for the Light themes. base64 svg (Optional) - LPCWSTR pwszLightThemeLogo; - - // Plugin Authenticator Logo for the Dark themes. base64 svg (Optional) - LPCWSTR pwszDarkThemeLogo; - - // CTAP CBOR encoded authenticatorGetInfo - DWORD cbAuthenticatorInfo; - _Field_size_bytes_(cbAuthenticatorInfo) - PBYTE pbAuthenticatorInfo; - -} EXPERIMENTAL_WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS, *EXPERIMENTAL_PWEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS; -typedef const EXPERIMENTAL_WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS *EXPERIMENTAL_PCWEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS; - -typedef struct _EXPERIMENTAL_WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_RESPONSE { - // Plugin operation signing Public Key - Used to sign the request in the EXPERIMENTAL_PluginPerformOperation. Refer pluginauthenticator.h. - DWORD cbOpSignPubKey; - _Field_size_bytes_(cbOpSignPubKey) - PBYTE pbOpSignPubKey; - -} EXPERIMENTAL_WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_RESPONSE, *EXPERIMENTAL_PWEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_RESPONSE; -typedef const EXPERIMENTAL_WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_RESPONSE *EXPERIMENTAL_PCWEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_RESPONSE; - -HRESULT -WINAPI -EXPERIMENTAL_WebAuthNPluginAddAuthenticator( - _In_ EXPERIMENTAL_PCWEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS pPluginAddAuthenticatorOptions, - _Outptr_result_maybenull_ EXPERIMENTAL_PWEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_RESPONSE *ppPluginAddAuthenticatorResponse); - -void -WINAPI -EXPERIMENTAL_WebAuthNPluginFreeAddAuthenticatorResponse( - _In_opt_ EXPERIMENTAL_PWEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_RESPONSE pPluginAddAuthenticatorResponse); - -// -// Plugin Authenticator API: WebAuthNRemovePluginAuthenticator: Remove Plugin Authenticator -// - -HRESULT -WINAPI -EXPERIMENTAL_WebAuthNPluginRemoveAuthenticator( - _In_ LPCWSTR pwszPluginClsId); - -// -// Plugin Authenticator API: WebAuthNPluginAuthenticatorUpdateDetails: Update Credential Metadata for Browser AutoFill Scenarios -// - -typedef struct _EXPERIMENTAL_WEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS { - // Authenticator Name (Optional) - LPCWSTR pwszAuthenticatorName; - - // Plugin COM ClsId - LPCWSTR pwszPluginClsId; - - // Plugin COM New ClsId (Optional) - LPCWSTR pwszNewPluginClsId; - - // Plugin Authenticator Logo for the Light themes. base64 svg (Optional) - LPCWSTR pwszLightThemeLogo; - - // Plugin Authenticator Logo for the Dark themes. base64 svg (Optional) - LPCWSTR pwszDarkThemeLogo; - - // CTAP CBOR encoded authenticatorGetInfo (Optional) - DWORD cbAuthenticatorInfo; - _Field_size_bytes_(cbAuthenticatorInfo) - PBYTE pbAuthenticatorInfo; - -} EXPERIMENTAL_WEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS, *EXPERIMENTAL_PWEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS; -typedef const EXPERIMENTAL_WEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS *EXPERIMENTAL_PCWEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS; - -HRESULT -WINAPI -EXPERIMENTAL_WebAuthNPluginUpdateAuthenticatorDetails( - _In_ EXPERIMENTAL_PCWEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS pPluginUpdateAuthenticatorDetails); - -#endif //__midl - -// -// Plugin Authenticator API: WebAuthNPluginAuthenticatorAddCredentials: Add Credential Metadata for Browser AutoFill Scenarios -// - - -typedef struct _EXPERIMENTAL_WEBAUTHN_PLUGIN_CREDENTIAL_DETAILS { - // Size of pbCredentialId. - DWORD cbCredentialId; - - // Credential Identifier bytes. This field is required. - #ifdef __midl - [size_is(cbCredentialId)] - #else - _Field_size_bytes_(cbCredentialId) - #endif - PBYTE pbCredentialId; - - // Identifier for the RP. This field is required. - PWSTR pwszRpId; - - // Contains the friendly name of the Relying Party, such as "Acme Corporation", "Widgets Inc" or "Awesome Site". - // This field is required. - PWSTR pwszRpName; - - // Identifier for the User. This field is required. - DWORD cbUserId; - - // User Identifier bytes. This field is required. - #ifdef __midl - [size_is(cbUserId)] - #else - _Field_size_bytes_(cbUserId) - #endif - PBYTE pbUserId; - - // Contains a detailed name for this account, such as "john.p.smith@example.com". - PWSTR pwszUserName; - - // For User: Contains the friendly name associated with the user account such as "John P. Smith". - PWSTR pwszUserDisplayName; - -} EXPERIMENTAL_WEBAUTHN_PLUGIN_CREDENTIAL_DETAILS, *EXPERIMENTAL_PWEBAUTHN_PLUGIN_CREDENTIAL_DETAILS; -typedef const EXPERIMENTAL_WEBAUTHN_PLUGIN_CREDENTIAL_DETAILS *EXPERIMENTAL_PCWEBAUTHN_PLUGIN_CREDENTIAL_DETAILS; - -typedef struct _EXPERIMENTAL_WEBAUTHN_PLUGIN_CREDENTIAL_DETAILS_LIST { - // Plugin COM ClsId - PWSTR pwszPluginClsId; - - // count of credentials - DWORD cCredentialDetails; - - #ifdef __midl - [size_is(cCredentialDetails)] - #else - _Field_size_(cCredentialDetails) - #endif - EXPERIMENTAL_PWEBAUTHN_PLUGIN_CREDENTIAL_DETAILS *pCredentialDetails; - -} EXPERIMENTAL_WEBAUTHN_PLUGIN_CREDENTIAL_DETAILS_LIST, *EXPERIMENTAL_PWEBAUTHN_PLUGIN_CREDENTIAL_DETAILS_LIST; -typedef const EXPERIMENTAL_WEBAUTHN_PLUGIN_CREDENTIAL_DETAILS_LIST *EXPERIMENTAL_PCWEBAUTHN_PLUGIN_CREDENTIAL_DETAILS_LIST; - -#ifndef __midl - -HRESULT -WINAPI -EXPERIMENTAL_WebAuthNPluginAuthenticatorAddCredentials( - _In_ EXPERIMENTAL_PWEBAUTHN_PLUGIN_CREDENTIAL_DETAILS_LIST pCredentialDetailsList); - -// -// Plugin Authenticator API: WebAuthNPluginAuthenticatorRemoveCredentials: Remove Credential Metadata for Browser AutoFill Scenarios -// - -HRESULT -WINAPI -EXPERIMENTAL_WebAuthNPluginAuthenticatorRemoveCredentials( - _In_ EXPERIMENTAL_PWEBAUTHN_PLUGIN_CREDENTIAL_DETAILS_LIST pCredentialDetailsList); - -// -// Plugin Authenticator API: WebAuthNPluginAuthenticatorRemoveCredentials: Remove All Credential Metadata for Browser AutoFill Scenarios -// - -HRESULT -WINAPI -EXPERIMENTAL_WebAuthNPluginAuthenticatorRemoveAllCredentials( - _In_ LPCWSTR pwszPluginClsId); - -// -// Plugin Authenticator API: WebAuthNPluginAuthenticatorGetAllCredentials: Get All Credential Metadata cached for Browser AutoFill Scenarios -// -HRESULT -WINAPI -EXPERIMENTAL_WebAuthNPluginAuthenticatorGetAllCredentials( - _In_ LPCWSTR pwszPluginClsId, - _Outptr_result_maybenull_ EXPERIMENTAL_PWEBAUTHN_PLUGIN_CREDENTIAL_DETAILS_LIST *ppCredentialDetailsList); - -// -// Hello UV API for Plugin: WebAuthNPluginPerformUv: Perform Hello UV related operations -// - -typedef enum _EXPERIMENTAL_WEBAUTHN_PLUGIN_PERFORM_UV_OPERATION_TYPE -{ - PerformUv = 1, - GetUvCount, - GetPubKey -} EXPERIMENTAL_WEBAUTHN_PLUGIN_PERFORM_UV_OPERATION_TYPE; - -typedef struct _EXPERIMENTAL_WEBAUTHN_PLUGIN_PERFORM_UV { - HWND hwnd; - GUID* transactionId; - EXPERIMENTAL_WEBAUTHN_PLUGIN_PERFORM_UV_OPERATION_TYPE type; - PCWSTR pwszUsername; - PCWSTR pwszContext; -} EXPERIMENTAL_WEBAUTHN_PLUGIN_PERFORM_UV, *EXPERIMENTAL_PWEBAUTHN_PLUGIN_PERFROM_UV; -typedef const EXPERIMENTAL_WEBAUTHN_PLUGIN_PERFORM_UV *EXPERIMENTAL_PCWEBAUTHN_PLUGIN_PERFORM_UV; - -typedef struct _EXPERIMENTAL_WEBAUTHN_PLUGIN_PERFORM_UV_RESPONSE { - DWORD cbResponse; - PBYTE pbResponse; -} EXPERIMENTAL_WEBAUTHN_PLUGIN_PERFORM_UV_RESPONSE, *EXPERIMENTAL_PWEBAUTHN_PLUGIN_PERFORM_UV_RESPONSE; -typedef const EXPERIMENTAL_WEBAUTHN_PLUGIN_PERFORM_UV_RESPONSE *EXPERIMENTAL_PCWEBAUTHN_PLUGIN_PERFORM_UV_RESPONSE; - -HRESULT -WINAPI -EXPERIMENTAL_WebAuthNPluginPerformUv( - _In_ EXPERIMENTAL_PCWEBAUTHN_PLUGIN_PERFORM_UV pPluginPerformUv, - _Outptr_result_maybenull_ EXPERIMENTAL_PWEBAUTHN_PLUGIN_PERFORM_UV_RESPONSE *ppPluginPerformUvRespose); - -void -WINAPI -EXPERIMENTAL_WebAuthNPluginFreePerformUvResponse( - _In_opt_ EXPERIMENTAL_PWEBAUTHN_PLUGIN_PERFORM_UV_RESPONSE ppPluginPerformUvResponse); - -#define EXPERIMENTAL_WEBAUTHN_CTAPCBOR_AUTHENTICATOR_OPTIONS_VERSION_1 1 -#define EXPERIMENTAL_WEBAUTHN_CTAPCBOR_AUTHENTICATOR_OPTIONS_CURRENT_VERSION EXPERIMENTAL_WEBAUTHN_CTAPCBOR_AUTHENTICATOR_OPTIONS_VERSION_1 -typedef struct _EXPERIMENTAL_WEBAUTHN_CTAPCBOR_AUTHENTICATOR_OPTIONS { - //Version of this structure, to allow for modifications in the future. - DWORD dwVersion; - - // Following have following values: - // +1 - TRUE - // 0 - Not defined - // -1 - FALSE - //up: "true" | "false" - LONG lUp; - //uv: "true" | "false" - LONG lUv; - //rk: "true" | "false" - LONG lRequireResidentKey; -} EXPERIMENTAL_WEBAUTHN_CTAPCBOR_AUTHENTICATOR_OPTIONS, *EXPERIMENTAL_PWEBAUTHN_CTAPCBOR_AUTHENTICATOR_OPTIONS; -typedef const EXPERIMENTAL_WEBAUTHN_CTAPCBOR_AUTHENTICATOR_OPTIONS *EXPERIMENTAL_PCWEBAUTHN_CTAPCBOR_AUTHENTICATOR_OPTIONS; - -#define EXPERIMENTAL_WEBAUTHN_CTAPCBOR_ECC_PUBLIC_KEY_VERSION_1 1 -#define EXPERIMENTAL_WEBAUTHN_CTAPCBOR_ECC_PUBLIC_KEY_CURRENT_VERSION EXPERIMENTAL_WEBAUTHN_CTAPCBOR_ECC_PUBLIC_KEY_VERSION_1 -typedef struct _EXPERIMENTAL_WEBAUTHN_CTAPCBOR_ECC_PUBLIC_KEY { - //Version of this structure, to allow for modifications in the future. - DWORD dwVersion; - - // Key type - LONG lKty; - - // Hash Algorithm: ES256, ES384, ES512 - LONG lAlg; - - // Curve - LONG lCrv; - - //Size of "x" (X Coordinate) - DWORD cbX; - - //"x" (X Coordinate) data. Big Endian. - PBYTE pbX; - - //Size of "y" (Y Coordinate) - DWORD cbY; - - //"y" (Y Coordinate) data. Big Endian. - PBYTE pbY; -} EXPERIMENTAL_WEBAUTHN_CTAPCBOR_ECC_PUBLIC_KEY, *EXPERIMENTAL_PWEBAUTHN_CTAPCBOR_ECC_PUBLIC_KEY; -typedef const EXPERIMENTAL_WEBAUTHN_CTAPCBOR_ECC_PUBLIC_KEY *EXPERIMENTAL_PCWEBAUTHN_CTAPCBOR_ECC_PUBLIC_KEY; - -#define EXPERIMENTAL_WEBAUTHN_CTAPCBOR_HMAC_SALT_EXTENSION_VERSION_1 1 -#define EXPERIMENTAL_WEBAUTHN_CTAPCBOR_HMAC_SALT_EXTENSION_CURRENT_VERSION EXPERIMENTAL_WEBAUTHN_CTAPCBOR_HMAC_SALT_EXTENSION_VERSION_1 -typedef struct _EXPERIMENTAL_WEBAUTHN_CTAPCBOR_HMAC_SALT_EXTENSION { - //Version of this structure, to allow for modifications in the future. - DWORD dwVersion; - - // Platform's key agreement public key - EXPERIMENTAL_PWEBAUTHN_CTAPCBOR_ECC_PUBLIC_KEY pKeyAgreement; - - DWORD cbEncryptedSalt; - PBYTE pbEncryptedSalt; - - DWORD cbSaltAuth; - PBYTE pbSaltAuth; -} EXPERIMENTAL_WEBAUTHN_CTAPCBOR_HMAC_SALT_EXTENSION, *EXPERIMENTAL_PWEBAUTHN_CTAPCBOR_HMAC_SALT_EXTENSION; -typedef const EXPERIMENTAL_WEBAUTHN_CTAPCBOR_HMAC_SALT_EXTENSION *EXPERIMENTAL_PCWEBAUTHN_CTAPCBOR_HMAC_SALT_EXTENSION; - -#define EXPERIMENTAL_WEBAUTHN_CTAPCBOR_MAKE_CREDENTIAL_REQUEST_VERSION_1 1 -#define EXPERIMENTAL_WEBAUTHN_CTAPCBOR_MAKE_CREDENTIAL_REQUEST_CURRENT_VERSION EXPERIMENTAL_WEBAUTHN_CTAPCBOR_MAKE_CREDENTIAL_REQUEST_VERSION_1 -typedef struct _EXPERIMENTAL_WEBAUTHN_CTAPCBOR_MAKE_CREDENTIAL_REQUEST { - //Version of this structure, to allow for modifications in the future. - DWORD dwVersion; - - //Input RP ID. Raw UTF8 bytes before conversion. - //These are the bytes to be hashed in the Authenticator Data. - DWORD cbRpId; - PBYTE pbRpId; - - //Client Data Hash - DWORD cbClientDataHash; - PBYTE pbClientDataHash; - - //RP Information - PCWEBAUTHN_RP_ENTITY_INFORMATION pRpInformation; - - //User Information - PCWEBAUTHN_USER_ENTITY_INFORMATION pUserInformation; - - // Crypto Parameters - WEBAUTHN_COSE_CREDENTIAL_PARAMETERS WebAuthNCredentialParameters; - - //Credentials used for exclusion - WEBAUTHN_CREDENTIAL_LIST CredentialList; - - //Optional extensions to parse when performing the operation. - DWORD cbCborExtensionsMap; - PBYTE pbCborExtensionsMap; - - // Authenticator Options (Optional) - EXPERIMENTAL_PWEBAUTHN_CTAPCBOR_AUTHENTICATOR_OPTIONS pAuthenticatorOptions; - - // Pin Auth (Optional) - BOOL fEmptyPinAuth; // Zero length PinAuth is included in the request - DWORD cbPinAuth; - PBYTE pbPinAuth; - - //"hmac-secret": true extension - LONG lHmacSecretExt; - - // "hmac-secret-mc" extension - EXPERIMENTAL_PWEBAUTHN_CTAPCBOR_HMAC_SALT_EXTENSION pHmacSecretMcExtension; - - //"prf" extension - LONG lPrfExt; - DWORD cbHmacSecretSaltValues; - PBYTE pbHmacSecretSaltValues; - - //"credProtect" extension. Nonzero if present - DWORD dwCredProtect; - - // Nonzero if present - DWORD dwPinProtocol; - - // Nonzero if present - DWORD dwEnterpriseAttestation; - - //"credBlob" extension. Nonzero if present - DWORD cbCredBlobExt; - PBYTE pbCredBlobExt; - - //"largeBlobKey": true extension - LONG lLargeBlobKeyExt; - - //"largeBlob": extension - DWORD dwLargeBlobSupport; - - //"minPinLength": true extension - LONG lMinPinLengthExt; - - // "json" extension. Nonzero if present - DWORD cbJsonExt; - PBYTE pbJsonExt; -} EXPERIMENTAL_WEBAUTHN_CTAPCBOR_MAKE_CREDENTIAL_REQUEST, *EXPERIMENTAL_PWEBAUTHN_CTAPCBOR_MAKE_CREDENTIAL_REQUEST; -typedef const EXPERIMENTAL_WEBAUTHN_CTAPCBOR_MAKE_CREDENTIAL_REQUEST *EXPERIMENTAL_PCWEBAUTHN_CTAPCBOR_MAKE_CREDENTIAL_REQUEST; - -_Success_(return == S_OK) -HRESULT -WINAPI -EXPERIMENTAL_WebAuthNEncodeMakeCredentialResponse( - _In_ PCWEBAUTHN_CREDENTIAL_ATTESTATION pCredentialAttestation, - _Out_ DWORD *pcbResp, - _Outptr_result_buffer_maybenull_(*pcbResp) BYTE **ppbResp - ); - -_Success_(return == S_OK) -HRESULT -WINAPI -EXPERIMENTAL_WebAuthNDecodeMakeCredentialRequest( - _In_ DWORD cbEncoded, - _In_reads_bytes_(cbEncoded) const BYTE *pbEncoded, - _Outptr_ EXPERIMENTAL_PWEBAUTHN_CTAPCBOR_MAKE_CREDENTIAL_REQUEST *ppMakeCredentialRequest - ); - -void -WINAPI -EXPERIMENTAL_WebAuthNFreeDecodedMakeCredentialRequest( - _In_opt_ EXPERIMENTAL_PWEBAUTHN_CTAPCBOR_MAKE_CREDENTIAL_REQUEST pMakeCredentialRequest - ); - -#define EXPERIMENTAL_WEBAUTHN_CTAPCBOR_GET_ASSERTION_REQUEST_VERSION_1 1 -#define EXPERIMENTAL_WEBAUTHN_CTAPCBOR_GET_ASSERTION_REQUEST_CURRENT_VERSION EXPERIMENTAL_WEBAUTHN_CTAPCBOR_GET_ASSERTION_REQUEST_VERSION_1 -typedef struct _EXPERIMENTAL_WEBAUTHN_CTAPCBOR_GET_ASSERTION_REQUEST { - //Version of this structure, to allow for modifications in the future. - DWORD dwVersion; - - //RP ID. After UTF8 to Unicode conversion, - PCWSTR pwszRpId; - - //Input RP ID. Raw UTF8 bytes before conversion. - //These are the bytes to be hashed in the Authenticator Data. - DWORD cbRpId; - PBYTE pbRpId; - - //Client Data Hash - DWORD cbClientDataHash; - PBYTE pbClientDataHash; - - //Credentials used for inclusion - WEBAUTHN_CREDENTIAL_LIST CredentialList; - - //Optional extensions to parse when performing the operation. - DWORD cbCborExtensionsMap; - PBYTE pbCborExtensionsMap; - - // Authenticator Options (Optional) - EXPERIMENTAL_PWEBAUTHN_CTAPCBOR_AUTHENTICATOR_OPTIONS pAuthenticatorOptions; - - // Pin Auth (Optional) - BOOL fEmptyPinAuth; // Zero length PinAuth is included in the request - DWORD cbPinAuth; - PBYTE pbPinAuth; - - // HMAC Salt Extension (Optional) - EXPERIMENTAL_PWEBAUTHN_CTAPCBOR_HMAC_SALT_EXTENSION pHmacSaltExtension; - - // PRF Extension - DWORD cbHmacSecretSaltValues; - PBYTE pbHmacSecretSaltValues; - - DWORD dwPinProtocol; - - //"credBlob": true extension - LONG lCredBlobExt; - - //"largeBlobKey": true extension - LONG lLargeBlobKeyExt; - - //"largeBlob" extension - DWORD dwCredLargeBlobOperation; - DWORD cbCredLargeBlobCompressed; - PBYTE pbCredLargeBlobCompressed; - DWORD dwCredLargeBlobOriginalSize; - - // "json" extension. Nonzero if present - DWORD cbJsonExt; - PBYTE pbJsonExt; -} EXPERIMENTAL_WEBAUTHN_CTAPCBOR_GET_ASSERTION_REQUEST, *EXPERIMENTAL_PWEBAUTHN_CTAPCBOR_GET_ASSERTION_REQUEST; -typedef const EXPERIMENTAL_WEBAUTHN_CTAPCBOR_GET_ASSERTION_REQUEST *EXPERIMENTAL_PCWEBAUTHN_CTAPCBOR_GET_ASSERTION_REQUEST; - -_Success_(return == S_OK) -HRESULT -WINAPI -EXPERIMENTAL_WebAuthNDecodeGetAssertionRequest( - _In_ DWORD cbEncoded, - _In_reads_bytes_(cbEncoded) const BYTE *pbEncoded, - _Outptr_ EXPERIMENTAL_PWEBAUTHN_CTAPCBOR_GET_ASSERTION_REQUEST *ppGetAssertionRequest - ); - -void -WINAPI -EXPERIMENTAL_WebAuthNFreeDecodedGetAssertionRequest( - _In_opt_ EXPERIMENTAL_PWEBAUTHN_CTAPCBOR_GET_ASSERTION_REQUEST pGetAssertionRequest - ); - -typedef struct _EXPERIMENTAL_WEBAUTHN_CTAPCBOR_GET_ASSERTION_RESPONSE { - // [1] credential (optional) - // [2] authenticatorData - // [3] signature - WEBAUTHN_ASSERTION WebAuthNAssertion; - - // [4] user (optional) - PCWEBAUTHN_USER_ENTITY_INFORMATION pUserInformation; - - // [5] numberOfCredentials (optional) - DWORD dwNumberOfCredentials; - - // [6] userSelected (optional) - LONG lUserSelected; - - // [7] largeBlobKey (optional) - DWORD cbLargeBlobKey; - PBYTE pbLargeBlobKey; - - // [8] unsignedExtensionOutputs - DWORD cbUnsignedExtensionOutputs; - PBYTE pbUnsignedExtensionOutputs; -} EXPERIMENTAL_WEBAUTHN_CTAPCBOR_GET_ASSERTION_RESPONSE, *EXPERIMENTAL_PWEBAUTHN_CTAPCBOR_GET_ASSERTION_RESPONSE; -typedef const EXPERIMENTAL_PWEBAUTHN_CTAPCBOR_GET_ASSERTION_RESPONSE *EXPERIMENTAL_PCWEBAUTHN_CTAPCBOR_GET_ASSERTION_RESPONSE; - -_Success_(return == S_OK) -HRESULT -WINAPI -EXPERIMENTAL_WebAuthNEncodeGetAssertionResponse( - _In_ EXPERIMENTAL_PCWEBAUTHN_CTAPCBOR_GET_ASSERTION_RESPONSE pGetAssertionResponse, - _Out_ DWORD *pcbResp, - _Outptr_result_buffer_maybenull_(*pcbResp) BYTE **ppbResp - ); - -#endif //__midl - - -#ifdef __cplusplus -} // Balance extern "C" above -#endif - -#endif // WINAPI_FAMILY_PARTITION -#pragma endregion - +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#ifndef __WEBAUTHN_H_ +#define __WEBAUTHN_H_ + +#pragma once + +#include + +#pragma region Desktop Family or OneCore Family +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM) + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef WINAPI +#define WINAPI __stdcall +#endif + +#ifndef INITGUID +#define INITGUID +#include +#undef INITGUID +#else +#include +#endif + +//+------------------------------------------------------------------------------------------ +// API Version Information. +// Caller should check for WebAuthNGetApiVersionNumber to check the presence of relevant APIs +// and features for their usage. +//------------------------------------------------------------------------------------------- + +#define WEBAUTHN_API_VERSION_1 1 +// WEBAUTHN_API_VERSION_1 : Baseline Version +// Data Structures and their sub versions: +// - WEBAUTHN_RP_ENTITY_INFORMATION : 1 +// - WEBAUTHN_USER_ENTITY_INFORMATION : 1 +// - WEBAUTHN_CLIENT_DATA : 1 +// - WEBAUTHN_COSE_CREDENTIAL_PARAMETER : 1 +// - WEBAUTHN_COSE_CREDENTIAL_PARAMETERS : Not Applicable +// - WEBAUTHN_CREDENTIAL : 1 +// - WEBAUTHN_CREDENTIALS : Not Applicable +// - WEBAUTHN_CREDENTIAL_EX : 1 +// - WEBAUTHN_CREDENTIAL_LIST : Not Applicable +// - WEBAUTHN_EXTENSION : Not Applicable +// - WEBAUTHN_EXTENSIONS : Not Applicable +// - WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS : 3 +// - WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS : 4 +// - WEBAUTHN_COMMON_ATTESTATION : 1 +// - WEBAUTHN_CREDENTIAL_ATTESTATION : 3 +// - WEBAUTHN_ASSERTION : 1 +// Extensions: +// - WEBAUTHN_EXTENSIONS_IDENTIFIER_HMAC_SECRET +// APIs: +// - WebAuthNGetApiVersionNumber +// - WebAuthNIsUserVerifyingPlatformAuthenticatorAvailable +// - WebAuthNAuthenticatorMakeCredential +// - WebAuthNAuthenticatorGetAssertion +// - WebAuthNFreeCredentialAttestation +// - WebAuthNFreeAssertion +// - WebAuthNGetCancellationId +// - WebAuthNCancelCurrentOperation +// - WebAuthNGetErrorName +// - WebAuthNGetW3CExceptionDOMError +// Transports: +// - WEBAUTHN_CTAP_TRANSPORT_USB +// - WEBAUTHN_CTAP_TRANSPORT_NFC +// - WEBAUTHN_CTAP_TRANSPORT_BLE +// - WEBAUTHN_CTAP_TRANSPORT_INTERNAL + +#define WEBAUTHN_API_VERSION_2 2 +// WEBAUTHN_API_VERSION_2 : Delta From WEBAUTHN_API_VERSION_1 +// Added Extensions: +// - WEBAUTHN_EXTENSIONS_IDENTIFIER_CRED_PROTECT +// + +#define WEBAUTHN_API_VERSION_3 3 +// WEBAUTHN_API_VERSION_3 : Delta From WEBAUTHN_API_VERSION_2 +// Data Structures and their sub versions: +// - WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS : 4 +// - WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS : 5 +// - WEBAUTHN_CREDENTIAL_ATTESTATION : 4 +// - WEBAUTHN_ASSERTION : 2 +// Added Extensions: +// - WEBAUTHN_EXTENSIONS_IDENTIFIER_CRED_BLOB +// - WEBAUTHN_EXTENSIONS_IDENTIFIER_MIN_PIN_LENGTH +// + +#define WEBAUTHN_API_VERSION_4 4 +// WEBAUTHN_API_VERSION_4 : Delta From WEBAUTHN_API_VERSION_3 +// Data Structures and their sub versions: +// - WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS : 5 +// - WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS : 6 +// - WEBAUTHN_ASSERTION : 3 +// - WEBAUTHN_GET_CREDENTIALS_OPTIONS : 1 +// - WEBAUTHN_CREDENTIAL_DETAILS : 1 +// APIs: +// - WebAuthNGetPlatformCredentialList +// - WebAuthNFreePlatformCredentialList +// - WebAuthNDeletePlatformCredential +// + +#define WEBAUTHN_API_VERSION_5 5 +// WEBAUTHN_API_VERSION_5 : Delta From WEBAUTHN_API_VERSION_4 +// Data Structures and their sub versions: +// - WEBAUTHN_CREDENTIAL_DETAILS : 2 +// Extension Changes: +// - Enabled LARGE_BLOB Support +// + +#define WEBAUTHN_API_VERSION_6 6 +// WEBAUTHN_API_VERSION_6 : Delta From WEBAUTHN_API_VERSION_5 +// Data Structures and their sub versions: +// - WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS : 6 +// - WEBAUTHN_CREDENTIAL_ATTESTATION : 5 +// - WEBAUTHN_ASSERTION : 4 +// Transports: +// - WEBAUTHN_CTAP_TRANSPORT_HYBRID + +#define WEBAUTHN_API_VERSION_7 7 +// WEBAUTHN_API_VERSION_7 : Delta From WEBAUTHN_API_VERSION_6 +// Data Structures and their sub versions: +// - WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS : 7 +// - WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS : 7 +// - WEBAUTHN_CREDENTIAL_ATTESTATION : 6 +// - WEBAUTHN_ASSERTION : 5 + +#define WEBAUTHN_API_VERSION_8 8 +// WEBAUTHN_API_VERSION_8 : Delta From WEBAUTHN_API_VERSION_7 +// Data Structures and their sub versions: +// - WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS : 8 +// - WEBAUTHN_CREDENTIAL_DETAILS : 3 +// - WEBAUTHN_CREDENTIAL_ATTESTATION : 7 +// - WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS : 8 +// + +#define WEBAUTHN_API_VERSION_9 9 +// WEBAUTHN_API_VERSION_9 : Delta From WEBAUTHN_API_VERSION_8 +// Data Structures and their sub versions: +// - WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS : 9 +// - WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS : 9 +// - WEBAUTHN_ASSERTION : 6 +// - WEBAUTHN_CREDENTIAL_DETAILS : 4 +// - WEBAUTHN_CREDENTIAL_ATTESTATION : 8 +// - WEBAUTHN_AUTHENTICATOR_DETAILS : 1 +// - WEBAUTHN_AUTHENTICATOR_DETAILS_LIST : Not Applicable +// APIs: +// - WebAuthNGetAuthenticatorList +// - WebAuthNFreeAuthenticatorList + +#define WEBAUTHN_API_CURRENT_VERSION WEBAUTHN_API_VERSION_9 + +//+------------------------------------------------------------------------------------------ +// Information about an RP Entity +//------------------------------------------------------------------------------------------- + +#define WEBAUTHN_RP_ENTITY_INFORMATION_CURRENT_VERSION 1 + +typedef struct _WEBAUTHN_RP_ENTITY_INFORMATION { + // Version of this structure, to allow for modifications in the future. + // This field is required and should be set to CURRENT_VERSION above. + DWORD dwVersion; + + // Identifier for the RP. This field is required. + PCWSTR pwszId; + + // Contains the friendly name of the Relying Party, such as "Acme Corporation", "Widgets Inc" or "Awesome Site". + // This field is required. + PCWSTR pwszName; + + // Optional URL pointing to RP's logo. + PCWSTR pwszIcon; +} WEBAUTHN_RP_ENTITY_INFORMATION, *PWEBAUTHN_RP_ENTITY_INFORMATION; +typedef const WEBAUTHN_RP_ENTITY_INFORMATION *PCWEBAUTHN_RP_ENTITY_INFORMATION; + +//+------------------------------------------------------------------------------------------ +// Information about an User Entity +//------------------------------------------------------------------------------------------- +#define WEBAUTHN_MAX_USER_ID_LENGTH 64 + +#define WEBAUTHN_USER_ENTITY_INFORMATION_CURRENT_VERSION 1 + +typedef struct _WEBAUTHN_USER_ENTITY_INFORMATION { + // Version of this structure, to allow for modifications in the future. + // This field is required and should be set to CURRENT_VERSION above. + DWORD dwVersion; + + // Identifier for the User. This field is required. + DWORD cbId; + _Field_size_bytes_(cbId) + PBYTE pbId; + + // Contains a detailed name for this account, such as "john.p.smith@example.com". + PCWSTR pwszName; + + // Optional URL that can be used to retrieve an image containing the user's current avatar, + // or a data URI that contains the image data. + PCWSTR pwszIcon; + + // For User: Contains the friendly name associated with the user account by the Relying Party, such as "John P. Smith". + PCWSTR pwszDisplayName; +} WEBAUTHN_USER_ENTITY_INFORMATION, *PWEBAUTHN_USER_ENTITY_INFORMATION; +typedef const WEBAUTHN_USER_ENTITY_INFORMATION *PCWEBAUTHN_USER_ENTITY_INFORMATION; + +//+------------------------------------------------------------------------------------------ +// Information about client data. +//------------------------------------------------------------------------------------------- + +#define WEBAUTHN_HASH_ALGORITHM_SHA_256 L"SHA-256" +#define WEBAUTHN_HASH_ALGORITHM_SHA_384 L"SHA-384" +#define WEBAUTHN_HASH_ALGORITHM_SHA_512 L"SHA-512" + +#define WEBAUTHN_CLIENT_DATA_CURRENT_VERSION 1 + +typedef struct _WEBAUTHN_CLIENT_DATA { + // Version of this structure, to allow for modifications in the future. + // This field is required and should be set to CURRENT_VERSION above. + DWORD dwVersion; + + // Size of the pbClientDataJSON field. + DWORD cbClientDataJSON; + // UTF-8 encoded JSON serialization of the client data. + _Field_size_bytes_(cbClientDataJSON) + PBYTE pbClientDataJSON; + + // Hash algorithm ID used to hash the pbClientDataJSON field. + LPCWSTR pwszHashAlgId; +} WEBAUTHN_CLIENT_DATA, *PWEBAUTHN_CLIENT_DATA; +typedef const WEBAUTHN_CLIENT_DATA *PCWEBAUTHN_CLIENT_DATA; + +//+------------------------------------------------------------------------------------------ +// Information about credential parameters. +//------------------------------------------------------------------------------------------- + +#define WEBAUTHN_CREDENTIAL_TYPE_PUBLIC_KEY L"public-key" + +#define WEBAUTHN_COSE_ALGORITHM_ECDSA_P256_WITH_SHA256 -7 +#define WEBAUTHN_COSE_ALGORITHM_ECDSA_P384_WITH_SHA384 -35 +#define WEBAUTHN_COSE_ALGORITHM_ECDSA_P521_WITH_SHA512 -36 + +#define WEBAUTHN_COSE_ALGORITHM_RSASSA_PKCS1_V1_5_WITH_SHA256 -257 +#define WEBAUTHN_COSE_ALGORITHM_RSASSA_PKCS1_V1_5_WITH_SHA384 -258 +#define WEBAUTHN_COSE_ALGORITHM_RSASSA_PKCS1_V1_5_WITH_SHA512 -259 + +#define WEBAUTHN_COSE_ALGORITHM_RSA_PSS_WITH_SHA256 -37 +#define WEBAUTHN_COSE_ALGORITHM_RSA_PSS_WITH_SHA384 -38 +#define WEBAUTHN_COSE_ALGORITHM_RSA_PSS_WITH_SHA512 -39 + +#define WEBAUTHN_COSE_CREDENTIAL_PARAMETER_CURRENT_VERSION 1 + +typedef struct _WEBAUTHN_COSE_CREDENTIAL_PARAMETER { + // Version of this structure, to allow for modifications in the future. + DWORD dwVersion; + + // Well-known credential type specifying a credential to create. + LPCWSTR pwszCredentialType; + + // Well-known COSE algorithm specifying the algorithm to use for the credential. + LONG lAlg; +} WEBAUTHN_COSE_CREDENTIAL_PARAMETER, *PWEBAUTHN_COSE_CREDENTIAL_PARAMETER; +typedef const WEBAUTHN_COSE_CREDENTIAL_PARAMETER *PCWEBAUTHN_COSE_CREDENTIAL_PARAMETER; + +typedef struct _WEBAUTHN_COSE_CREDENTIAL_PARAMETERS { + DWORD cCredentialParameters; + _Field_size_(cCredentialParameters) + PWEBAUTHN_COSE_CREDENTIAL_PARAMETER pCredentialParameters; +} WEBAUTHN_COSE_CREDENTIAL_PARAMETERS, *PWEBAUTHN_COSE_CREDENTIAL_PARAMETERS; +typedef const WEBAUTHN_COSE_CREDENTIAL_PARAMETERS *PCWEBAUTHN_COSE_CREDENTIAL_PARAMETERS; + +//+------------------------------------------------------------------------------------------ +// Information about credential. +//------------------------------------------------------------------------------------------- +#define WEBAUTHN_CREDENTIAL_CURRENT_VERSION 1 + +typedef struct _WEBAUTHN_CREDENTIAL { + // Version of this structure, to allow for modifications in the future. + DWORD dwVersion; + + // Size of pbID. + DWORD cbId; + // Unique ID for this particular credential. + _Field_size_bytes_(cbId) + PBYTE pbId; + + // Well-known credential type specifying what this particular credential is. + LPCWSTR pwszCredentialType; +} WEBAUTHN_CREDENTIAL, *PWEBAUTHN_CREDENTIAL; +typedef const WEBAUTHN_CREDENTIAL *PCWEBAUTHN_CREDENTIAL; + +typedef struct _WEBAUTHN_CREDENTIALS { + DWORD cCredentials; + _Field_size_(cCredentials) + PWEBAUTHN_CREDENTIAL pCredentials; +} WEBAUTHN_CREDENTIALS, *PWEBAUTHN_CREDENTIALS; +typedef const WEBAUTHN_CREDENTIALS *PCWEBAUTHN_CREDENTIALS; + +//+------------------------------------------------------------------------------------------ +// Information about credential with extra information, such as, dwTransports +//------------------------------------------------------------------------------------------- + +#define WEBAUTHN_CTAP_TRANSPORT_USB 0x00000001 +#define WEBAUTHN_CTAP_TRANSPORT_NFC 0x00000002 +#define WEBAUTHN_CTAP_TRANSPORT_BLE 0x00000004 +#define WEBAUTHN_CTAP_TRANSPORT_TEST 0x00000008 +#define WEBAUTHN_CTAP_TRANSPORT_INTERNAL 0x00000010 +#define WEBAUTHN_CTAP_TRANSPORT_HYBRID 0x00000020 +#define WEBAUTHN_CTAP_TRANSPORT_SMART_CARD 0x00000040 +#define WEBAUTHN_CTAP_TRANSPORT_FLAGS_MASK 0x0000007F + +#define WEBAUTHN_CTAP_TRANSPORT_USB_STRING "usb" +#define WEBAUTHN_CTAP_TRANSPORT_NFC_STRING "nfc" +#define WEBAUTHN_CTAP_TRANSPORT_BLE_STRING "ble" +#define WEBAUTHN_CTAP_TRANSPORT_SMART_CARD_STRING "smart-card" +#define WEBAUTHN_CTAP_TRANSPORT_HYBRID_STRING "hybrid" +#define WEBAUTHN_CTAP_TRANSPORT_INTERNAL_STRING "internal" + +#define WEBAUTHN_CREDENTIAL_EX_CURRENT_VERSION 1 + +typedef struct _WEBAUTHN_CREDENTIAL_EX { + // Version of this structure, to allow for modifications in the future. + DWORD dwVersion; + + // Size of pbID. + DWORD cbId; + // Unique ID for this particular credential. + _Field_size_bytes_(cbId) + PBYTE pbId; + + // Well-known credential type specifying what this particular credential is. + LPCWSTR pwszCredentialType; + + // Transports. 0 implies no transport restrictions. + DWORD dwTransports; +} WEBAUTHN_CREDENTIAL_EX, *PWEBAUTHN_CREDENTIAL_EX; +typedef const WEBAUTHN_CREDENTIAL_EX *PCWEBAUTHN_CREDENTIAL_EX; + +//+------------------------------------------------------------------------------------------ +// Information about credential list with extra information +//------------------------------------------------------------------------------------------- + +typedef struct _WEBAUTHN_CREDENTIAL_LIST { + DWORD cCredentials; + _Field_size_(cCredentials) + PWEBAUTHN_CREDENTIAL_EX *ppCredentials; +} WEBAUTHN_CREDENTIAL_LIST, *PWEBAUTHN_CREDENTIAL_LIST; +typedef const WEBAUTHN_CREDENTIAL_LIST *PCWEBAUTHN_CREDENTIAL_LIST; + +//+------------------------------------------------------------------------------------------ +// Information about linked devices +//------------------------------------------------------------------------------------------- + +#define CTAPCBOR_HYBRID_STORAGE_LINKED_DATA_VERSION_1 1 +#define CTAPCBOR_HYBRID_STORAGE_LINKED_DATA_CURRENT_VERSION CTAPCBOR_HYBRID_STORAGE_LINKED_DATA_VERSION_1 + +// Deprecated +typedef struct _CTAPCBOR_HYBRID_STORAGE_LINKED_DATA +{ + // Version + DWORD dwVersion; + + // Contact Id + DWORD cbContactId; + _Field_size_bytes_(cbContactId) + PBYTE pbContactId; + + // Link Id + DWORD cbLinkId; + _Field_size_bytes_(cbLinkId) + PBYTE pbLinkId; + + // Link secret + DWORD cbLinkSecret; + _Field_size_bytes_(cbLinkSecret) + PBYTE pbLinkSecret; + + // Authenticator Public Key + DWORD cbPublicKey; + _Field_size_bytes_(cbPublicKey) + PBYTE pbPublicKey; + + // Authenticator Name + PCWSTR pwszAuthenticatorName; + + // Tunnel server domain + WORD wEncodedTunnelServerDomain; +} CTAPCBOR_HYBRID_STORAGE_LINKED_DATA, *PCTAPCBOR_HYBRID_STORAGE_LINKED_DATA; +typedef const CTAPCBOR_HYBRID_STORAGE_LINKED_DATA *PCCTAPCBOR_HYBRID_STORAGE_LINKED_DATA; + +//+------------------------------------------------------------------------------------------ +// Authenticator Information for WebAuthNGetAuthenticatorList API +//------------------------------------------------------------------------------------------- + +#define WEBAUTHN_AUTHENTICATOR_DETAILS_OPTIONS_VERSION_1 1 +#define WEBAUTHN_AUTHENTICATOR_DETAILS_OPTIONS_CURRENT_VERSION WEBAUTHN_AUTHENTICATOR_DETAILS_OPTIONS_VERSION_1 + +typedef struct _WEBAUTHN_AUTHENTICATOR_DETAILS_OPTIONS { + // Version of this structure, to allow for modifications in the future. + DWORD dwVersion; + +} WEBAUTHN_AUTHENTICATOR_DETAILS_OPTIONS, *PWEBAUTHN_AUTHENTICATOR_DETAILS_OPTIONS; +typedef const WEBAUTHN_AUTHENTICATOR_DETAILS_OPTIONS *PCWEBAUTHN_AUTHENTICATOR_DETAILS_OPTIONS; + +#define WEBAUTHN_AUTHENTICATOR_DETAILS_VERSION_1 1 +#define WEBAUTHN_AUTHENTICATOR_DETAILS_CURRENT_VERSION WEBAUTHN_AUTHENTICATOR_DETAILS_VERSION_1 + +typedef struct _WEBAUTHN_AUTHENTICATOR_DETAILS { + // Version of this structure, to allow for modifications in the future. + DWORD dwVersion; + + // Authenticator ID + DWORD cbAuthenticatorId; + _Field_size_bytes_(cbAuthenticatorId) + PBYTE pbAuthenticatorId; + + // Authenticator Name + PCWSTR pwszAuthenticatorName; + + // Authenticator logo (expected to be in SVG format) + DWORD cbAuthenticatorLogo; + _Field_size_bytes_(cbAuthenticatorLogo) + PBYTE pbAuthenticatorLogo; + + // Is the authenticator currently locked? When locked, this authenticator's credentials + // might not be present or updated in WebAuthNGetPlatformCredentialList. + BOOL bLocked; + +} WEBAUTHN_AUTHENTICATOR_DETAILS, *PWEBAUTHN_AUTHENTICATOR_DETAILS; +typedef const WEBAUTHN_AUTHENTICATOR_DETAILS *PCWEBAUTHN_AUTHENTICATOR_DETAILS; + +typedef struct _WEBAUTHN_AUTHENTICATOR_DETAILS_LIST { + // Authenticator Details + DWORD cAuthenticatorDetails; + _Field_size_(cAuthenticatorDetails) + PWEBAUTHN_AUTHENTICATOR_DETAILS *ppAuthenticatorDetails; + +} WEBAUTHN_AUTHENTICATOR_DETAILS_LIST, *PWEBAUTHN_AUTHENTICATOR_DETAILS_LIST; +typedef const WEBAUTHN_AUTHENTICATOR_DETAILS_LIST *PCWEBAUTHN_AUTHENTICATOR_DETAILS_LIST; + +//+------------------------------------------------------------------------------------------ +// Credential Information for WebAuthNGetPlatformCredentialList API +//------------------------------------------------------------------------------------------- + +#define WEBAUTHN_CREDENTIAL_DETAILS_VERSION_1 1 +#define WEBAUTHN_CREDENTIAL_DETAILS_VERSION_2 2 +#define WEBAUTHN_CREDENTIAL_DETAILS_VERSION_3 3 +#define WEBAUTHN_CREDENTIAL_DETAILS_VERSION_4 4 +#define WEBAUTHN_CREDENTIAL_DETAILS_CURRENT_VERSION WEBAUTHN_CREDENTIAL_DETAILS_VERSION_4 + +typedef struct _WEBAUTHN_CREDENTIAL_DETAILS { + // Version of this structure, to allow for modifications in the future. + DWORD dwVersion; + + // Size of pbCredentialID. + DWORD cbCredentialID; + _Field_size_bytes_(cbCredentialID) + PBYTE pbCredentialID; + + // RP Info + PWEBAUTHN_RP_ENTITY_INFORMATION pRpInformation; + + // User Info + PWEBAUTHN_USER_ENTITY_INFORMATION pUserInformation; + + // Removable or not. + BOOL bRemovable; + + // + // The following fields have been added in WEBAUTHN_CREDENTIAL_DETAILS_VERSION_2 + // + + // Backed Up or not. + BOOL bBackedUp; + + // + // The following fields have been added in WEBAUTHN_CREDENTIAL_DETAILS_VERSION_3 + // + PCWSTR pwszAuthenticatorName; + + // The logo is expected to be in the svg format + DWORD cbAuthenticatorLogo; + _Field_size_bytes_(cbAuthenticatorLogo) + PBYTE pbAuthenticatorLogo; + + // ThirdPartyPayment Credential or not. + BOOL bThirdPartyPayment; + + // + // The following fields have been added in WEBAUTHN_CREDENTIAL_DETAILS_VERSION_4 + // + + // Applicable Transports + DWORD dwTransports; + +} WEBAUTHN_CREDENTIAL_DETAILS, *PWEBAUTHN_CREDENTIAL_DETAILS; +typedef const WEBAUTHN_CREDENTIAL_DETAILS *PCWEBAUTHN_CREDENTIAL_DETAILS; + +typedef struct _WEBAUTHN_CREDENTIAL_DETAILS_LIST { + DWORD cCredentialDetails; + _Field_size_(cCredentialDetails) + PWEBAUTHN_CREDENTIAL_DETAILS *ppCredentialDetails; +} WEBAUTHN_CREDENTIAL_DETAILS_LIST, *PWEBAUTHN_CREDENTIAL_DETAILS_LIST; +typedef const WEBAUTHN_CREDENTIAL_DETAILS_LIST *PCWEBAUTHN_CREDENTIAL_DETAILS_LIST; + +#define WEBAUTHN_GET_CREDENTIALS_OPTIONS_VERSION_1 1 +#define WEBAUTHN_GET_CREDENTIALS_OPTIONS_CURRENT_VERSION WEBAUTHN_GET_CREDENTIALS_OPTIONS_VERSION_1 + +typedef struct _WEBAUTHN_GET_CREDENTIALS_OPTIONS { + // Version of this structure, to allow for modifications in the future. + DWORD dwVersion; + + // Optional. + LPCWSTR pwszRpId; + + // Optional. BrowserInPrivate Mode. Defaulting to FALSE. + BOOL bBrowserInPrivateMode; +} WEBAUTHN_GET_CREDENTIALS_OPTIONS, *PWEBAUTHN_GET_CREDENTIALS_OPTIONS; +typedef const WEBAUTHN_GET_CREDENTIALS_OPTIONS *PCWEBAUTHN_GET_CREDENTIALS_OPTIONS; + +//+------------------------------------------------------------------------------------------ +// PRF values. +//------------------------------------------------------------------------------------------- + +#define WEBAUTHN_CTAP_ONE_HMAC_SECRET_LENGTH 32 + +// SALT values below by default are converted into RAW Hmac-Secret values as per PRF extension. +// - SHA-256(UTF8Encode("WebAuthn PRF") || 0x00 || Value) +// +// Set WEBAUTHN_AUTHENTICATOR_HMAC_SECRET_VALUES_FLAG in dwFlags in WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS, +// if caller wants to provide RAW Hmac-Secret SALT values directly. In that case, +// values if provided MUST be of WEBAUTHN_CTAP_ONE_HMAC_SECRET_LENGTH size. + +typedef struct _WEBAUTHN_HMAC_SECRET_SALT { + // Size of pbFirst. + DWORD cbFirst; + _Field_size_bytes_(cbFirst) + PBYTE pbFirst; // Required + + // Size of pbSecond. + DWORD cbSecond; + _Field_size_bytes_(cbSecond) + PBYTE pbSecond; +} WEBAUTHN_HMAC_SECRET_SALT, *PWEBAUTHN_HMAC_SECRET_SALT; +typedef const WEBAUTHN_HMAC_SECRET_SALT *PCWEBAUTHN_HMAC_SECRET_SALT; + +typedef struct _WEBAUTHN_CRED_WITH_HMAC_SECRET_SALT { + // Size of pbCredID. + DWORD cbCredID; + _Field_size_bytes_(cbCredID) + PBYTE pbCredID; // Required + + // PRF Values for above credential + PWEBAUTHN_HMAC_SECRET_SALT pHmacSecretSalt; // Required +} WEBAUTHN_CRED_WITH_HMAC_SECRET_SALT, *PWEBAUTHN_CRED_WITH_HMAC_SECRET_SALT; +typedef const WEBAUTHN_CRED_WITH_HMAC_SECRET_SALT *PCWEBAUTHN_CRED_WITH_HMAC_SECRET_SALT; + +typedef struct _WEBAUTHN_HMAC_SECRET_SALT_VALUES { + PWEBAUTHN_HMAC_SECRET_SALT pGlobalHmacSalt; + + DWORD cCredWithHmacSecretSaltList; + _Field_size_(cCredWithHmacSecretSaltList) + PWEBAUTHN_CRED_WITH_HMAC_SECRET_SALT pCredWithHmacSecretSaltList; +} WEBAUTHN_HMAC_SECRET_SALT_VALUES, *PWEBAUTHN_HMAC_SECRET_SALT_VALUES; +typedef const WEBAUTHN_HMAC_SECRET_SALT_VALUES *PCWEBAUTHN_HMAC_SECRET_SALT_VALUES; + +//+------------------------------------------------------------------------------------------ +// Hmac-Secret extension +//------------------------------------------------------------------------------------------- + +#define WEBAUTHN_EXTENSIONS_IDENTIFIER_HMAC_SECRET L"hmac-secret" +// Below type definitions is for WEBAUTHN_EXTENSIONS_IDENTIFIER_HMAC_SECRET +// MakeCredential Input Type: BOOL. +// - pvExtension must point to a BOOL with the value TRUE. +// - cbExtension must contain the sizeof(BOOL). +// MakeCredential Output Type: BOOL. +// - pvExtension will point to a BOOL with the value TRUE if credential +// was successfully created with HMAC_SECRET. +// - cbExtension will contain the sizeof(BOOL). +// GetAssertion Input Type: Not Supported +// GetAssertion Output Type: Not Supported + +//+------------------------------------------------------------------------------------------ +// credProtect extension +//------------------------------------------------------------------------------------------- + +#define WEBAUTHN_USER_VERIFICATION_ANY 0 +#define WEBAUTHN_USER_VERIFICATION_OPTIONAL 1 +#define WEBAUTHN_USER_VERIFICATION_OPTIONAL_WITH_CREDENTIAL_ID_LIST 2 +#define WEBAUTHN_USER_VERIFICATION_REQUIRED 3 + +typedef struct _WEBAUTHN_CRED_PROTECT_EXTENSION_IN { + // One of the above WEBAUTHN_USER_VERIFICATION_* values + DWORD dwCredProtect; + // Set the following to TRUE to require authenticator support for the credProtect extension + BOOL bRequireCredProtect; +} WEBAUTHN_CRED_PROTECT_EXTENSION_IN, *PWEBAUTHN_CRED_PROTECT_EXTENSION_IN; +typedef const WEBAUTHN_CRED_PROTECT_EXTENSION_IN *PCWEBAUTHN_CRED_PROTECT_EXTENSION_IN; + + +#define WEBAUTHN_EXTENSIONS_IDENTIFIER_CRED_PROTECT L"credProtect" +// Below type definitions is for WEBAUTHN_EXTENSIONS_IDENTIFIER_CRED_PROTECT +// MakeCredential Input Type: WEBAUTHN_CRED_PROTECT_EXTENSION_IN. +// - pvExtension must point to a WEBAUTHN_CRED_PROTECT_EXTENSION_IN struct +// - cbExtension will contain the sizeof(WEBAUTHN_CRED_PROTECT_EXTENSION_IN). +// MakeCredential Output Type: DWORD. +// - pvExtension will point to a DWORD with one of the above WEBAUTHN_USER_VERIFICATION_* values +// if credential was successfully created with CRED_PROTECT. +// - cbExtension will contain the sizeof(DWORD). +// GetAssertion Input Type: Not Supported +// GetAssertion Output Type: Not Supported + +//+------------------------------------------------------------------------------------------ +// credBlob extension +//------------------------------------------------------------------------------------------- + +typedef struct _WEBAUTHN_CRED_BLOB_EXTENSION { + // Size of pbCredBlob. + DWORD cbCredBlob; + _Field_size_bytes_(cbCredBlob) + PBYTE pbCredBlob; +} WEBAUTHN_CRED_BLOB_EXTENSION, *PWEBAUTHN_CRED_BLOB_EXTENSION; +typedef const WEBAUTHN_CRED_BLOB_EXTENSION *PCWEBAUTHN_CRED_BLOB_EXTENSION; + + +#define WEBAUTHN_EXTENSIONS_IDENTIFIER_CRED_BLOB L"credBlob" +// Below type definitions is for WEBAUTHN_EXTENSIONS_IDENTIFIER_CRED_BLOB +// MakeCredential Input Type: WEBAUTHN_CRED_BLOB_EXTENSION. +// - pvExtension must point to a WEBAUTHN_CRED_BLOB_EXTENSION struct +// - cbExtension must contain the sizeof(WEBAUTHN_CRED_BLOB_EXTENSION). +// MakeCredential Output Type: BOOL. +// - pvExtension will point to a BOOL with the value TRUE if credBlob was successfully created +// - cbExtension will contain the sizeof(BOOL). +// GetAssertion Input Type: BOOL. +// - pvExtension must point to a BOOL with the value TRUE to request the credBlob. +// - cbExtension must contain the sizeof(BOOL). +// GetAssertion Output Type: WEBAUTHN_CRED_BLOB_EXTENSION. +// - pvExtension will point to a WEBAUTHN_CRED_BLOB_EXTENSION struct if the authenticator +// returns the credBlob in the signed extensions +// - cbExtension will contain the sizeof(WEBAUTHN_CRED_BLOB_EXTENSION). + +//+------------------------------------------------------------------------------------------ +// minPinLength extension +//------------------------------------------------------------------------------------------- + +#define WEBAUTHN_EXTENSIONS_IDENTIFIER_MIN_PIN_LENGTH L"minPinLength" +// Below type definitions is for WEBAUTHN_EXTENSIONS_IDENTIFIER_MIN_PIN_LENGTH +// MakeCredential Input Type: BOOL. +// - pvExtension must point to a BOOL with the value TRUE to request the minPinLength. +// - cbExtension must contain the sizeof(BOOL). +// MakeCredential Output Type: DWORD. +// - pvExtension will point to a DWORD with the minimum pin length if returned by the authenticator +// - cbExtension will contain the sizeof(DWORD). +// GetAssertion Input Type: Not Supported +// GetAssertion Output Type: Not Supported + +//+------------------------------------------------------------------------------------------ +// Information about Extensions. +//------------------------------------------------------------------------------------------- +typedef struct _WEBAUTHN_EXTENSION { + LPCWSTR pwszExtensionIdentifier; + DWORD cbExtension; + PVOID pvExtension; +} WEBAUTHN_EXTENSION, *PWEBAUTHN_EXTENSION; +typedef const WEBAUTHN_EXTENSION *PCWEBAUTHN_EXTENSION; + +typedef struct _WEBAUTHN_EXTENSIONS { + DWORD cExtensions; + _Field_size_(cExtensions) + PWEBAUTHN_EXTENSION pExtensions; +} WEBAUTHN_EXTENSIONS, *PWEBAUTHN_EXTENSIONS; +typedef const WEBAUTHN_EXTENSIONS *PCWEBAUTHN_EXTENSIONS; + +//+------------------------------------------------------------------------------------------ +// Options. +//------------------------------------------------------------------------------------------- + +#define WEBAUTHN_AUTHENTICATOR_ATTACHMENT_ANY 0 +#define WEBAUTHN_AUTHENTICATOR_ATTACHMENT_PLATFORM 1 +#define WEBAUTHN_AUTHENTICATOR_ATTACHMENT_CROSS_PLATFORM 2 +#define WEBAUTHN_AUTHENTICATOR_ATTACHMENT_CROSS_PLATFORM_U2F_V2 3 + +#define WEBAUTHN_USER_VERIFICATION_REQUIREMENT_ANY 0 +#define WEBAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED 1 +#define WEBAUTHN_USER_VERIFICATION_REQUIREMENT_PREFERRED 2 +#define WEBAUTHN_USER_VERIFICATION_REQUIREMENT_DISCOURAGED 3 + +#define WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_ANY 0 +#define WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_NONE 1 +#define WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_INDIRECT 2 +#define WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT 3 + +#define WEBAUTHN_ENTERPRISE_ATTESTATION_NONE 0 +#define WEBAUTHN_ENTERPRISE_ATTESTATION_VENDOR_FACILITATED 1 +#define WEBAUTHN_ENTERPRISE_ATTESTATION_PLATFORM_MANAGED 2 + +#define WEBAUTHN_LARGE_BLOB_SUPPORT_NONE 0 +#define WEBAUTHN_LARGE_BLOB_SUPPORT_REQUIRED 1 +#define WEBAUTHN_LARGE_BLOB_SUPPORT_PREFERRED 2 + +#define WEBAUTHN_CREDENTIAL_HINT_SECURITY_KEY L"security-key" +#define WEBAUTHN_CREDENTIAL_HINT_CLIENT_DEVICE L"client-device" +#define WEBAUTHN_CREDENTIAL_HINT_HYBRID L"hybrid" + +#define WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_1 1 +#define WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_2 2 +#define WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_3 3 +#define WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_4 4 +#define WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_5 5 +#define WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_6 6 +#define WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_7 7 +#define WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_8 8 +#define WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_9 9 +#define WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_CURRENT_VERSION WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_9 + +typedef struct _WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS { + // Version of this structure, to allow for modifications in the future. + DWORD dwVersion; + + // Time that the operation is expected to complete within. + // This is used as guidance, and can be overridden by the platform. + DWORD dwTimeoutMilliseconds; + + // Credentials used for exclusion. + WEBAUTHN_CREDENTIALS CredentialList; + + // Optional extensions to parse when performing the operation. + WEBAUTHN_EXTENSIONS Extensions; + + // Optional. Platform vs Cross-Platform Authenticators. + DWORD dwAuthenticatorAttachment; + + // Optional. Require key to be resident or not. Defaulting to FALSE. + BOOL bRequireResidentKey; + + // User Verification Requirement. + DWORD dwUserVerificationRequirement; + + // Attestation Conveyance Preference. + DWORD dwAttestationConveyancePreference; + + // Reserved for future Use + DWORD dwFlags; + + // + // The following fields have been added in WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_2 + // + + // Cancellation Id - Optional - See WebAuthNGetCancellationId + GUID *pCancellationId; + + // + // The following fields have been added in WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_3 + // + + // Exclude Credential List. If present, "CredentialList" will be ignored. + PWEBAUTHN_CREDENTIAL_LIST pExcludeCredentialList; + + // + // The following fields have been added in WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_4 + // + + // Enterprise Attestation + DWORD dwEnterpriseAttestation; + + // Large Blob Support: none, required or preferred + // + // NTE_INVALID_PARAMETER when large blob required or preferred and + // bRequireResidentKey isn't set to TRUE + DWORD dwLargeBlobSupport; + + // Optional. Prefer key to be resident. Defaulting to FALSE. When TRUE, + // overrides the above bRequireResidentKey. + BOOL bPreferResidentKey; + + // + // The following fields have been added in WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_5 + // + + // Optional. BrowserInPrivate Mode. Defaulting to FALSE. + BOOL bBrowserInPrivateMode; + + // + // The following fields have been added in WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_6 + // + + // Enable PRF + BOOL bEnablePrf; + + // + // The following fields have been added in WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_7 + // + + // Deprecated + // Optional. Linked Device Connection Info. + PCTAPCBOR_HYBRID_STORAGE_LINKED_DATA pLinkedDevice; + + // Size of pbJsonExt + DWORD cbJsonExt; + _Field_size_bytes_(cbJsonExt) + PBYTE pbJsonExt; + + // + // The following fields have been added in WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_8 + // + + // PRF extension "eval" values which will be converted into HMAC-SECRET values according to WebAuthn Spec. + // Set WEBAUTHN_AUTHENTICATOR_HMAC_SECRET_VALUES_FLAG in dwFlags above, if caller wants to provide RAW Hmac-Secret SALT values directly. + // In that case, values provided MUST be of WEBAUTHN_CTAP_ONE_HMAC_SECRET_LENGTH size. + PWEBAUTHN_HMAC_SECRET_SALT pPRFGlobalEval; + + // PublicKeyCredentialHints (https://w3c.github.io/webauthn/#enum-hints) + DWORD cCredentialHints; + _Field_size_(cCredentialHints) + LPCWSTR *ppwszCredentialHints; + + // Enable ThirdPartyPayment + BOOL bThirdPartyPayment; + + // + // The following fields have been added in WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_9 + // + + // Web Origin. For Remote Web App scenario. + PCWSTR pwszRemoteWebOrigin; + + // UTF-8 encoded JSON serialization of the PublicKeyCredentialCreationOptions. + DWORD cbPublicKeyCredentialCreationOptionsJSON; + _Field_size_bytes_(cbPublicKeyCredentialCreationOptionsJSON) + PBYTE pbPublicKeyCredentialCreationOptionsJSON; + + // Authenticator ID got from WebAuthNGetAuthenticatorList API. + DWORD cbAuthenticatorId; + _Field_size_bytes_(cbAuthenticatorId) + PBYTE pbAuthenticatorId; + +} WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS, *PWEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS; +typedef const WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS *PCWEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS; + +#define WEBAUTHN_CRED_LARGE_BLOB_OPERATION_NONE 0 +#define WEBAUTHN_CRED_LARGE_BLOB_OPERATION_GET 1 +#define WEBAUTHN_CRED_LARGE_BLOB_OPERATION_SET 2 +#define WEBAUTHN_CRED_LARGE_BLOB_OPERATION_DELETE 3 + +#define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_1 1 +#define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_2 2 +#define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_3 3 +#define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_4 4 +#define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_5 5 +#define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_6 6 +#define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_7 7 +#define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_8 8 +#define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_9 9 +#define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_CURRENT_VERSION WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_9 + +/* + Information about flags. +*/ + +#define WEBAUTHN_AUTHENTICATOR_HMAC_SECRET_VALUES_FLAG 0x00100000 + +typedef struct _WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS { + // Version of this structure, to allow for modifications in the future. + DWORD dwVersion; + + // Time that the operation is expected to complete within. + // This is used as guidance, and can be overridden by the platform. + DWORD dwTimeoutMilliseconds; + + // Allowed Credentials List. + WEBAUTHN_CREDENTIALS CredentialList; + + // Optional extensions to parse when performing the operation. + WEBAUTHN_EXTENSIONS Extensions; + + // Optional. Platform vs Cross-Platform Authenticators. + DWORD dwAuthenticatorAttachment; + + // User Verification Requirement. + DWORD dwUserVerificationRequirement; + + // Flags + DWORD dwFlags; + + // + // The following fields have been added in WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_2 + // + + // Optional identifier for the U2F AppId. Converted to UTF8 before being hashed. Not lower cased. + PCWSTR pwszU2fAppId; + + // If the following is non-NULL, then, set to TRUE if the above pwszU2fAppid was used instead of + // PCWSTR pwszRpId; + BOOL *pbU2fAppId; + + // + // The following fields have been added in WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_3 + // + + // Cancellation Id - Optional - See WebAuthNGetCancellationId + GUID *pCancellationId; + + // + // The following fields have been added in WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_4 + // + + // Allow Credential List. If present, "CredentialList" will be ignored. + PWEBAUTHN_CREDENTIAL_LIST pAllowCredentialList; + + // + // The following fields have been added in WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_5 + // + + DWORD dwCredLargeBlobOperation; + + // Size of pbCredLargeBlob + DWORD cbCredLargeBlob; + _Field_size_bytes_(cbCredLargeBlob) + PBYTE pbCredLargeBlob; + + // + // The following fields have been added in WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_6 + // + + // PRF values which will be converted into HMAC-SECRET values according to WebAuthn Spec. + PWEBAUTHN_HMAC_SECRET_SALT_VALUES pHmacSecretSaltValues; + + // Optional. BrowserInPrivate Mode. Defaulting to FALSE. + BOOL bBrowserInPrivateMode; + + // + // The following fields have been added in WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_7 + // + + // Deprecated + // Optional. Linked Device Connection Info. + PCTAPCBOR_HYBRID_STORAGE_LINKED_DATA pLinkedDevice; + + // Optional. Allowlist MUST contain 1 credential applicable for Hybrid transport. + BOOL bAutoFill; + + // Size of pbJsonExt + DWORD cbJsonExt; + _Field_size_bytes_(cbJsonExt) + PBYTE pbJsonExt; + + // + // The following fields have been added in WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_8 + // + + // PublicKeyCredentialHints (https://w3c.github.io/webauthn/#enum-hints) + DWORD cCredentialHints; + _Field_size_(cCredentialHints) + LPCWSTR *ppwszCredentialHints; + + // + // The following fields have been added in WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_9 + // + + // Web Origin. For Remote Web App scenario. + PCWSTR pwszRemoteWebOrigin; + + // UTF-8 encoded JSON serialization of the PublicKeyCredentialRequestOptions. + DWORD cbPublicKeyCredentialRequestOptionsJSON; + _Field_size_bytes_(cbPublicKeyCredentialRequestOptionsJSON) + PBYTE pbPublicKeyCredentialRequestOptionsJSON; + + // Authenticator ID got from WebAuthNGetAuthenticatorList API. + DWORD cbAuthenticatorId; + _Field_size_bytes_(cbAuthenticatorId) + PBYTE pbAuthenticatorId; + +} WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS, *PWEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS; +typedef const WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS *PCWEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS; + + +//+------------------------------------------------------------------------------------------ +// Attestation Info. +// +//------------------------------------------------------------------------------------------- +#define WEBAUTHN_ATTESTATION_DECODE_NONE 0 +#define WEBAUTHN_ATTESTATION_DECODE_COMMON 1 +// WEBAUTHN_ATTESTATION_DECODE_COMMON supports format types +// L"packed" +// L"fido-u2f" + +#define WEBAUTHN_ATTESTATION_VER_TPM_2_0 L"2.0" + +typedef struct _WEBAUTHN_X5C { + // Length of X.509 encoded certificate + DWORD cbData; + // X.509 encoded certificate bytes + _Field_size_bytes_(cbData) + PBYTE pbData; +} WEBAUTHN_X5C, *PWEBAUTHN_X5C; + +// Supports either Self or Full Basic Attestation + +// Note, new fields will be added to the following data structure to +// support additional attestation format types, such as, TPM. +// When fields are added, the dwVersion will be incremented. +// +// Therefore, your code must make the following check: +// "if (dwVersion >= WEBAUTHN_COMMON_ATTESTATION_CURRENT_VERSION)" + +#define WEBAUTHN_COMMON_ATTESTATION_CURRENT_VERSION 1 + +typedef struct _WEBAUTHN_COMMON_ATTESTATION { + // Version of this structure, to allow for modifications in the future. + DWORD dwVersion; + + // Hash and Padding Algorithm + // + // The following won't be set for "fido-u2f" which assumes "ES256". + PCWSTR pwszAlg; + LONG lAlg; // COSE algorithm + + // Signature that was generated for this attestation. + DWORD cbSignature; + _Field_size_bytes_(cbSignature) + PBYTE pbSignature; + + // Following is set for Full Basic Attestation. If not, set then, this is Self Attestation. + // Array of X.509 DER encoded certificates. The first certificate is the signer, leaf certificate. + DWORD cX5c; + _Field_size_(cX5c) + PWEBAUTHN_X5C pX5c; + + // Following are also set for tpm + PCWSTR pwszVer; // L"2.0" + DWORD cbCertInfo; + _Field_size_bytes_(cbCertInfo) + PBYTE pbCertInfo; + DWORD cbPubArea; + _Field_size_bytes_(cbPubArea) + PBYTE pbPubArea; +} WEBAUTHN_COMMON_ATTESTATION, *PWEBAUTHN_COMMON_ATTESTATION; +typedef const WEBAUTHN_COMMON_ATTESTATION *PCWEBAUTHN_COMMON_ATTESTATION; + +#define WEBAUTHN_ATTESTATION_TYPE_PACKED L"packed" +#define WEBAUTHN_ATTESTATION_TYPE_U2F L"fido-u2f" +#define WEBAUTHN_ATTESTATION_TYPE_TPM L"tpm" +#define WEBAUTHN_ATTESTATION_TYPE_NONE L"none" + +#define WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_1 1 +#define WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_2 2 +#define WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_3 3 +#define WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_4 4 +#define WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_5 5 +#define WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_6 6 +#define WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_7 7 +#define WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_8 8 +#define WEBAUTHN_CREDENTIAL_ATTESTATION_CURRENT_VERSION WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_8 + +typedef struct _WEBAUTHN_CREDENTIAL_ATTESTATION { + // Version of this structure, to allow for modifications in the future. + DWORD dwVersion; + + // Attestation format type + PCWSTR pwszFormatType; + + // Size of cbAuthenticatorData. + DWORD cbAuthenticatorData; + // Authenticator data that was created for this credential. + _Field_size_bytes_(cbAuthenticatorData) + PBYTE pbAuthenticatorData; + + // Size of CBOR encoded attestation information + //0 => encoded as CBOR null value. + DWORD cbAttestation; + //Encoded CBOR attestation information + _Field_size_bytes_(cbAttestation) + PBYTE pbAttestation; + + DWORD dwAttestationDecodeType; + // Following depends on the dwAttestationDecodeType + // WEBAUTHN_ATTESTATION_DECODE_NONE + // NULL - not able to decode the CBOR attestation information + // WEBAUTHN_ATTESTATION_DECODE_COMMON + // PWEBAUTHN_COMMON_ATTESTATION; + PVOID pvAttestationDecode; + + // The CBOR encoded Attestation Object to be returned to the RP. + DWORD cbAttestationObject; + _Field_size_bytes_(cbAttestationObject) + PBYTE pbAttestationObject; + + // The CredentialId bytes extracted from the Authenticator Data. + // Used by Edge to return to the RP. + DWORD cbCredentialId; + _Field_size_bytes_(cbCredentialId) + PBYTE pbCredentialId; + + // + // Following fields have been added in WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_2 + // + + WEBAUTHN_EXTENSIONS Extensions; + + // + // Following fields have been added in WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_3 + // + + // One of the WEBAUTHN_CTAP_TRANSPORT_* bits will be set corresponding to + // the transport that was used. + DWORD dwUsedTransport; + + // + // Following fields have been added in WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_4 + // + + BOOL bEpAtt; + BOOL bLargeBlobSupported; + BOOL bResidentKey; + + // + // Following fields have been added in WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_5 + // + + BOOL bPrfEnabled; + + // + // Following fields have been added in WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_6 + // + + DWORD cbUnsignedExtensionOutputs; + _Field_size_bytes_(cbUnsignedExtensionOutputs) + PBYTE pbUnsignedExtensionOutputs; + + // + // Following fields have been added in WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_7 + // + + PWEBAUTHN_HMAC_SECRET_SALT pHmacSecret; + + // ThirdPartyPayment Credential or not. + BOOL bThirdPartyPayment; + + // + // Following fields have been added in WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_8 + // + + // Multiple WEBAUTHN_CTAP_TRANSPORT_* bits will be set corresponding to + // the transports that are supported. + DWORD dwTransports; + + // UTF-8 encoded JSON serialization of the client data. + DWORD cbClientDataJSON; + _Field_size_bytes_(cbClientDataJSON) + PBYTE pbClientDataJSON; + + // UTF-8 encoded JSON serialization of the RegistrationResponse. + DWORD cbRegistrationResponseJSON; + _Field_size_bytes_(cbRegistrationResponseJSON) + PBYTE pbRegistrationResponseJSON; + +} WEBAUTHN_CREDENTIAL_ATTESTATION, *PWEBAUTHN_CREDENTIAL_ATTESTATION; +typedef const WEBAUTHN_CREDENTIAL_ATTESTATION *PCWEBAUTHN_CREDENTIAL_ATTESTATION; + + +//+------------------------------------------------------------------------------------------ +// authenticatorGetAssertion output. +//------------------------------------------------------------------------------------------- + +#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_NONE 0 +#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_SUCCESS 1 +#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_NOT_SUPPORTED 2 +#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_INVALID_DATA 3 +#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_INVALID_PARAMETER 4 +#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_NOT_FOUND 5 +#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_MULTIPLE_CREDENTIALS 6 +#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_LACK_OF_SPACE 7 +#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_PLATFORM_ERROR 8 +#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_AUTHENTICATOR_ERROR 9 + +#define WEBAUTHN_ASSERTION_VERSION_1 1 +#define WEBAUTHN_ASSERTION_VERSION_2 2 +#define WEBAUTHN_ASSERTION_VERSION_3 3 +#define WEBAUTHN_ASSERTION_VERSION_4 4 +#define WEBAUTHN_ASSERTION_VERSION_5 5 +#define WEBAUTHN_ASSERTION_VERSION_6 6 +#define WEBAUTHN_ASSERTION_CURRENT_VERSION WEBAUTHN_ASSERTION_VERSION_6 + +typedef struct _WEBAUTHN_ASSERTION { + // Version of this structure, to allow for modifications in the future. + DWORD dwVersion; + + // Size of cbAuthenticatorData. + DWORD cbAuthenticatorData; + // Authenticator data that was created for this assertion. + _Field_size_bytes_(cbAuthenticatorData) + PBYTE pbAuthenticatorData; + + // Size of pbSignature. + DWORD cbSignature; + // Signature that was generated for this assertion. + _Field_size_bytes_(cbSignature) + PBYTE pbSignature; + + // Credential that was used for this assertion. + WEBAUTHN_CREDENTIAL Credential; + + // Size of User Id + DWORD cbUserId; + // UserId + _Field_size_bytes_(cbUserId) + PBYTE pbUserId; + + // + // Following fields have been added in WEBAUTHN_ASSERTION_VERSION_2 + // + + WEBAUTHN_EXTENSIONS Extensions; + + // Size of pbCredLargeBlob + DWORD cbCredLargeBlob; + _Field_size_bytes_(cbCredLargeBlob) + PBYTE pbCredLargeBlob; + + DWORD dwCredLargeBlobStatus; + + // + // Following fields have been added in WEBAUTHN_ASSERTION_VERSION_3 + // + + PWEBAUTHN_HMAC_SECRET_SALT pHmacSecret; + + // + // Following fields have been added in WEBAUTHN_ASSERTION_VERSION_4 + // + + // One of the WEBAUTHN_CTAP_TRANSPORT_* bits will be set corresponding to + // the transport that was used. + DWORD dwUsedTransport; + + // + // Following fields have been added in WEBAUTHN_ASSERTION_VERSION_5 + // + + DWORD cbUnsignedExtensionOutputs; + _Field_size_bytes_(cbUnsignedExtensionOutputs) + PBYTE pbUnsignedExtensionOutputs; + + // + // Following fields have been added in WEBAUTHN_ASSERTION_VERSION_6 + // + + // UTF-8 encoded JSON serialization of the client data. + DWORD cbClientDataJSON; + _Field_size_bytes_(cbClientDataJSON) + PBYTE pbClientDataJSON; + + // UTF-8 encoded JSON serialization of the AuthenticationResponse. + DWORD cbAuthenticationResponseJSON; + _Field_size_bytes_(cbAuthenticationResponseJSON) + PBYTE pbAuthenticationResponseJSON; + +} WEBAUTHN_ASSERTION, *PWEBAUTHN_ASSERTION; +typedef const WEBAUTHN_ASSERTION *PCWEBAUTHN_ASSERTION; + +//+------------------------------------------------------------------------------------------ +// APIs. +//------------------------------------------------------------------------------------------- + +DWORD +WINAPI +WebAuthNGetApiVersionNumber(); + +HRESULT +WINAPI +WebAuthNIsUserVerifyingPlatformAuthenticatorAvailable( + _Out_ BOOL *pbIsUserVerifyingPlatformAuthenticatorAvailable); + + +HRESULT +WINAPI +WebAuthNAuthenticatorMakeCredential( + _In_ HWND hWnd, + _In_ PCWEBAUTHN_RP_ENTITY_INFORMATION pRpInformation, + _In_ PCWEBAUTHN_USER_ENTITY_INFORMATION pUserInformation, + _In_ PCWEBAUTHN_COSE_CREDENTIAL_PARAMETERS pPubKeyCredParams, + _In_ PCWEBAUTHN_CLIENT_DATA pWebAuthNClientData, + _In_opt_ PCWEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS pWebAuthNMakeCredentialOptions, + _Outptr_result_maybenull_ PWEBAUTHN_CREDENTIAL_ATTESTATION *ppWebAuthNCredentialAttestation); + + +HRESULT +WINAPI +WebAuthNAuthenticatorGetAssertion( + _In_ HWND hWnd, + _In_ LPCWSTR pwszRpId, + _In_ PCWEBAUTHN_CLIENT_DATA pWebAuthNClientData, + _In_opt_ PCWEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS pWebAuthNGetAssertionOptions, + _Outptr_result_maybenull_ PWEBAUTHN_ASSERTION *ppWebAuthNAssertion); + +void +WINAPI +WebAuthNFreeCredentialAttestation( + _In_opt_ PWEBAUTHN_CREDENTIAL_ATTESTATION pWebAuthNCredentialAttestation); + +void +WINAPI +WebAuthNFreeAssertion( + _In_ PWEBAUTHN_ASSERTION pWebAuthNAssertion); + +HRESULT +WINAPI +WebAuthNGetCancellationId( + _Out_ GUID* pCancellationId); + +HRESULT +WINAPI +WebAuthNCancelCurrentOperation( + _In_ const GUID* pCancellationId); + +// Returns NTE_NOT_FOUND when credentials are not found. +HRESULT +WINAPI +WebAuthNGetPlatformCredentialList( + _In_ PCWEBAUTHN_GET_CREDENTIALS_OPTIONS pGetCredentialsOptions, + _Outptr_result_maybenull_ PWEBAUTHN_CREDENTIAL_DETAILS_LIST *ppCredentialDetailsList); + +void +WINAPI +WebAuthNFreePlatformCredentialList( + _In_ PWEBAUTHN_CREDENTIAL_DETAILS_LIST pCredentialDetailsList); + +HRESULT +WINAPI +WebAuthNDeletePlatformCredential( + _In_ DWORD cbCredentialId, + _In_reads_bytes_(cbCredentialId) const BYTE *pbCredentialId + ); + +// Returns NTE_NOT_FOUND when authenticator details are not found. +HRESULT +WINAPI +WebAuthNGetAuthenticatorList( + _In_opt_ PCWEBAUTHN_AUTHENTICATOR_DETAILS_OPTIONS pWebAuthNGetAuthenticatorListOptions, + _Outptr_result_maybenull_ PWEBAUTHN_AUTHENTICATOR_DETAILS_LIST* ppAuthenticatorDetailsList); + +void +WINAPI +WebAuthNFreeAuthenticatorList( + _In_ PWEBAUTHN_AUTHENTICATOR_DETAILS_LIST pAuthenticatorDetailsList); + +// +// Returns the following Error Names: +// L"Success" - S_OK +// L"InvalidStateError" - NTE_EXISTS +// L"ConstraintError" - HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), +// NTE_NOT_SUPPORTED, +// NTE_TOKEN_KEYSET_STORAGE_FULL +// L"NotSupportedError" - NTE_INVALID_PARAMETER +// L"NotAllowedError" - NTE_DEVICE_NOT_FOUND, +// NTE_NOT_FOUND, +// HRESULT_FROM_WIN32(ERROR_CANCELLED), +// NTE_USER_CANCELLED, +// HRESULT_FROM_WIN32(ERROR_TIMEOUT) +// L"UnknownError" - All other hr values +// +PCWSTR +WINAPI +WebAuthNGetErrorName( + _In_ HRESULT hr); + +HRESULT +WINAPI +WebAuthNGetW3CExceptionDOMError( + _In_ HRESULT hr); + + +#ifdef __cplusplus +} // Balance extern "C" above +#endif + +#endif // WINAPI_FAMILY_PARTITION +#pragma endregion + +#endif // __WEBAUTHN_H_ diff --git a/apps/desktop/desktop_native/windows_plugin_authenticator/include/webauthnplugin.h b/apps/desktop/desktop_native/windows_plugin_authenticator/include/webauthnplugin.h new file mode 100644 index 00000000000..bffd2049187 --- /dev/null +++ b/apps/desktop/desktop_native/windows_plugin_authenticator/include/webauthnplugin.h @@ -0,0 +1,588 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include + +#pragma region Desktop Family or OneCore Family +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM) + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef WINAPI +#define WINAPI __stdcall +#endif + +#ifndef INITGUID +#define INITGUID +#include +#undef INITGUID +#else +#include +#endif + +//+------------------------------------------------------------------------------------------ +// APIs. +//------------------------------------------------------------------------------------------- + +typedef enum _PLUGIN_AUTHENTICATOR_STATE +{ + AuthenticatorState_Disabled = 0, + AuthenticatorState_Enabled +} AUTHENTICATOR_STATE; + +HRESULT +WINAPI +WebAuthNPluginGetAuthenticatorState( + _In_ REFCLSID rclsid, + _Out_ AUTHENTICATOR_STATE* pluginAuthenticatorState +); + +// +// Plugin Authenticator API: WebAuthNAddPluginAuthenticator: Add Plugin Authenticator +// + +typedef struct _WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS { + // Authenticator Name + LPCWSTR pwszAuthenticatorName; + + // Plugin COM ClsId + REFCLSID rclsid; + + // Plugin RPID (Optional. Required for a nested WebAuthN call originating from a plugin) + LPCWSTR pwszPluginRpId; + + // Plugin Authenticator Logo for the Light themes. base64 encoded SVG 1.1 (Optional) + LPCWSTR pwszLightThemeLogoSvg; + + // Plugin Authenticator Logo for the Dark themes. base64 encoded SVG 1.1 (Optional) + LPCWSTR pwszDarkThemeLogoSvg; + + // CTAP CBOR encoded authenticatorGetInfo + DWORD cbAuthenticatorInfo; + _Field_size_bytes_(cbAuthenticatorInfo) + const BYTE* pbAuthenticatorInfo; + + // List of supported RP IDs (Relying Party IDs). Should be 0/nullptr if all RPs are supported. + DWORD cSupportedRpIds; + const LPCWSTR* ppwszSupportedRpIds; + +} WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS, *PWEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS; +typedef const WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS *PCWEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS; + +typedef struct _WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_RESPONSE { + // Plugin operation signing Public Key - Used to sign the request in PCWEBAUTHN_PLUGIN_OPERATION_REQUEST. Refer pluginauthenticator.h. + DWORD cbOpSignPubKey; + _Field_size_bytes_(cbOpSignPubKey) + PBYTE pbOpSignPubKey; + +} WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_RESPONSE, *PWEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_RESPONSE; +typedef const WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_RESPONSE *PCWEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_RESPONSE; + +HRESULT +WINAPI +WebAuthNPluginAddAuthenticator( + _In_ PCWEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS pPluginAddAuthenticatorOptions, + _Outptr_result_maybenull_ PWEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_RESPONSE* ppPluginAddAuthenticatorResponse); + +void +WINAPI +WebAuthNPluginFreeAddAuthenticatorResponse( + _In_opt_ PWEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_RESPONSE pPluginAddAuthenticatorResponse); + +// +// Plugin Authenticator API: WebAuthNRemovePluginAuthenticator: Remove Plugin Authenticator +// + +HRESULT +WINAPI +WebAuthNPluginRemoveAuthenticator( + _In_ REFCLSID rclsid); + +// +// Plugin Authenticator API: WebAuthNPluginAuthenticatorUpdateDetails: Update Credential Metadata for Browser AutoFill Scenarios +// + +typedef struct _WEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS { + // Authenticator Name (Optional) + LPCWSTR pwszAuthenticatorName; + + // Plugin COM ClsId + REFCLSID rclsid; + + // New Plugin COM ClsId (Optional) + REFCLSID rclsidNew; + + // Plugin Authenticator Logo for the Light themes. base64 encoded SVG 1.1 (Optional) + LPCWSTR pwszLightThemeLogoSvg; + + // Plugin Authenticator Logo for the Dark themes. base64 encoded SVG 1.1 (Optional) + LPCWSTR pwszDarkThemeLogoSvg; + + // CTAP CBOR encoded authenticatorGetInfo + DWORD cbAuthenticatorInfo; + _Field_size_bytes_(cbAuthenticatorInfo) + const BYTE* pbAuthenticatorInfo; + + // List of supported RP IDs (Relying Party IDs). Should be 0/nullptr if all RPs are supported. + DWORD cSupportedRpIds; + const LPCWSTR* ppwszSupportedRpIds; + +} WEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS, *PWEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS; +typedef const WEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS *PCWEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS; + +HRESULT +WINAPI +WebAuthNPluginUpdateAuthenticatorDetails( + _In_ PCWEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS pPluginUpdateAuthenticatorDetails); + +// +// Plugin Authenticator API: WebAuthNPluginAuthenticatorAddCredentials: Add Credential Metadata for Browser AutoFill Scenarios +// + +typedef struct _WEBAUTHN_PLUGIN_CREDENTIAL_DETAILS { + // Size of pbCredentialId. + DWORD cbCredentialId; + + // Credential Identifier bytes. This field is required. + _Field_size_bytes_(cbCredentialId) + const BYTE* pbCredentialId; + + // Identifier for the RP. This field is required. + LPCWSTR pwszRpId; + + // Contains the friendly name of the Relying Party, such as "Acme Corporation", "Widgets Inc" or "Awesome Site". + // This field is required. + LPCWSTR pwszRpName; + + // Identifier for the User. This field is required. + DWORD cbUserId; + + // User Identifier bytes. This field is required. + _Field_size_bytes_(cbUserId) + const BYTE* pbUserId; + + // Contains a detailed name for this account, such as "john.p.smith@example.com". + LPCWSTR pwszUserName; + + // For User: Contains the friendly name associated with the user account such as "John P. Smith". + LPCWSTR pwszUserDisplayName; + +} WEBAUTHN_PLUGIN_CREDENTIAL_DETAILS, *PWEBAUTHN_PLUGIN_CREDENTIAL_DETAILS; +typedef const WEBAUTHN_PLUGIN_CREDENTIAL_DETAILS *PCWEBAUTHN_PLUGIN_CREDENTIAL_DETAILS; + +HRESULT +WINAPI +WebAuthNPluginAuthenticatorAddCredentials( + _In_ REFCLSID rclsid, + _In_ DWORD cCredentialDetails, + _In_reads_(cCredentialDetails) PCWEBAUTHN_PLUGIN_CREDENTIAL_DETAILS pCredentialDetails); + +// +// Plugin Authenticator API: WebAuthNPluginAuthenticatorRemoveCredentials: Remove Credential Metadata for Browser AutoFill Scenarios +// + +HRESULT +WINAPI +WebAuthNPluginAuthenticatorRemoveCredentials( + _In_ REFCLSID rclsid, + _In_ DWORD cCredentialDetails, + _In_reads_(cCredentialDetails) PCWEBAUTHN_PLUGIN_CREDENTIAL_DETAILS pCredentialDetails); + +// +// Plugin Authenticator API: WebAuthNPluginAuthenticatorRemoveCredentials: Remove All Credential Metadata for Browser AutoFill Scenarios +// + +HRESULT +WINAPI +WebAuthNPluginAuthenticatorRemoveAllCredentials( + _In_ REFCLSID rclsid); + +// +// Plugin Authenticator API: WebAuthNPluginAuthenticatorGetAllCredentials: Get All Credential Metadata cached for Browser AutoFill Scenarios +// + +HRESULT +WINAPI +WebAuthNPluginAuthenticatorGetAllCredentials( + _In_ REFCLSID rclsid, + _Out_ DWORD* pcCredentialDetails, + _Outptr_result_buffer_maybenull_(*pcCredentialDetails) PWEBAUTHN_PLUGIN_CREDENTIAL_DETAILS* ppCredentialDetailsArray); + +// +// Plugin Authenticator API: WebAuthNPluginAuthenticatorFreeCredentialDetailsList: Free Credential Metadata cached for Browser AutoFill Scenarios +// + +void +WINAPI +WebAuthNPluginAuthenticatorFreeCredentialDetailsArray( + _In_ DWORD cCredentialDetails, + _In_reads_(cCredentialDetails) PWEBAUTHN_PLUGIN_CREDENTIAL_DETAILS pCredentialDetailsArray); + +// +// Hello UV API for Plugin: WebAuthNPluginPerformUv: Perform Hello UV related operations +// + +typedef enum _WEBAUTHN_PLUGIN_PERFORM_UV_OPERATION_TYPE +{ + PerformUserVerification = 1, + GetUserVerificationCount, + GetPublicKey +} WEBAUTHN_PLUGIN_PERFORM_UV_OPERATION_TYPE; + +typedef struct _WEBAUTHN_PLUGIN_USER_VERIFICATION_REQUEST { + + // Windows handle of the top-level window displayed by the plugin and currently is in foreground as part of the ongoing webauthn operation. + HWND hwnd; + + // The webauthn transaction id from the WEBAUTHN_PLUGIN_OPERATION_REQUEST + REFGUID rguidTransactionId; + + // The username attached to the credential that is in use for this webauthn operation + LPCWSTR pwszUsername; + + // A text hint displayed on the windows hello prompt + LPCWSTR pwszDisplayHint; +} WEBAUTHN_PLUGIN_USER_VERIFICATION_REQUEST, *PWEBAUTHN_PLUGIN_USER_VERIFICATION_REQUEST; +typedef const WEBAUTHN_PLUGIN_USER_VERIFICATION_REQUEST *PCWEBAUTHN_PLUGIN_USER_VERIFICATION_REQUEST; + +HRESULT +WINAPI +WebAuthNPluginPerformUserVerification( + _In_ PCWEBAUTHN_PLUGIN_USER_VERIFICATION_REQUEST pPluginUserVerification, + _Out_ DWORD* pcbResponse, + _Outptr_result_bytebuffer_maybenull_(*pcbResponse) PBYTE* ppbResponse); + +void +WINAPI +WebAuthNPluginFreeUserVerificationResponse( + _In_opt_ PBYTE ppbResponse); + +HRESULT +WINAPI +WebAuthNPluginGetUserVerificationCount( + _In_ REFCLSID rclsid, + _Out_ DWORD* pdwVerificationCount); + +HRESULT +WINAPI +WebAuthNPluginGetUserVerificationPublicKey( + _In_ REFCLSID rclsid, + _Out_ DWORD* pcbPublicKey, + _Outptr_result_bytebuffer_(*pcbPublicKey) PBYTE* ppbPublicKey); // Free using WebAuthNPluginFreePublicKeyResponse + +HRESULT +WINAPI +WebAuthNPluginGetOperationSigningPublicKey( + _In_ REFCLSID rclsid, + _Out_ DWORD* pcbOpSignPubKey, + _Outptr_result_buffer_maybenull_(*pcbOpSignPubKey) PBYTE* ppbOpSignPubKey); // Free using WebAuthNPluginFreePublicKeyResponse + +void WINAPI WebAuthNPluginFreePublicKeyResponse( + _In_opt_ PBYTE pbOpSignPubKey); + +#define WEBAUTHN_CTAPCBOR_AUTHENTICATOR_OPTIONS_VERSION_1 1 +#define WEBAUTHN_CTAPCBOR_AUTHENTICATOR_OPTIONS_CURRENT_VERSION WEBAUTHN_CTAPCBOR_AUTHENTICATOR_OPTIONS_VERSION_1 +typedef struct _WEBAUTHN_CTAPCBOR_AUTHENTICATOR_OPTIONS { + //Version of this structure, to allow for modifications in the future. + DWORD dwVersion; + + // Following have following values: + // +1 - TRUE + // 0 - Not defined + // -1 - FALSE + //up: "true" | "false" + LONG lUp; + //uv: "true" | "false" + LONG lUv; + //rk: "true" | "false" + LONG lRequireResidentKey; +} WEBAUTHN_CTAPCBOR_AUTHENTICATOR_OPTIONS, *PWEBAUTHN_CTAPCBOR_AUTHENTICATOR_OPTIONS; +typedef const WEBAUTHN_CTAPCBOR_AUTHENTICATOR_OPTIONS *PCWEBAUTHN_CTAPCBOR_AUTHENTICATOR_OPTIONS; + +#define WEBAUTHN_CTAPCBOR_ECC_PUBLIC_KEY_VERSION_1 1 +#define WEBAUTHN_CTAPCBOR_ECC_PUBLIC_KEY_CURRENT_VERSION WEBAUTHN_CTAPCBOR_ECC_PUBLIC_KEY_VERSION_1 +typedef struct _WEBAUTHN_CTAPCBOR_ECC_PUBLIC_KEY { + //Version of this structure, to allow for modifications in the future. + DWORD dwVersion; + + // Key type + LONG lKty; + + // Hash Algorithm: ES256, ES384, ES512 + LONG lAlg; + + // Curve + LONG lCrv; + + //Size of "x" (X Coordinate) + DWORD cbX; + + //"x" (X Coordinate) data. Big Endian. + PBYTE pbX; + + //Size of "y" (Y Coordinate) + DWORD cbY; + + //"y" (Y Coordinate) data. Big Endian. + PBYTE pbY; +} WEBAUTHN_CTAPCBOR_ECC_PUBLIC_KEY, *PWEBAUTHN_CTAPCBOR_ECC_PUBLIC_KEY; +typedef const WEBAUTHN_CTAPCBOR_ECC_PUBLIC_KEY *PCWEBAUTHN_CTAPCBOR_ECC_PUBLIC_KEY; + +#define WEBAUTHN_CTAPCBOR_HMAC_SALT_EXTENSION_VERSION_1 1 +#define WEBAUTHN_CTAPCBOR_HMAC_SALT_EXTENSION_CURRENT_VERSION WEBAUTHN_CTAPCBOR_HMAC_SALT_EXTENSION_VERSION_1 +typedef struct _WEBAUTHN_CTAPCBOR_HMAC_SALT_EXTENSION { + //Version of this structure, to allow for modifications in the future. + DWORD dwVersion; + + // Platform's key agreement public key + PWEBAUTHN_CTAPCBOR_ECC_PUBLIC_KEY pKeyAgreement; + + DWORD cbEncryptedSalt; + PBYTE pbEncryptedSalt; + + DWORD cbSaltAuth; + PBYTE pbSaltAuth; +} WEBAUTHN_CTAPCBOR_HMAC_SALT_EXTENSION, *PWEBAUTHN_CTAPCBOR_HMAC_SALT_EXTENSION; +typedef const WEBAUTHN_CTAPCBOR_HMAC_SALT_EXTENSION *PCWEBAUTHN_CTAPCBOR_HMAC_SALT_EXTENSION; + +#define WEBAUTHN_CTAPCBOR_MAKE_CREDENTIAL_REQUEST_VERSION_1 1 +#define WEBAUTHN_CTAPCBOR_MAKE_CREDENTIAL_REQUEST_CURRENT_VERSION WEBAUTHN_CTAPCBOR_MAKE_CREDENTIAL_REQUEST_VERSION_1 +typedef struct _WEBAUTHN_CTAPCBOR_MAKE_CREDENTIAL_REQUEST { + //Version of this structure, to allow for modifications in the future. + DWORD dwVersion; + + //Input RP ID. Raw UTF8 bytes before conversion. + //These are the bytes to be hashed in the Authenticator Data. + DWORD cbRpId; + PBYTE pbRpId; + + //Client Data Hash + DWORD cbClientDataHash; + PBYTE pbClientDataHash; + + //RP Information + PCWEBAUTHN_RP_ENTITY_INFORMATION pRpInformation; + + //User Information + PCWEBAUTHN_USER_ENTITY_INFORMATION pUserInformation; + + // Crypto Parameters + WEBAUTHN_COSE_CREDENTIAL_PARAMETERS WebAuthNCredentialParameters; + + //Credentials used for exclusion + WEBAUTHN_CREDENTIAL_LIST CredentialList; + + //Optional extensions to parse when performing the operation. + DWORD cbCborExtensionsMap; + PBYTE pbCborExtensionsMap; + + // Authenticator Options (Optional) + PWEBAUTHN_CTAPCBOR_AUTHENTICATOR_OPTIONS pAuthenticatorOptions; + + // Pin Auth (Optional) + BOOL fEmptyPinAuth; // Zero length PinAuth is included in the request + DWORD cbPinAuth; + PBYTE pbPinAuth; + + //"hmac-secret": true extension + LONG lHmacSecretExt; + + // "hmac-secret-mc" extension + PWEBAUTHN_CTAPCBOR_HMAC_SALT_EXTENSION pHmacSecretMcExtension; + + //"prf" extension + LONG lPrfExt; + DWORD cbHmacSecretSaltValues; + PBYTE pbHmacSecretSaltValues; + + //"credProtect" extension. Nonzero if present + DWORD dwCredProtect; + + // Nonzero if present + DWORD dwPinProtocol; + + // Nonzero if present + DWORD dwEnterpriseAttestation; + + //"credBlob" extension. Nonzero if present + DWORD cbCredBlobExt; + PBYTE pbCredBlobExt; + + //"largeBlobKey": true extension + LONG lLargeBlobKeyExt; + + //"largeBlob": extension + DWORD dwLargeBlobSupport; + + //"minPinLength": true extension + LONG lMinPinLengthExt; + + // "json" extension. Nonzero if present + DWORD cbJsonExt; + PBYTE pbJsonExt; +} WEBAUTHN_CTAPCBOR_MAKE_CREDENTIAL_REQUEST, *PWEBAUTHN_CTAPCBOR_MAKE_CREDENTIAL_REQUEST; +typedef const WEBAUTHN_CTAPCBOR_MAKE_CREDENTIAL_REQUEST *PCWEBAUTHN_CTAPCBOR_MAKE_CREDENTIAL_REQUEST; + +_Success_(return == S_OK) +HRESULT +WINAPI +WebAuthNEncodeMakeCredentialResponse( + _In_ PCWEBAUTHN_CREDENTIAL_ATTESTATION pCredentialAttestation, + _Out_ DWORD* pcbResp, + _Outptr_result_buffer_maybenull_(*pcbResp) BYTE** ppbResp + ); + +_Success_(return == S_OK) +HRESULT +WINAPI +WebAuthNDecodeMakeCredentialRequest( + _In_ DWORD cbEncoded, + _In_reads_bytes_(cbEncoded) const BYTE* pbEncoded, + _Outptr_ PWEBAUTHN_CTAPCBOR_MAKE_CREDENTIAL_REQUEST* ppMakeCredentialRequest + ); + +void +WINAPI +WebAuthNFreeDecodedMakeCredentialRequest( + _In_opt_ PWEBAUTHN_CTAPCBOR_MAKE_CREDENTIAL_REQUEST pMakeCredentialRequest + ); + +#define WEBAUTHN_CTAPCBOR_GET_ASSERTION_REQUEST_VERSION_1 1 +#define WEBAUTHN_CTAPCBOR_GET_ASSERTION_REQUEST_CURRENT_VERSION WEBAUTHN_CTAPCBOR_GET_ASSERTION_REQUEST_VERSION_1 +typedef struct _WEBAUTHN_CTAPCBOR_GET_ASSERTION_REQUEST { + //Version of this structure, to allow for modifications in the future. + DWORD dwVersion; + + //RP ID. After UTF8 to Unicode conversion, + PCWSTR pwszRpId; + + //Input RP ID. Raw UTF8 bytes before conversion. + //These are the bytes to be hashed in the Authenticator Data. + DWORD cbRpId; + PBYTE pbRpId; + + //Client Data Hash + DWORD cbClientDataHash; + PBYTE pbClientDataHash; + + //Credentials used for inclusion + WEBAUTHN_CREDENTIAL_LIST CredentialList; + + //Optional extensions to parse when performing the operation. + DWORD cbCborExtensionsMap; + PBYTE pbCborExtensionsMap; + + // Authenticator Options (Optional) + PWEBAUTHN_CTAPCBOR_AUTHENTICATOR_OPTIONS pAuthenticatorOptions; + + // Pin Auth (Optional) + BOOL fEmptyPinAuth; // Zero length PinAuth is included in the request + DWORD cbPinAuth; + PBYTE pbPinAuth; + + // HMAC Salt Extension (Optional) + PWEBAUTHN_CTAPCBOR_HMAC_SALT_EXTENSION pHmacSaltExtension; + + // PRF Extension + DWORD cbHmacSecretSaltValues; + PBYTE pbHmacSecretSaltValues; + + DWORD dwPinProtocol; + + //"credBlob": true extension + LONG lCredBlobExt; + + //"largeBlobKey": true extension + LONG lLargeBlobKeyExt; + + //"largeBlob" extension + DWORD dwCredLargeBlobOperation; + DWORD cbCredLargeBlobCompressed; + PBYTE pbCredLargeBlobCompressed; + DWORD dwCredLargeBlobOriginalSize; + + // "json" extension. Nonzero if present + DWORD cbJsonExt; + PBYTE pbJsonExt; +} WEBAUTHN_CTAPCBOR_GET_ASSERTION_REQUEST, *PWEBAUTHN_CTAPCBOR_GET_ASSERTION_REQUEST; +typedef const WEBAUTHN_CTAPCBOR_GET_ASSERTION_REQUEST *PCWEBAUTHN_CTAPCBOR_GET_ASSERTION_REQUEST; + +_Success_(return == S_OK) +HRESULT +WINAPI +WebAuthNDecodeGetAssertionRequest( + _In_ DWORD cbEncoded, + _In_reads_bytes_(cbEncoded) const BYTE* pbEncoded, + _Outptr_ PWEBAUTHN_CTAPCBOR_GET_ASSERTION_REQUEST* ppGetAssertionRequest + ); + +void +WINAPI +WebAuthNFreeDecodedGetAssertionRequest( + _In_opt_ PWEBAUTHN_CTAPCBOR_GET_ASSERTION_REQUEST pGetAssertionRequest + ); + +typedef struct _WEBAUTHN_CTAPCBOR_GET_ASSERTION_RESPONSE { + // [1] credential (optional) + // [2] authenticatorData + // [3] signature + WEBAUTHN_ASSERTION WebAuthNAssertion; + + // [4] user (optional) + PCWEBAUTHN_USER_ENTITY_INFORMATION pUserInformation; + + // [5] numberOfCredentials (optional) + DWORD dwNumberOfCredentials; + + // [6] userSelected (optional) + LONG lUserSelected; + + // [7] largeBlobKey (optional) + DWORD cbLargeBlobKey; + PBYTE pbLargeBlobKey; + + // [8] unsignedExtensionOutputs + DWORD cbUnsignedExtensionOutputs; + PBYTE pbUnsignedExtensionOutputs; +} WEBAUTHN_CTAPCBOR_GET_ASSERTION_RESPONSE, *PWEBAUTHN_CTAPCBOR_GET_ASSERTION_RESPONSE; +typedef const WEBAUTHN_CTAPCBOR_GET_ASSERTION_RESPONSE *PCWEBAUTHN_CTAPCBOR_GET_ASSERTION_RESPONSE; + +_Success_(return == S_OK) +HRESULT +WINAPI +WebAuthNEncodeGetAssertionResponse( + _In_ PCWEBAUTHN_CTAPCBOR_GET_ASSERTION_RESPONSE pGetAssertionResponse, + _Out_ DWORD* pcbResp, + _Outptr_result_buffer_maybenull_(*pcbResp) BYTE** ppbResp + ); + +typedef void (CALLBACK* WEBAUTHN_PLUGIN_STATUS_CHANGE_CALLBACK )(void* context); + +HRESULT +WINAPI +WebAuthNPluginRegisterStatusChangeCallback( + _In_ WEBAUTHN_PLUGIN_STATUS_CHANGE_CALLBACK callback, + _In_ void* context, + _In_ REFCLSID rclsid, + _Out_ DWORD* pdwRegister + ); + +HRESULT +WINAPI +WebAuthNPluginUnregisterStatusChangeCallback( + _In_ DWORD* pdwRegister + ); + + +#ifdef __cplusplus +} // Balance extern "C" above +#endif + +#endif // WINAPI_FAMILY_PARTITION +#pragma endregion + + diff --git a/apps/desktop/desktop_native/windows_plugin_authenticator/src/assert.rs b/apps/desktop/desktop_native/windows_plugin_authenticator/src/assert.rs index 8973b44a39d..11299c240f3 100644 --- a/apps/desktop/desktop_native/windows_plugin_authenticator/src/assert.rs +++ b/apps/desktop/desktop_native/windows_plugin_authenticator/src/assert.rs @@ -142,10 +142,10 @@ fn send_assertion_request( }; debug_log(&format!( - "Assertion request data - RP ID: {}, Client data hash: {} bytes, Allowed credentials: {}", - request.rpid, - request.client_data_hash.len(), - request.allowed_credentials.len() + "Assertion request data - RP ID: {}, Client data hash: {} bytes, Allowed credentials: {:?}", + passkey_request.rp_id, + passkey_request.client_data_hash.len(), + passkey_request.allowed_credentials, )); debug_log(format!( @@ -219,11 +219,17 @@ unsafe fn create_get_assertion_response( )); } + // [5] numberOfCredentials (optional) + cbor_response.push(( + ciborium::Value::Integer(5.into()), + ciborium::Value::Integer(1.into()), + )); + let cbor_value = ciborium::Value::Map(cbor_response); // Encode to CBOR with error handling let mut cbor_data = Vec::new(); - cbor_data.push(0); // CTAP_STATUS_OK + // cbor_data.push(0x00); // CTAP2_OK if let Err(e) = ciborium::ser::into_writer(&cbor_value, &mut cbor_data) { debug_log(&format!( "ERROR: Failed to encode CBOR assertion response: {:?}", @@ -232,6 +238,11 @@ unsafe fn create_get_assertion_response( return Err(HRESULT(-1)); } + debug_log(&format!( + "Formatted CBOR assertion response: {:?}", + cbor_data + )); + let response_len = cbor_data.len(); // Allocate memory for the response data @@ -357,9 +368,8 @@ pub unsafe fn experimental_plugin_get_assertion( }; debug_log(&format!( - "Get assertion request - RP: {}, Allowed credentials: {}", - rpid, - allowed_credentials.len() + "Get assertion request - RP: {}, Allowed credentials: {:?}", + rpid, allowed_credentials )); // Send assertion request @@ -433,4 +443,31 @@ pub unsafe fn experimental_plugin_get_assertion( } #[cfg(test)] -mod tests {} +mod tests { + use std::ptr::slice_from_raw_parts; + + use super::create_get_assertion_response; + + #[test] + fn test_create_native_assertion_response() { + let credential_id = vec![1, 2, 3, 4]; + let authenticator_data = vec![5, 6, 7, 8]; + let signature = vec![9, 10, 11, 12]; + let user_handle = vec![13, 14, 15, 16]; + let slice = unsafe { + let response = *create_get_assertion_response( + credential_id, + authenticator_data, + signature, + user_handle, + ) + .unwrap(); + &*slice_from_raw_parts( + response.encoded_response_pointer, + response.encoded_response_byte_count as usize, + ) + }; + // CTAP2_OK, Map(5 elements) + assert_eq!([0x00, 0xa5], slice[..2]); + } +} diff --git a/apps/desktop/desktop_native/windows_plugin_authenticator/src/com_provider.rs b/apps/desktop/desktop_native/windows_plugin_authenticator/src/com_provider.rs index 2d6024722d1..370bc3bc503 100644 --- a/apps/desktop/desktop_native/windows_plugin_authenticator/src/com_provider.rs +++ b/apps/desktop/desktop_native/windows_plugin_authenticator/src/com_provider.rs @@ -126,16 +126,16 @@ pub unsafe fn parse_credential_list(credential_list: &WEBAUTHN_CREDENTIAL_LIST) )); continue; } - // Extract credential ID bytes + // For some reason, we're getting hex strings from Windows instead of bytes. let credential_id_slice = std::slice::from_raw_parts(credential.pbId, credential.cbId as usize); - allowed_credentials.push(credential_id_slice.to_vec()); debug_log(&format!( - "Parsed credential {}: {} bytes", - i, credential.cbId + "Parsed credential {}: {} bytes, {:?}", + i, credential.cbId, &credential_id_slice, )); + allowed_credentials.push(credential_id_slice.to_vec()); } debug_log(&format!( diff --git a/apps/desktop/desktop_native/windows_plugin_authenticator/src/com_registration.rs b/apps/desktop/desktop_native/windows_plugin_authenticator/src/com_registration.rs index ed138f80406..63670a63b34 100644 --- a/apps/desktop/desktop_native/windows_plugin_authenticator/src/com_registration.rs +++ b/apps/desktop/desktop_native/windows_plugin_authenticator/src/com_registration.rs @@ -276,27 +276,27 @@ mod tests { // Verify it's a map with expected keys if let Value::Map(map) = decoded.unwrap() { assert!( - map.contains_key(&Value::Integer(1.into())), + map.iter().any(|(k, _)| k == &Value::Integer(1.into())), "Should contain versions (key 1)" ); assert!( - map.contains_key(&Value::Integer(2.into())), + map.iter().any(|(k, _)| k == &Value::Integer(2.into())), "Should contain extensions (key 2)" ); assert!( - map.contains_key(&Value::Integer(3.into())), + map.iter().any(|(k, _)| k == &Value::Integer(3.into())), "Should contain aaguid (key 3)" ); assert!( - map.contains_key(&Value::Integer(4.into())), + map.iter().any(|(k, _)| k == &Value::Integer(4.into())), "Should contain options (key 4)" ); assert!( - map.contains_key(&Value::Integer(9.into())), + map.iter().any(|(k, _)| k == &Value::Integer(9.into())), "Should contain transports (key 9)" ); assert!( - map.contains_key(&Value::Integer(10.into())), + map.iter().any(|(k, _)| k == &Value::Integer(10.into())), "Should contain algorithms (key 10)" ); } else { diff --git a/apps/desktop/desktop_native/windows_plugin_authenticator/src/webauthn.rs b/apps/desktop/desktop_native/windows_plugin_authenticator/src/webauthn.rs index e64242ce6e5..9985d1b6da5 100644 --- a/apps/desktop/desktop_native/windows_plugin_authenticator/src/webauthn.rs +++ b/apps/desktop/desktop_native/windows_plugin_authenticator/src/webauthn.rs @@ -7,18 +7,18 @@ use windows_core::*; -use crate::util::{debug_log, delay_load, WindowsString}; use crate::com_buffer::ComBuffer; +use crate::util::{debug_log, delay_load, WindowsString}; /// Windows WebAuthn Authenticator Options structure /// Header File Name: _EXPERIMENTAL_WEBAUTHN_CTAPCBOR_AUTHENTICATOR_OPTIONS #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ExperimentalWebAuthnCtapCborAuthenticatorOptions { - pub version: u32, // DWORD dwVersion - pub user_presence: i32, // LONG lUp: +1=TRUE, 0=Not defined, -1=FALSE - pub user_verification: i32, // LONG lUv: +1=TRUE, 0=Not defined, -1=FALSE - pub require_resident_key: i32, // LONG lRequireResidentKey: +1=TRUE, 0=Not defined, -1=FALSE + pub version: u32, // DWORD dwVersion + pub user_presence: i32, // LONG lUp: +1=TRUE, 0=Not defined, -1=FALSE + pub user_verification: i32, // LONG lUv: +1=TRUE, 0=Not defined, -1=FALSE + pub require_resident_key: i32, // LONG lRequireResidentKey: +1=TRUE, 0=Not defined, -1=FALSE } /// Used when adding a Windows plugin authenticator (stable API). @@ -27,15 +27,15 @@ pub struct ExperimentalWebAuthnCtapCborAuthenticatorOptions { #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct WebAuthnPluginAddAuthenticatorOptions { - pub authenticator_name: *const u16, // LPCWSTR - pub rclsid: *const GUID, // REFCLSID (changed from string) - pub rpid: *const u16, // LPCWSTR (optional) - pub light_theme_logo_svg: *const u16, // LPCWSTR (optional, base64 SVG) - pub dark_theme_logo_svg: *const u16, // LPCWSTR (optional, base64 SVG) + pub authenticator_name: *const u16, // LPCWSTR + pub rclsid: *const GUID, // REFCLSID (changed from string) + pub rpid: *const u16, // LPCWSTR (optional) + pub light_theme_logo_svg: *const u16, // LPCWSTR (optional, base64 SVG) + pub dark_theme_logo_svg: *const u16, // LPCWSTR (optional, base64 SVG) pub cbor_authenticator_info_byte_count: u32, - pub cbor_authenticator_info: *const u8, // const BYTE* - pub supported_rp_ids_count: u32, // NEW in stable - pub supported_rp_ids: *const *const u16, // NEW in stable: array of LPCWSTR + pub cbor_authenticator_info: *const u8, // const BYTE* + pub supported_rp_ids_count: u32, // NEW in stable + pub supported_rp_ids: *const *const u16, // NEW in stable: array of LPCWSTR } /// Used as a response type when adding a Windows plugin authenticator (stable API). @@ -56,13 +56,13 @@ pub struct WebAuthnPluginAddAuthenticatorResponse { #[derive(Debug, Copy, Clone)] pub struct WebAuthnPluginCredentialDetails { pub credential_id_byte_count: u32, - pub credential_id_pointer: *const u8, // Changed to const in stable - pub rpid: *const u16, // Changed to const (LPCWSTR) - pub rp_friendly_name: *const u16, // Changed to const (LPCWSTR) + pub credential_id_pointer: *const u8, // Changed to const in stable + pub rpid: *const u16, // Changed to const (LPCWSTR) + pub rp_friendly_name: *const u16, // Changed to const (LPCWSTR) pub user_id_byte_count: u32, - pub user_id_pointer: *const u8, // Changed to const - pub user_name: *const u16, // Changed to const (LPCWSTR) - pub user_display_name: *const u16, // Changed to const (LPCWSTR) + pub user_id_pointer: *const u8, // Changed to const + pub user_name: *const u16, // Changed to const (LPCWSTR) + pub user_display_name: *const u16, // Changed to const (LPCWSTR) } // Keep experimental version for internal use @@ -78,7 +78,8 @@ impl WebAuthnPluginCredentialDetails { user_display_name: String, ) -> Self { // Allocate credential_id bytes with COM - let (credential_id_pointer, credential_id_byte_count) = ComBuffer::from_buffer(&credential_id); + let (credential_id_pointer, credential_id_byte_count) = + ComBuffer::from_buffer(&credential_id); // Allocate user_id bytes with COM let (user_id_pointer, user_id_byte_count) = ComBuffer::from_buffer(&user_id); @@ -139,23 +140,25 @@ impl ExperimentalWebAuthnPluginCredentialDetailsList { credentials: Vec, ) -> Self { // Convert credentials to COM-allocated pointers - let credential_pointers: Vec<*mut ExperimentalWebAuthnPluginCredentialDetails> = credentials - .into_iter() - .map(|cred| { - // Use COM allocation for each credential struct - ComBuffer::with_object(cred) - }) - .collect(); + let credential_pointers: Vec<*mut ExperimentalWebAuthnPluginCredentialDetails> = + credentials + .into_iter() + .map(|cred| { + // Use COM allocation for each credential struct + ComBuffer::with_object(cred) + }) + .collect(); let credentials_len = credential_pointers.len(); // Allocate the array of pointers using COM as well let credentials_pointer = if credentials_len > 0 { - let pointer_array_bytes = credential_pointers.len() * std::mem::size_of::<*mut ExperimentalWebAuthnPluginCredentialDetails>(); + let pointer_array_bytes = credential_pointers.len() + * std::mem::size_of::<*mut ExperimentalWebAuthnPluginCredentialDetails>(); let (ptr, _) = ComBuffer::from_buffer(unsafe { std::slice::from_raw_parts( credential_pointers.as_ptr() as *const u8, - pointer_array_bytes + pointer_array_bytes, ) }); ptr as *mut *mut ExperimentalWebAuthnPluginCredentialDetails @@ -177,9 +180,9 @@ impl ExperimentalWebAuthnPluginCredentialDetailsList { // Stable API function signatures - now use REFCLSID and flat arrays pub type WebAuthNPluginAuthenticatorAddCredentialsFnDeclaration = unsafe extern "cdecl" fn( - rclsid: *const GUID, // Changed from string to GUID reference + rclsid: *const GUID, // Changed from string to GUID reference cCredentialDetails: u32, - pCredentialDetails: *const WebAuthnPluginCredentialDetails, // Flat array, not list + pCredentialDetails: *const WebAuthnPluginCredentialDetails, // Flat array, not list ) -> HRESULT; pub type WebAuthNPluginAuthenticatorRemoveCredentialsFnDeclaration = @@ -192,8 +195,8 @@ pub type WebAuthNPluginAuthenticatorRemoveCredentialsFnDeclaration = pub type WebAuthNPluginAuthenticatorGetAllCredentialsFnDeclaration = unsafe extern "cdecl" fn( rclsid: *const GUID, - pcCredentialDetails: *mut u32, // Out param for count - ppCredentialDetailsArray: *mut *mut WebAuthnPluginCredentialDetails, // Out param for array + pcCredentialDetails: *mut u32, // Out param for count + ppCredentialDetailsArray: *mut *mut WebAuthnPluginCredentialDetails, // Out param for array ) -> HRESULT; pub type WebAuthNPluginAuthenticatorFreeCredentialDetailsArrayFnDeclaration = @@ -203,9 +206,7 @@ pub type WebAuthNPluginAuthenticatorFreeCredentialDetailsArrayFnDeclaration = ); pub type WebAuthNPluginAuthenticatorRemoveAllCredentialsFnDeclaration = - unsafe extern "cdecl" fn( - rclsid: *const GUID, - ) -> HRESULT; + unsafe extern "cdecl" fn(rclsid: *const GUID) -> HRESULT; pub fn add_credentials( clsid_guid: GUID, @@ -245,7 +246,7 @@ pub fn add_credentials( debug_log("API call succeeded"); Ok(()) - }, + } None => { debug_log("Failed to load WebAuthNPluginAuthenticatorAddCredentials function from webauthn.dll"); Err(String::from("Error: Can't complete add_credentials(), as the function WebAuthNPluginAuthenticatorAddCredentials can't be loaded.")) @@ -440,9 +441,7 @@ fn free_credential_details_array( } } -pub fn remove_all_credentials( - clsid_guid: GUID, -) -> std::result::Result<(), String> { +pub fn remove_all_credentials(clsid_guid: GUID) -> std::result::Result<(), String> { debug_log("Loading WebAuthNPluginAuthenticatorRemoveAllCredentials function..."); let result = unsafe { @@ -470,7 +469,7 @@ pub fn remove_all_credentials( debug_log("API call succeeded"); Ok(()) - }, + } None => { debug_log("Failed to load WebAuthNPluginAuthenticatorRemoveAllCredentials function from webauthn.dll"); Err(String::from("Error: Can't complete remove_all_credentials(), as the function WebAuthNPluginAuthenticatorRemoveAllCredentials can't be loaded.")) diff --git a/apps/desktop/package.json b/apps/desktop/package.json index c84fd2fba7e..95246b70a6c 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -49,6 +49,7 @@ "pack:mac:masdev": "npm run clean:dist && electron-builder --mac mas-dev --universal -p never", "pack:mac:masdev:with-extension": "npm run clean:dist && npm run build:macos-extension:masdev && electron-builder --mac mas-dev --universal -p never", "pack:win": "npm run clean:dist && electron-builder --win --x64 --arm64 --ia32 -p never -c.win.signtoolOptions.certificateSubjectName=\"8bit Solutions LLC\"", + "pack:win:arm64": "npm run clean:dist && electron-builder --win --arm64 -p never -c.win.signtoolOptions.certificateSubjectName=\"8bit Solutions LLC\"", "pack:win:beta": "npm run clean:dist && electron-builder --config electron-builder.beta.json --win --x64 --arm64 --ia32 -p never -c.win.signtoolOptions.certificateSubjectName=\"8bit Solutions LLC\"", "pack:win:ci": "npm run clean:dist && electron-builder --win --x64 --arm64 --ia32 -p never", "dist:dir": "npm run build && npm run pack:dir", diff --git a/apps/desktop/sign.js b/apps/desktop/sign.js index 6a42666c46f..9fd0c9cd4fb 100644 --- a/apps/desktop/sign.js +++ b/apps/desktop/sign.js @@ -18,5 +18,21 @@ exports.default = async function (configuration) { stdio: "inherit", }, ); + } else if (process.env.ELECTRON_BUILDER_SIGN_CERT) { + const certFile = process.env.ELECTRON_BUILDER_SIGN_CERT + const certPw = process.env.ELECTRON_BUILDER_SIGN_CERT_PW + console.log(`[*] Signing file: ${configuration.path} with ${certFile}`); + require("child_process").execSync( + "signtool.exe sign" + + " /fd SHA256" + + " /a" + + ` /f "${certFile}"` + + ` /p "${process.env.ELECTRON_BUILDER_SIGN_CERT_PW}"` + + ` "${configuration.path}"`, + { + stdio: "inherit", + }, + ); } }; + diff --git a/apps/desktop/src/autofill/preload.ts b/apps/desktop/src/autofill/preload.ts index fcb2f646743..dbec1e0f93f 100644 --- a/apps/desktop/src/autofill/preload.ts +++ b/apps/desktop/src/autofill/preload.ts @@ -32,6 +32,7 @@ export default { ) => { const { clientId, sequenceNumber, request } = data; fn(clientId, sequenceNumber, request, (error, response) => { + console.log("autofill.passkeyRegistration IPC response", error, response) if (error) { ipcRenderer.send("autofill.completeError", { clientId, diff --git a/apps/desktop/src/autofill/services/desktop-autofill.service.ts b/apps/desktop/src/autofill/services/desktop-autofill.service.ts index 7f443549c5b..ef9a5644e96 100644 --- a/apps/desktop/src/autofill/services/desktop-autofill.service.ts +++ b/apps/desktop/src/autofill/services/desktop-autofill.service.ts @@ -92,7 +92,7 @@ export class DesktopAutofillService implements OnDestroy { // } let fido2Credentials: NativeAutofillFido2Credential[]; - let passwordCredentials: NativeAutofillPasswordCredential[]; + let passwordCredentials: NativeAutofillPasswordCredential[] = []; fido2Credentials = (await getCredentialsForAutofill(cipherViews)).map((credential) => ({ type: "fido2", @@ -229,7 +229,7 @@ export class DesktopAutofillService implements OnDestroy { ipc.autofill.listenPasskeyAssertion(async (clientId, sequenceNumber, request, callback) => { this.logService.warning("listenPasskeyAssertion", clientId, sequenceNumber, request); - + // II: Stopped here! const controller = new AbortController(); void this.fido2AuthenticatorService .getAssertion( @@ -278,6 +278,7 @@ export class DesktopAutofillService implements OnDestroy { request: autofill.PasskeyRegistrationRequest, response: Fido2AuthenticatorMakeCredentialResult, ): autofill.PasskeyRegistrationResponse { + this.logService.debug("converting registrationResponse to Windows format") return { rpId: request.rpId, clientDataHash: request.clientDataHash, diff --git a/apps/desktop/src/main.ts b/apps/desktop/src/main.ts index fbb83a1bf56..ce83f972b0f 100644 --- a/apps/desktop/src/main.ts +++ b/apps/desktop/src/main.ts @@ -130,6 +130,8 @@ export class Main { } this.logService = new ElectronLogMainService(null, app.getPath("userData")); + this.logService.info("IS THIS THING ON?") + this.logService.debug("IS THIS THING ON? [debug]") const storageDefaults: any = {}; this.storageService = new ElectronStorageService(app.getPath("userData"), storageDefaults); @@ -303,8 +305,15 @@ export class Main { new ChromiumImporterService(); + this.nativeAutofillMain = new NativeAutofillMain(this.logService, this.windowMain); - void this.nativeAutofillMain.init(); + app + .whenReady() + .then(async () => { + this.logService.debug("ATTEMPTING TO INITIALIZE NATIVE AUTOFILL") + await this.nativeAutofillMain.init(); + + }) this.mainDesktopAutotypeService = new MainDesktopAutotypeService( this.logService, diff --git a/apps/desktop/src/platform/main/autofill/native-autofill.main.ts b/apps/desktop/src/platform/main/autofill/native-autofill.main.ts index a9e8e7c5abb..0714ff335e6 100644 --- a/apps/desktop/src/platform/main/autofill/native-autofill.main.ts +++ b/apps/desktop/src/platform/main/autofill/native-autofill.main.ts @@ -29,20 +29,33 @@ export class NativeAutofillMain { async init() { const enableWindowsPasskeyProvider = true; + this.logService.debug("Windows passkey provider enabled: " + enableWindowsPasskeyProvider) if (enableWindowsPasskeyProvider) { - this.windowsMain.initWindows(); - this.windowsMain.setupWindowsRendererIPCHandlers(); - } + let err = this.windowsMain.initWindows(); + if (err) { + this.logService.debug("Error occurred while initialized windows plugin:", err) + throw err + } + this.logService.debug("Windows passkey provider initialized: " + enableWindowsPasskeyProvider) + this.logService.debug("Setting up windows renderers") + this.windowsMain.setupWindowsRendererIPCHandlers(); + this.logService.debug("Setting up windows renderers done.") + } + this.logService.debug("Set up autofill IPC handlers: ") + + /* ipcMain.handle( "autofill.runCommand", ( _event: any, params: RunCommandParams, ): Promise> => { + this.logService.debug("Received event:", "autofill.runCommand", params) return this.runCommand(params); }, ); + */ this.ipcServer = await autofill.IpcServer.listen( "af", @@ -87,6 +100,7 @@ export class NativeAutofillMain { }, ); + /* ipcMain.on("autofill.completePasskeyRegistration", (event, data) => { this.logService.warning("autofill.completePasskeyRegistration", data); const { clientId, sequenceNumber, response } = data; @@ -104,6 +118,7 @@ export class NativeAutofillMain { const { clientId, sequenceNumber, error } = data; this.ipcServer.completeError(clientId, sequenceNumber, String(error)); }); + */ } private async runCommand( diff --git a/apps/desktop/src/platform/main/autofill/native-autofill.windows.main.ts b/apps/desktop/src/platform/main/autofill/native-autofill.windows.main.ts index 05a88d6b0dc..d1ab9cd0148 100644 --- a/apps/desktop/src/platform/main/autofill/native-autofill.windows.main.ts +++ b/apps/desktop/src/platform/main/autofill/native-autofill.windows.main.ts @@ -18,7 +18,16 @@ export class NativeAutofillWindowsMain { ) {} initWindows() { - passkey_authenticator.register(); + try { + passkey_authenticator.register(); + } + catch (err) { + this.logService.error("Failed to register windows passkey plugin:", err) + return JSON.stringify({ + "type": "error", + "message": "Failed to register windows passkey plugin" + }) + } void passkey_authenticator.onRequest(async (error, event) => { this.logService.info("Passkey request received:", { error, event }); @@ -241,6 +250,7 @@ export class NativeAutofillWindowsMain { _event: any, params: RunCommandParams, ): Promise> => { + this.logService.debug("Received event (windows):", "autofill.runCommand", params) return this.runCommand(params); }, ); diff --git a/apps/desktop/src/platform/services/electron-log.main.service.ts b/apps/desktop/src/platform/services/electron-log.main.service.ts index 947f4449271..2d5070527ab 100644 --- a/apps/desktop/src/platform/services/electron-log.main.service.ts +++ b/apps/desktop/src/platform/services/electron-log.main.service.ts @@ -22,7 +22,7 @@ export class ElectronLogMainService extends BaseLogService { return; } - log.transports.file.level = "info"; + log.transports.file.level = "debug"; if (this.logDir != null) { log.transports.file.resolvePathFn = () => path.join(this.logDir, "app.log"); } diff --git a/libs/common/src/platform/services/fido2/credential-id-utils.ts b/libs/common/src/platform/services/fido2/credential-id-utils.ts index 08ea33114f5..f595f48914d 100644 --- a/libs/common/src/platform/services/fido2/credential-id-utils.ts +++ b/libs/common/src/platform/services/fido2/credential-id-utils.ts @@ -9,7 +9,9 @@ export function parseCredentialId(encodedCredentialId: string): ArrayBuffer { return Fido2Utils.stringToBuffer(encodedCredentialId.slice(4)); } - return guidToRawFormat(encodedCredentialId).buffer; + let arr = guidToRawFormat(encodedCredentialId); + console.log("guidToRawFormat output:", arr) + return arr.buffer; } catch { return undefined; } @@ -19,12 +21,14 @@ export function parseCredentialId(encodedCredentialId: string): ArrayBuffer { * Compares two credential IDs for equality. */ export function compareCredentialIds(a: ArrayBuffer, b: ArrayBuffer): boolean { + console.log("compareCredentialIds:", a, b) if (a.byteLength !== b.byteLength) { return false; } const viewA = new Uint8Array(a); const viewB = new Uint8Array(b); + console.log("Comparing credential IDs:", viewA, viewB) for (let i = 0; i < viewA.length; i++) { if (viewA[i] !== viewB[i]) { diff --git a/libs/common/src/platform/services/fido2/fido2-authenticator.service.ts b/libs/common/src/platform/services/fido2/fido2-authenticator.service.ts index e560a77cc2e..6888ed8d6f5 100644 --- a/libs/common/src/platform/services/fido2/fido2-authenticator.service.ts +++ b/libs/common/src/platform/services/fido2/fido2-authenticator.service.ts @@ -32,6 +32,7 @@ import { compareCredentialIds, parseCredentialId } from "./credential-id-utils"; import { p1363ToDer } from "./ecdsa-utils"; import { Fido2Utils } from "./fido2-utils"; import { guidToStandardFormat } from "./guid-utils"; +import { PrimarySecondaryStorageService } from "../../storage/primary-secondary-storage.service"; // AAGUID: d548826e-79b4-db40-a3d8-11116f7e8349 export const AAGUID = new Uint8Array([ @@ -62,12 +63,15 @@ export class Fido2AuthenticatorService window: ParentWindowReference, abortController?: AbortController, ): Promise { + this.logService.debug("[Fido2AuthenticatorService] makeCredential") + this.logService.debug("[Fido2AuthenticatorService] create new session") const userInterfaceSession = await this.userInterface.newSession( params.fallbackSupported, window, abortController, ); + this.logService.debug("[Fido2AuthenticatorService] try create new credential") try { if (params.credTypesAndPubKeyAlgs.every((p) => p.alg !== Fido2AlgorithmIdentifier.ES256)) { const requestedAlgorithms = params.credTypesAndPubKeyAlgs.map((p) => p.alg).join(", "); @@ -101,6 +105,7 @@ export class Fido2AuthenticatorService throw new Fido2AuthenticatorError(Fido2AuthenticatorErrorCode.Unknown); } + this.logService.debug("Ensuring unlocked vault before creating credential") await userInterfaceSession.ensureUnlockedVault(); // Avoid syncing if we did it reasonably soon as the only reason for syncing is to validate excludeCredentials @@ -128,6 +133,8 @@ export class Fido2AuthenticatorService let userVerified = false; let credentialId: string; let pubKeyDer: ArrayBuffer; + + this.logService.debug("[Fido2AuthenticatorService] Prompting user to confirm creating credential") const response = await userInterfaceSession.confirmNewCredential({ credentialName: params.rpEntity.name, userName: params.userEntity.name, @@ -435,15 +442,29 @@ export class Fido2AuthenticatorService credentials: PublicKeyCredentialDescriptor[], rpId: string, ): Promise { + this.logService.debug("[findCredentialsById]:", credentials, rpId) if (credentials.length === 0) { return []; } const activeUserId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId)); const ciphers = await this.cipherService.getAllDecrypted(activeUserId); + this.logService.debug("[findCredentialsById] ciphers:", ciphers) return ciphers.filter( - (cipher) => - !cipher.isDeleted && + (cipher) => { + this.logService.debug(cipher.id, + !cipher.isDeleted, + cipher.type === CipherType.Login, + cipher.login.hasFido2Credentials, + cipher.login.fido2Credentials[0].rpId === rpId, + credentials.some((credential) => { + let credId = cipher.login.fido2Credentials[0].credentialId + let parsedCredId = parseCredentialId(credId) + this.logService.debug(credential.id, credential.id.byteLength, typeof(credential.id), credId, parsedCredId, parsedCredId.byteLength, typeof(parsedCredId)) + return compareCredentialIds(credential.id, parsedCredId) + }), + ) + return !cipher.isDeleted && cipher.type === CipherType.Login && cipher.login.hasFido2Credentials && cipher.login.fido2Credentials[0].rpId === rpId && @@ -452,13 +473,16 @@ export class Fido2AuthenticatorService credential.id, parseCredentialId(cipher.login.fido2Credentials[0].credentialId), ), - ), + ) + } ); } private async findCredentialsByRp(rpId: string): Promise { + this.logService.debug("[findCredentialByRp]:", rpId) const activeUserId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId)); const ciphers = await this.cipherService.getAllDecrypted(activeUserId); + this.logService.debug("[findCredentialsByRp] ciphers:", ciphers) return ciphers.filter( (cipher) => !cipher.isDeleted &&