question

MahaboobAslam-5545 avatar image
0 Votes"
MahaboobAslam-5545 asked ·

FIDO2 C++ based application using WebAuthn.dll for "YUBIKEY 5 NFC" (External authenticator) gives "This Security Key doesn't look familier. Please try a different one."

Hi

I am writing FIDO2 C++ based application using WebAuthn.dll for "YUBIKEY 5 NFC" (External authenticator) using the following WebAutheN APIs of Microsoft from the
https://github.com/microsoft/webauthn/blob/master/webauthn.h


             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);



I am able to get the registration successfully with the IdP (Identity Provider) using C++ API WebAuthNAuthenticatorMakeCredential() in my code.

But when it comes to Authentication, i am facing problem with the api WebAuthNAuthenticatorGetAssertion() as follows:

"This Security Key doesn't look familiar. Please try a different one."

image

Below is my code :
============

             HWND  hWnd = GetForegroundWindow();
             LPCWSTR   pwszRpId = L"tenet.domain.com";
                    
                             //My client data in json format is as below...
              sClientData64 = {"type":"webauthn.get","challenge":"MKB9ApSESppXbU-oVW_M","origin":"https://tenet.domain.com","crossOrigin":true};

             WEBAUTHN_CLIENT_DATA oClientData_in = { WEBAUTHN_CLIENT_DATA_CURRENT_VERSION,
                                 static_cast<DWORD>(sClientData64.length()),
                                 (PBYTE)(sClientData64.data()),
                                 WEBAUTHN_HASH_ALGORITHM_SHA_256 
                                               };


I tried to manipulate the values as in the following link: https://github.com/Yubico/python-fido2/blob/master/fido2/win_api.py to implement
the structure "WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS" below:

My allow list code is as follows:
====================

             std::vector<WEBAUTHN_CREDENTIAL_EX> allowCredentials;                
             WEBAUTHN_CREDENTIAL_EX* pAllowCredentials = nullptr;
             std::vector<WEBAUTHN_CREDENTIAL_EX*> allowCredentialsPtrs;
                
             WEBAUTHN_CREDENTIAL_LIST allowCredentialList = { 0 };
             WEBAUTHN_CREDENTIAL_LIST* pAllowCredentialList = nullptr;

             DWORD dwVersion = WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_4; // the value is 4

             if(dwversion is >= 4)
             {
                 DWORD winTransports = 0;
                            
                 std::string sAuthenticatorType = "usb";
                 int nTransport = 0;
                 if(sAuthenticatorType == "usb")
                 { 
                     nTransport = 1;
                 }
                    
                 if (nTransport & U2F_AUTHENTICATOR_TRANSPORT_USB)
                 {
                     winTransports |= WEBAUTHN_CTAP_TRANSPORT_USB;
                 }                    

                 WEBAUTHN_CREDENTIAL_EX webCredEx = {    WEBAUTHN_CREDENTIAL_EX_CURRENT_VERSION,
                                     static_cast<DWORD>(sCredentialId.length()),
                                     ((BYTE*)(sCredentialId.c_str())),
                                     WEBAUTHN_CREDENTIAL_TYPE_PUBLIC_KEY,
                                     winTransports
                                       };

                 allowCredentials.push_back(webCredEx);                

                 pAllowCredentials = allowCredentials.data();
                 for (DWORD i = 0; i < allowCredentials.size(); i++)
                 {
                     allowCredentialsPtrs.push_back(&pAllowCredentials[i]);
                 }
                 allowCredentialList.cCredentials = allowCredentials.size();  // original
                 allowCredentialList.ppCredentials = allowCredentialsPtrs.data(); // original
                 pAllowCredentialList = &allowCredentialList;  // my AllowCredentialList value
             }

// Credentials is as follows:
==================

             WEBAUTHN_CREDENTIALS webCredentials = {0,NULL};

             DWORD dwVersion = WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_3; // the value is 3

             if(dwversion is >= 3)
             {
                 std::vector<WEBAUTHN_CREDENTIAL> vCredential;
                 std::vector<WEBAUTHN_CREDENTIAL*> pCredential;
                 WEBAUTHN_CREDENTIAL webAuthCredential = {WEBAUTHN_CREDENTIAL_CURRENT_VERSION,
                                   static_cast<DWORD>(sCredentialId.length()),
                                   ((BYTE*)(sCredentialId.c_str())),
                                  WEBAUTHN_CREDENTIAL_TYPE_PUBLIC_KEY
                                 };
                 WEBAUTHN_CREDENTIAL *pwebCredential;
                 vCredential.push_back(webAuthCredential);
                 pwebCredential = vCredential.data();
                 for (DWORD i = 0; i < vCredential.size(); i++)
                 {
                     pCredential.push_back(&pwebCredential[i]);
                 }
                 webCredentials.cCredentials = vCredential.size();
                 webCredentials.pCredentials = pwebCredential;
             }

// filling this structure based on the dwVersion.. as the code above.

             WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS   oWebAuthNGetAssertionOptions = { 
                        dwVersion,  // version
                        10000,  // time in milliseconds
                        webCredentials,  //WEBAUTHN_CREDENTIALS  
                        {0, NULL},  //WEBAUTHN_EXTENSIONS
                        dwAuthenticatorAttachement,  // for Platform (Windows Hello) vs Cross platform authenticator (Yubikey)
                          winUserVerificationReq,  // user Verification Required (preferred)
                        0,  // dwFlags
                        NULL, // as json data received it is null
                                                 pbU2fAppIdUsed, //(FALSE) this is a pointer
                        NULL,  // pCancellationId
                        pAllowCredentialList  // allowList if (dwversion is >= 4) else allowlist is null
                                };

             WEBAUTHN_ASSERTION* pWebAuthNAssertion = nullptr;  // this is an output parameter, 

              // on calling, I get a dialog popup saying  " This Security key doesn't look familiar. please try a different one."

             hResult = WebAuthNAuthenticatorGetAssertion(hWnd, pwszRpId &oClientData_in, &oWebAuthNAssertionOptions, &pWebAuthNAssertion);  

I took the python code for reference from the https://github.com/Yubico/python-fido2/blob/master/fido2/win_api.py

             if (dwVersion >= 3)
                     self.pCancellationId = cancellationId  (NULL)

                 if self.dwVersion >= 4:
                     clist = WebAuthNCredentialList(credentials)
                     self.pAllowCredentialList = ctypes.pointer(clist)
                 else:
                     self.CredentialList = WebAuthNCredentials(credentials)

========================================================================



Please let me know, if any thing has to added in my code.

Thankyou.












windows-10-security
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

TeemoTang-MSFT avatar image
0 Votes"
TeemoTang-MSFT answered ·

Please note: for development related issue, you could ask for help from github forum.
https://github.com/topics/webauthn
The reason why we recommend posting appropriately is you will get the most qualified pool of respondents, and other partners who read the forums regularly can either share their knowledge or learn.
Thanks for your understanding and cooperating.
Windows 10 security forum is used for discussing the issue which is related to Windows 10 built-in security features such as Windows Defender.


If the Answer is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

aseigler avatar image
0 Votes"
aseigler answered ·

Do you get any further if you replace webCredentials with {0, NULL} and/or set pAllowCredentialList to NULL in the oWebAuthNGetAssertionOptions? I would start there and work forward.

·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.