⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 249059 in webkit


Ignore:
Timestamp:
Aug 23, 2019, 11:56:03 AM (7 years ago)
Author:
jiewen_tan@apple.com
Message:

[WebAuthn] Support NFC authenticators for iOS
https://bugs.webkit.org/show_bug.cgi?id=188624
<rdar://problem/43354214>

Reviewed by Chris Dumez.

Source/WebCore:

Tests: http/wpt/webauthn/ctap-nfc-failure.https.html

http/wpt/webauthn/public-key-credential-create-failure-nfc.https.html
http/wpt/webauthn/public-key-credential-create-success-nfc.https.html
http/wpt/webauthn/public-key-credential-get-failure-nfc.https.html
http/wpt/webauthn/public-key-credential-get-success-nfc.https.html

  • Modules/webauthn/apdu/ApduResponse.h:

Adds a new method to support moving m_data.

  • Modules/webauthn/fido/FidoConstants.h:

Adds constants for NFC applet selection.

Source/WebKit:

This patch implements support for NFC authenticators including both FIDO2 and U2F ones. It utilizes a private
framework called NearField instead of CoreNFC to be able to supply a custom UI later if necessary.

The patch follows almost the same flow as previous HID and Local authenticator support.
1) Discovery is via NfcService which will invoke NFHardwareManager to start a generic NFC reader session.
2) Once a reader session is established, a NfcConnection is created to start the polling and register the WKNFReaderSessionDelegate
to wait for 'didDetectTags'.
3) When tags are detected, NfcConnection will determine if it meets our requriements: { type, connectability, fido applet availability }.
The first tag that meets all requirement will then be returned for WebAuthn operations.
4) The first WebAuthn operation is to send authenticatorGetInfo command to determine the supported protocol, and then initialize corresponding
authenticators. Noted, the sending/receiving of this command is now abstracted into FidoService which will be shared across HidService and NfcService.
5) From then, the actual WebAuthn request, either makeCredential or getAssertion will be sent.

For testing, this patch follows the same flow as well.
1) MockNfcService overrides NfcService to mock the behavior of NFC Tags discovery.
2) The same class also swizzles methods from NFReaderSession to mock tag connection and communication.

  • Platform/spi/Cocoa/NearFieldSPI.h: Added.
  • Sources.txt:
  • SourcesCocoa.txt:
  • UIProcess/API/C/WKWebsiteDataStoreRef.cpp:

(WKWebsiteDataStoreSetWebAuthenticationMockConfiguration):

  • UIProcess/WebAuthentication/AuthenticatorManager.cpp:

(WebKit::AuthenticatorManagerInternal::collectTransports):

  • UIProcess/WebAuthentication/AuthenticatorTransportService.cpp:

(WebKit::AuthenticatorTransportService::create):
(WebKit::AuthenticatorTransportService::createMock):

  • UIProcess/WebAuthentication/Cocoa/HidService.h:
  • UIProcess/WebAuthentication/Cocoa/HidService.mm:

(WebKit::HidService::HidService):
(WebKit::HidService::deviceAdded):
(WebKit::HidService::continueAddDeviceAfterGetInfo): Deleted.

  • UIProcess/WebAuthentication/Cocoa/NearFieldSoftLink.h: Copied from Source/WebKit/UIProcess/WebAuthentication/Cocoa/HidService.h.
  • UIProcess/WebAuthentication/Cocoa/NearFieldSoftLink.mm: Copied from Source/WebKit/UIProcess/WebAuthentication/Cocoa/HidService.h.
  • UIProcess/WebAuthentication/Cocoa/NfcConnection.h: Copied from Source/WebKit/UIProcess/WebAuthentication/Cocoa/HidService.h.
  • UIProcess/WebAuthentication/Cocoa/NfcConnection.mm: Added.

(WebKit::fido::compareVersion):
(WebKit::NfcConnection::NfcConnection):
(WebKit::NfcConnection::~NfcConnection):
(WebKit::NfcConnection::transact const):
(WebKit::NfcConnection::didDetectTags const):

  • UIProcess/WebAuthentication/Cocoa/NfcService.h: Copied from Source/WebKit/UIProcess/WebAuthentication/Cocoa/HidService.h.
  • UIProcess/WebAuthentication/Cocoa/NfcService.mm: Added.

(WebKit::NfcService::NfcService):
(WebKit::NfcService::~NfcService):
(WebKit::NfcService::didConnectTag):
(WebKit::NfcService::startDiscoveryInternal):
(WebKit::NfcService::platformStartDiscovery):

  • UIProcess/WebAuthentication/Cocoa/WKNFReaderSessionDelegate.h: Copied from Source/WebKit/UIProcess/WebAuthentication/Cocoa/HidService.h.
  • UIProcess/WebAuthentication/Cocoa/WKNFReaderSessionDelegate.mm: Copied from Source/WebKit/UIProcess/WebAuthentication/Cocoa/HidService.h.

(-[WKNFReaderSessionDelegate initWithConnection:]):
(-[WKNFReaderSessionDelegate readerSession:didDetectTags:]):

  • UIProcess/WebAuthentication/Mock/MockHidConnection.cpp:

(WebKit::MockHidConnection::send):
(WebKit::MockHidConnection::registerDataReceivedCallbackInternal):
(WebKit::MockHidConnection::parseRequest):
(WebKit::MockHidConnection::feedReports):
(WebKit::MockHidConnection::shouldContinueFeedReports):

  • UIProcess/WebAuthentication/Mock/MockNfcService.h: Copied from Source/WebKit/UIProcess/WebAuthentication/Cocoa/HidService.h.
  • UIProcess/WebAuthentication/Mock/MockNfcService.mm: Added.

(-[WKMockNFTag type]):
(-[WKMockNFTag initWithNFTag:]):
(-[WKMockNFTag description]):
(-[WKMockNFTag isEqualToNFTag:]):
(-[WKMockNFTag initWithType:]):
(WebKit::MockNfcService::MockNfcService):
(WebKit::MockNfcService::transceive):
(WebKit::MockNfcService::platformStartDiscovery):
(WebKit::MockNfcService::detectTags const):

  • UIProcess/WebAuthentication/Mock/MockWebAuthenticationConfiguration.h:
  • UIProcess/WebAuthentication/fido/CtapAuthenticator.cpp:
  • UIProcess/WebAuthentication/fido/CtapAuthenticator.h:
  • UIProcess/WebAuthentication/fido/CtapNfcDriver.cpp: Added.

(WebKit::CtapNfcDriver::CtapNfcDriver):
(WebKit::CtapNfcDriver::transact):
(WebKit::CtapNfcDriver::respondAsync const):

  • UIProcess/WebAuthentication/fido/CtapNfcDriver.h: Copied from Source/WebKit/UIProcess/WebAuthentication/Cocoa/HidService.h.
  • UIProcess/WebAuthentication/fido/FidoService.cpp: Added.

(WebKit::FidoService::FidoService):
(WebKit::FidoService::getInfo):
(WebKit::FidoService::continueAfterGetInfo):

  • UIProcess/WebAuthentication/fido/FidoService.h: Copied from Source/WebKit/UIProcess/WebAuthentication/Cocoa/HidService.h.
  • UIProcess/WebAuthentication/fido/U2fAuthenticator.cpp:
  • UIProcess/WebAuthentication/fido/U2fAuthenticator.h:
  • UIProcess/ios/WebPageProxyIOS.mm:
  • WebKit.xcodeproj/project.pbxproj:

Source/WTF:

  • wtf/Platform.h:

Add a feature flag for NearField.

Tools:

  • WebKitTestRunner/InjectedBundle/TestRunner.cpp:

(WTR::TestRunner::setWebAuthenticationMockConfiguration):
Setup NFC mock testing configuration.

LayoutTests:

  • http/wpt/webauthn/ctap-nfc-failure.https-expected.txt: Added.
  • http/wpt/webauthn/ctap-nfc-failure.https.html: Added.
  • http/wpt/webauthn/public-key-credential-create-failure-nfc.https-expected.txt: Added.
  • http/wpt/webauthn/public-key-credential-create-failure-nfc.https.html: Added.
  • http/wpt/webauthn/public-key-credential-create-success-hid.https-expected.txt:
  • http/wpt/webauthn/public-key-credential-create-success-hid.https.html:

This patch replaces the "local" keyword with "hid".

  • http/wpt/webauthn/public-key-credential-create-success-nfc.https-expected.txt: Added.
  • http/wpt/webauthn/public-key-credential-create-success-nfc.https.html: Added.
  • http/wpt/webauthn/public-key-credential-get-failure-nfc.https-expected.txt: Added.
  • http/wpt/webauthn/public-key-credential-get-failure-nfc.https.html: Added.
  • http/wpt/webauthn/public-key-credential-get-success-nfc.https-expected.txt: Added.
  • http/wpt/webauthn/public-key-credential-get-success-nfc.https.html: Added.
  • http/wpt/webauthn/resources/util.js:
  • platform/ios-simulator-wk2/TestExpectations:

Skip NFC tests for simulators.

