diff --git a/index.bs b/index.bs
index 89e05d10e..27cec2f24 100644
--- a/index.bs
+++ b/index.bs
@@ -7517,6 +7517,218 @@ Note: this extension may be implemented for [=authenticators=] that do not use [
:: The results of evaluating the PRF for the inputs given in {{AuthenticationExtensionsPRFInputs/eval}} or {{AuthenticationExtensionsPRFInputs/evalByCredential}}. Outputs may not be available during [=registration=]; see comments in {{AuthenticationExtensionsPRFInputs/eval}}.
+
+#### Test vectors: Web Authentication API #### {#prf-extension-test-vectors-webauthn}
+
+[INFORMATIVE]
+
+The following examples may be used to test [=[WAC]=] implementations of and [=[WRP]=] usage of the [=prf=] extension.
+The examples are not exhaustive.
+
+- The {{AuthenticationExtensionsPRFOutputs/enabled}} output is always present during [=registration ceremonies=],
+ and never present during [=authentication ceremonies=]:
+
+
+ // Example extension inputs:
+ { prf: {} }
+
+ // Example client extension outputs from navigator.credentials.create():
+ { prf: { enabled: true } }
+ { prf: { enabled: false } }
+
+ // Example client extension outputs from navigator.credentials.get():
+ { prf: {} }
+
+
+- The {{AuthenticationExtensionsPRFOutputs/results}} output may be present
+ during [=registration ceremonies=] or [=authentication ceremonies=]
+ if the {{AuthenticationExtensionsPRFInputs/eval}} or {{AuthenticationExtensionsPRFInputs/evalByCredential}} input is present:
+
+
+ // Example extension inputs:
+ { prf: { eval: { first: new Uint8Array([1, 2, 3, 4]) } } }
+
+ // Example client extension outputs from navigator.credentials.create():
+ { prf: { enabled: true } }
+ { prf: { enabled: false } }
+ { prf: { enabled: true, results: { first: ArrayBuffer } } }
+
+ // Example client extension outputs from navigator.credentials.get():
+ { prf: {} }
+ { prf: { results: { first: ArrayBuffer } } }
+
+
+- The {{AuthenticationExtensionsPRFOutputs/results}}.{{AuthenticationExtensionsPRFValues/second}}
output
+ is present if and only if the {{AuthenticationExtensionsPRFOutputs/results}} output is present
+ and the {{AuthenticationExtensionsPRFValues/second}}
input was present in the chosen PRF inputs:
+
+
+ // Example extension inputs:
+ {
+ prf: {
+ eval: {
+ first: new Uint8Array([1, 2, 3, 4]),
+ second: new Uint8Array([5, 6, 7, 8]),
+ },
+ evalByCredential: {
+ "e02eZ9lPp0UdkF4vGRO4-NxlhWBkL1FCmsmb1tTfRyE": {
+ first: new Uint8Array([9, 10, 11, 12]),
+ }
+ }
+ }
+ }
+
+ // Example client extension outputs from navigator.credentials.get() if credential "e02eZ9lP..." was used:
+ { prf: { results: { first: ArrayBuffer } } }
+
+ // Example client extension outputs from navigator.credentials.get() if a different credential was used:
+ { prf: {} }
+ { prf: { results: { first: ArrayBuffer, second: ArrayBuffer } } }
+
+
+- The {{AuthenticationExtensionsPRFValues/first}} and {{AuthenticationExtensionsPRFValues/second}} outputs
+ may be any {{BufferSource}} type.
+ Equal {{AuthenticationExtensionsPRFValues/first}} and {{AuthenticationExtensionsPRFValues/second}} inputs
+ result in equal {{AuthenticationExtensionsPRFValues/first}} and {{AuthenticationExtensionsPRFValues/second}} outputs:
+
+
+ // Example extension inputs:
+ {
+ prf: {
+ evalByCredential: {
+ "e02eZ9lPp0UdkF4vGRO4-NxlhWBkL1FCmsmb1tTfRyE": {
+ first: new Uint8Array([9, 10, 11, 12]),
+ second: new Uint8Array([9, 10, 11, 12])
+ }
+ }
+ }
+ }
+
+ // Example client extension outputs from navigator.credentials.get():
+ {
+ prf: {
+ results: {
+ first: new Uint8Array([0xc4, 0x17, 0x2e, 0x98, 0x2e, 0x90, 0x97, 0xc3, 0x9a, 0x6c, 0x0c, 0xb7, 0x20, 0xcb, 0x37, 0x5b, 0x92, 0xe3, 0xfc, 0xad, 0x15, 0x4a, 0x63, 0xe4, 0x3a, 0x93, 0xf1, 0x09, 0x6b, 0x1e, 0x19, 0x73]),
+ second: new Uint32Array([0x982e17c4, 0xc397902e, 0xb70c6c9a, 0x5b37cb20, 0xadfce392, 0xe4634a15, 0x09f1933a, 0x73191e6b]),
+ }
+ }
+ }
+
+
+Pseudo-random values used in this section were generated as follows:
+
+- "e02eZ9lPp0UdkF4vGRO4-NxlhWBkL1FCmsmb1tTfRyE" = Base64Url(SHA-256(UTF-8("WebAuthn PRF test vectors") || 0x00))
+- h'c4172e982e9097c39a6c0cb720cb375b92e3fcad154a63e43a93f1096b1e1973' = SHA-256(UTF-8("WebAuthn PRF test vectors") || 0x01)
+
+
+#### Test vectors: CTAP2 `hmac-secret` extension #### {#prf-extension-test-vectors-ctap}
+
+[INFORMATIVE]
+
+The following examples may be used to test [=[WAC]=] implementations
+of how the [=prf=] extension uses the [[FIDO-CTAP]] `hmac-secret` extension.
+The examples are given in CDDL [[RFC8610]] notation.
+The examples are not exhaustive.
+
+- The following shared definitions are used in all subsequent examples:
+
+
+ ; Given input parameters:
+ platform_key_agreement_private_key = 0x0971bc7fb1be48270adcd3d9a5fc15d5fb0f335b3071ff36a54c007fa6c76514
+ authenticator_key_agreement_public_key = {
+ 1: 2,
+ 3: -25,
+ -1: 1,
+ -2: h'a30522c2de402b561965c3cf949a1cab020c6f6ea36fcf7e911ac1a0f1515300',
+ -3: h'9961a929abdb2f42e6566771887d41484d889e735e3248518a53112d2b915f00',
+ }
+ authenticator_cred_random = h'437e065e723a98b2f08f39d8baf7c53ecb3c363c5e5104bdaaf5d5ca2e028154'
+
+
+ The {{AuthenticationExtensionsPRFValues/first}} and {{AuthenticationExtensionsPRFValues/second}} inputs
+ are mapped in the examples as `prf_eval_first` and `prf_eval_second`, respectively.
+ The `prf_results_first` and `prf_results_second` values in the examples
+ are mapped to the
+ {{AuthenticationExtensionsPRFOutputs/results}}.{{AuthenticationExtensionsPRFValues/first}}
+ and {{AuthenticationExtensionsPRFOutputs/results}}.{{AuthenticationExtensionsPRFValues/second}}
+ outputs, respectively.
+
+- Single input case using PIN protocol 2:
+
+
+ ; Inputs from Relying Party:
+ prf_eval_first = h'576562417574686e20505246207465737420766563746f727302'
+
+ ; Client computes:
+ shared_secret = h'0c63083de8170101d38bcf8bd72309568ddb4550867e23404b35d85712f7c20d8bc911ee23c06034cbc14290b9669bec07739053c5a416e313ef905c79955876'
+ salt1 = h'527413ebb48293772df30f031c5ac4650c7de14bf9498671ae163447b6a772b3'
+ salt_enc = h'437e065e723a98b2f08f39d8baf7c53ebbb2ed3e746b87576fd81f95def5757cad24be18eaef892e97692e684e07da53'
+
+ ; Authenticator computes:
+ output1 = h'3c33e07d202c3b029cc21f1722767021bf27d595933b3d2b6a1b9d5dddc77fae'
+ output_enc = h'3bfaa48f7952330d63e35ff8cd5bca48d2a12823828915749287256ab146272f9fb437bf65691243c3f504bd7ea6d5e6'
+
+ ; Client decrypts:
+ prf_results_first = h'3c33e07d202c3b029cc21f1722767021bf27d595933b3d2b6a1b9d5dddc77fae'
+
+
+- Two input case using PIN protocol 2:
+
+
+ ; Inputs from Relying Party:
+ prf_eval_first = h'576562417574686e20505246207465737420766563746f727302'
+ prf_eval_second = h'576562417574686e20505246207465737420766563746f727303'
+
+ ; Client computes:
+ shared_secret = h'0c63083de8170101d38bcf8bd72309568ddb4550867e23404b35d85712f7c20d8bc911ee23c06034cbc14290b9669bec07739053c5a416e313ef905c79955876'
+ salt1 = h'527413ebb48293772df30f031c5ac4650c7de14bf9498671ae163447b6a772b3'
+ salt2 = h'd68ac03329a10ee5e0ec834492bb9a96a0e547baf563bf78ccbe8789b22e776b'
+ salt_enc = h'23dde5e3462daf36559b85c4ac5f9656aa9bfd81c1dc2bf8533c8b9f3882854786b4f500e25b4e3d81f7fc7c742362294d92926c883b3fae1a3673246464bf730446e1fa4698c432a9092477c5dde5e3'
+
+ ; Authenticator computes:
+ output1 = h'3c33e07d202c3b029cc21f1722767021bf27d595933b3d2b6a1b9d5dddc77fae'
+ output2 = h'a62a8773b19cda90d7ed4ef72a80a804320dbd3997e2f663805ad1fd3293d50b'
+ output_enc = h'90ee52f739043bc17b3488a74306d7801debb5b61f18662c648a25b5b5678ede482cdaff99a537a44f064fcb10ce6e04dfd27619dc96a0daff8507e499296b1eecf0981f7c8518b277a7a3018f5ec6fb'
+
+ ; Client decrypts:
+ prf_results_first = h'3c33e07d202c3b029cc21f1722767021bf27d595933b3d2b6a1b9d5dddc77fae'
+ prf_results_second = h'a62a8773b19cda90d7ed4ef72a80a804320dbd3997e2f663805ad1fd3293d50b'
+
+
+- Single input case using PIN protocol 1:
+
+
+ ; Inputs from Relying Party:
+ prf_eval_first = h'576562417574686e20505246207465737420766563746f727302'
+
+ ; Client computes:
+ shared_secret = h'23e5ed7157c25892b77732fb9c8a107e3518800db2af4142f9f4adfacb771d39'
+ salt1 = h'527413ebb48293772df30f031c5ac4650c7de14bf9498671ae163447b6a772b3'
+ salt_enc = h'ab8c878bb05d04700f077ed91845ec9c503c925cb12b327ddbeb4243c397f913'
+
+ ; Authenticator computes:
+ output1 = h'3c33e07d202c3b029cc21f1722767021bf27d595933b3d2b6a1b9d5dddc77fae'
+ output_enc = h'15d4e4f3f04109b492b575c1b38c28585b6719cf8d61304215108d939f37ccfb'
+
+ ; Client decrypts:
+ prf_results_first = h'3c33e07d202c3b029cc21f1722767021bf27d595933b3d2b6a1b9d5dddc77fae'
+
+
+Inputs and pseudo-random values used in this section were generated as follows:
+
+- seed = UTF-8("WebAuthn PRF test vectors")
+- prf_eval_first = seed || 0x02
+- prf_eval_second = seed || 0x03
+- platform_key_agreement_private_key = SHA-256(seed || 0x04)
+- authenticator_key_agreement_public_key = P256-Public-Key(sk)
+ where sk = SHA-256(seed || 0x05)
+- authenticator_cred_random = SHA-256(seed || 0x06)
+- `iv` in single-input `salt_enc` with PIN protocol 2: Truncated SHA-256(seed || 0x07)
+- `iv` in two-input `salt_enc` with PIN protocol 2: Truncated SHA-256(seed || 0x08)
+- `iv` in single-input `output_enc` with PIN protocol 2: Truncated SHA-256(seed || 0x09)
+- `iv` in two-input `output_enc` with PIN protocol 2: Truncated SHA-256(seed || 0x0a)
+
+
### Large blob storage extension (largeBlob) ### {#sctn-large-blob-extension}
This [=client extension|client=] [=registration extension=] and [=authentication extension=] allows a [=[RP]=] to store opaque data associated with a credential. Since [=authenticators=] can only store small amounts of data, and most [=[RPS]=] are online services that can store arbitrary amounts of state for a user, this is only useful in specific cases. For example, the [=[RP]=] might wish to issue certificates rather than run a centralised authentication service.