Location:
trunk
Files:
16 added
31 edited
9 copied

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r249051 r249059  
     12019-08-20  Jiewen Tan  <jiewen_tan@apple.com>
     2
     3        [WebAuthn] Support NFC authenticators for iOS
     4        https://bugs.webkit.org/show_bug.cgi?id=188624
     5        <rdar://problem/43354214>
     6
     7        Reviewed by Chris Dumez.
     8
     9        * http/wpt/webauthn/ctap-nfc-failure.https-expected.txt: Added.
     10        * http/wpt/webauthn/ctap-nfc-failure.https.html: Added.
     11        * http/wpt/webauthn/public-key-credential-create-failure-nfc.https-expected.txt: Added.
     12        * http/wpt/webauthn/public-key-credential-create-failure-nfc.https.html: Added.
     13        * http/wpt/webauthn/public-key-credential-create-success-hid.https-expected.txt:
     14        * http/wpt/webauthn/public-key-credential-create-success-hid.https.html:
     15        This patch replaces the "local" keyword with "hid".
     16        * http/wpt/webauthn/public-key-credential-create-success-nfc.https-expected.txt: Added.
     17        * http/wpt/webauthn/public-key-credential-create-success-nfc.https.html: Added.
     18        * http/wpt/webauthn/public-key-credential-get-failure-nfc.https-expected.txt: Added.
     19        * http/wpt/webauthn/public-key-credential-get-failure-nfc.https.html: Added.
     20        * http/wpt/webauthn/public-key-credential-get-success-nfc.https-expected.txt: Added.
     21        * http/wpt/webauthn/public-key-credential-get-success-nfc.https.html: Added.
     22        * http/wpt/webauthn/resources/util.js:
     23        * platform/ios-simulator-wk2/TestExpectations:
     24        Skip NFC tests for simulators.
     25
    1262019-08-23  Russell Epstein  <repstein@apple.com>
    227
  • trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-hid.https-expected.txt

    r245638 r249059  
    11
    2 PASS PublicKeyCredential's [[create]] with minimum options in a mock local authenticator.
    3 PASS PublicKeyCredential's [[create]] with authenticatorSelection { 'cross-platform' } in a mock local authenticator.
    4 PASS PublicKeyCredential's [[create]] with requireResidentKey { false } in a mock local authenticator.
    5 PASS PublicKeyCredential's [[create]] with userVerification { 'preferred' } in a mock local authenticator.
    6 PASS PublicKeyCredential's [[create]] with userVerification { 'discouraged' } in a mock local authenticator.
    7 PASS PublicKeyCredential's [[create]] with mixed options in a mock local authenticator.
     2PASS PublicKeyCredential's [[create]] with minimum options in a mock hid authenticator.
     3PASS PublicKeyCredential's [[create]] with authenticatorSelection { 'cross-platform' } in a mock hid authenticator.
     4PASS PublicKeyCredential's [[create]] with requireResidentKey { false } in a mock hid authenticator.
     5PASS PublicKeyCredential's [[create]] with userVerification { 'preferred' } in a mock hid authenticator.
     6PASS PublicKeyCredential's [[create]] with userVerification { 'discouraged' } in a mock hid authenticator.
     7PASS PublicKeyCredential's [[create]] with mixed options in a mock hid authenticator.
    88PASS PublicKeyCredential's [[create]] with two consecutive requests.
    9 PASS PublicKeyCredential's [[create]] with none attestation in a mock local authenticator.
    10 PASS PublicKeyCredential's [[create]] with direct attestation in a mock local authenticator.
    11 PASS PublicKeyCredential's [[create]] with indirect attestation in a mock local authenticator.
     9PASS PublicKeyCredential's [[create]] with none attestation in a mock hid authenticator.
     10PASS PublicKeyCredential's [[create]] with direct attestation in a mock hid authenticator.
     11PASS PublicKeyCredential's [[create]] with indirect attestation in a mock hid authenticator.
    1212
  • trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-hid.https.html

    r245638 r249059  
    1010        testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", payloadBase64: [testCreationMessageBase64] } });
    1111
    12     function checkResult(credential, isNoneAttestation = true)
    13     {
    14         // Check response
    15         assert_array_equals(Base64URL.parse(credential.id), Base64URL.parse(testHidCredentialIdBase64));
    16         assert_equals(credential.type, 'public-key');
    17         assert_array_equals(new Uint8Array(credential.rawId), Base64URL.parse(testHidCredentialIdBase64));
    18         assert_equals(bytesToASCIIString(credential.response.clientDataJSON), '{"type":"webauthn.create","challenge":"MTIzNDU2","origin":"https://localhost:9443"}');
    19         assert_not_exists(credential.getClientExtensionResults(), "appid");
    20 
    21         // Check attestation
    22         const attestationObject = CBOR.decode(credential.response.attestationObject);
    23         if (isNoneAttestation)
    24             assert_equals(attestationObject.fmt, "none");
    25         else
    26             assert_equals(attestationObject.fmt, "packed");
    27         // Check authData
    28         const authData = decodeAuthData(attestationObject.authData);
    29         assert_equals(bytesToHexString(authData.rpIdHash), "46cc7fb9679d55b2db9092e1c8d9e5e1d02b7580f0b4812c770962e1e48f5ad8");
    30         assert_equals(authData.flags, 65);
    31         assert_equals(authData.counter, 78);
    32         if (isNoneAttestation)
    33             assert_equals(bytesToHexString(authData.aaguid), "00000000000000000000000000000000");
    34         else
    35             assert_equals(bytesToHexString(authData.aaguid), "f8a011f38c0a4d15800617111f9edc7d");
    36         assert_array_equals(authData.credentialID, Base64URL.parse(testHidCredentialIdBase64));
    37         // Check packed attestation
    38         assert_true(checkPublicKey(authData.publicKey));
    39         if (isNoneAttestation)
    40             assert_object_equals(attestationObject.attStmt, { });
    41         else {
    42             assert_equals(attestationObject.attStmt.alg, -7);
    43             assert_equals(attestationObject.attStmt.x5c.length, 1);
    44         }
    45     }
    46 
    47     promise_test(t => {
    48         const options = {
    49             publicKey: {
    50                 rp: {
    51                     name: "localhost",
    52                 },
    53                 user: {
    54                     name: "John Appleseed",
    55                     id: Base64URL.parse(testUserhandleBase64),
    56                     displayName: "Appleseed",
    57                 },
    58                 challenge: Base64URL.parse("MTIzNDU2"),
    59                 pubKeyCredParams: [{ type: "public-key", alg: -7 }],
    60                 timeout: 100
    61             }
    62         };
    63 
    64         return navigator.credentials.create(options).then(credential => {
    65             checkResult(credential);
    66         });
    67     }, "PublicKeyCredential's [[create]] with minimum options in a mock local authenticator.");
     12    promise_test(t => {
     13        const options = {
     14            publicKey: {
     15                rp: {
     16                    name: "localhost",
     17                },
     18                user: {
     19                    name: "John Appleseed",
     20                    id: Base64URL.parse(testUserhandleBase64),
     21                    displayName: "Appleseed",
     22                },
     23                challenge: Base64URL.parse("MTIzNDU2"),
     24                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
     25                timeout: 100
     26            }
     27        };
     28
     29        return navigator.credentials.create(options).then(credential => {
     30            checkCtapMakeCredentialResult(credential);
     31        });
     32    }, "PublicKeyCredential's [[create]] with minimum options in a mock hid authenticator.");
    6833
    6934    promise_test(t => {
     
    8651
    8752        return navigator.credentials.create(options).then(credential => {
    88             checkResult(credential);
    89         });
    90     }, "PublicKeyCredential's [[create]] with authenticatorSelection { 'cross-platform' } in a mock local authenticator.");
     53            checkCtapMakeCredentialResult(credential);
     54        });
     55    }, "PublicKeyCredential's [[create]] with authenticatorSelection { 'cross-platform' } in a mock hid authenticator.");
    9156
    9257    promise_test(t => {
     
    10974
    11075        return navigator.credentials.create(options).then(credential => {
    111             checkResult(credential);
    112         });
    113     }, "PublicKeyCredential's [[create]] with requireResidentKey { false } in a mock local authenticator.");
     76            checkCtapMakeCredentialResult(credential);
     77        });
     78    }, "PublicKeyCredential's [[create]] with requireResidentKey { false } in a mock hid authenticator.");
    11479
    11580    promise_test(t => {
     
    13297
    13398        return navigator.credentials.create(options).then(credential => {
    134             checkResult(credential);
    135         });
    136     }, "PublicKeyCredential's [[create]] with userVerification { 'preferred' } in a mock local authenticator.");
     99            checkCtapMakeCredentialResult(credential);
     100        });
     101    }, "PublicKeyCredential's [[create]] with userVerification { 'preferred' } in a mock hid authenticator.");
    137102
    138103    promise_test(t => {
     
    155120
    156121        return navigator.credentials.create(options).then(credential => {
    157             checkResult(credential);
    158         });
    159     }, "PublicKeyCredential's [[create]] with userVerification { 'discouraged' } in a mock local authenticator.");
     122            checkCtapMakeCredentialResult(credential);
     123        });
     124    }, "PublicKeyCredential's [[create]] with userVerification { 'discouraged' } in a mock hid authenticator.");
    160125
    161126    promise_test(t => {
     
    178143
    179144        return navigator.credentials.create(options).then(credential => {
    180             checkResult(credential);
    181         });
    182     }, "PublicKeyCredential's [[create]] with mixed options in a mock local authenticator.");
     145            checkCtapMakeCredentialResult(credential);
     146        });
     147    }, "PublicKeyCredential's [[create]] with mixed options in a mock hid authenticator.");
    183148
    184149    promise_test(t => {
     
    201166        promiseRejects(t, "NotAllowedError", navigator.credentials.create(options), "This request has been voided by a new request.");
    202167        return navigator.credentials.create(options).then(credential => {
    203             checkResult(credential);
     168            checkCtapMakeCredentialResult(credential);
    204169        });
    205170    }, "PublicKeyCredential's [[create]] with two consecutive requests.");
     
    224189
    225190        return navigator.credentials.create(options).then(credential => {
    226             checkResult(credential);
    227         });
    228     }, "PublicKeyCredential's [[create]] with none attestation in a mock local authenticator.");
     191            checkCtapMakeCredentialResult(credential);
     192        });
     193    }, "PublicKeyCredential's [[create]] with none attestation in a mock hid authenticator.");
    229194
    230195    promise_test(t => {
     
    247212
    248213        return navigator.credentials.create(options).then(credential => {
    249             checkResult(credential, false);
    250         });
    251     }, "PublicKeyCredential's [[create]] with direct attestation in a mock local authenticator.");
     214            checkCtapMakeCredentialResult(credential, false);
     215        });
     216    }, "PublicKeyCredential's [[create]] with direct attestation in a mock hid authenticator.");
    252217
    253218    promise_test(t => {
     
    270235
    271236        return navigator.credentials.create(options).then(credential => {
    272             checkResult(credential, false);
    273         });
    274     }, "PublicKeyCredential's [[create]] with indirect attestation in a mock local authenticator.");
     237            checkCtapMakeCredentialResult(credential, false);
     238        });
     239    }, "PublicKeyCredential's [[create]] with indirect attestation in a mock hid authenticator.");
    275240</script>
  • trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-u2f.https.html

    r245638 r249059  
    66<script src="./resources/cbor.js"></script>
    77<script>
    8     function checkResult(credential, isNoneAttestation = true)
    9     {
    10         // Check response
    11         assert_array_equals(Base64URL.parse(credential.id), Base64URL.parse(testU2fCredentialIdBase64));
    12         assert_equals(credential.type, 'public-key');
    13         assert_array_equals(new Uint8Array(credential.rawId), Base64URL.parse(testU2fCredentialIdBase64));
    14         assert_equals(bytesToASCIIString(credential.response.clientDataJSON), '{"type":"webauthn.create","challenge":"MTIzNDU2","origin":"https://localhost:9443"}');
    15         assert_not_exists(credential.getClientExtensionResults(), "appid");
    16 
    17         // Check attestation
    18         const attestationObject = CBOR.decode(credential.response.attestationObject);
    19         if (isNoneAttestation)
    20             assert_equals(attestationObject.fmt, "none");
    21         else
    22             assert_equals(attestationObject.fmt, "fido-u2f");
    23         // Check authData
    24         const authData = decodeAuthData(attestationObject.authData);
    25         assert_equals(bytesToHexString(authData.rpIdHash), "49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d9763");
    26         assert_equals(authData.flags, 65);
    27         assert_equals(authData.counter, 0);
    28         assert_equals(bytesToHexString(authData.aaguid), "00000000000000000000000000000000");
    29         assert_array_equals(authData.credentialID, Base64URL.parse(testU2fCredentialIdBase64));
    30         // Check fido-u2f attestation
    31         assert_true(checkPublicKey(authData.publicKey));
    32         if (isNoneAttestation)
    33             assert_object_equals(attestationObject.attStmt, { });
    34         else
    35             assert_equals(attestationObject.attStmt.x5c.length, 1);
    36     }
    37 
    388    promise_test(t => {
    399        const options = {
     
    5626            testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", isU2f: true, payloadBase64: [testU2fRegisterResponse] } });
    5727        return navigator.credentials.create(options).then(credential => {
    58             checkResult(credential);
     28            checkU2fMakeCredentialResult(credential);
    5929        });
    6030    }, "PublicKeyCredential's [[create]] with minimum options in a mock u2f authenticator.");
     
    8151            testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", isU2f: true, payloadBase64: [testU2fApduWrongDataOnlyResponseBase64, testU2fRegisterResponse] } });
    8252        return navigator.credentials.create(options).then(credential => {
    83             checkResult(credential);
     53            checkU2fMakeCredentialResult(credential);
    8454        });
    8555    }, "PublicKeyCredential's [[create]] with excludeCredentials in a mock u2f authenticator.");
     
    10676            testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", isU2f: true, payloadBase64: [testU2fApduWrongDataOnlyResponseBase64, testU2fApduWrongDataOnlyResponseBase64, testU2fRegisterResponse] } });
    10777        return navigator.credentials.create(options).then(credential => {
    108             checkResult(credential);
     78            checkU2fMakeCredentialResult(credential);
    10979        });
    11080    }, "PublicKeyCredential's [[create]] with excludeCredentials in a mock u2f authenticator. 2");
     
    130100            testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", isU2f: true, payloadBase64: [testU2fApduConditionsNotSatisfiedOnlyResponseBase64, testU2fApduConditionsNotSatisfiedOnlyResponseBase64, testU2fRegisterResponse] } });
    131101        return navigator.credentials.create(options).then(credential => {
    132             checkResult(credential);
     102            checkU2fMakeCredentialResult(credential);
    133103        });
    134104    }, "PublicKeyCredential's [[create]] with test of user presence in a mock u2f authenticator.");
     
    155125            testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", isU2f: true, payloadBase64: [testU2fRegisterResponse] } });
    156126        return navigator.credentials.create(options).then(credential => {
    157             checkResult(credential);
     127            checkU2fMakeCredentialResult(credential);
    158128        });
    159129    }, "PublicKeyCredential's [[create]] with none attestation in a mock u2f authenticator.");
     
    180150            testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", isU2f: true, payloadBase64: [testU2fRegisterResponse] } });
    181151        return navigator.credentials.create(options).then(credential => {
    182             checkResult(credential, false);
     152            checkU2fMakeCredentialResult(credential, false);
    183153        });
    184154    }, "PublicKeyCredential's [[create]] with indirect attestation in a mock u2f authenticator.");
     
    205175            testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", isU2f: true, payloadBase64: [testU2fRegisterResponse] } });
    206176        return navigator.credentials.create(options).then(credential => {
    207             checkResult(credential, false);
     177            checkU2fMakeCredentialResult(credential, false);
    208178        });
    209179    }, "PublicKeyCredential's [[create]] with direct attestation in a mock u2f authenticator.");
  • trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-hid.https.html

    r245052 r249059  
    99        testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", payloadBase64: [testAssertionMessageBase64] } });
    1010
    11     function checkResult(credential)
    12     {
    13         // Check respond
    14         assert_array_equals(Base64URL.parse(credential.id), Base64URL.parse(testHidCredentialIdBase64));
    15         assert_equals(credential.type, 'public-key');
    16         assert_array_equals(new Uint8Array(credential.rawId), Base64URL.parse(testHidCredentialIdBase64));
    17         assert_equals(bytesToASCIIString(credential.response.clientDataJSON), '{"type":"webauthn.get","challenge":"MTIzNDU2","origin":"https://localhost:9443"}');
    18         assert_equals(credential.response.userHandle, null);
    19         assert_not_exists(credential.getClientExtensionResults(), "appid");
    20 
    21         // Check authData
    22         const authData = decodeAuthData(new Uint8Array(credential.response.authenticatorData));
    23         assert_equals(bytesToHexString(authData.rpIdHash), "46cc7fb9679d55b2db9092e1c8d9e5e1d02b7580f0b4812c770962e1e48f5ad8");
    24         assert_equals(authData.flags, 1);
    25         assert_equals(authData.counter, 80);
    26     }
    27 
    2811    promise_test(t => {
    2912        const options = {
     
    3518
    3619        return navigator.credentials.get(options).then(credential => {
    37             return checkResult(credential);
     20            return checkCtapGetAssertionResult(credential);
    3821        });
    3922    }, "PublicKeyCredential's [[get]] with minimum options in a mock hid authenticator.");
     
    5134
    5235        return navigator.credentials.get(options).then(credential => {
    53             return checkResult(credential);
     36            return checkCtapGetAssertionResult(credential);
    5437        });
    5538    }, "PublicKeyCredential's [[get]] with matched allow credentials in a mock hid authenticator.");
     
    6548
    6649        return navigator.credentials.get(options).then(credential => {
    67             return checkResult(credential);
     50            return checkCtapGetAssertionResult(credential);
    6851        });
    6952    }, "PublicKeyCredential's [[get]] with userVerification { preferred } in a mock hid authenticator.");
     
    7962
    8063        return navigator.credentials.get(options).then(credential => {
    81             return checkResult(credential);
     64            return checkCtapGetAssertionResult(credential);
    8265        });
    8366    }, "PublicKeyCredential's [[get]] with userVerification { discouraged } in a mock hid authenticator.");
     
    9679
    9780        return navigator.credentials.get(options).then(credential => {
    98             return checkResult(credential);
     81            return checkCtapGetAssertionResult(credential);
    9982        });
    10083    }, "PublicKeyCredential's [[get]] with mixed options in a mock hid authenticator.");
     
    11093        promiseRejects(t, "NotAllowedError", navigator.credentials.get(options), "This request has been voided by a new request.");
    11194        return navigator.credentials.get(options).then(credential => {
    112             return checkResult(credential);
     95            return checkCtapGetAssertionResult(credential);
    11396        });
    11497    }, "PublicKeyCredential's [[get]] with two consecutive requests.");
  • trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-u2f.https.html

    r245500 r249059  
    55<script src="./resources/util.js"></script>
    66<script>
    7     const defaultAppIDHash = "c2671b6eb9233197d5f2b1288a55ba4f0860f96f7199bba32fe6da7c3f0f31e5";
    8 
    9     function checkResult(credential, isAppID = false, appIDHash = defaultAppIDHash)
    10     {
    11         // Check respond
    12         assert_array_equals(Base64URL.parse(credential.id), Base64URL.parse(testU2fCredentialIdBase64));
    13         assert_equals(credential.type, 'public-key');
    14         assert_array_equals(new Uint8Array(credential.rawId), Base64URL.parse(testU2fCredentialIdBase64));
    15         assert_equals(bytesToASCIIString(credential.response.clientDataJSON), '{"type":"webauthn.get","challenge":"MTIzNDU2","origin":"https://localhost:9443"}');
    16         assert_equals(credential.response.userHandle, null);
    17         if (!isAppID)
    18             assert_not_exists(credential.getClientExtensionResults(), "appid");
    19         else
    20             assert_true(credential.getClientExtensionResults().appid);
    21 
    22         // Check authData
    23         const authData = decodeAuthData(new Uint8Array(credential.response.authenticatorData));
    24         if (!isAppID)
    25             assert_equals(bytesToHexString(authData.rpIdHash), "49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d9763");
    26         else
    27             assert_equals(bytesToHexString(authData.rpIdHash), appIDHash);
    28         assert_equals(authData.flags, 1);
    29         assert_equals(authData.counter, 59);
    30     }
    31 
    327    promise_test(t => {
    338        const options = {
     
    4217            testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", isU2f: true, payloadBase64: [testU2fSignResponse] } });
    4318        return navigator.credentials.get(options).then(credential => {
    44             return checkResult(credential);
     19            return checkU2fGetAssertionResult(credential);
    4520        });
    4621    }, "PublicKeyCredential's [[get]] with minimum options in a mock hid authenticator.");
     
    5833            testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", isU2f: true, payloadBase64: [testU2fApduWrongDataOnlyResponseBase64, testU2fSignResponse] } });
    5934        return navigator.credentials.get(options).then(credential => {
    60             return checkResult(credential);
     35            return checkU2fGetAssertionResult(credential);
    6136        });
    6237    }, "PublicKeyCredential's [[get]] with more allow credentials in a mock hid authenticator.");
     
    7449            testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", isU2f: true, payloadBase64: [testU2fApduConditionsNotSatisfiedOnlyResponseBase64, testU2fApduConditionsNotSatisfiedOnlyResponseBase64, testU2fSignResponse] } });
    7550        return navigator.credentials.get(options).then(credential => {
    76             return checkResult(credential);
     51            return checkU2fGetAssertionResult(credential);
    7752        });
    7853    }, "PublicKeyCredential's [[get]] with test of user presence in a mock hid authenticator.");
     
    9267            testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", isU2f: true, payloadBase64: [testU2fSignResponse] } });
    9368        return navigator.credentials.get(options).then(credential => {
    94             return checkResult(credential);
     69            return checkU2fGetAssertionResult(credential);
    9570        });
    9671    }, "PublicKeyCredential's [[get]] with empty extensions in a mock hid authenticator.");
     
    10984            testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", isU2f: true, payloadBase64: [testU2fSignResponse] } });
    11085        return navigator.credentials.get(options).then(credential => {
    111             return checkResult(credential);
     86            return checkU2fGetAssertionResult(credential);
    11287        });
    11388    }, "PublicKeyCredential's [[get]] with same site AppID but not used in a mock hid authenticator.");
     
    126101            testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", isU2f: true, payloadBase64: [testU2fApduWrongDataOnlyResponseBase64, testU2fSignResponse] } });
    127102        return navigator.credentials.get(options).then(credential => {
    128             return checkResult(credential, true);
     103            return checkU2fGetAssertionResult(credential, true);
    129104        });
    130105    }, "PublicKeyCredential's [[get]] with empty AppID in a mock hid authenticator.");
     
    144119            testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", isU2f: true, payloadBase64: [testU2fApduWrongDataOnlyResponseBase64, testU2fSignResponse] } });
    145120        return navigator.credentials.get(options).then(credential => {
    146             return checkResult(credential, true, "7eabc5cc3251bdc59115ef87b5f7ee74cb03747e39ba8341748565cc129c0719");
     121            return checkU2fGetAssertionResult(credential, true, "7eabc5cc3251bdc59115ef87b5f7ee74cb03747e39ba8341748565cc129c0719");
    147122        });
    148123    }, "PublicKeyCredential's [[get]] with an AppID in a mock hid authenticator.");
     
    161136            testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", isU2f: true, payloadBase64: [testU2fApduWrongDataOnlyResponseBase64, testU2fApduWrongDataOnlyResponseBase64, testU2fSignResponse] } });
    162137        return navigator.credentials.get(options).then(credential => {
    163             return checkResult(credential);
     138            return checkU2fGetAssertionResult(credential);
    164139        });
    165140    }, "PublicKeyCredential's [[get]] with multiple credentials and AppID is not used in a mock hid authenticator.");
     
    178153            testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", isU2f: true, payloadBase64: [testU2fApduWrongDataOnlyResponseBase64, testU2fApduWrongDataOnlyResponseBase64, testU2fApduWrongDataOnlyResponseBase64, testU2fSignResponse] } });
    179154        return navigator.credentials.get(options).then(credential => {
    180             return checkResult(credential, true);
     155            return checkU2fGetAssertionResult(credential, true);
    181156        });
    182157    }, "PublicKeyCredential's [[get]] with multiple credentials and AppID is used in a mock hid authenticator.");
     
    195170            testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", canDowngrade: true, payloadBase64: [testCtapErrInvalidCredentialResponseBase64, testU2fSignResponse] } });
    196171        return navigator.credentials.get(options).then(credential => {
    197             return checkResult(credential);
     172            return checkU2fGetAssertionResult(credential);
    198173        });
    199174    }, "PublicKeyCredential's [[get]] with downgraded authenticator in a mock hid authenticator.");
     
    212187            testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", canDowngrade: true, payloadBase64: [testCtapErrInvalidCredentialResponseBase64, testU2fApduWrongDataOnlyResponseBase64, testU2fSignResponse] } });
    213188        return navigator.credentials.get(options).then(credential => {
    214             return checkResult(credential, true, "7eabc5cc3251bdc59115ef87b5f7ee74cb03747e39ba8341748565cc129c0719");
     189            return checkU2fGetAssertionResult(credential, true, "7eabc5cc3251bdc59115ef87b5f7ee74cb03747e39ba8341748565cc129c0719");
    215190        });
    216191    }, "PublicKeyCredential's [[get]] with downgraded authenticator in a mock hid authenticator. (AppID)");
  • trunk/LayoutTests/http/wpt/webauthn/resources/util.js

    r245500 r249059  
    100100const testCtapErrCredentialExcludedOnlyResponseBase64 = "GQ==";
    101101const testCtapErrInvalidCredentialResponseBase64 = "Ig==";
     102const testNfcU2fVersionBase64 = "VTJGX1YykAA=";
     103const testNfcCtapVersionBase64 = "RklET18yXzCQAA==";
     104const testGetInfoResponseApduBase64 =
     105    "AKYBgmZVMkZfVjJoRklET18yXzACgWtobWFjLXNlY3JldANQbUS6m/bsLkm5MAyP" +
     106    "6SDLcwSkYnJr9WJ1cPVkcGxhdPRpY2xpZW50UGlu9AUZBLAGgQGQAA==";
     107const testCreationMessageApduBase64 =
     108    "AKMBZnBhY2tlZAJYxEbMf7lnnVWy25CS4cjZ5eHQK3WA8LSBLHcJYuHkj1rYQQAA" +
     109    "AE74oBHzjApNFYAGFxEfntx9AEAoCK3O6P5OyXN6V/f+9nAga0NA2Cgp4V3mgSJ5" +
     110    "jOHLMDrmxp/S0rbD+aihru1C0aAN3BkiM6GNy5nSlDVqOgTgpQECAyYgASFYIEFb" +
     111    "he3RkNud6sgyraBGjlh1pzTlCZehQlL/b18HZ6WGIlggJgfUd/en9p5AIqMQbUni" +
     112    "nEeXdFLkvW0/zV5BpEjjNxADo2NhbGcmY3NpZ1hHMEUCIQDKg+ZBmEBtf0lWq4Re" +
     113    "dH4/i/LOYqOR4uR2NAj2zQmw9QIgbTXb4hvFbj4T27bv/rGrc+y+0puoYOBkBk9P" +
     114    "mCewWlNjeDVjgVkCwjCCAr4wggGmoAMCAQICBHSG/cIwDQYJKoZIhvcNAQELBQAw" +
     115    "LjEsMCoGA1UEAxMjWXViaWNvIFUyRiBSb290IENBIFNlcmlhbCA0NTcyMDA2MzEw" +
     116    "IBcNMTQwODAxMDAwMDAwWhgPMjA1MDA5MDQwMDAwMDBaMG8xCzAJBgNVBAYTAlNF" +
     117    "MRIwEAYDVQQKDAlZdWJpY28gQUIxIjAgBgNVBAsMGUF1dGhlbnRpY2F0b3IgQXR0" +
     118    "ZXN0YXRpb24xKDAmBgNVBAMMH1l1YmljbyBVMkYgRUUgU2VyaWFsIDE5NTUwMDM4" +
     119    "NDIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASVXfOt9yR9MXXv/ZzE8xpOh466" +
     120    "4YEJVmFQ+ziLLl9lJ79XQJqlgaUNCsUvGERcChNUihNTyKTlmnBOUjvATevto2ww" +
     121    "ajAiBgkrBgEEAYLECgIEFTEuMy42LjEuNC4xLjQxNDgyLjEuMTATBgsrBgEEAYLl" +
     122    "HAIBAQQEAwIFIDAhBgsrBgEEAYLlHAEBBAQSBBD4oBHzjApNFYAGFxEfntx9MAwG" +
     123    "A1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggEBADFcSIDmmlJ+OGaJvWn9Cqhv" +
     124    "SeueToVFQVVvqtALOgCKHdwB+Wx29mg2GpHiMsgQp5xjB0ybbnpG6x212FxESJ+G" +
     125    "inZD0ipchi7APwPlhIvjgH16zVX44a4e4hOsc6tLIOP71SaMsHuHgCcdH0vg5d2s" +
     126    "c006WJe9TXO6fzV+ogjJnYpNKQLmCXoAXE3JBNwKGBIOCvfQDPyWmiiG5bGxYfPt" +
     127    "y8Z3pnjX+1MDnM2hhr40ulMxlSNDnX/ZSnDyMGIbk8TOQmjTF02UO8auP8k3wt5D" +
     128    "1rROIRU9+FCSX5WQYi68RuDrGMZB8P5+byoJqbKQdxn2LmE1oZAyohPAmLcoPO6Q" +
     129    "AA==";
     130const testAssertionMessageApduBase64 =
     131    "AKMBomJpZFhAKAitzuj+Tslzelf3/vZwIGtDQNgoKeFd5oEieYzhyzA65saf0tK2" +
     132    "w/mooa7tQtGgDdwZIjOhjcuZ0pQ1ajoE4GR0eXBlanB1YmxpYy1rZXkCWCVGzH+5" +
     133    "Z51VstuQkuHI2eXh0Ct1gPC0gSx3CWLh5I9a2AEAAABQA1hHMEUCIQCSFTuuBWgB" +
     134    "4/F0VB7DlUVM09IHPmxe1MzHUwRoCRZbCAIgGKov6xoAx2MEf6/6qNs8OutzhP2C" +
     135    "QoJ1L7Fe64G9uBeQAA==";
    102136
    103137const RESOURCES_DIR = "/WebKit/webauthn/resources/";
     
    298332    return true;
    299333}
     334
     335function checkCtapMakeCredentialResult(credential, isNoneAttestation = true)
     336{
     337    // Check response
     338    assert_array_equals(Base64URL.parse(credential.id), Base64URL.parse(testHidCredentialIdBase64));
     339    assert_equals(credential.type, 'public-key');
     340    assert_array_equals(new Uint8Array(credential.rawId), Base64URL.parse(testHidCredentialIdBase64));
     341    assert_equals(bytesToASCIIString(credential.response.clientDataJSON), '{"type":"webauthn.create","challenge":"MTIzNDU2","origin":"https://localhost:9443"}');
     342    assert_not_exists(credential.getClientExtensionResults(), "appid");
     343
     344    // Check attestation
     345    const attestationObject = CBOR.decode(credential.response.attestationObject);
     346    if (isNoneAttestation)
     347        assert_equals(attestationObject.fmt, "none");
     348    else
     349        assert_equals(attestationObject.fmt, "packed");
     350    // Check authData
     351    const authData = decodeAuthData(attestationObject.authData);
     352    assert_equals(bytesToHexString(authData.rpIdHash), "46cc7fb9679d55b2db9092e1c8d9e5e1d02b7580f0b4812c770962e1e48f5ad8");
     353    assert_equals(authData.flags, 65);
     354    assert_equals(authData.counter, 78);
     355    if (isNoneAttestation)
     356        assert_equals(bytesToHexString(authData.aaguid), "00000000000000000000000000000000");
     357    else
     358        assert_equals(bytesToHexString(authData.aaguid), "f8a011f38c0a4d15800617111f9edc7d");
     359    assert_array_equals(authData.credentialID, Base64URL.parse(testHidCredentialIdBase64));
     360    // Check packed attestation
     361    assert_true(checkPublicKey(authData.publicKey));
     362    if (isNoneAttestation)
     363        assert_object_equals(attestationObject.attStmt, { });
     364    else {
     365        assert_equals(attestationObject.attStmt.alg, -7);
     366        assert_equals(attestationObject.attStmt.x5c.length, 1);
     367    }
     368}
     369
     370function checkU2fMakeCredentialResult(credential, isNoneAttestation = true)
     371{
     372    // Check response
     373    assert_array_equals(Base64URL.parse(credential.id), Base64URL.parse(testU2fCredentialIdBase64));
     374    assert_equals(credential.type, 'public-key');
     375    assert_array_equals(new Uint8Array(credential.rawId), Base64URL.parse(testU2fCredentialIdBase64));
     376    assert_equals(bytesToASCIIString(credential.response.clientDataJSON), '{"type":"webauthn.create","challenge":"MTIzNDU2","origin":"https://localhost:9443"}');
     377    assert_not_exists(credential.getClientExtensionResults(), "appid");
     378
     379    // Check attestation
     380    const attestationObject = CBOR.decode(credential.response.attestationObject);
     381    if (isNoneAttestation)
     382        assert_equals(attestationObject.fmt, "none");
     383    else
     384        assert_equals(attestationObject.fmt, "fido-u2f");
     385    // Check authData
     386    const authData = decodeAuthData(attestationObject.authData);
     387    assert_equals(bytesToHexString(authData.rpIdHash), "49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d9763");
     388    assert_equals(authData.flags, 65);
     389    assert_equals(authData.counter, 0);
     390    assert_equals(bytesToHexString(authData.aaguid), "00000000000000000000000000000000");
     391    assert_array_equals(authData.credentialID, Base64URL.parse(testU2fCredentialIdBase64));
     392    // Check fido-u2f attestation
     393    assert_true(checkPublicKey(authData.publicKey));
     394    if (isNoneAttestation)
     395        assert_object_equals(attestationObject.attStmt, { });
     396    else
     397        assert_equals(attestationObject.attStmt.x5c.length, 1);
     398}
     399
     400function checkCtapGetAssertionResult(credential)
     401{
     402    // Check respond
     403    assert_array_equals(Base64URL.parse(credential.id), Base64URL.parse(testHidCredentialIdBase64));
     404    assert_equals(credential.type, 'public-key');
     405    assert_array_equals(new Uint8Array(credential.rawId), Base64URL.parse(testHidCredentialIdBase64));
     406    assert_equals(bytesToASCIIString(credential.response.clientDataJSON), '{"type":"webauthn.get","challenge":"MTIzNDU2","origin":"https://localhost:9443"}');
     407    assert_equals(credential.response.userHandle, null);
     408    assert_not_exists(credential.getClientExtensionResults(), "appid");
     409
     410    // Check authData
     411    const authData = decodeAuthData(new Uint8Array(credential.response.authenticatorData));
     412    assert_equals(bytesToHexString(authData.rpIdHash), "46cc7fb9679d55b2db9092e1c8d9e5e1d02b7580f0b4812c770962e1e48f5ad8");
     413    assert_equals(authData.flags, 1);
     414    assert_equals(authData.counter, 80);
     415}
     416
     417function checkU2fGetAssertionResult(credential, isAppID = false, appIDHash = "c2671b6eb9233197d5f2b1288a55ba4f0860f96f7199bba32fe6da7c3f0f31e5")
     418{
     419    // Check respond
     420    assert_array_equals(Base64URL.parse(credential.id), Base64URL.parse(testU2fCredentialIdBase64));
     421    assert_equals(credential.type, 'public-key');
     422    assert_array_equals(new Uint8Array(credential.rawId), Base64URL.parse(testU2fCredentialIdBase64));
     423    assert_equals(bytesToASCIIString(credential.response.clientDataJSON), '{"type":"webauthn.get","challenge":"MTIzNDU2","origin":"https://localhost:9443"}');
     424    assert_equals(credential.response.userHandle, null);
     425    if (!isAppID)
     426        assert_not_exists(credential.getClientExtensionResults(), "appid");
     427    else
     428        assert_true(credential.getClientExtensionResults().appid);
     429
     430    // Check authData
     431    const authData = decodeAuthData(new Uint8Array(credential.response.authenticatorData));
     432    if (!isAppID)
     433        assert_equals(bytesToHexString(authData.rpIdHash), "49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d9763");
     434    else
     435        assert_equals(bytesToHexString(authData.rpIdHash), appIDHash);
     436    assert_equals(authData.flags, 1);
     437    assert_equals(authData.counter, 59);
     438}
  • trunk/LayoutTests/platform/ios-simulator-wk2/TestExpectations

    r248734 r249059  
    9090
    9191webkit.org/b/172001 scrollingcoordinator/ios/sync-layer-positions-after-scroll.html [ Pass Failure ]
     92
     93# NearField.framework doesn't present in the simulator, and therefore skip all WebAuthn NFC tests
     94http/wpt/webauthn/ctap-nfc-failure.https.html [ Skip ]
     95http/wpt/webauthn/public-key-credential-create-failure-nfc.https.html [ Skip ]
     96http/wpt/webauthn/public-key-credential-create-success-nfc.https.html [ Skip ]
     97http/wpt/webauthn/public-key-credential-get-failure-nfc.https.html [ Skip ]
     98http/wpt/webauthn/public-key-credential-get-success-nfc.https.html [ Skip ]
  • trunk/Source/WTF/ChangeLog

    r249036 r249059  
     12019-08-21  Jiewen Tan  <jiewen_tan@apple.com>
     2
     3        [WebAuthn] Support NFC authenticators for iOS
     4        https://bugs.webkit.org/show_bug.cgi?id=188624
     5        <rdar://problem/43354214>
     6
     7        Reviewed by Chris Dumez.
     8
     9        * wtf/Platform.h:
     10        Add a feature flag for NearField.
     11
    1122019-08-22  Andy Estes  <aestes@apple.com>
    213
  • trunk/Source/WTF/wtf/Platform.h

    r249036 r249059  
    16421642#define HAVE_DATA_PROTECTION_KEYCHAIN 1
    16431643#endif
     1644
     1645#if !PLATFORM(IOS_FAMILY_SIMULATOR)
     1646#define HAVE_NEAR_FIELD 1
     1647#endif
     1648
     1649#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500) || (PLATFORM(IOS_FAMILY) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 130000)
     1650#define HAVE_NF_READER_SESSION_UPDATE_UI_ALERT_MESSAGE 1
     1651#endif
  • trunk/Source/WebCore/ChangeLog

    r249058 r249059  
     12019-08-20  Jiewen Tan  <jiewen_tan@apple.com>
     2
     3        [WebAuthn] Support NFC authenticators for iOS
     4        https://bugs.webkit.org/show_bug.cgi?id=188624
     5        <rdar://problem/43354214>
     6
     7        Reviewed by Chris Dumez.
     8
     9        Tests: http/wpt/webauthn/ctap-nfc-failure.https.html
     10               http/wpt/webauthn/public-key-credential-create-failure-nfc.https.html
     11               http/wpt/webauthn/public-key-credential-create-success-nfc.https.html
     12               http/wpt/webauthn/public-key-credential-get-failure-nfc.https.html
     13               http/wpt/webauthn/public-key-credential-get-success-nfc.https.html
     14
     15        * Modules/webauthn/apdu/ApduResponse.h:
     16        Adds a new method to support moving m_data.
     17        * Modules/webauthn/fido/FidoConstants.h:
     18        Adds constants for NFC applet selection.
     19
    1202019-08-23  Ross Kirsling  <ross.kirsling@sony.com>
    221
  • trunk/Source/WebCore/Modules/webauthn/apdu/ApduResponse.h

    r242776 r249059  
    6262
    6363    const Vector<uint8_t>& data() const { return m_data; }
     64    Vector<uint8_t>& data() { return m_data; }
    6465    Status status() const { return m_responseStatus; }
    6566
  • trunk/Source/WebCore/Modules/webauthn/fido/FidoConstants.h

    r245638 r249059  
    221221// CTAPHID Usage Page and Usage
    222222// https://fidoalliance.org/specs/fido-v2.0-ps-20170927/fido-client-to-authenticator-protocol-v2.0-ps-20170927.html#hid-report-descriptor-and-device-discovery
    223 const uint32_t kCTAPHIDUsagePage = 0xF1D0;
    224 const uint32_t kCTAPHIDUsage = 0x01;
     223const uint32_t kCtapHidUsagePage = 0xF1D0;
     224const uint32_t kCtapHidUsage = 0x01;
     225
     226// CTAPNFC Applet selection command and responses
     227// https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#nfc-applet-selection
     228const uint8_t kCtapNfcAppletSelectionCommand[] = {
     229    0x00, 0xA4, 0x04, 0x00, // CLA, INS, P1, P2
     230    0x08, // L
     231    0xA0, 0x00, 0x00, 0x06, 0x47, // RID
     232    0x2F, 0x00, 0x01 // PIX
     233};
     234
     235const uint8_t kCtapNfcAppletSelectionU2f[] = {
     236    0x55, 0x32, 0x46, 0x5F, 0x56, 0x32, // Version
     237    0x90, 0x00 // APDU response code
     238};
     239
     240const uint8_t kCtapNfcAppletSelectionCtap[] = {
     241    0x46, 0x49, 0x44, 0x4f, 0x5f, 0x32, 0x5f, 0x30, // Version
     242    0x90, 0x00 // APDU response code
     243};
     244
     245// https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#nfc-command-framing
     246const uint8_t kCtapNfcApduCla = 0x80;
     247const uint8_t kCtapNfcApduIns = 0x10;
    225248
    226249} // namespace fido
  • trunk/Source/WebKit/ChangeLog

    r249056 r249059  
     12019-08-20  Jiewen Tan  <jiewen_tan@apple.com>
     2
     3        [WebAuthn] Support NFC authenticators for iOS
     4        https://bugs.webkit.org/show_bug.cgi?id=188624
     5        <rdar://problem/43354214>
     6
     7        Reviewed by Chris Dumez.
     8
     9        This patch implements support for NFC authenticators including both FIDO2 and U2F ones. It utilizes a private
     10        framework called NearField instead of CoreNFC to be able to supply a custom UI later if necessary.
     11
     12        The patch follows almost the same flow as previous HID and Local authenticator support.
     13        1) Discovery is via NfcService which will invoke NFHardwareManager to start a generic NFC reader session.
     14        2) Once a reader session is established, a NfcConnection is created to start the polling and register the WKNFReaderSessionDelegate
     15        to wait for 'didDetectTags'.
     16        3) When tags are detected, NfcConnection will determine if it meets our requriements: { type, connectability, fido applet availability }.
     17        The first tag that meets all requirement will then be returned for WebAuthn operations.
     18        4) The first WebAuthn operation is to send authenticatorGetInfo command to determine the supported protocol, and then initialize corresponding
     19        authenticators. Noted, the sending/receiving of this command is now abstracted into FidoService which will be shared across HidService and NfcService.
     20        5) From then, the actual WebAuthn request, either makeCredential or getAssertion will be sent.
     21
     22        For testing, this patch follows the same flow as well.
     23        1) MockNfcService overrides NfcService to mock the behavior of NFC Tags discovery.
     24        2) The same class also swizzles methods from NFReaderSession to mock tag connection and communication.
     25
     26        * Platform/spi/Cocoa/NearFieldSPI.h: Added.
     27        * Sources.txt:
     28        * SourcesCocoa.txt:
     29        * UIProcess/API/C/WKWebsiteDataStoreRef.cpp:
     30        (WKWebsiteDataStoreSetWebAuthenticationMockConfiguration):
     31        * UIProcess/WebAuthentication/AuthenticatorManager.cpp:
     32        (WebKit::AuthenticatorManagerInternal::collectTransports):
     33        * UIProcess/WebAuthentication/AuthenticatorTransportService.cpp:
     34        (WebKit::AuthenticatorTransportService::create):
     35        (WebKit::AuthenticatorTransportService::createMock):
     36        * UIProcess/WebAuthentication/Cocoa/HidService.h:
     37        * UIProcess/WebAuthentication/Cocoa/HidService.mm:
     38        (WebKit::HidService::HidService):
     39        (WebKit::HidService::deviceAdded):
     40        (WebKit::HidService::continueAddDeviceAfterGetInfo): Deleted.
     41        * UIProcess/WebAuthentication/Cocoa/NearFieldSoftLink.h: Copied from Source/WebKit/UIProcess/WebAuthentication/Cocoa/HidService.h.
     42        * UIProcess/WebAuthentication/Cocoa/NearFieldSoftLink.mm: Copied from Source/WebKit/UIProcess/WebAuthentication/Cocoa/HidService.h.
     43        * UIProcess/WebAuthentication/Cocoa/NfcConnection.h: Copied from Source/WebKit/UIProcess/WebAuthentication/Cocoa/HidService.h.
     44        * UIProcess/WebAuthentication/Cocoa/NfcConnection.mm: Added.
     45        (WebKit::fido::compareVersion):
     46        (WebKit::NfcConnection::NfcConnection):
     47        (WebKit::NfcConnection::~NfcConnection):
     48        (WebKit::NfcConnection::transact const):
     49        (WebKit::NfcConnection::didDetectTags const):
     50        * UIProcess/WebAuthentication/Cocoa/NfcService.h: Copied from Source/WebKit/UIProcess/WebAuthentication/Cocoa/HidService.h.
     51        * UIProcess/WebAuthentication/Cocoa/NfcService.mm: Added.
     52        (WebKit::NfcService::NfcService):
     53        (WebKit::NfcService::~NfcService):
     54        (WebKit::NfcService::didConnectTag):
     55        (WebKit::NfcService::startDiscoveryInternal):
     56        (WebKit::NfcService::platformStartDiscovery):
     57        * UIProcess/WebAuthentication/Cocoa/WKNFReaderSessionDelegate.h: Copied from Source/WebKit/UIProcess/WebAuthentication/Cocoa/HidService.h.
     58        * UIProcess/WebAuthentication/Cocoa/WKNFReaderSessionDelegate.mm: Copied from Source/WebKit/UIProcess/WebAuthentication/Cocoa/HidService.h.
     59        (-[WKNFReaderSessionDelegate initWithConnection:]):
     60        (-[WKNFReaderSessionDelegate readerSession:didDetectTags:]):
     61        * UIProcess/WebAuthentication/Mock/MockHidConnection.cpp:
     62        (WebKit::MockHidConnection::send):
     63        (WebKit::MockHidConnection::registerDataReceivedCallbackInternal):
     64        (WebKit::MockHidConnection::parseRequest):
     65        (WebKit::MockHidConnection::feedReports):
     66        (WebKit::MockHidConnection::shouldContinueFeedReports):
     67        * UIProcess/WebAuthentication/Mock/MockNfcService.h: Copied from Source/WebKit/UIProcess/WebAuthentication/Cocoa/HidService.h.
     68        * UIProcess/WebAuthentication/Mock/MockNfcService.mm: Added.
     69        (-[WKMockNFTag type]):
     70        (-[WKMockNFTag initWithNFTag:]):
     71        (-[WKMockNFTag description]):
     72        (-[WKMockNFTag isEqualToNFTag:]):
     73        (-[WKMockNFTag initWithType:]):
     74        (WebKit::MockNfcService::MockNfcService):
     75        (WebKit::MockNfcService::transceive):
     76        (WebKit::MockNfcService::platformStartDiscovery):
     77        (WebKit::MockNfcService::detectTags const):
     78        * UIProcess/WebAuthentication/Mock/MockWebAuthenticationConfiguration.h:
     79        * UIProcess/WebAuthentication/fido/CtapAuthenticator.cpp:
     80        * UIProcess/WebAuthentication/fido/CtapAuthenticator.h:
     81        * UIProcess/WebAuthentication/fido/CtapNfcDriver.cpp: Added.
     82        (WebKit::CtapNfcDriver::CtapNfcDriver):
     83        (WebKit::CtapNfcDriver::transact):
     84        (WebKit::CtapNfcDriver::respondAsync const):
     85        * UIProcess/WebAuthentication/fido/CtapNfcDriver.h: Copied from Source/WebKit/UIProcess/WebAuthentication/Cocoa/HidService.h.
     86        * UIProcess/WebAuthentication/fido/FidoService.cpp: Added.
     87        (WebKit::FidoService::FidoService):
     88        (WebKit::FidoService::getInfo):
     89        (WebKit::FidoService::continueAfterGetInfo):
     90        * UIProcess/WebAuthentication/fido/FidoService.h: Copied from Source/WebKit/UIProcess/WebAuthentication/Cocoa/HidService.h.
     91        * UIProcess/WebAuthentication/fido/U2fAuthenticator.cpp:
     92        * UIProcess/WebAuthentication/fido/U2fAuthenticator.h:
     93        * UIProcess/ios/WebPageProxyIOS.mm:
     94        * WebKit.xcodeproj/project.pbxproj:
     95
    1962019-08-23  Kate Cheney  <katherine_cheney@apple.com>
    297
  • trunk/Source/WebKit/Sources.txt

    r248734 r249059  
    409409UIProcess/WebAuthentication/fido/CtapAuthenticator.cpp
    410410UIProcess/WebAuthentication/fido/CtapHidDriver.cpp
     411UIProcess/WebAuthentication/fido/CtapNfcDriver.cpp
     412UIProcess/WebAuthentication/fido/FidoService.cpp
    411413UIProcess/WebAuthentication/fido/U2fAuthenticator.cpp
    412414
  • trunk/Source/WebKit/SourcesCocoa.txt

    r249001 r249059  
    498498UIProcess/WebAuthentication/Cocoa/LocalConnection.mm
    499499UIProcess/WebAuthentication/Cocoa/LocalService.mm
     500UIProcess/WebAuthentication/Cocoa/NearFieldSoftLink.mm @no-unify
     501UIProcess/WebAuthentication/Cocoa/NfcConnection.mm
     502UIProcess/WebAuthentication/Cocoa/NfcService.mm
     503UIProcess/WebAuthentication/Cocoa/WKNFReaderSessionDelegate.mm
    500504
    501505UIProcess/WebAuthentication/Mock/MockLocalConnection.mm
    502506UIProcess/WebAuthentication/Mock/MockLocalService.mm
     507UIProcess/WebAuthentication/Mock/MockNfcService.mm
    503508
    504509UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm
  • trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp

    r248734 r249059  
    633633        if (stage == "info")
    634634            hid.stage = WebKit::MockWebAuthenticationConfiguration::Hid::Stage::Info;
    635         if (stage == "request")
     635        else if (stage == "request")
    636636            hid.stage = WebKit::MockWebAuthenticationConfiguration::Hid::Stage::Request;
    637637
     
    639639        if (subStage == "init")
    640640            hid.subStage = WebKit::MockWebAuthenticationConfiguration::Hid::SubStage::Init;
    641         if (subStage == "msg")
     641        else if (subStage == "msg")
    642642            hid.subStage = WebKit::MockWebAuthenticationConfiguration::Hid::SubStage::Msg;
    643643
     
    645645        if (error == "success")
    646646            hid.error = WebKit::MockWebAuthenticationConfiguration::Hid::Error::Success;
    647         if (error == "data-not-sent")
     647        else if (error == "data-not-sent")
    648648            hid.error = WebKit::MockWebAuthenticationConfiguration::Hid::Error::DataNotSent;
    649         if (error == "empty-report")
     649        else if (error == "empty-report")
    650650            hid.error = WebKit::MockWebAuthenticationConfiguration::Hid::Error::EmptyReport;
    651         if (error == "wrong-channel-id")
     651        else if (error == "wrong-channel-id")
    652652            hid.error = WebKit::MockWebAuthenticationConfiguration::Hid::Error::WrongChannelId;
    653         if (error == "malicious-payload")
     653        else if (error == "malicious-payload")
    654654            hid.error = WebKit::MockWebAuthenticationConfiguration::Hid::Error::MaliciousPayload;
    655         if (error == "unsupported-options")
     655        else if (error == "unsupported-options")
    656656            hid.error = WebKit::MockWebAuthenticationConfiguration::Hid::Error::UnsupportedOptions;
    657         if (error == "wrong-nonce")
     657        else if (error == "wrong-nonce")
    658658            hid.error = WebKit::MockWebAuthenticationConfiguration::Hid::Error::WrongNonce;
    659659
     
    679679    }
    680680
     681    if (auto nfcRef = static_cast<WKDictionaryRef>(WKDictionaryGetItemForKey(configurationRef, adoptWK(WKStringCreateWithUTF8CString("Nfc")).get()))) {
     682        WebKit::MockWebAuthenticationConfiguration::Nfc nfc;
     683
     684        auto error = WebKit::toImpl(static_cast<WKStringRef>(WKDictionaryGetItemForKey(nfcRef, adoptWK(WKStringCreateWithUTF8CString("Error")).get())))->string();
     685        if (error == "success")
     686            nfc.error = WebKit::MockWebAuthenticationConfiguration::Nfc::Error::Success;
     687        else if (error == "no-tags")
     688            nfc.error = WebKit::MockWebAuthenticationConfiguration::Nfc::Error::NoTags;
     689        else if (error == "wrong-tag-type")
     690            nfc.error = WebKit::MockWebAuthenticationConfiguration::Nfc::Error::WrongTagType;
     691        else if (error == "no-connections")
     692            nfc.error = WebKit::MockWebAuthenticationConfiguration::Nfc::Error::NoConnections;
     693        else if (error == "malicious-payload")
     694            nfc.error = WebKit::MockWebAuthenticationConfiguration::Nfc::Error::MaliciousPayload;
     695
     696        if (auto payloadBase64 = static_cast<WKArrayRef>(WKDictionaryGetItemForKey(nfcRef, adoptWK(WKStringCreateWithUTF8CString("PayloadBase64")).get())))
     697            nfc.payloadBase64 = WebKit::toImpl(payloadBase64)->toStringVector();
     698
     699        if (auto multipleTags = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(nfcRef, adoptWK(WKStringCreateWithUTF8CString("MultipleTags")).get())))
     700            nfc.multipleTags = WKBooleanGetValue(multipleTags);
     701
     702        configuration.nfc = WTFMove(nfc);
     703    }
     704
    681705    WebKit::toImpl(dataStoreRef)->websiteDataStore().setMockWebAuthenticationConfiguration(WTFMove(configuration));
    682706#endif
  • trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp

    r246369 r249059  
    3939
    4040#if PLATFORM(MAC)
     41const size_t maxTransportNumber = 3;
     42#else
    4143const size_t maxTransportNumber = 2;
    42 #else
    43 const size_t maxTransportNumber = 1;
    4444#endif
    4545
     
    4747const unsigned maxTimeOutValue = 120000;
    4848
    49 // FIXME(188624, 188625): Support NFC and BLE authenticators.
     49// FIXME(188625): Support BLE authenticators.
    5050static AuthenticatorManager::TransportSet collectTransports(const Optional<PublicKeyCredentialCreationOptions::AuthenticatorSelectionCriteria>& authenticatorSelection)
    5151{
     
    5858        ASSERT_UNUSED(addResult, addResult.isNewEntry);
    5959#endif
     60        addResult = result.add(AuthenticatorTransport::Nfc);
     61        ASSERT_UNUSED(addResult, addResult.isNewEntry);
    6062        return result;
    6163    }
     
    6769    }
    6870    if (authenticatorSelection->authenticatorAttachment == PublicKeyCredentialCreationOptions::AuthenticatorAttachment::CrossPlatform) {
    69 #if PLATFORM(MAC)
    70         auto addResult = result.add(AuthenticatorTransport::Usb);
     71        auto addResult = result.add(AuthenticatorTransport::Nfc);
     72        ASSERT_UNUSED(addResult, addResult.isNewEntry);
     73#if PLATFORM(MAC)
     74        addResult = result.add(AuthenticatorTransport::Usb);
    7175        ASSERT_UNUSED(addResult, addResult.isNewEntry);
    7276#endif
     
    9397        ASSERT_UNUSED(addResult, addResult.isNewEntry);
    9498#endif
     99        addResult = result.add(AuthenticatorTransport::Nfc);
     100        ASSERT_UNUSED(addResult, addResult.isNewEntry);
    95101        return result;
    96102    }
     
    101107#if PLATFORM(MAC)
    102108            result.add(AuthenticatorTransport::Usb);
     109#endif
     110            result.add(AuthenticatorTransport::Nfc);
    103111            return result;
    104 #endif
    105112        }
    106113        if (!result.contains(AuthenticatorTransport::Internal) && allowCredential.transports.contains(AuthenticatorTransport::Internal))
     
    110117            result.add(AuthenticatorTransport::Usb);
    111118#endif
     119        if (!result.contains(AuthenticatorTransport::Nfc) && allowCredential.transports.contains(AuthenticatorTransport::Nfc))
     120            result.add(AuthenticatorTransport::Nfc);
    112121        if (result.size() >= maxTransportNumber)
    113122            return result;
  • trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorTransportService.cpp

    r238166 r249059  
    3333#include "MockHidService.h"
    3434#include "MockLocalService.h"
     35#include "MockNfcService.h"
     36#include "NfcService.h"
    3537#include <wtf/RunLoop.h>
    3638
     
    4648        return makeUniqueRef<HidService>(observer);
    4749#endif
     50    case WebCore::AuthenticatorTransport::Nfc:
     51        return makeUniqueRef<NfcService>(observer);
    4852    default:
    4953        ASSERT_NOT_REACHED();
     
    6165        return makeUniqueRef<MockHidService>(observer, configuration);
    6266#endif
     67    case WebCore::AuthenticatorTransport::Nfc:
     68        return makeUniqueRef<MockNfcService>(observer, configuration);
    6369    default:
    6470        ASSERT_NOT_REACHED();
  • trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/HidService.h

    r238468 r249059  
    2828#if ENABLE(WEB_AUTHN) && PLATFORM(MAC)
    2929
    30 #include "AuthenticatorTransportService.h"
     30#include "FidoService.h"
    3131#include <IOKit/hid/IOHIDManager.h>
    3232#include <wtf/RetainPtr.h>
     
    3535namespace WebKit {
    3636
    37 class CtapHidDriver;
    3837class HidConnection;
    3938
    40 class HidService : public AuthenticatorTransportService {
     39class HidService : public FidoService {
    4140public:
    4241    explicit HidService(Observer&);
     
    5251    virtual UniqueRef<HidConnection> createHidConnection(IOHIDDeviceRef) const;
    5352
    54     void continueAddDeviceAfterGetInfo(CtapHidDriver* deviceRef, Vector<uint8_t>&& info);
    55 
    5653    RetainPtr<IOHIDManagerRef> m_manager;
    57     // Keeping drivers alive when they are initializing authenticators.
    58     HashSet<std::unique_ptr<CtapHidDriver>> m_drivers;
    5954};
    6055
  • trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/HidService.mm

    r248846 r249059  
    2929#if ENABLE(WEB_AUTHN) && PLATFORM(MAC)
    3030
    31 #import "CtapAuthenticator.h"
    3231#import "CtapHidDriver.h"
    3332#import "HidConnection.h"
    34 #import "U2fAuthenticator.h"
    35 #import <WebCore/DeviceRequestConverter.h>
    36 #import <WebCore/DeviceResponseConverter.h>
    37 #import <WebCore/FidoConstants.h>
    38 #import <WebCore/FidoHidMessage.h>
    39 #import <wtf/RunLoop.h>
    4033
    4134namespace WebKit {
     
    5750
    5851HidService::HidService(Observer& observer)
    59     : AuthenticatorTransportService(observer)
     52    : FidoService(observer)
    6053{
    6154    m_manager = adoptCF(IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone));
    6255    NSDictionary *matchingDictionary = @{
    63         @kIOHIDPrimaryUsagePageKey: adoptNS([NSNumber numberWithInt:kCTAPHIDUsagePage]).get(),
    64         @kIOHIDPrimaryUsageKey: adoptNS([NSNumber numberWithInt:kCTAPHIDUsage]).get()
     56        @kIOHIDPrimaryUsagePageKey: adoptNS([NSNumber numberWithInt:kCtapHidUsagePage]).get(),
     57        @kIOHIDPrimaryUsageKey: adoptNS([NSNumber numberWithInt:kCtapHidUsage]).get()
    6558    };
    6659    IOHIDManagerSetDeviceMatching(m_manager.get(), (__bridge CFDictionaryRef)matchingDictionary);
     
    9386void HidService::deviceAdded(IOHIDDeviceRef device)
    9487{
    95     auto driver = makeUnique<CtapHidDriver>(createHidConnection(device));
    96     // Get authenticator info from the device.
    97     driver->transact(encodeEmptyAuthenticatorRequest(CtapRequestCommand::kAuthenticatorGetInfo), [weakThis = makeWeakPtr(*this), ptr = driver.get()](Vector<uint8_t>&& response) {
    98         ASSERT(RunLoop::isMain());
    99         if (!weakThis)
    100             return;
    101         weakThis->continueAddDeviceAfterGetInfo(ptr, WTFMove(response));
    102     });
    103     auto addResult = m_drivers.add(WTFMove(driver));
    104     ASSERT_UNUSED(addResult, addResult.isNewEntry);
    105 }
    106 
    107 void HidService::continueAddDeviceAfterGetInfo(CtapHidDriver* ptr, Vector<uint8_t>&& response)
    108 {
    109     std::unique_ptr<CtapHidDriver> driver = m_drivers.take(ptr);
    110     if (!driver || !observer() || response.isEmpty())
    111         return;
    112 
    113     auto info = readCTAPGetInfoResponse(response);
    114     if (info && info->versions().find(ProtocolVersion::kCtap) != info->versions().end()) {
    115         observer()->authenticatorAdded(CtapAuthenticator::create(WTFMove(driver), WTFMove(*info)));
    116         return;
    117     }
    118     LOG_ERROR("Couldn't parse a ctap get info response.");
    119     driver->setProtocol(ProtocolVersion::kU2f);
    120     observer()->authenticatorAdded(U2fAuthenticator::create(WTFMove(driver)));
     88    getInfo(WTF::makeUnique<CtapHidDriver>(createHidConnection(device)));
    12189}
    12290
  • trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NearFieldSoftLink.h

    r249058 r249059  
    11/*
    2  * Copyright (C) 2018 Apple Inc. All rights reserved.
     2 * Copyright (C) 2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2626#pragma once
    2727
    28 #if ENABLE(WEB_AUTHN) && PLATFORM(MAC)
     28#if ENABLE(WEB_AUTHN)
    2929
    30 #include "AuthenticatorTransportService.h"
    31 #include <IOKit/hid/IOHIDManager.h>
    32 #include <wtf/RetainPtr.h>
    33 #include <wtf/UniqueRef.h>
     30#import "NearFieldSPI.h"
     31#import <wtf/SoftLinking.h>
    3432
    35 namespace WebKit {
     33SOFT_LINK_FRAMEWORK_FOR_HEADER(WebKit, NearField);
    3634
    37 class CtapHidDriver;
    38 class HidConnection;
     35SOFT_LINK_CLASS_FOR_HEADER(WebKit, NFTag);
     36SOFT_LINK_CLASS_FOR_HEADER(WebKit, NFSession);
     37SOFT_LINK_CLASS_FOR_HEADER(WebKit, NFReaderSession);
     38SOFT_LINK_CLASS_FOR_HEADER(WebKit, NFHardwareManager);
    3939
    40 class HidService : public AuthenticatorTransportService {
    41 public:
    42     explicit HidService(Observer&);
    43     ~HidService();
    44 
    45     void deviceAdded(IOHIDDeviceRef);
    46 
    47 private:
    48     void startDiscoveryInternal() final;
    49 
    50     // Overrided by MockHidService.
    51     virtual void platformStartDiscovery();
    52     virtual UniqueRef<HidConnection> createHidConnection(IOHIDDeviceRef) const;
    53 
    54     void continueAddDeviceAfterGetInfo(CtapHidDriver* deviceRef, Vector<uint8_t>&& info);
    55 
    56     RetainPtr<IOHIDManagerRef> m_manager;
    57     // Keeping drivers alive when they are initializing authenticators.
    58     HashSet<std::unique_ptr<CtapHidDriver>> m_drivers;
    59 };
    60 
    61 } // namespace WebKit
    62 
    63 #endif // ENABLE(WEB_AUTHN) && PLATFORM(MAC)
     40#endif // ENABLE(WEB_AUTHN)
  • trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NearFieldSoftLink.mm

    r249058 r249059  
    11/*
    2  * Copyright (C) 2018 Apple Inc. All rights reserved.
     2 * Copyright (C) 2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2424 */
    2525
    26 #pragma once
     26#import "config.h"
    2727
    28 #if ENABLE(WEB_AUTHN) && PLATFORM(MAC)
     28#import <wtf/SoftLinking.h>
    2929
    30 #include "AuthenticatorTransportService.h"
    31 #include <IOKit/hid/IOHIDManager.h>
    32 #include <wtf/RetainPtr.h>
    33 #include <wtf/UniqueRef.h>
     30#if ENABLE(WEB_AUTHN)
    3431
    35 namespace WebKit {
     32SOFT_LINK_PRIVATE_FRAMEWORK_FOR_SOURCE(WebKit, NearField);
    3633
    37 class CtapHidDriver;
    38 class HidConnection;
     34SOFT_LINK_CLASS_FOR_SOURCE(WebKit, NearField, NFTag);
     35SOFT_LINK_CLASS_FOR_SOURCE(WebKit, NearField, NFSession);
     36SOFT_LINK_CLASS_FOR_SOURCE(WebKit, NearField, NFReaderSession);
    3937
    40 class HidService : public AuthenticatorTransportService {
    41 public:
    42     explicit HidService(Observer&);
    43     ~HidService();
     38#if PLATFORM(MAC)
     39SOFT_LINK_CLASS_FOR_SOURCE_OPTIONAL(WebKit, NearField, NFHardwareManager);
     40#else
     41SOFT_LINK_CLASS_FOR_SOURCE(WebKit, NearField, NFHardwareManager);
     42#endif
    4443
    45     void deviceAdded(IOHIDDeviceRef);
    46 
    47 private:
    48     void startDiscoveryInternal() final;
    49 
    50     // Overrided by MockHidService.
    51     virtual void platformStartDiscovery();
    52     virtual UniqueRef<HidConnection> createHidConnection(IOHIDDeviceRef) const;
    53 
    54     void continueAddDeviceAfterGetInfo(CtapHidDriver* deviceRef, Vector<uint8_t>&& info);
    55 
    56     RetainPtr<IOHIDManagerRef> m_manager;
    57     // Keeping drivers alive when they are initializing authenticators.
    58     HashSet<std::unique_ptr<CtapHidDriver>> m_drivers;
    59 };
    60 
    61 } // namespace WebKit
    62 
    63 #endif // ENABLE(WEB_AUTHN) && PLATFORM(MAC)
     44#endif // ENABLE(WEB_AUTHN)
  • trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcConnection.h

    r249058 r249059  
    11/*
    2  * Copyright (C) 2018 Apple Inc. All rights reserved.
     2 * Copyright (C) 2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2626#pragma once
    2727
    28 #if ENABLE(WEB_AUTHN) && PLATFORM(MAC)
     28#if ENABLE(WEB_AUTHN) && HAVE(NEAR_FIELD)
    2929
    30 #include "AuthenticatorTransportService.h"
    31 #include <IOKit/hid/IOHIDManager.h>
     30#include <wtf/FastMalloc.h>
     31#include <wtf/Noncopyable.h>
    3232#include <wtf/RetainPtr.h>
    33 #include <wtf/UniqueRef.h>
     33#include <wtf/WeakPtr.h>
     34
     35OBJC_CLASS NFReaderSession;
     36OBJC_CLASS NSArray;
     37OBJC_CLASS WKNFReaderSessionDelegate;
    3438
    3539namespace WebKit {
    3640
    37 class CtapHidDriver;
    38 class HidConnection;
     41class NfcService;
    3942
    40 class HidService : public AuthenticatorTransportService {
     43class NfcConnection : public CanMakeWeakPtr<NfcConnection> {
     44    WTF_MAKE_FAST_ALLOCATED;
     45    WTF_MAKE_NONCOPYABLE(NfcConnection);
    4146public:
    42     explicit HidService(Observer&);
    43     ~HidService();
     47    NfcConnection(RetainPtr<NFReaderSession>&&, NfcService&);
     48    ~NfcConnection();
    4449
    45     void deviceAdded(IOHIDDeviceRef);
     50    Vector<uint8_t> transact(Vector<uint8_t>&& data) const;
     51
     52    // For WKNFReaderSessionDelegate
     53    void didDetectTags(NSArray *) const;
    4654
    4755private:
    48     void startDiscoveryInternal() final;
    49 
    50     // Overrided by MockHidService.
    51     virtual void platformStartDiscovery();
    52     virtual UniqueRef<HidConnection> createHidConnection(IOHIDDeviceRef) const;
    53 
    54     void continueAddDeviceAfterGetInfo(CtapHidDriver* deviceRef, Vector<uint8_t>&& info);
    55 
    56     RetainPtr<IOHIDManagerRef> m_manager;
    57     // Keeping drivers alive when they are initializing authenticators.
    58     HashSet<std::unique_ptr<CtapHidDriver>> m_drivers;
     56    RetainPtr<NFReaderSession> m_session;
     57    RetainPtr<WKNFReaderSessionDelegate> m_delegate;
     58    WeakPtr<NfcService> m_service;
    5959};
    6060
    6161} // namespace WebKit
    6262
    63 #endif // ENABLE(WEB_AUTHN) && PLATFORM(MAC)
     63#endif // ENABLE(WEB_AUTHN) && HAVE(NEAR_FIELD)
  • trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcService.h

    r249058 r249059  
    11/*
    2  * Copyright (C) 2018 Apple Inc. All rights reserved.
     2 * Copyright (C) 2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2626#pragma once
    2727
    28 #if ENABLE(WEB_AUTHN) && PLATFORM(MAC)
     28#if ENABLE(WEB_AUTHN)
    2929
    30 #include "AuthenticatorTransportService.h"
    31 #include <IOKit/hid/IOHIDManager.h>
    32 #include <wtf/RetainPtr.h>
    33 #include <wtf/UniqueRef.h>
     30#include "FidoService.h"
     31
     32OBJC_CLASS NFReaderSession;
    3433
    3534namespace WebKit {
    3635
    37 class CtapHidDriver;
    38 class HidConnection;
     36class CtapNfcDriver;
    3937
    40 class HidService : public AuthenticatorTransportService {
     38class NfcService : public FidoService {
    4139public:
    42     explicit HidService(Observer&);
    43     ~HidService();
     40    explicit NfcService(Observer&);
     41    ~NfcService();
    4442
    45     void deviceAdded(IOHIDDeviceRef);
     43    // For NfcConnection.
     44    void didConnectTag();
     45
     46#if HAVE(NEAR_FIELD)
     47protected:
     48    void setDriver(std::unique_ptr<CtapNfcDriver>&&);
     49#endif
    4650
    4751private:
    4852    void startDiscoveryInternal() final;
     53    void continueAddDeviceAfterGetInfo(Vector<uint8_t>&& response);
    4954
    50     // Overrided by MockHidService.
     55    // Overrided by MockNfcService.
    5156    virtual void platformStartDiscovery();
    52     virtual UniqueRef<HidConnection> createHidConnection(IOHIDDeviceRef) const;
    5357
    54     void continueAddDeviceAfterGetInfo(CtapHidDriver* deviceRef, Vector<uint8_t>&& info);
    55 
    56     RetainPtr<IOHIDManagerRef> m_manager;
    57     // Keeping drivers alive when they are initializing authenticators.
    58     HashSet<std::unique_ptr<CtapHidDriver>> m_drivers;
     58#if HAVE(NEAR_FIELD)
     59    // Only one reader session is allowed per time.
     60    // Keep the reader session alive here when it tries to connect to a tag.
     61    std::unique_ptr<CtapNfcDriver> m_driver;
     62#endif
    5963};
    6064
    6165} // namespace WebKit
    6266
    63 #endif // ENABLE(WEB_AUTHN) && PLATFORM(MAC)
     67#endif // ENABLE(WEB_AUTHN)
  • trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/WKNFReaderSessionDelegate.h

    r249058 r249059  
    11/*
    2  * Copyright (C) 2018 Apple Inc. All rights reserved.
     2 * Copyright (C) 2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2626#pragma once
    2727
    28 #if ENABLE(WEB_AUTHN) && PLATFORM(MAC)
     28#if ENABLE(WEB_AUTHN) && HAVE(NEAR_FIELD)
    2929
    30 #include "AuthenticatorTransportService.h"
    31 #include <IOKit/hid/IOHIDManager.h>
    32 #include <wtf/RetainPtr.h>
    33 #include <wtf/UniqueRef.h>
     30#import "NearFieldSPI.h"
    3431
    3532namespace WebKit {
     33class NfcConnection;
     34}
    3635
    37 class CtapHidDriver;
    38 class HidConnection;
     36@interface WKNFReaderSessionDelegate : NSObject <NFReaderSessionDelegate>
    3937
    40 class HidService : public AuthenticatorTransportService {
    41 public:
    42     explicit HidService(Observer&);
    43     ~HidService();
     38- (instancetype)initWithConnection:(WebKit::NfcConnection&)connection;
    4439
    45     void deviceAdded(IOHIDDeviceRef);
     40@end
    4641
    47 private:
    48     void startDiscoveryInternal() final;
    49 
    50     // Overrided by MockHidService.
    51     virtual void platformStartDiscovery();
    52     virtual UniqueRef<HidConnection> createHidConnection(IOHIDDeviceRef) const;
    53 
    54     void continueAddDeviceAfterGetInfo(CtapHidDriver* deviceRef, Vector<uint8_t>&& info);
    55 
    56     RetainPtr<IOHIDManagerRef> m_manager;
    57     // Keeping drivers alive when they are initializing authenticators.
    58     HashSet<std::unique_ptr<CtapHidDriver>> m_drivers;
    59 };
    60 
    61 } // namespace WebKit
    62 
    63 #endif // ENABLE(WEB_AUTHN) && PLATFORM(MAC)
     42#endif // ENABLE(WEB_AUTHN) && HAVE(NEAR_FIELD)
  • trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/WKNFReaderSessionDelegate.mm

    r249058 r249059  
    11/*
    2  * Copyright (C) 2018 Apple Inc. All rights reserved.
     2 * Copyright (C) 2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2424 */
    2525
    26 #pragma once
     26#import "config.h"
     27#import "WKNFReaderSessionDelegate.h"
    2728
    28 #if ENABLE(WEB_AUTHN) && PLATFORM(MAC)
     29#if ENABLE(WEB_AUTHN) && HAVE(NEAR_FIELD)
    2930
    30 #include "AuthenticatorTransportService.h"
    31 #include <IOKit/hid/IOHIDManager.h>
    32 #include <wtf/RetainPtr.h>
    33 #include <wtf/UniqueRef.h>
     31#import "NfcConnection.h"
     32#import <wtf/RunLoop.h>
     33#import <wtf/WeakPtr.h>
    3434
    35 namespace WebKit {
     35#import "NearFieldSoftLink.h"
    3636
    37 class CtapHidDriver;
    38 class HidConnection;
     37@implementation WKNFReaderSessionDelegate {
     38    WeakPtr<WebKit::NfcConnection> _connection;
     39}
    3940
    40 class HidService : public AuthenticatorTransportService {
    41 public:
    42     explicit HidService(Observer&);
    43     ~HidService();
     41- (instancetype)initWithConnection:(WebKit::NfcConnection&)connection
     42{
     43    if ((self = [super init]))
     44        _connection = makeWeakPtr(connection);
     45    return self;
     46}
    4447
    45     void deviceAdded(IOHIDDeviceRef);
     48// Executed in a different thread.
     49- (void)readerSession:(NFReaderSession*)theSession didDetectTags:(NSArray<NFTag *> *)tags
     50{
     51    ASSERT(!RunLoop::isMain());
    4652
    47 private:
    48     void startDiscoveryInternal() final;
     53    RunLoop::main().dispatch([connection = _connection, tags = retainPtr(tags)] {
     54        if (!connection)
     55            return;
     56        connection->didDetectTags(tags.get());
     57    });
     58}
    4959
    50     // Overrided by MockHidService.
    51     virtual void platformStartDiscovery();
    52     virtual UniqueRef<HidConnection> createHidConnection(IOHIDDeviceRef) const;
     60@end
    5361
    54     void continueAddDeviceAfterGetInfo(CtapHidDriver* deviceRef, Vector<uint8_t>&& info);
    55 
    56     RetainPtr<IOHIDManagerRef> m_manager;
    57     // Keeping drivers alive when they are initializing authenticators.
    58     HashSet<std::unique_ptr<CtapHidDriver>> m_drivers;
    59 };
    60 
    61 } // namespace WebKit
    62 
    63 #endif // ENABLE(WEB_AUTHN) && PLATFORM(MAC)
     62#endif // ENABLE(WEB_AUTHN) && HAVE(NEAR_FIELD)
  • trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockHidConnection.cpp

    r245852 r249059  
    3939
    4040namespace WebKit {
    41 using Mock = MockWebAuthenticationConfiguration::Hid;
     41using MockHid = MockWebAuthenticationConfiguration::Hid;
    4242using namespace WebCore;
    4343using namespace cbor;
     
    8383
    8484            auto sent = DataSent::Yes;
    85             if (weakThis->stagesMatch() && weakThis->m_configuration.hid->error == Mock::Error::DataNotSent)
     85            if (weakThis->stagesMatch() && weakThis->m_configuration.hid->error == MockHid::Error::DataNotSent)
    8686                sent = DataSent::No;
    8787            callback(sent);
     
    9393void MockHidConnection::registerDataReceivedCallbackInternal()
    9494{
    95     if (stagesMatch() && m_configuration.hid->error == Mock::Error::EmptyReport) {
     95    if (stagesMatch() && m_configuration.hid->error == MockHid::Error::EmptyReport) {
    9696        receiveReport({ });
    9797        shouldContinueFeedReports();
     
    124124    if (m_requestMessage->cmd() == FidoHidDeviceCommand::kInit) {
    125125        auto previousSubStage = m_subStage;
    126         m_subStage = Mock::SubStage::Init;
    127         if (previousSubStage == Mock::SubStage::Msg)
    128             m_stage = Mock::Stage::Request;
     126        m_subStage = MockHid::SubStage::Init;
     127        if (previousSubStage == MockHid::SubStage::Msg)
     128            m_stage = MockHid::Stage::Request;
    129129    }
    130130    if (m_requestMessage->cmd() == FidoHidDeviceCommand::kCbor || m_requestMessage->cmd() == FidoHidDeviceCommand::kMsg)
    131         m_subStage = Mock::SubStage::Msg;
    132 
    133     if (m_stage == Mock::Stage::Request && m_subStage == Mock::SubStage::Msg) {
     131        m_subStage = MockHid::SubStage::Msg;
     132
     133    if (m_stage == MockHid::Stage::Request && m_subStage == MockHid::SubStage::Msg) {
    134134        // Make sure we issue different msg cmd for CTAP and U2F.
    135135        if (m_configuration.hid->canDowngrade && !m_configuration.hid->isU2f)
     
    177177
    178178    // Store nonce.
    179     if (m_subStage == Mock::SubStage::Init) {
     179    if (m_subStage == MockHid::SubStage::Init) {
    180180        m_nonce = m_requestMessage->getMessagePayload();
    181181        ASSERT(m_nonce.size() == kHidInitNonceLength);
     
    192192    using namespace MockHidConnectionInternal;
    193193
    194     if (m_subStage == Mock::SubStage::Init) {
     194    if (m_subStage == MockHid::SubStage::Init) {
    195195        Vector<uint8_t> payload;
    196196        payload.reserveInitialCapacity(kHidInitResponseSize);
    197197        payload.appendVector(m_nonce);
    198198        size_t writePosition = payload.size();
    199         if (stagesMatch() && m_configuration.hid->error == Mock::Error::WrongNonce)
     199        if (stagesMatch() && m_configuration.hid->error == MockHid::Error::WrongNonce)
    200200            payload[0]--;
    201201        payload.grow(kHidInitResponseSize);
    202202        cryptographicallyRandomValues(payload.data() + writePosition, CtapChannelIdSize);
    203203        auto channel = kHidBroadcastChannel;
    204         if (stagesMatch() && m_configuration.hid->error == Mock::Error::WrongChannelId)
     204        if (stagesMatch() && m_configuration.hid->error == MockHid::Error::WrongChannelId)
    205205            channel--;
    206206        FidoHidInitPacket initPacket(channel, FidoHidDeviceCommand::kInit, WTFMove(payload), payload.size());
     
    211211
    212212    Optional<FidoHidMessage> message;
    213     if (m_stage == Mock::Stage::Info && m_subStage == Mock::SubStage::Msg) {
     213    if (m_stage == MockHid::Stage::Info && m_subStage == MockHid::SubStage::Msg) {
    214214        Vector<uint8_t> infoData;
    215215        if (m_configuration.hid->canDowngrade)
     
    218218            infoData = encodeAsCBOR(AuthenticatorGetInfoResponse({ ProtocolVersion::kCtap }, Vector<uint8_t>(aaguidLength, 0u)));
    219219        infoData.insert(0, static_cast<uint8_t>(CtapDeviceResponseCode::kSuccess)); // Prepend status code.
    220         if (stagesMatch() && m_configuration.hid->error == Mock::Error::WrongChannelId)
     220        if (stagesMatch() && m_configuration.hid->error == MockHid::Error::WrongChannelId)
    221221            message = FidoHidMessage::create(m_currentChannel - 1, FidoHidDeviceCommand::kCbor, infoData);
    222222        else {
     
    228228    }
    229229
    230     if (m_stage == Mock::Stage::Request && m_subStage == Mock::SubStage::Msg) {
     230    if (m_stage == MockHid::Stage::Request && m_subStage == MockHid::SubStage::Msg) {
    231231        if (m_configuration.hid->keepAlive) {
    232232            m_configuration.hid->keepAlive = false;
     
    236236            return;
    237237        }
    238         if (stagesMatch() && m_configuration.hid->error == Mock::Error::UnsupportedOptions && (m_requireResidentKey || m_requireUserVerification))
     238        if (stagesMatch() && m_configuration.hid->error == MockHid::Error::UnsupportedOptions && (m_requireResidentKey || m_requireUserVerification))
    239239            message = FidoHidMessage::create(m_currentChannel, FidoHidDeviceCommand::kCbor, { static_cast<uint8_t>(CtapDeviceResponseCode::kCtap2ErrUnsupportedOption) });
    240240        else {
     
    255255    while (message->numPackets()) {
    256256        auto report = message->popNextPacket();
    257         if (!isFirst && stagesMatch() && m_configuration.hid->error == Mock::Error::WrongChannelId)
     257        if (!isFirst && stagesMatch() && m_configuration.hid->error == MockHid::Error::WrongChannelId)
    258258            report = FidoHidContinuationPacket(m_currentChannel - 1, 0, { }).getSerializedData();
    259259        // Packets are feed asynchronously to mimic actual data transmission.
     
    277277        return;
    278278    m_configuration.hid->continueAfterErrorData = false;
    279     m_configuration.hid->error = Mock::Error::Success;
     279    m_configuration.hid->error = MockHid::Error::Success;
    280280    continueFeedReports();
    281281}
  • trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockNfcService.h

    r249058 r249059  
    11/*
    2  * Copyright (C) 2018 Apple Inc. All rights reserved.
     2 * Copyright (C) 2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2626#pragma once
    2727
    28 #if ENABLE(WEB_AUTHN) && PLATFORM(MAC)
     28#if ENABLE(WEB_AUTHN)
    2929
    30 #include "AuthenticatorTransportService.h"
    31 #include <IOKit/hid/IOHIDManager.h>
    32 #include <wtf/RetainPtr.h>
    33 #include <wtf/UniqueRef.h>
     30#include "MockWebAuthenticationConfiguration.h"
     31#include "NfcService.h"
     32
     33OBJC_CLASS NSData;
    3434
    3535namespace WebKit {
    3636
    37 class CtapHidDriver;
    38 class HidConnection;
     37struct MockWebAuthenticationConfiguration;
    3938
    40 class HidService : public AuthenticatorTransportService {
     39class MockNfcService final : public NfcService {
    4140public:
    42     explicit HidService(Observer&);
    43     ~HidService();
     41    MockNfcService(Observer&, const MockWebAuthenticationConfiguration&);
    4442
    45     void deviceAdded(IOHIDDeviceRef);
     43    NSData* transceive();
    4644
    4745private:
    48     void startDiscoveryInternal() final;
     46    void platformStartDiscovery() final;
    4947
    50     // Overrided by MockHidService.
    51     virtual void platformStartDiscovery();
    52     virtual UniqueRef<HidConnection> createHidConnection(IOHIDDeviceRef) const;
     48    void detectTags() const;
    5349
    54     void continueAddDeviceAfterGetInfo(CtapHidDriver* deviceRef, Vector<uint8_t>&& info);
    55 
    56     RetainPtr<IOHIDManagerRef> m_manager;
    57     // Keeping drivers alive when they are initializing authenticators.
    58     HashSet<std::unique_ptr<CtapHidDriver>> m_drivers;
     50    MockWebAuthenticationConfiguration m_configuration;
    5951};
    6052
    6153} // namespace WebKit
    6254
    63 #endif // ENABLE(WEB_AUTHN) && PLATFORM(MAC)
     55#endif // ENABLE(WEB_AUTHN)
  • trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockWebAuthenticationConfiguration.h

    r245500 r249059  
    7373    };
    7474
     75    struct Nfc {
     76        enum class Error : uint8_t {
     77            Success,
     78            NoTags,
     79            WrongTagType,
     80            NoConnections,
     81            MaliciousPayload
     82        };
     83
     84        Error error { Error::Success };
     85        Vector<String> payloadBase64;
     86        bool multipleTags { false };
     87    };
     88
    7589    bool silentFailure { false };
    7690    Optional<Local> local;
    7791    Optional<Hid> hid;
     92    Optional<Nfc> nfc;
    7893};
    7994
  • trunk/Source/WebKit/UIProcess/WebAuthentication/fido/CtapAuthenticator.cpp

    r248631 r249059  
    2727#include "CtapAuthenticator.h"
    2828
    29 #if ENABLE(WEB_AUTHN) && PLATFORM(MAC)
     29#if ENABLE(WEB_AUTHN)
    3030
    3131#include "CtapDriver.h"
     
    116116} // namespace WebKit
    117117
    118 #endif // ENABLE(WEB_AUTHN) && PLATFORM(MAC)
     118#endif // ENABLE(WEB_AUTHN)
  • trunk/Source/WebKit/UIProcess/WebAuthentication/fido/CtapAuthenticator.h

    r248631 r249059  
    2626#pragma once
    2727
    28 #if ENABLE(WEB_AUTHN) && PLATFORM(MAC)
     28#if ENABLE(WEB_AUTHN)
    2929
    3030#include "Authenticator.h"
     
    5959} // namespace WebKit
    6060
    61 #endif // ENABLE(WEB_AUTHN) && PLATFORM(MAC)
     61#endif // ENABLE(WEB_AUTHN)
  • trunk/Source/WebKit/UIProcess/WebAuthentication/fido/CtapNfcDriver.h

    r249058 r249059  
    11/*
    2  * Copyright (C) 2018 Apple Inc. All rights reserved.
     2 * Copyright (C) 2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2626#pragma once
    2727
    28 #if ENABLE(WEB_AUTHN) && PLATFORM(MAC)
     28#if ENABLE(WEB_AUTHN) && HAVE(NEAR_FIELD)
    2929
    30 #include "AuthenticatorTransportService.h"
    31 #include <IOKit/hid/IOHIDManager.h>
    32 #include <wtf/RetainPtr.h>
     30#include "CtapDriver.h"
     31#include "NfcConnection.h"
    3332#include <wtf/UniqueRef.h>
    3433
    3534namespace WebKit {
    3635
    37 class CtapHidDriver;
    38 class HidConnection;
     36// The following implements the CTAP NFC protocol:
     37// https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#nfc
     38class CtapNfcDriver : public CtapDriver {
     39public:
     40    explicit CtapNfcDriver(UniqueRef<NfcConnection>&&);
    3941
    40 class HidService : public AuthenticatorTransportService {
    41 public:
    42     explicit HidService(Observer&);
    43     ~HidService();
    44 
    45     void deviceAdded(IOHIDDeviceRef);
     42    void transact(Vector<uint8_t>&& data, ResponseCallback&&) final;
    4643
    4744private:
    48     void startDiscoveryInternal() final;
     45    void respondAsync(ResponseCallback&&, Vector<uint8_t>&& response) const;
    4946
    50     // Overrided by MockHidService.
    51     virtual void platformStartDiscovery();
    52     virtual UniqueRef<HidConnection> createHidConnection(IOHIDDeviceRef) const;
    53 
    54     void continueAddDeviceAfterGetInfo(CtapHidDriver* deviceRef, Vector<uint8_t>&& info);
    55 
    56     RetainPtr<IOHIDManagerRef> m_manager;
    57     // Keeping drivers alive when they are initializing authenticators.
    58     HashSet<std::unique_ptr<CtapHidDriver>> m_drivers;
     47    UniqueRef<NfcConnection> m_connection;
    5948};
    6049
    6150} // namespace WebKit
    6251
    63 #endif // ENABLE(WEB_AUTHN) && PLATFORM(MAC)
     52#endif // ENABLE(WEB_AUTHN) && HAVE(NEAR_FIELD)
  • trunk/Source/WebKit/UIProcess/WebAuthentication/fido/FidoService.h

    r249058 r249059  
    11/*
    2  * Copyright (C) 2018 Apple Inc. All rights reserved.
     2 * Copyright (C) 2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2626#pragma once
    2727
    28 #if ENABLE(WEB_AUTHN) && PLATFORM(MAC)
     28#if ENABLE(WEB_AUTHN)
    2929
    3030#include "AuthenticatorTransportService.h"
    31 #include <IOKit/hid/IOHIDManager.h>
     31#include "CtapDriver.h"
    3232#include <wtf/RetainPtr.h>
    3333#include <wtf/UniqueRef.h>
     
    3535namespace WebKit {
    3636
    37 class CtapHidDriver;
    38 class HidConnection;
     37class FidoService : public AuthenticatorTransportService {
     38public:
     39    explicit FidoService(Observer&);
    3940
    40 class HidService : public AuthenticatorTransportService {
    41 public:
    42     explicit HidService(Observer&);
    43     ~HidService();
    44 
    45     void deviceAdded(IOHIDDeviceRef);
     41protected:
     42    void getInfo(std::unique_ptr<CtapDriver>&&);
    4643
    4744private:
    48     void startDiscoveryInternal() final;
     45    void continueAfterGetInfo(WeakPtr<CtapDriver>&&, Vector<uint8_t>&& info);
    4946
    50     // Overrided by MockHidService.
    51     virtual void platformStartDiscovery();
    52     virtual UniqueRef<HidConnection> createHidConnection(IOHIDDeviceRef) const;
    53 
    54     void continueAddDeviceAfterGetInfo(CtapHidDriver* deviceRef, Vector<uint8_t>&& info);
    55 
    56     RetainPtr<IOHIDManagerRef> m_manager;
    57     // Keeping drivers alive when they are initializing authenticators.
    58     HashSet<std::unique_ptr<CtapHidDriver>> m_drivers;
     47    // Keeping drivers alive when they are getting info from devices.
     48    HashSet<std::unique_ptr<CtapDriver>> m_drivers;
    5949};
    6050
    6151} // namespace WebKit
    6252
    63 #endif // ENABLE(WEB_AUTHN) && PLATFORM(MAC)
     53#endif // ENABLE(WEB_AUTHN)
  • trunk/Source/WebKit/UIProcess/WebAuthentication/fido/U2fAuthenticator.cpp

    r248631 r249059  
    2727#include "U2fAuthenticator.h"
    2828
    29 #if ENABLE(WEB_AUTHN) && PLATFORM(MAC)
     29#if ENABLE(WEB_AUTHN)
    3030
    3131#include "CtapDriver.h"
     
    239239} // namespace WebKit
    240240
    241 #endif // ENABLE(WEB_AUTHN) && PLATFORM(MAC)
     241#endif // ENABLE(WEB_AUTHN)
  • trunk/Source/WebKit/UIProcess/WebAuthentication/fido/U2fAuthenticator.h

    r248631 r249059  
    2626#pragma once
    2727
    28 #if ENABLE(WEB_AUTHN) && PLATFORM(MAC)
     28#if ENABLE(WEB_AUTHN)
    2929
    3030#include "Authenticator.h"
     
    8080} // namespace WebKit
    8181
    82 #endif // ENABLE(WEB_AUTHN) && PLATFORM(MAC)
     82#endif // ENABLE(WEB_AUTHN)
  • trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm

    r249051 r249059  
    4949#import "UIKitSPI.h"
    5050#import "UserData.h"
     51#import "VersionChecks.h"
    5152#import "VideoFullscreenManagerProxy.h"
    5253#import "ViewUpdateDispatcherMessages.h"
  • trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj

    r249001 r249059  
    10361036                53CFBBC82224D1B500266546 /* TextCheckerCompletion.h in Headers */ = {isa = PBXBuildFile; fileRef = 53CFBBC72224D1B000266546 /* TextCheckerCompletion.h */; };
    10371037                570AB8F320AE3BD700B8BE87 /* SecKeyProxyStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 570AB8F220AE3BD700B8BE87 /* SecKeyProxyStore.h */; };
     1038                570DAAAE23026F5C00E8FC04 /* NfcService.h in Headers */ = {isa = PBXBuildFile; fileRef = 570DAAAC23026F5C00E8FC04 /* NfcService.h */; };
     1039                570DAAC22303730300E8FC04 /* NfcConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 570DAAC02303730300E8FC04 /* NfcConnection.h */; };
     1040                570DAAC623037F7F00E8FC04 /* WKNFReaderSessionDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 570DAAC423037F7E00E8FC04 /* WKNFReaderSessionDelegate.h */; };
     1041                570DAACA230385FD00E8FC04 /* CtapNfcDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 570DAAC8230385FD00E8FC04 /* CtapNfcDriver.h */; };
    10381042                572FD44322265CE200A1ECC3 /* WebViewDidMoveToWindowObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = 572FD44122265CE200A1ECC3 /* WebViewDidMoveToWindowObserver.h */; };
    10391043                57597EB921811D9A0037F924 /* CtapHidDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 57597EB721811D9A0037F924 /* CtapHidDriver.h */; };
     
    10441048                57AC8F50217FEED90055438C /* HidConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 57AC8F4E217FEED90055438C /* HidConnection.h */; };
    10451049                57B4B46020B504AC00D4AD79 /* ClientCertificateAuthenticationXPCConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 57B4B45E20B504AB00D4AD79 /* ClientCertificateAuthenticationXPCConstants.h */; };
     1050                57B826412304EB3E00B72EB0 /* NearFieldSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 57B826402304EB3E00B72EB0 /* NearFieldSPI.h */; };
     1051                57B826442304F14000B72EB0 /* NearFieldSoftLink.h in Headers */ = {isa = PBXBuildFile; fileRef = 57B826422304F14000B72EB0 /* NearFieldSoftLink.h */; };
     1052                57B826452304F14000B72EB0 /* NearFieldSoftLink.mm in Sources */ = {isa = PBXBuildFile; fileRef = 57B826432304F14000B72EB0 /* NearFieldSoftLink.mm */; };
     1053                57B8264823050C5100B72EB0 /* FidoService.h in Headers */ = {isa = PBXBuildFile; fileRef = 57B8264623050C5100B72EB0 /* FidoService.h */; };
     1054                57B8264C230603C100B72EB0 /* MockNfcService.h in Headers */ = {isa = PBXBuildFile; fileRef = 57B8264A230603C100B72EB0 /* MockNfcService.h */; };
    10461055                57BBEA6D22BC0BFE00273995 /* SOAuthorizationLoadPolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = 57BBEA6C22BC0BFE00273995 /* SOAuthorizationLoadPolicy.h */; };
    10471056                57DCED6E2142EE5E0016B847 /* WebAuthenticatorCoordinatorMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57DCED6B2142EAE20016B847 /* WebAuthenticatorCoordinatorMessageReceiver.cpp */; };
     
    34763485                570AB90320B2541C00B8BE87 /* SecKeyProxyStore.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SecKeyProxyStore.mm; sourceTree = "<group>"; };
    34773486                570B73CF230236DD00FAEC53 /* CtapDriver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CtapDriver.h; sourceTree = "<group>"; };
     3487                570DAAAC23026F5C00E8FC04 /* NfcService.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NfcService.h; sourceTree = "<group>"; };
     3488                570DAAAD23026F5C00E8FC04 /* NfcService.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = NfcService.mm; sourceTree = "<group>"; };
     3489                570DAAB0230273D200E8FC04 /* NearField.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NearField.framework; path = System/Library/PrivateFrameworks/NearField.framework; sourceTree = SDKROOT; };
     3490                570DAAC02303730300E8FC04 /* NfcConnection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NfcConnection.h; sourceTree = "<group>"; };
     3491                570DAAC12303730300E8FC04 /* NfcConnection.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = NfcConnection.mm; sourceTree = "<group>"; };
     3492                570DAAC423037F7E00E8FC04 /* WKNFReaderSessionDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WKNFReaderSessionDelegate.h; sourceTree = "<group>"; };
     3493                570DAAC523037F7E00E8FC04 /* WKNFReaderSessionDelegate.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = WKNFReaderSessionDelegate.mm; sourceTree = "<group>"; };
     3494                570DAAC8230385FD00E8FC04 /* CtapNfcDriver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CtapNfcDriver.h; sourceTree = "<group>"; };
     3495                570DAAC9230385FD00E8FC04 /* CtapNfcDriver.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CtapNfcDriver.cpp; sourceTree = "<group>"; };
    34783496                572FD44122265CE200A1ECC3 /* WebViewDidMoveToWindowObserver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebViewDidMoveToWindowObserver.h; sourceTree = "<group>"; };
    34793497                575075A720AB763600693EA9 /* WebCredentialMac.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = WebCredentialMac.mm; sourceTree = "<group>"; };
     
    35003518                57B4B45D20B504AB00D4AD79 /* AuthenticationManagerCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AuthenticationManagerCocoa.mm; sourceTree = "<group>"; };
    35013519                57B4B45E20B504AB00D4AD79 /* ClientCertificateAuthenticationXPCConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClientCertificateAuthenticationXPCConstants.h; sourceTree = "<group>"; };
     3520                57B826402304EB3E00B72EB0 /* NearFieldSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NearFieldSPI.h; sourceTree = "<group>"; };
     3521                57B826422304F14000B72EB0 /* NearFieldSoftLink.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NearFieldSoftLink.h; sourceTree = "<group>"; };
     3522                57B826432304F14000B72EB0 /* NearFieldSoftLink.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = NearFieldSoftLink.mm; sourceTree = "<group>"; };
     3523                57B8264623050C5100B72EB0 /* FidoService.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FidoService.h; sourceTree = "<group>"; };
     3524                57B8264723050C5100B72EB0 /* FidoService.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FidoService.cpp; sourceTree = "<group>"; };
     3525                57B8264A230603C100B72EB0 /* MockNfcService.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MockNfcService.h; sourceTree = "<group>"; };
     3526                57B8264B230603C100B72EB0 /* MockNfcService.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MockNfcService.mm; sourceTree = "<group>"; };
    35023527                57BBEA6C22BC0BFE00273995 /* SOAuthorizationLoadPolicy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOAuthorizationLoadPolicy.h; sourceTree = "<group>"; };
    35033528                57DCED6A2142EAE20016B847 /* WebAuthenticatorCoordinatorMessages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebAuthenticatorCoordinatorMessages.h; path = DerivedSources/WebKit2/WebAuthenticatorCoordinatorMessages.h; sourceTree = BUILT_PRODUCTS_DIR; };
     
    61966221                                57DCEDAA214B9B430016B847 /* DeviceIdentitySPI.h */,
    61976222                                2DAADA8E2298C21000E36B0C /* DeviceManagementSPI.h */,
     6223                                57B826402304EB3E00B72EB0 /* NearFieldSPI.h */,
    61986224                                3754D5441B3A29FD003A4C7F /* NSInvocationSPI.h */,
    61996225                                37B47E2C1D64DB76005F4EFF /* objcSPI.h */,
     
    69626988                        children = (
    69636989                                5750F32A2032D4E500389347 /* LocalAuthentication.framework */,
     6990                                570DAAB0230273D200E8FC04 /* NearField.framework */,
    69646991                        );
    69656992                        name = Frameworks;
     
    69747001                                57597EC021818BE20037F924 /* CtapHidDriver.cpp */,
    69757002                                57597EB721811D9A0037F924 /* CtapHidDriver.h */,
     7003                                570DAAC9230385FD00E8FC04 /* CtapNfcDriver.cpp */,
     7004                                570DAAC8230385FD00E8FC04 /* CtapNfcDriver.h */,
     7005                                57B8264723050C5100B72EB0 /* FidoService.cpp */,
     7006                                57B8264623050C5100B72EB0 /* FidoService.h */,
    69767007                                57EB2E3921E1983E00B89CDF /* U2fAuthenticator.cpp */,
    69777008                                57EB2E3821E1983E00B89CDF /* U2fAuthenticator.h */,
     
    70377068                                57DCED9A2148B0830016B847 /* LocalService.h */,
    70387069                                57DCEDA02148FA0F0016B847 /* LocalService.mm */,
     7070                                57B826422304F14000B72EB0 /* NearFieldSoftLink.h */,
     7071                                57B826432304F14000B72EB0 /* NearFieldSoftLink.mm */,
     7072                                570DAAC02303730300E8FC04 /* NfcConnection.h */,
     7073                                570DAAC12303730300E8FC04 /* NfcConnection.mm */,
     7074                                570DAAAC23026F5C00E8FC04 /* NfcService.h */,
     7075                                570DAAAD23026F5C00E8FC04 /* NfcService.mm */,
     7076                                570DAAC423037F7E00E8FC04 /* WKNFReaderSessionDelegate.h */,
     7077                                570DAAC523037F7E00E8FC04 /* WKNFReaderSessionDelegate.mm */,
    70397078                        );
    70407079                        path = Cocoa;
     
    70547093                                57DCEDC1214F114C0016B847 /* MockLocalService.h */,
    70557094                                57DCEDC2214F114C0016B847 /* MockLocalService.mm */,
     7095                                57B8264A230603C100B72EB0 /* MockNfcService.h */,
     7096                                57B8264B230603C100B72EB0 /* MockNfcService.mm */,
    70567097                                57DCEDBE214CA01B0016B847 /* MockWebAuthenticationConfiguration.h */,
    70577098                        );
     
    93609401                                57597EBD218184900037F924 /* CtapAuthenticator.h in Headers */,
    93619402                                57597EB921811D9A0037F924 /* CtapHidDriver.h in Headers */,
     9403                                570DAACA230385FD00E8FC04 /* CtapNfcDriver.h in Headers */,
    93629404                                C55F91711C59676E0029E92D /* DataDetectionResult.h in Headers */,
    93639405                                1AC75380183BE50F0072CB15 /* DataReference.h in Headers */,
     
    93919433                                51B15A8513843A3900321AD8 /* EnvironmentUtilities.h in Headers */,
    93929434                                1AA575FB1496B52600A4EE06 /* EventDispatcher.h in Headers */,
     9435                                57B8264823050C5100B72EB0 /* FidoService.h in Headers */,
    93939436                                00B9661A18E25AE100CE1F88 /* FindClient.h in Headers */,
    93949437                                1A90C1F41264FD71003E44D4 /* FindController.h in Headers */,
     
    94799522                                57DCEDC7214F18300016B847 /* MockLocalConnection.h in Headers */,
    94809523                                57DCEDC3214F114C0016B847 /* MockLocalService.h in Headers */,
     9524                                57B8264C230603C100B72EB0 /* MockNfcService.h in Headers */,
    94819525                                57DCEDBF214F0DCF0016B847 /* MockWebAuthenticationConfiguration.h in Headers */,
    94829526                                C0E3AA7C1209E83C00A49D01 /* Module.h in Headers */,
     
    94869530                                57FD318022B35158008D0E8B /* NavigationSOAuthorizationSession.h in Headers */,
    94879531                                1ABC3DF61899E437004F0626 /* NavigationState.h in Headers */,
     9532                                57B826442304F14000B72EB0 /* NearFieldSoftLink.h in Headers */,
     9533                                57B826412304EB3E00B72EB0 /* NearFieldSPI.h in Headers */,
    94889534                                1A6FBA2A11E6862700DB1371 /* NetscapeBrowserFuncs.h in Headers */,
    94899535                                1A6FBD2811E69BC200DB1371 /* NetscapePlugin.h in Headers */,
     
    95319577                                532159551DBAE7290054AA3C /* NetworkSessionCocoa.h in Headers */,
    95329578                                417915B92257046F00D6F97E /* NetworkSocketChannel.h in Headers */,
     9579                                570DAAC22303730300E8FC04 /* NfcConnection.h in Headers */,
     9580                                570DAAAE23026F5C00E8FC04 /* NfcService.h in Headers */,
    95339581                                31A2EC5614899C0900810D71 /* NotificationPermissionRequest.h in Headers */,
    95349582                                3131261F148FF82C00BA2A39 /* NotificationPermissionRequestManager.h in Headers */,
     
    1015910207                                1AA13212191D5924009C1489 /* WKNavigationResponsePrivate.h in Headers */,
    1016010208                                2D3A65DF1A7C3A7D00CAC637 /* WKNavigationResponseRef.h in Headers */,
     10209                                570DAAC623037F7F00E8FC04 /* WKNFReaderSessionDelegate.h in Headers */,
    1016110210                                318BE17914743E6F00A8FBB2 /* WKNotification.h in Headers */,
    1016210211                                318BE17114743DB100A8FBB2 /* WKNotificationManager.h in Headers */,
     
    1114311192                                2D92A782212B6A7100F493FD /* MessageSender.cpp in Sources */,
    1114411193                                2D92A77A212B6A6100F493FD /* Module.cpp in Sources */,
     11194                                57B826452304F14000B72EB0 /* NearFieldSoftLink.mm in Sources */,
    1114511195                                2D913443212CF9F000128AFD /* NetscapeBrowserFuncs.cpp in Sources */,
    1114611196                                2D913444212CF9F000128AFD /* NetscapePlugin.cpp in Sources */,
  • trunk/Tools/ChangeLog

    r249046 r249059  
     12019-08-20  Jiewen Tan  <jiewen_tan@apple.com>
     2
     3        [WebAuthn] Support NFC authenticators for iOS
     4        https://bugs.webkit.org/show_bug.cgi?id=188624
     5        <rdar://problem/43354214>
     6
     7        Reviewed by Chris Dumez.
     8
     9        * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
     10        (WTR::TestRunner::setWebAuthenticationMockConfiguration):
     11        Setup NFC mock testing configuration.
     12
    1132019-08-23  Aakash Jain  <aakash_jain@apple.com>
    214
  • trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp

    r249013 r249059  
    27102710    }
    27112711
     2712    JSRetainPtr<JSStringRef> nfcPropertyName(Adopt, JSStringCreateWithUTF8CString("nfc"));
     2713    JSValueRef nfcValue = JSObjectGetProperty(context, configuration, nfcPropertyName.get(), 0);
     2714    if (!JSValueIsUndefined(context, nfcValue) && !JSValueIsNull(context, nfcValue)) {
     2715        if (!JSValueIsObject(context, nfcValue))
     2716            return;
     2717        JSObjectRef nfc = JSValueToObject(context, nfcValue, 0);
     2718
     2719        JSRetainPtr<JSStringRef> errorPropertyName(Adopt, JSStringCreateWithUTF8CString("error"));
     2720        JSValueRef errorValue = JSObjectGetProperty(context, nfc, errorPropertyName.get(), 0);
     2721        if (!JSValueIsString(context, errorValue))
     2722            return;
     2723
     2724        Vector<WKRetainPtr<WKStringRef>> nfcKeys;
     2725        Vector<WKRetainPtr<WKTypeRef>> nfcValues;
     2726        nfcKeys.append(adoptWK(WKStringCreateWithUTF8CString("Error")));
     2727        nfcValues.append(toWK(adopt(JSValueToStringCopy(context, errorValue, 0)).get()));
     2728
     2729        JSRetainPtr<JSStringRef> payloadBase64PropertyName(Adopt, JSStringCreateWithUTF8CString("payloadBase64"));
     2730        JSValueRef payloadBase64Value = JSObjectGetProperty(context, nfc, payloadBase64PropertyName.get(), 0);
     2731        if (!JSValueIsUndefined(context, payloadBase64Value) && !JSValueIsNull(context, payloadBase64Value)) {
     2732            if (!JSValueIsArray(context, payloadBase64Value))
     2733                return;
     2734
     2735            JSObjectRef payloadBase64 = JSValueToObject(context, payloadBase64Value, nullptr);
     2736            static auto lengthProperty = adopt(JSStringCreateWithUTF8CString("length"));
     2737            JSValueRef payloadBase64LengthValue = JSObjectGetProperty(context, payloadBase64, lengthProperty.get(), nullptr);
     2738            if (!JSValueIsNumber(context, payloadBase64LengthValue))
     2739                return;
     2740
     2741            auto payloadBase64s = adoptWK(WKMutableArrayCreate());
     2742            auto payloadBase64Length = static_cast<size_t>(JSValueToNumber(context, payloadBase64LengthValue, nullptr));
     2743            for (size_t i = 0; i < payloadBase64Length; ++i) {
     2744                JSValueRef payloadBase64Value = JSObjectGetPropertyAtIndex(context, payloadBase64, i, nullptr);
     2745                if (!JSValueIsString(context, payloadBase64Value))
     2746                    continue;
     2747                WKArrayAppendItem(payloadBase64s.get(), toWK(adopt(JSValueToStringCopy(context, payloadBase64Value, 0)).get()).get());
     2748            }
     2749
     2750            nfcKeys.append(adoptWK(WKStringCreateWithUTF8CString("PayloadBase64")));
     2751            nfcValues.append(payloadBase64s);
     2752        }
     2753
     2754        JSRetainPtr<JSStringRef> multipleTagsPropertyName(Adopt, JSStringCreateWithUTF8CString("multipleTags"));
     2755        JSValueRef multipleTagsValue = JSObjectGetProperty(context, nfc, multipleTagsPropertyName.get(), 0);
     2756        if (!JSValueIsUndefined(context, multipleTagsValue) && !JSValueIsNull(context, multipleTagsValue)) {
     2757            if (!JSValueIsBoolean(context, multipleTagsValue))
     2758                return;
     2759            bool multipleTags = JSValueToBoolean(context, multipleTagsValue);
     2760            nfcKeys.append(adoptWK(WKStringCreateWithUTF8CString("MultipleTags")));
     2761            nfcValues.append(adoptWK(WKBooleanCreate(multipleTags)).get());
     2762        }
     2763
     2764        Vector<WKStringRef> rawNfcKeys;
     2765        Vector<WKTypeRef> rawNfcValues;
     2766        rawNfcKeys.resize(nfcKeys.size());
     2767        rawNfcValues.resize(nfcValues.size());
     2768        for (size_t i = 0; i < nfcKeys.size(); ++i) {
     2769            rawNfcKeys[i] = nfcKeys[i].get();
     2770            rawNfcValues[i] = nfcValues[i].get();
     2771        }
     2772
     2773        configurationKeys.append(adoptWK(WKStringCreateWithUTF8CString("Nfc")));
     2774        configurationValues.append(adoptWK(WKDictionaryCreate(rawNfcKeys.data(), rawNfcValues.data(), rawNfcKeys.size())));
     2775    }
     2776
    27122777    Vector<WKStringRef> rawConfigurationKeys;
    27132778    Vector<WKTypeRef> rawConfigurationValues;
Note: See TracChangeset for help on using the changeset viewer.